From 59258d1f71d36502cf778dd089409146fd085c12 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Thu, 9 Apr 2015 03:31:20 +0200 Subject: Add support for extra arguments --- src/generator.cpp | 5 +++-- src/generator.hpp | 9 ++++++++- src/lex.cpp | 3 ++- src/output.cpp | 31 +++++++++++++++++++++++++++++-- src/parser.cpp | 28 ++++++++++++++++++++++++++++ src/parser.hpp | 1 + src/parser_state.hpp | 16 ++++++++++++++++ src/solar.cpp | 7 ++++++- 8 files changed, 93 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/generator.cpp b/src/generator.cpp index 31dac2a..16f08d0 100644 --- a/src/generator.cpp +++ b/src/generator.cpp @@ -120,9 +120,10 @@ void generator_t::generate_itemsets() { generator_t::generator_t(const std::vector, std::string>> &rules0, const std::map &nonterm_types0, const std::map> &term_types0, - const std::string &header_block0, const std::string &source_block0) + const std::string &header_block0, const std::string &source_block0, + const std::vector> &extra_args0) : rules(rules0), nonterm_types(nonterm_types0), term_types(term_types0), - header_block(header_block0), source_block(source_block0) { + header_block(header_block0), source_block(source_block0), extra_args(extra_args0) { for (size_t i = 0; i < rules.size(); i++) { item_t rule = std::get<0>(rules[i]); diff --git a/src/generator.hpp b/src/generator.hpp index 23f4f9d..b0bd4c9 100644 --- a/src/generator.hpp +++ b/src/generator.hpp @@ -66,6 +66,8 @@ private: std::string header_block; std::string source_block; + std::vector> extra_args; + void close_set(std::set *set); std::set get_set(const std::string &nonterm); @@ -164,11 +166,16 @@ public: return source_block; } + const std::vector> & get_extra_args() const { + return extra_args; + } + generator_t(const std::vector, std::string>> &rules0, const std::map &nonterm_types0, const std::map> &term_types0, - const std::string &header_block0, const std::string &source_block0); + const std::string &header_block0, const std::string &source_block0, + const std::vector> &extra_args0); }; } diff --git a/src/lex.cpp b/src/lex.cpp index 7dfc013..c97e03d 100644 --- a/src/lex.cpp +++ b/src/lex.cpp @@ -42,6 +42,7 @@ struct keyword_t { /* the keyword list must be sorted */ static const keyword_t keywords[] = { + {"%extra_arg", TOK_EXTRA_ARG}, {"%header", TOK_HEADER}, {"%source", TOK_SOURCE}, {"%type", TOK_TYPE}, @@ -229,7 +230,7 @@ int lex_t::lex_keyword(parser_value_t *value) { while (next(false)) { char cur = current(); - if (!((cur >= 'a' && cur <= 'z') || (cur >= '0' && cur <= '9') || cur == '-')) + if (!((cur >= 'a' && cur <= 'z') || (cur >= '0' && cur <= '9') || cur == '_')) break; } diff --git a/src/output.cpp b/src/output.cpp index 7f074ab..33c6bb1 100644 --- a/src/output.cpp +++ b/src/output.cpp @@ -101,7 +101,12 @@ void output_t::emit_header() { std::fprintf(header_file, "%scontext_t * %salloc(void *(*alloc_func)(size_t));\n", prefix(), prefix()); std::fprintf(header_file, "void %sfree(%scontext_t *parser, void (*free_func)(void *));\n\n", prefix(), prefix()); - std::fprintf(header_file, "int %spush(%scontext_t *parser, int token, const %stoken_value_t *value);\n", prefix(), prefix(), prefix()); + std::fprintf(header_file, "int %spush(%scontext_t *parser, int token, const %stoken_value_t *value", prefix(), prefix(), prefix()); + + for (const auto &arg : generator->get_extra_args()) + std::fprintf(header_file, ", %s %s", arg.first.c_str(), arg.second.c_str()); + + std::fprintf(header_file, ");\n"); } void output_t::emit_reduction(unsigned rule_id) { @@ -133,6 +138,15 @@ void output_t::emit_reduction(unsigned rule_id) { empty = false; } + for (const auto &arg : generator->get_extra_args()) { + if (!empty) + std::fprintf(source_file, ", "); + + std::fprintf(source_file, "%s %s", arg.first.c_str(), arg.second.c_str()); + + empty = false; + } + if (empty) std::fprintf(source_file, "void"); @@ -207,6 +221,15 @@ void output_t::emit_state_reduce(const item_t &item, int rule_id) { empty = false; } + for (const auto &arg : generator->get_extra_args()) { + if (!empty) + std::fprintf(source_file, ", "); + + std::fprintf(source_file, "%s", arg.second.c_str()); + + empty = false; + } + std::fprintf(source_file, ");\n"); } @@ -312,7 +335,11 @@ void output_t::emit_source() { emit_reductions(); - std::fprintf(source_file, "int %spush(%scontext_t *parser, int token, const %stoken_value_t *value) {\n", prefix(), prefix(), prefix()); + std::fprintf(source_file, "int %spush(%scontext_t *parser, int token, const %stoken_value_t *value", prefix(), prefix(), prefix()); + for (const auto &arg : generator->get_extra_args()) + std::fprintf(source_file, ", %s %s", arg.first.c_str(), arg.second.c_str()); + std::fprintf(source_file, ") {\n"); + std::fprintf(source_file, "\twhile (1) {\n"); std::fprintf(source_file, "\t\tswitch (parser->stack[parser->top].state) {\n"); diff --git a/src/parser.cpp b/src/parser.cpp index 84159dc..0333243 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -45,6 +45,8 @@ enum parser_state { STATE_TYPE_TERM_BLOCK, STATE_HEADER, STATE_SOURCE, + STATE_EXTRA_ARG, + STATE_EXTRA_ARG_NAME, }; struct parser { @@ -80,6 +82,10 @@ int parser_push(parser_t *parser, int token, const parser_value_t *value, parser parser->state = STATE_HEADER; return 1; + case TOK_EXTRA_ARG: + parser->state = STATE_EXTRA_ARG; + return 1; + case 0: return 0; } @@ -234,6 +240,7 @@ int parser_push(parser_t *parser, int token, const parser_value_t *value, parser parser->state = STATE_INIT; return 1; } + break; case STATE_HEADER: if (token == TOK_BLOCK) { @@ -244,6 +251,7 @@ int parser_push(parser_t *parser, int token, const parser_value_t *value, parser } break; + case STATE_SOURCE: if (token == TOK_BLOCK) { state->set_source_block(value->str); @@ -253,6 +261,26 @@ int parser_push(parser_t *parser, int token, const parser_value_t *value, parser } break; + + case STATE_EXTRA_ARG: + if (token == TOK_BLOCK) { + state->add_extra_arg(value->str); + free(value->str); + parser->state = STATE_EXTRA_ARG_NAME; + return 1; + } + break; + + case STATE_EXTRA_ARG_NAME: + switch (token) { + case TOK_SYMBOL: + case TOK_SYMBOL_UC: + case TOK_SYMBOL_LC: + state->set_extra_arg_name(value->str); + free(value->str); + parser->state = STATE_INIT; + return 1; + } } switch (token) { diff --git a/src/parser.hpp b/src/parser.hpp index 9117914..61bfab4 100644 --- a/src/parser.hpp +++ b/src/parser.hpp @@ -43,6 +43,7 @@ enum parser_token_t { TOK_TYPE, TOK_SOURCE, TOK_HEADER, + TOK_EXTRA_ARG, }; typedef struct parser_value { diff --git a/src/parser_state.hpp b/src/parser_state.hpp index b183898..5dcce54 100644 --- a/src/parser_state.hpp +++ b/src/parser_state.hpp @@ -47,6 +47,9 @@ private: std::string header_block; std::string source_block; + std::string current_extra_arg; + std::vector> extra_args; + public: parser_state_t() : current("") {} @@ -78,6 +81,19 @@ public: source_block = value; } + const std::vector> & get_extra_args() const { + return extra_args; + } + + void add_extra_arg(const char *type) { + current_extra_arg = type; + } + + void set_extra_arg_name(const char *name) { + extra_args.emplace_back(current_extra_arg, name); + } + + void new_rule(const char *nonterm); void add_rule_nonterminal(const char *nonterm); void add_rule_terminal(const char *term); diff --git a/src/solar.cpp b/src/solar.cpp index 46c7fad..7e211a5 100644 --- a/src/solar.cpp +++ b/src/solar.cpp @@ -87,7 +87,12 @@ int main(int argc, char *argv[]) { if (!read_grammar(argv[1], &state)) return 1; - generator_t generator(state.get_rules(), state.get_nonterm_types(), state.get_term_types(), state.get_header_block(), state.get_source_block()); + generator_t generator(state.get_rules(), + state.get_nonterm_types(), + state.get_term_types(), + state.get_header_block(), + state.get_source_block(), + state.get_extra_args()); output_t output(&generator, argv[3], argv[2]); output.write(); -- cgit v1.2.3