| ▲ | adrian_b 5 hours ago | |
I assume that they refer to what you do when you write a Yacc or Bison file or any other input file for a similar parser generator. A Yacc file contains the grammar of the language to be parsed, but to each grammar rule you can attach a C function that will be invoked by the generated parser when matching that rule. That C function is the "semantic action" registered for the corresponding grammar production rule. For instance, by registering appropriate "semantic actions" the generated parser can become a language interpreter, e.g. when matching a multiplication expression a function that does multiplication is invoked, and so on. If the parser is intended for a compiler, not for an interpreter, the "semantic actions" may generate some intermediate format of the compiled program, like that used by LLVM. | ||
| ▲ | direwolf20 3 hours ago | parent [-] | |
Executing the operation inside the semantic action only works for simple calculators. Otherwise you have the problem that the line of code may run multiple times even though it's only parsed once. Usually you make the semantic actions build an AST - a data value that holds the program fragment you just parsed, e.g. new NumberLiteral(atoi(parsed_text)), new FunctionCall(function_identifier_ast, [arg1_ast, arg2_ast]), new BinaryExpression(left_ast, '+', right_ast) Older compilers with less memory may have compiled each function as it was parsed, but it's pretty typical these days for the parser to output a whole-file AST that you process separately. | ||