From 9c990ae801b949de2728bfff4258aa90f9c96a52 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Wed, 8 Apr 2015 23:49:42 +0200 Subject: Allow adding source blocks to the top the of header and source files --- src/generator.cpp | 6 ++++-- src/generator.hpp | 16 +++++++++++++++- src/lex.cpp | 2 ++ src/output.cpp | 10 +++++++++- src/parser.cpp | 29 +++++++++++++++++++++++++++++ src/parser.hpp | 2 ++ src/parser_state.hpp | 19 +++++++++++++++++++ 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::string>> &rules0, const std::map &nonterm_types0, - const std::map> &term_types0) - : rules(rules0), nonterm_types(nonterm_types0), term_types(term_types0) { + const std::map> &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 nonterm_types; std::map> term_types; + std::string header_block; + std::string source_block; + + void close_set(std::set *set); std::set 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::string>> &rules0, const std::map &nonterm_types0, - const std::map> &term_types0); + const std::map> &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(); -- cgit v1.2.3