// vim: set filetype=none: // (Lemon files have .y extensions like Yacc files but are not Yacc.) %include { #include #include #include #include "../lib/mlrutil.h" #include "./ex_ast.h" #include "../containers/sllv.h" #define DO_WRITE_APPEND // transitional pending lemon-memory issue // ================================================================ // AST: // * parens, commas, semis, line endings, whitespace are all stripped away // * variable names and literal values remain as leaf nodes of the AST // * = + - * / ** {function names} remain as non-leaf nodes of the AST // CST: See ex2_cst.c // // Note: This parser accepts many things that are invalid, e.g. // * begin{end{}} -- begin/end not at top level // * begin{$x=1} -- references to stream records at begin/end // * break/continue outside of for/while/do-while // * $x=x -- boundvars outside of for-loop variable bindings // All of the above are enforced by the CST builder, which takes this parser's output AST as input. // This is done (a) to keep this grammar from being overly complex, and (b) so we can get much more // informative error messages in C than in Lemon ('syntax error'). // // The parser hooks all build up an abstract syntax tree specifically for the CST builder. // For clearer visuals on what the ASTs look like: // * See ex2_cst.c // * See reg_test/run's filter -v and put -v outputs, e.g. in reg_test/expected/out // * Do "mlr -n put -v 'your expression goes here'" // ================================================================ } %token_type {ex_ast_node_t*} %default_type {ex_ast_node_t*} %extra_argument {ex_ast_t* past} //void token_destructor(ex_ast_node_t t) { // printf("In token_destructor t->text(%s)=t->type(%lf)\n", t->text, t->type); //} //%token_destructor {token_destructor($$);} %parse_accept { } // The caller is expected to provide more context. %syntax_error { fprintf(stderr, "mlr DSL: syntax error.\n"); } // ================================================================ md_body ::= md_statement_list(B). { past->proot = B; } // ---------------------------------------------------------------- md_statement_list(A) ::= md_statement(B). { if (B->type == MD_AST_NODE_TYPE_NOP) { A = ex_ast_node_alloc_zary("list", MD_AST_NODE_TYPE_STATEMENT_BLOCK); } else { A = ex_ast_node_alloc_unary("list", MD_AST_NODE_TYPE_STATEMENT_BLOCK, B); } } //md_statement_list(A) ::= md_statement(B) MD_SEMICOLON md_statement_list(C). { // if (B->type == MD_AST_NODE_TYPE_NOP) { // A = C; // } else { // A = ex_ast_node_prepend_arg(C, B); // } //} md_statement_list(A) ::= md_statement_list(B) MD_SEMICOLON md_statement(C). { if (C->type == MD_AST_NODE_TYPE_NOP) { A = B; } else { A = ex_ast_node_append_arg(B, C); } } md_statement(A) ::= md_srec_assignment(B). { A = B; } // ---------------------------------------------------------------- md_srec_assignment(A) ::= md_field_name(B) MD_TOKEN_ASSIGN(O) md_rhs(C). { A = ex_ast_node_alloc_binary(O->text, MD_AST_NODE_TYPE_SREC_ASSIGNMENT, B, C); } md_field_name(A) ::= MD_TOKEN_FIELD_NAME(B). { //char* dollar_name = B->text; //char* no_dollar_name = &dollar_name[1]; //A = ex_ast_node_alloc(no_dollar_name, B->type); A = ex_ast_node_alloc(B->text, B->type); } md_rhs(A) ::= md_atom_or_fcn(B). { A = B; } // ---------------------------------------------------------------- md_atom_or_fcn(A) ::= MD_TOKEN_NUMBER(B). { A = B; }