diff options
Diffstat (limited to 'src/parser.cpp')
-rw-r--r-- | src/parser.cpp | 125 |
1 files changed, 120 insertions, 5 deletions
diff --git a/src/parser.cpp b/src/parser.cpp index a1ee376..9d2fbce 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -36,6 +36,13 @@ enum parser_state { STATE_RULE_BAR, STATE_RULE_EQUAL, STATE_RULE, + STATE_RULE_VAR_PRE, + STATE_RULE_VAR, + STATE_RULE_VAR_POST, + STATE_TYPE, + STATE_TYPE_NONTERM, + STATE_TYPE_TERM, + STATE_TYPE_TERM_BLOCK, }; struct parser { @@ -53,12 +60,16 @@ int parser_push(parser_t *parser, int token, const parser_value_t *value, parser switch (parser->state) { case STATE_INIT: switch (token) { - case TOK_NONTERM: + case TOK_SYMBOL_LC: parser->state = STATE_RULE_BAR; state->new_rule(value->str); free(value->str); return 1; + case TOK_TYPE: + parser->state = STATE_TYPE; + return 1; + case 0: return 0; } @@ -83,12 +94,12 @@ int parser_push(parser_t *parser, int token, const parser_value_t *value, parser case STATE_RULE: switch (token) { - case TOK_NONTERM: + case TOK_SYMBOL_LC: state->add_rule_nonterminal(value->str); free(value->str); return 1; - case TOK_TERM: + case TOK_SYMBOL_UC: state->add_rule_terminal(value->str); free(value->str); return 1; @@ -103,6 +114,10 @@ int parser_push(parser_t *parser, int token, const parser_value_t *value, parser parser->state = STATE_INIT; return 1; + case '(': + parser->state = STATE_RULE_VAR_PRE; + return 1; + case ';': state->add_rule(); parser->state = STATE_INIT; @@ -110,11 +125,111 @@ int parser_push(parser_t *parser, int token, const parser_value_t *value, parser } break; + + case STATE_RULE_VAR_PRE: + switch (token) { + case TOK_SYMBOL: + case TOK_SYMBOL_UC: + case TOK_SYMBOL_LC: + state->add_rule_var(value->str); + free(value->str); + parser->state = STATE_RULE_VAR; + return 1; + } + + break; + + case STATE_RULE_VAR: + if (token == ')') { + parser->state = STATE_RULE; + return 1; + } + + break; + + case STATE_RULE_VAR_POST: + switch (token) { + case TOK_SYMBOL_LC: + state->add_rule_nonterminal(value->str); + free(value->str); + return 1; + + case TOK_SYMBOL_UC: + state->add_rule_terminal(value->str); + free(value->str); + return 1; + + case TOK_CHAR: + state->add_rule_terminal(value->number); + return 1; + + case TOK_BLOCK: + state->add_rule(value->str); + free(value->str); + parser->state = STATE_INIT; + return 1; + + case ';': + state->add_rule(); + parser->state = STATE_INIT; + return 1; + } + + break; + + case STATE_TYPE: + switch (token) { + case TOK_SYMBOL_LC: + state->add_type_nonterminal(value->str); + free(value->str); + parser->state = STATE_TYPE_NONTERM; + return 1; + + case TOK_SYMBOL_UC: + state->add_type_terminal(value->str); + free(value->str); + parser->state = STATE_TYPE_TERM; + return 1; + } + + break; + + case STATE_TYPE_NONTERM: + if (token == TOK_BLOCK) { + state->set_type_nonterminal(value->str); + free(value->str); + parser->state = STATE_INIT; + return 1; + } + + break; + + case STATE_TYPE_TERM: + if (token == TOK_BLOCK) { + state->set_type_terminal(value->str); + free(value->str); + parser->state = STATE_TYPE_TERM_BLOCK; + return 1; + } + + break; + + case STATE_TYPE_TERM_BLOCK: + switch (token) { + case TOK_SYMBOL: + case TOK_SYMBOL_UC: + case TOK_SYMBOL_LC: + state->set_type_terminal_name(value->str); + free(value->str); + parser->state = STATE_INIT; + return 1; + } } switch (token) { - case TOK_NONTERM: - case TOK_TERM: + case TOK_SYMBOL: + case TOK_SYMBOL_UC: + case TOK_SYMBOL_LC: case TOK_CHAR: case TOK_BLOCK: free(value->str);; |