You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Vinícius Garcia edited this page May 3, 2017
·
14 revisions
The framework supports a feature to allow an user to describe a custom parser to be used to parse reserved words. This is very useful, you can use it to define constant values like: True, False, Null, etc. Or you can use them for more complex concepts, for example:
calculator::calculate("my_instance = new my_class(arg1, arg2);");
The new operator has a special meaning and will cause the parsing of the rest of the expression to use different rules. For instance my_class is not a function so if the normal rules were to be applied it would throw an exception stating that the call operator () is undefined for the operands my_class and (arg1, arg2).
So although this is an advanced feature it is quite useful, and is not too hard to use.
Declaring a new Reserved Word
To declare a new reserved word you must first declare a parser function like this:
// expr starts right after the key-word, so if you print expr,// you'll see the part of the expression that was not parsed yet.voidTrueParser(constchar* expr, constchar** rest, rpnBuilder* data) {
data->handle_token(trueToken->clone());
}
After that you just need to add it to the reserved words map:
It is useful when you want a character to have a meaning regardless of the character that follows it, e.g. the = character on the expression:
v =-1
Should be interpreted just like:
v = -1
This would not be possible if = was a reserved word, since the interpreter would read both characters =- as a single operator.
A More Advanced Example
Lets get to a more complex example: Lets declare a function keyword to mark a function declaration. The example below was extracted from the JSpy Programming Language that uses CParse as its base engine.
Side Note: Since the function being parsed would be a nameless function, even if the user provide a name it will be ignored. That is an expected behavior.
voidfunction_parser(constchar* expr, constchar** rest, rpnBuilder* data) {
// Ignore white spaces:while (isspace(*expr)) ++expr;
if (isalpha(*expr) || *expr == '_') {
// Ignore the name if provided:while (isalnum(*expr) || *expr == '_') ++expr;
// Ignore white spaces:while (isspace(*expr)) ++expr;
}
data->handle_token(newCompiledFunc(expr, &expr, data->scope));
// ... some code omitted ...
*rest = expr;
}