summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Schiffer <mschiffer@universe-factory.net>2015-04-09 03:31:20 +0200
committerMatthias Schiffer <mschiffer@universe-factory.net>2015-04-09 03:31:20 +0200
commit59258d1f71d36502cf778dd089409146fd085c12 (patch)
treed9974750b88a979113adba40a6db4b48d750bdd4
parent80abbf2be25e4c760fe80c9f6694047db6c7cfe4 (diff)
downloadsolar-59258d1f71d36502cf778dd089409146fd085c12.tar
solar-59258d1f71d36502cf778dd089409146fd085c12.zip
Add support for extra arguments
-rw-r--r--src/generator.cpp5
-rw-r--r--src/generator.hpp9
-rw-r--r--src/lex.cpp3
-rw-r--r--src/output.cpp31
-rw-r--r--src/parser.cpp28
-rw-r--r--src/parser.hpp1
-rw-r--r--src/parser_state.hpp16
-rw-r--r--src/solar.cpp7
8 files changed, 93 insertions, 7 deletions
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::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::string &header_block0, const std::string &source_block0)
+ const std::string &header_block0, const std::string &source_block0,
+ const std::vector<std::pair<std::string, std::string>> &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<std::pair<std::string, std::string>> extra_args;
+
void close_set(std::set<item_t> *set);
std::set<item_t> get_set(const std::string &nonterm);
@@ -164,11 +166,16 @@ public:
return source_block;
}
+ const std::vector<std::pair<std::string, std::string>> & get_extra_args() const {
+ return extra_args;
+ }
+
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::string &header_block0, const std::string &source_block0);
+ const std::string &header_block0, const std::string &source_block0,
+ const std::vector<std::pair<std::string, std::string>> &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<std::pair<std::string, std::string>> extra_args;
+
public:
parser_state_t() : current("") {}
@@ -78,6 +81,19 @@ public:
source_block = value;
}
+ const std::vector<std::pair<std::string, std::string>> & 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();