diff options
-rw-r--r-- | src/generator.cpp | 6 | ||||
-rw-r--r-- | src/generator.hpp | 16 | ||||
-rw-r--r-- | src/lex.cpp | 2 | ||||
-rw-r--r-- | src/output.cpp | 10 | ||||
-rw-r--r-- | src/parser.cpp | 29 | ||||
-rw-r--r-- | src/parser.hpp | 2 | ||||
-rw-r--r-- | src/parser_state.hpp | 19 | ||||
-rw-r--r-- | src/solar.cpp | 2 |
8 files changed, 81 insertions, 5 deletions
diff --git a/src/generator.cpp b/src/generator.cpp index 9350f40..31dac2a 100644 --- a/src/generator.cpp +++ b/src/generator.cpp @@ -119,8 +119,10 @@ void generator_t::generate_itemsets() { generator_t::generator_t(const std::vector<std::tuple<item_t, std::vector<std::string>, std::string>> &rules0, const std::map<std::string, std::string> &nonterm_types0, - const std::map<symbol_t, std::pair<std::string, std::string>> &term_types0) - : rules(rules0), nonterm_types(nonterm_types0), term_types(term_types0) { + const std::map<symbol_t, std::pair<std::string, std::string>> &term_types0, + const std::string &header_block0, const std::string &source_block0) + : rules(rules0), nonterm_types(nonterm_types0), term_types(term_types0), + header_block(header_block0), source_block(source_block0) { 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 5f2cb22..23f4f9d 100644 --- a/src/generator.hpp +++ b/src/generator.hpp @@ -63,6 +63,10 @@ private: std::map<std::string, std::string> nonterm_types; std::map<symbol_t, std::pair<std::string, std::string>> term_types; + std::string header_block; + std::string source_block; + + void close_set(std::set<item_t> *set); std::set<item_t> get_set(const std::string &nonterm); @@ -152,9 +156,19 @@ public: return gotos; } + const std::string & get_header_block() const { + return header_block; + } + + const std::string & get_source_block() const { + return source_block; + } + + generator_t(const std::vector<std::tuple<item_t, std::vector<std::string>, std::string>> &rules0, const std::map<std::string, std::string> &nonterm_types0, - const std::map<symbol_t, std::pair<std::string, std::string>> &term_types0); + const std::map<symbol_t, std::pair<std::string, std::string>> &term_types0, + const std::string &header_block0, const std::string &source_block0); }; } diff --git a/src/lex.cpp b/src/lex.cpp index 3adfb5b..7dfc013 100644 --- a/src/lex.cpp +++ b/src/lex.cpp @@ -42,6 +42,8 @@ struct keyword_t { /* the keyword list must be sorted */ static const keyword_t keywords[] = { + {"%header", TOK_HEADER}, + {"%source", TOK_SOURCE}, {"%type", TOK_TYPE}, }; diff --git a/src/output.cpp b/src/output.cpp index 72e9a6e..e1ca496 100644 --- a/src/output.cpp +++ b/src/output.cpp @@ -88,6 +88,11 @@ void output_t::emit_token_value() { } void output_t::emit_header() { + std::fprintf(header_file, "#pragma once\n\n"); + + if (!generator->get_header_block().empty()) + std::fprintf(header_file, "%s\n", generator->get_header_block().c_str()); + emit_tokens(); emit_token_value(); @@ -261,12 +266,15 @@ void output_t::emit_header_include() { const char *slash = std::strrchr(header_filename.c_str(), sep); const char *basename = slash ? slash+1 : header_filename.c_str(); - std::fprintf(source_file, "#include \"%s\"\n\n\n", basename); + std::fprintf(source_file, "#include \"%s\"\n\n", basename); } void output_t::emit_source() { emit_header_include(); + if (!generator->get_source_block().empty()) + std::fprintf(source_file, "%s\n\n", generator->get_source_block().c_str()); + std::fprintf(source_file, "typedef union %ssymbol_value {\n", prefix()); std::fprintf(source_file, "\t%stoken_value_t token;\n", prefix()); diff --git a/src/parser.cpp b/src/parser.cpp index 9d2fbce..84159dc 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -43,6 +43,8 @@ enum parser_state { STATE_TYPE_NONTERM, STATE_TYPE_TERM, STATE_TYPE_TERM_BLOCK, + STATE_HEADER, + STATE_SOURCE, }; struct parser { @@ -70,6 +72,14 @@ int parser_push(parser_t *parser, int token, const parser_value_t *value, parser parser->state = STATE_TYPE; return 1; + case TOK_SOURCE: + parser->state = STATE_SOURCE; + return 1; + + case TOK_HEADER: + parser->state = STATE_HEADER; + return 1; + case 0: return 0; } @@ -224,6 +234,25 @@ int parser_push(parser_t *parser, int token, const parser_value_t *value, parser parser->state = STATE_INIT; return 1; } + + case STATE_HEADER: + if (token == TOK_BLOCK) { + state->set_header_block(value->str); + free(value->str); + parser->state = STATE_INIT; + return 1; + } + + break; + case STATE_SOURCE: + if (token == TOK_BLOCK) { + state->set_source_block(value->str); + free(value->str); + parser->state = STATE_INIT; + return 1; + } + + break; } switch (token) { diff --git a/src/parser.hpp b/src/parser.hpp index f677bf1..9117914 100644 --- a/src/parser.hpp +++ b/src/parser.hpp @@ -41,6 +41,8 @@ enum parser_token_t { TOK_CHAR, TOK_UINT, TOK_TYPE, + TOK_SOURCE, + TOK_HEADER, }; typedef struct parser_value { diff --git a/src/parser_state.hpp b/src/parser_state.hpp index 882fec2..b183898 100644 --- a/src/parser_state.hpp +++ b/src/parser_state.hpp @@ -44,6 +44,9 @@ private: std::string current_var; std::string current_type; + std::string header_block; + std::string source_block; + public: parser_state_t() : current("") {} @@ -59,6 +62,22 @@ public: return term_types; } + const std::string & get_header_block() const { + return header_block; + } + + void set_header_block(const char *value) { + header_block = value; + } + + const std::string & get_source_block() const { + return source_block; + } + + void set_source_block(const char *value) { + source_block = value; + } + 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 f3b04f6..46c7fad 100644 --- a/src/solar.cpp +++ b/src/solar.cpp @@ -87,7 +87,7 @@ 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()); + generator_t generator(state.get_rules(), state.get_nonterm_types(), state.get_term_types(), state.get_header_block(), state.get_source_block()); output_t output(&generator, argv[3], argv[2]); output.write(); |