Add support for extra arguments
This commit is contained in:
parent
80abbf2be2
commit
59258d1f71
8 changed files with 93 additions and 7 deletions
|
@ -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,
|
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<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)
|
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),
|
: 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++) {
|
for (size_t i = 0; i < rules.size(); i++) {
|
||||||
item_t rule = std::get<0>(rules[i]);
|
item_t rule = std::get<0>(rules[i]);
|
||||||
|
|
||||||
|
|
|
@ -66,6 +66,8 @@ private:
|
||||||
std::string header_block;
|
std::string header_block;
|
||||||
std::string source_block;
|
std::string source_block;
|
||||||
|
|
||||||
|
std::vector<std::pair<std::string, std::string>> extra_args;
|
||||||
|
|
||||||
|
|
||||||
void close_set(std::set<item_t> *set);
|
void close_set(std::set<item_t> *set);
|
||||||
std::set<item_t> get_set(const std::string &nonterm);
|
std::set<item_t> get_set(const std::string &nonterm);
|
||||||
|
@ -164,11 +166,16 @@ public:
|
||||||
return source_block;
|
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,
|
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<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);
|
const std::string &header_block0, const std::string &source_block0,
|
||||||
|
const std::vector<std::pair<std::string, std::string>> &extra_args0);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,6 +42,7 @@ struct keyword_t {
|
||||||
|
|
||||||
/* the keyword list must be sorted */
|
/* the keyword list must be sorted */
|
||||||
static const keyword_t keywords[] = {
|
static const keyword_t keywords[] = {
|
||||||
|
{"%extra_arg", TOK_EXTRA_ARG},
|
||||||
{"%header", TOK_HEADER},
|
{"%header", TOK_HEADER},
|
||||||
{"%source", TOK_SOURCE},
|
{"%source", TOK_SOURCE},
|
||||||
{"%type", TOK_TYPE},
|
{"%type", TOK_TYPE},
|
||||||
|
@ -229,7 +230,7 @@ int lex_t::lex_keyword(parser_value_t *value) {
|
||||||
while (next(false)) {
|
while (next(false)) {
|
||||||
char cur = current();
|
char cur = current();
|
||||||
|
|
||||||
if (!((cur >= 'a' && cur <= 'z') || (cur >= '0' && cur <= '9') || cur == '-'))
|
if (!((cur >= 'a' && cur <= 'z') || (cur >= '0' && cur <= '9') || cur == '_'))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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, "%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, "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) {
|
void output_t::emit_reduction(unsigned rule_id) {
|
||||||
|
@ -133,6 +138,15 @@ void output_t::emit_reduction(unsigned rule_id) {
|
||||||
empty = false;
|
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)
|
if (empty)
|
||||||
std::fprintf(source_file, "void");
|
std::fprintf(source_file, "void");
|
||||||
|
|
||||||
|
@ -207,6 +221,15 @@ void output_t::emit_state_reduce(const item_t &item, int rule_id) {
|
||||||
empty = false;
|
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");
|
std::fprintf(source_file, ");\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -312,7 +335,11 @@ void output_t::emit_source() {
|
||||||
|
|
||||||
emit_reductions();
|
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, "\twhile (1) {\n");
|
||||||
std::fprintf(source_file, "\t\tswitch (parser->stack[parser->top].state) {\n");
|
std::fprintf(source_file, "\t\tswitch (parser->stack[parser->top].state) {\n");
|
||||||
|
|
||||||
|
|
|
@ -45,6 +45,8 @@ enum parser_state {
|
||||||
STATE_TYPE_TERM_BLOCK,
|
STATE_TYPE_TERM_BLOCK,
|
||||||
STATE_HEADER,
|
STATE_HEADER,
|
||||||
STATE_SOURCE,
|
STATE_SOURCE,
|
||||||
|
STATE_EXTRA_ARG,
|
||||||
|
STATE_EXTRA_ARG_NAME,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct parser {
|
struct parser {
|
||||||
|
@ -80,6 +82,10 @@ int parser_push(parser_t *parser, int token, const parser_value_t *value, parser
|
||||||
parser->state = STATE_HEADER;
|
parser->state = STATE_HEADER;
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
case TOK_EXTRA_ARG:
|
||||||
|
parser->state = STATE_EXTRA_ARG;
|
||||||
|
return 1;
|
||||||
|
|
||||||
case 0:
|
case 0:
|
||||||
return 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;
|
parser->state = STATE_INIT;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case STATE_HEADER:
|
case STATE_HEADER:
|
||||||
if (token == TOK_BLOCK) {
|
if (token == TOK_BLOCK) {
|
||||||
|
@ -244,6 +251,7 @@ int parser_push(parser_t *parser, int token, const parser_value_t *value, parser
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case STATE_SOURCE:
|
case STATE_SOURCE:
|
||||||
if (token == TOK_BLOCK) {
|
if (token == TOK_BLOCK) {
|
||||||
state->set_source_block(value->str);
|
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;
|
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) {
|
switch (token) {
|
||||||
|
|
|
@ -43,6 +43,7 @@ enum parser_token_t {
|
||||||
TOK_TYPE,
|
TOK_TYPE,
|
||||||
TOK_SOURCE,
|
TOK_SOURCE,
|
||||||
TOK_HEADER,
|
TOK_HEADER,
|
||||||
|
TOK_EXTRA_ARG,
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct parser_value {
|
typedef struct parser_value {
|
||||||
|
|
|
@ -47,6 +47,9 @@ private:
|
||||||
std::string header_block;
|
std::string header_block;
|
||||||
std::string source_block;
|
std::string source_block;
|
||||||
|
|
||||||
|
std::string current_extra_arg;
|
||||||
|
std::vector<std::pair<std::string, std::string>> extra_args;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
parser_state_t() : current("") {}
|
parser_state_t() : current("") {}
|
||||||
|
|
||||||
|
@ -78,6 +81,19 @@ public:
|
||||||
source_block = value;
|
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 new_rule(const char *nonterm);
|
||||||
void add_rule_nonterminal(const char *nonterm);
|
void add_rule_nonterminal(const char *nonterm);
|
||||||
void add_rule_terminal(const char *term);
|
void add_rule_terminal(const char *term);
|
||||||
|
|
|
@ -87,7 +87,12 @@ int main(int argc, char *argv[]) {
|
||||||
if (!read_grammar(argv[1], &state))
|
if (!read_grammar(argv[1], &state))
|
||||||
return 1;
|
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_t output(&generator, argv[3], argv[2]);
|
||||||
output.write();
|
output.write();
|
||||||
|
|
Reference in a new issue