This version of the calculator adds library files. The save
command saves the global symbol table to a file, and the load
command loads symbols from a file into the global symbol table.
This calculator has a simple syntax:
start ::= statement-list statement-list ::= empty | statement-list statement statement ::= definition | quit | expression | "load" string | "save" string definition ::= "def" identifier optional-parameters "=" expression optional-parameters ::= empty | "(" optional-identifier-list ")" optional-identifier-list ::= empty | identifier-list identifier-list ::= identifier | identifier-list "," identifier expression ::= multiplicative-expression "+" multiplicative-expression | multiplicative-expression "-" multiplicative-expression multiplicative-expression ::= unary-expression "*" unary-expression | unary-expression "/" unary-expression unary-expression ::= "-" primary | "+" primary | primary primary ::= number | function-call | "(" expression ")" function-call ::= identifier optional_arguments optional_arguments ::= empty | "(" optional-expression-list ")" optional-expression-list ::= empty | expression-list expression-list ::= expression | expression-list "," expression
Function arguments are evaluated lazily. There are no variables, only functions, but function definitions can look just like variable assignments:
def pi = 3.141592653589792
The calculator reads expressions from the standard input, evaluates them, and prints the results to the standard output. It's that simple.
The calculator parses expression into a parse tree. The parser uses node objects. The node class uses the pimpl idiom with a tree of node_impl-derived classes.