Skip to content

Defining Reserved Words

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.
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;

Declaring a new Reserved Character

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 =-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.

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;
}

Clone this wiki locally