-
Notifications
You must be signed in to change notification settings - Fork 72
Defining Reserved Words
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.
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.
void TrueParser(const char* expr, const char** rest, rpnBuilder* data) {
data->handle_token(trueToken->clone());
}After that you just need to add it to the reserved words map:
struct Startup {
Startup() {
parserMap_t& parser = calculator::Default().parserMap;
parser.add("True", &TrueParser);
}
} Startup;A reserved character is almost the same thing as a reserved word and it is declared in much the same way, e.g.:
struct Startup {
Startup() {
parserMap_t& parser = calculator::Default().parserMap;
// Reserved word:
parser.add("//", &SlashCommentParser);
// Reserved character:
parser.add('/', &RegExpParser);
}
} Startup;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 =-1Should be interpreted just like:
v = -1This would not be possible if = was a reserved word, since the interpreter would read both characters =- as a single operator.
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.
void function_parser(const char* expr, const char** 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(new CompiledFunc(expr, &expr, data->scope));
// ... some code omitted ...
*rest = expr;
}