Allow adding source blocks to the top the of header and source files
This commit is contained in:
parent
7b8ebfcef1
commit
9c990ae801
8 changed files with 81 additions and 5 deletions
|
@ -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,
|
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,
|
||||||
: rules(rules0), nonterm_types(nonterm_types0), term_types(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++) {
|
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]);
|
||||||
|
|
||||||
|
|
|
@ -63,6 +63,10 @@ private:
|
||||||
std::map<std::string, std::string> nonterm_types;
|
std::map<std::string, std::string> nonterm_types;
|
||||||
std::map<symbol_t, std::pair<std::string, std::string>> term_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);
|
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);
|
||||||
|
|
||||||
|
@ -152,9 +156,19 @@ public:
|
||||||
return gotos;
|
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,
|
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);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,6 +42,8 @@ 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[] = {
|
||||||
|
{"%header", TOK_HEADER},
|
||||||
|
{"%source", TOK_SOURCE},
|
||||||
{"%type", TOK_TYPE},
|
{"%type", TOK_TYPE},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -88,6 +88,11 @@ void output_t::emit_token_value() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void output_t::emit_header() {
|
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_tokens();
|
||||||
emit_token_value();
|
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 *slash = std::strrchr(header_filename.c_str(), sep);
|
||||||
const char *basename = slash ? slash+1 : header_filename.c_str();
|
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() {
|
void output_t::emit_source() {
|
||||||
emit_header_include();
|
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, "typedef union %ssymbol_value {\n", prefix());
|
||||||
std::fprintf(source_file, "\t%stoken_value_t token;\n", prefix());
|
std::fprintf(source_file, "\t%stoken_value_t token;\n", prefix());
|
||||||
|
|
||||||
|
|
|
@ -43,6 +43,8 @@ enum parser_state {
|
||||||
STATE_TYPE_NONTERM,
|
STATE_TYPE_NONTERM,
|
||||||
STATE_TYPE_TERM,
|
STATE_TYPE_TERM,
|
||||||
STATE_TYPE_TERM_BLOCK,
|
STATE_TYPE_TERM_BLOCK,
|
||||||
|
STATE_HEADER,
|
||||||
|
STATE_SOURCE,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct parser {
|
struct parser {
|
||||||
|
@ -70,6 +72,14 @@ int parser_push(parser_t *parser, int token, const parser_value_t *value, parser
|
||||||
parser->state = STATE_TYPE;
|
parser->state = STATE_TYPE;
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
case TOK_SOURCE:
|
||||||
|
parser->state = STATE_SOURCE;
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
case TOK_HEADER:
|
||||||
|
parser->state = STATE_HEADER;
|
||||||
|
return 1;
|
||||||
|
|
||||||
case 0:
|
case 0:
|
||||||
return 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;
|
parser->state = STATE_INIT;
|
||||||
return 1;
|
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) {
|
switch (token) {
|
||||||
|
|
|
@ -41,6 +41,8 @@ enum parser_token_t {
|
||||||
TOK_CHAR,
|
TOK_CHAR,
|
||||||
TOK_UINT,
|
TOK_UINT,
|
||||||
TOK_TYPE,
|
TOK_TYPE,
|
||||||
|
TOK_SOURCE,
|
||||||
|
TOK_HEADER,
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct parser_value {
|
typedef struct parser_value {
|
||||||
|
|
|
@ -44,6 +44,9 @@ private:
|
||||||
std::string current_var;
|
std::string current_var;
|
||||||
std::string current_type;
|
std::string current_type;
|
||||||
|
|
||||||
|
std::string header_block;
|
||||||
|
std::string source_block;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
parser_state_t() : current("") {}
|
parser_state_t() : current("") {}
|
||||||
|
|
||||||
|
@ -59,6 +62,22 @@ public:
|
||||||
return term_types;
|
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 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,7 @@ 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());
|
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_t output(&generator, argv[3], argv[2]);
|
||||||
output.write();
|
output.write();
|
||||||
|
|
Reference in a new issue