Replace hand-written parser by one generated by solar itself :D

This commit is contained in:
Matthias Schiffer 2015-04-10 16:48:43 +02:00
parent a5d1689bc7
commit 5a54699f18
11 changed files with 1762 additions and 575 deletions

View file

@ -6,8 +6,7 @@ add_executable(solar
output.cpp output.cpp
output_lr0.cpp output_lr0.cpp
output_slr.cpp output_slr.cpp
parser.cpp parse.cpp
parser_state.cpp
solar.cpp solar.cpp
) )
set_target_properties(solar PROPERTIES COMPILE_FLAGS "-std=c++11 -Wall") set_target_properties(solar PROPERTIES COMPILE_FLAGS "-std=c++11 -Wall")

View file

@ -101,20 +101,21 @@ void lex_t::consume(bool consume_needspace) {
needspace = consume_needspace; needspace = consume_needspace;
} }
int lex_t::io_error(parser_value_t *value) { int lex_t::io_error(parse_token_value_t *value) {
value->error = "I/O error"; //value->error = "I/O error";
(void)value;
return -1; return -1;
} }
int lex_t::syntax_error(parser_value_t *value) { int lex_t::syntax_error(parse_token_value_t *value) {
if (std::ferror(file)) if (std::ferror(file))
return io_error(value); return io_error(value);
value->error = "syntax error"; //value->error = "syntax error";
return -1; return -1;
} }
int lex_t::consume_comment(parser_value_t *value) { int lex_t::consume_comment(parse_token_value_t *value) {
char prev = 0; char prev = 0;
while (next(true)) { while (next(true)) {
@ -130,20 +131,20 @@ int lex_t::consume_comment(parser_value_t *value) {
if (std::ferror(file)) if (std::ferror(file))
return io_error(value); return io_error(value);
value->error = "unterminated block comment"; //value->error = "unterminated block comment";
return -1; return -1;
} }
/* /*
int lex_t::unterminated_string(parser_value_t *value) { int lex_t::unterminated_string(parse_token_value_t *value) {
if (ferror(file)) if (ferror(file))
return io_error(value); return io_error(value);
value->error = "unterminated string"; //value->error = "unterminated string";
return -1; return -1;
} }
int lex_t::lex_string(parser_value_t *value) { int lex_t::lex_string(parse_token_value_t *value) {
char *buf = NULL; char *buf = NULL;
size_t len = 1024; size_t len = 1024;
size_t pos = 0; size_t pos = 0;
@ -193,7 +194,7 @@ int lex_t::lex_string(parser_value_t *value) {
return TOK_STRING; return TOK_STRING;
} }
int lex_t::lex_number(parser_value_t *value) { int lex_t::lex_number(parse_token_value_t *value) {
if (needspace) if (needspace)
return syntax_error(value); return syntax_error(value);
@ -223,7 +224,7 @@ int lex_t::lex_number(parser_value_t *value) {
return TOK_UINT; return TOK_UINT;
}*/ }*/
int lex_t::lex_keyword(parser_value_t *value) { int lex_t::lex_keyword(parse_token_value_t *value) {
if (needspace) if (needspace)
return syntax_error(value); return syntax_error(value);
@ -247,15 +248,15 @@ int lex_t::lex_keyword(parser_value_t *value) {
return ret->token; return ret->token;
} }
int lex_t::unterminated_block(parser_value_t *value) { int lex_t::unterminated_block(parse_token_value_t *value) {
if (ferror(file)) if (ferror(file))
return io_error(value); return io_error(value);
value->error = "unterminated code block"; //value->error = "unterminated code block";
return -1; return -1;
} }
int lex_t::lex_block(parser_value_t *value) { int lex_t::lex_block(parse_token_value_t *value) {
size_t parens = 0; size_t parens = 0;
bool line_comment = false; bool line_comment = false;
bool block_comment = false; bool block_comment = false;
@ -326,7 +327,7 @@ int lex_t::lex_block(parser_value_t *value) {
return TOK_BLOCK; return TOK_BLOCK;
} }
int lex_t::lex_symbol(parser_value_t *value) { int lex_t::lex_symbol(parse_token_value_t *value) {
if (needspace) if (needspace)
return syntax_error(value); return syntax_error(value);
@ -361,7 +362,7 @@ int lex_t::lex_symbol(parser_value_t *value) {
return TOK_SYMBOL; return TOK_SYMBOL;
} }
int lex_t::lex(parser_value_t *value) { int lex_t::lex(parse_token_value_t *value) {
int token; int token;
while (end > start) { while (end > start) {
@ -416,7 +417,7 @@ int lex_t::lex(parser_value_t *value) {
if (!next(true)) if (!next(true))
return syntax_error(value); return syntax_error(value);
value->number = current(); value->c = current();
if (!next(true) || current() != '\'') if (!next(true) || current() != '\'')
return syntax_error(value); return syntax_error(value);

View file

@ -26,7 +26,7 @@
#pragma once #pragma once
#include "parser.hpp" #include "parse.hpp"
#include <cstdio> #include <cstdio>
#include <cstring> #include <cstring>
@ -62,17 +62,17 @@ private:
bool next(bool move); bool next(bool move);
void consume(bool needspace); void consume(bool needspace);
int io_error(parser_value_t *value); int io_error(parse_token_value_t *value);
int syntax_error(parser_value_t *value); int syntax_error(parse_token_value_t *value);
int consume_comment(parser_value_t *value); int consume_comment(parse_token_value_t *value);
int unterminated_block(parser_value_t *value); int unterminated_block(parse_token_value_t *value);
//int unterminated_string(parser_value_t *value); //int unterminated_string(parse_token_value_t *value);
//int lex_string(parser_value_t *value); //int lex_string(parse_token_value_t *value);
//int lex_number(parser_value_t *value); //int lex_number(parse_token_value_t *value);
int lex_keyword(parser_value_t *value); int lex_keyword(parse_token_value_t *value);
int lex_block(parser_value_t *value); int lex_block(parse_token_value_t *value);
int lex_symbol(parser_value_t *value); int lex_symbol(parse_token_value_t *value);
char current() { char current() {
return buffer[start + tok_len]; return buffer[start + tok_len];
@ -92,7 +92,7 @@ public:
fclose(file); fclose(file);
} }
int lex(parser_value_t *value); int lex(parse_token_value_t *value);
const location_t & get_location() const { const location_t & get_location() const {
return loc; return loc;

1548
src/parse.cpp Normal file

File diff suppressed because it is too large Load diff

28
src/parse.hpp Normal file
View file

@ -0,0 +1,28 @@
#pragma once
#include "grammar.hpp"
enum parse_token_t {
TOK_BLOCK = 256,
TOK_CHAR = 257,
TOK_EXTRA_ARG = 258,
TOK_HEADER = 259,
TOK_SOURCE = 260,
TOK_SYMBOL = 261,
TOK_SYMBOL_LC = 262,
TOK_SYMBOL_UC = 263,
TOK_TYPE = 264,
};
typedef struct parse_token_value {
char c;
std::string * str;
} parse_token_value_t;
typedef struct parse_context parse_context_t;
parse_context_t * parse_alloc(void *(*alloc_func)(size_t));
void parse_free(parse_context_t *parser, void (*free_func)(void *));
int parse_push(parse_context_t *parser, int token, const parse_token_value_t *value, __attribute__((unused)) solar::grammar_t * grammar);

143
src/parse.y Normal file
View file

@ -0,0 +1,143 @@
%type SYMBOL {std::string *} str
%type SYMBOL_UC {std::string *} str
%type SYMBOL_LC {std::string *} str
%type BLOCK {std::string *} str
%type CHAR {char} c
%type rule {solar::rule_t *}
%type rhs {std::pair<std::vector<solar::symbol_t>, std::vector<std::string>> *}
%type action {std::string *}
%type symbol {solar::symbol_t *}
%type term {solar::symbol_t *}
%type varname {std::string *}
%header {
#include "grammar.hpp"
}
%extra_arg {__attribute__((unused)) solar::grammar_t *} grammar
grammar |=;
grammar |= grammar rule(rule) {
if (grammar->rules.empty()) {
solar::item_t init("");
init.get_rhs().push_back(solar::symbol_t::make_nonterm(rule->item.get_lhs().c_str()));
grammar->rules.emplace_back(solar::rule_t {std::move(init), std::vector<std::string>(), std::string()});
}
grammar->rules.push_back(*rule);
delete rule;
}
grammar |= grammar TYPE SYMBOL_LC(nonterm) BLOCK(type) {
grammar->nonterm_types.insert(std::make_pair(*nonterm, *type));
delete nonterm;
delete type;
}
grammar |= grammar TYPE term(term) BLOCK(type) varname(name) {
grammar->term_types.insert(std::make_pair(*term, std::make_pair(*type, *name)));
delete term;
delete type;
delete name;
}
grammar |= grammar SOURCE BLOCK(block) {
grammar->source_block = *block;
delete block;
}
grammar |= grammar HEADER BLOCK(block) {
grammar->header_block = *block;
delete block;
}
grammar |= grammar EXTRA_ARG BLOCK(type) varname(name) {
grammar->extra_args.push_back(std::make_pair(*type, *name));
delete type;
delete name;
}
rule |= SYMBOL_LC(lhs) '|' '=' rhs(rhs) action(action) {
auto *ret = new solar::rule_t {solar::item_t(*lhs, rhs->first), rhs->second, *action};
delete lhs;
delete rhs;
delete action;
return ret;
}
rhs |= {
return new std::pair<std::vector<solar::symbol_t>, std::vector<std::string>>();
}
rhs |= rhs(rhs) symbol(sym) {
rhs->first.push_back(*sym);
rhs->second.emplace_back();
delete sym;
return rhs;
}
rhs |= rhs(rhs) symbol(sym) '(' varname(var) ')' {
rhs->first.push_back(*sym);
rhs->second.push_back(*var);
delete sym;
delete var;
return rhs;
}
action |= ';' {
return new std::string;
}
action |= BLOCK(v) {
return v;
}
symbol |= term(v) {
return v;
}
symbol |= SYMBOL_LC(v) {
solar::symbol_t *ret = new solar::symbol_t(solar::symbol_t::make_nonterm(*v));
delete v;
return ret;
}
term |= SYMBOL_UC(v) {
solar::symbol_t *ret = new solar::symbol_t(solar::symbol_t::make_term(*v));
delete v;
return ret;
}
term |= CHAR(v) {
return new solar::symbol_t(solar::symbol_t::make_char(v));
}
varname |= SYMBOL_LC(v) {
return v;
}
varname |= SYMBOL_UC(v) {
return v;
}
varname |= SYMBOL(v) {
return v;
}

View file

@ -1,302 +0,0 @@
/*
Copyright (c) 2015, Matthias Schiffer <mschiffer@universe-factory.net>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "parser.hpp"
#include <cstdlib>
namespace solar {
enum parser_state {
STATE_INIT,
STATE_RULE_BAR,
STATE_RULE_EQUAL,
STATE_RULE,
STATE_RULE_VAR_PRE,
STATE_RULE_VAR,
STATE_RULE_VAR_POST,
STATE_TYPE,
STATE_TYPE_NONTERM,
STATE_TYPE_TERM,
STATE_TYPE_TERM_BLOCK,
STATE_HEADER,
STATE_SOURCE,
STATE_EXTRA_ARG,
STATE_EXTRA_ARG_NAME,
};
struct parser {
parser_state state;
};
parser_t * parser_alloc(void) {
parser_t *parser = (parser_t *)std::malloc(sizeof(parser_t));
parser->state = STATE_INIT;
return parser;
}
int parser_push(parser_t *parser, int token, const parser_value_t *value, parser_state_t *state) {
switch (parser->state) {
case STATE_INIT:
switch (token) {
case TOK_SYMBOL_LC:
parser->state = STATE_RULE_BAR;
state->new_rule(*value->str);
delete value->str;
return 1;
case TOK_TYPE:
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 TOK_EXTRA_ARG:
parser->state = STATE_EXTRA_ARG;
return 1;
case 0:
return 0;
}
break;
case STATE_RULE_BAR:
if (token == '|') {
parser->state = STATE_RULE_EQUAL;
return 1;
}
break;
case STATE_RULE_EQUAL:
if (token == '=') {
parser->state = STATE_RULE;
return 1;
}
break;
case STATE_RULE:
switch (token) {
case TOK_SYMBOL_LC:
state->add_rule_nonterminal(*value->str);
delete value->str;
return 1;
case TOK_SYMBOL_UC:
state->add_rule_terminal(*value->str);
delete value->str;
return 1;
case TOK_CHAR:
state->add_rule_terminal(value->number);
return 1;
case TOK_BLOCK:
state->add_rule(*value->str);
delete value->str;
parser->state = STATE_INIT;
return 1;
case '(':
parser->state = STATE_RULE_VAR_PRE;
return 1;
case ';':
state->add_rule();
parser->state = STATE_INIT;
return 1;
}
break;
case STATE_RULE_VAR_PRE:
switch (token) {
case TOK_SYMBOL:
case TOK_SYMBOL_UC:
case TOK_SYMBOL_LC:
state->add_rule_var(*value->str);
delete value->str;
parser->state = STATE_RULE_VAR;
return 1;
}
break;
case STATE_RULE_VAR:
if (token == ')') {
parser->state = STATE_RULE;
return 1;
}
break;
case STATE_RULE_VAR_POST:
switch (token) {
case TOK_SYMBOL_LC:
state->add_rule_nonterminal(*value->str);
delete value->str;
return 1;
case TOK_SYMBOL_UC:
state->add_rule_terminal(*value->str);
delete value->str;
return 1;
case TOK_CHAR:
state->add_rule_terminal(value->number);
return 1;
case TOK_BLOCK:
state->add_rule(*value->str);
delete value->str;
parser->state = STATE_INIT;
return 1;
case ';':
state->add_rule();
parser->state = STATE_INIT;
return 1;
}
break;
case STATE_TYPE:
switch (token) {
case TOK_SYMBOL_LC:
state->add_type_nonterminal(*value->str);
delete value->str;
parser->state = STATE_TYPE_NONTERM;
return 1;
case TOK_SYMBOL_UC:
state->add_type_terminal(*value->str);
delete value->str;
parser->state = STATE_TYPE_TERM;
return 1;
}
break;
case STATE_TYPE_NONTERM:
if (token == TOK_BLOCK) {
state->set_type_nonterminal(*value->str);
delete value->str;
parser->state = STATE_INIT;
return 1;
}
break;
case STATE_TYPE_TERM:
if (token == TOK_BLOCK) {
state->set_type_terminal(*value->str);
delete value->str;
parser->state = STATE_TYPE_TERM_BLOCK;
return 1;
}
break;
case STATE_TYPE_TERM_BLOCK:
switch (token) {
case TOK_SYMBOL:
case TOK_SYMBOL_UC:
case TOK_SYMBOL_LC:
state->set_type_terminal_name(*value->str);
delete value->str;
parser->state = STATE_INIT;
return 1;
}
break;
case STATE_HEADER:
if (token == TOK_BLOCK) {
state->set_header_block(*value->str);
delete value->str;
parser->state = STATE_INIT;
return 1;
}
break;
case STATE_SOURCE:
if (token == TOK_BLOCK) {
state->set_source_block(*value->str);
delete value->str;
parser->state = STATE_INIT;
return 1;
}
break;
case STATE_EXTRA_ARG:
if (token == TOK_BLOCK) {
state->add_extra_arg(*value->str);
delete 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);
delete value->str;
parser->state = STATE_INIT;
return 1;
}
}
switch (token) {
case TOK_SYMBOL:
case TOK_SYMBOL_UC:
case TOK_SYMBOL_LC:
case TOK_CHAR:
case TOK_BLOCK:
delete value->str;;
}
return -1;
}
void parser_free(parser_t *parser) {
std::free(parser);
}
}

View file

@ -1,62 +0,0 @@
/*
Copyright (c) 2015, Matthias Schiffer <mschiffer@universe-factory.net>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#include "parser_state.hpp"
#include <cstdint>
namespace solar {
enum parser_token_t {
TOK_SYMBOL = 256,
TOK_SYMBOL_UC,
TOK_SYMBOL_LC,
TOK_BLOCK,
TOK_CHAR,
TOK_TYPE,
TOK_SOURCE,
TOK_HEADER,
TOK_EXTRA_ARG,
};
typedef struct parser_value {
std::string *str;
uint64_t number;
const char *error;
} parser_value_t;
typedef struct parser parser_t;
parser_t * parser_alloc(void);
int parser_push(parser_t *parser, int token, const parser_value_t *value, parser_state_t *state);
void parser_free(parser_t *parser);
}

View file

@ -1,86 +0,0 @@
/*
Copyright (c) 2015, Matthias Schiffer <mschiffer@universe-factory.net>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "parser_state.hpp"
namespace solar {
void parser_state_t::new_rule(const std::string &nonterm) {
if (grammar.rules.empty()) {
// start rule
add_rule_nonterminal(nonterm);
add_rule();
}
current = item_t(nonterm);
current_vars = std::vector<std::string>();
}
void parser_state_t::add_rule_nonterminal(const std::string &nonterm) {
current.get_rhs().emplace_back(symbol_t::make_nonterm(nonterm));
current_vars.emplace_back();
}
void parser_state_t::add_rule_terminal(const std::string &term) {
current.get_rhs().emplace_back(symbol_t::make_term(term));
current_vars.emplace_back();
}
void parser_state_t::add_rule_terminal(unsigned char term) {
current.get_rhs().emplace_back(symbol_t::make_char(term));
current_vars.emplace_back();
}
void parser_state_t::add_rule(const std::string &action) {
grammar.rules.emplace_back(rule_t{std::move(current), std::move(current_vars), action});
}
void parser_state_t::add_rule_var(const std::string &var) {
current_vars.back() = var;
}
void parser_state_t::add_type_nonterminal(const std::string &nonterm) {
current_var = nonterm;
}
void parser_state_t::add_type_terminal(const std::string &term) {
current_var = term;
}
void parser_state_t::set_type_nonterminal(const std::string &type) {
grammar.nonterm_types.insert(std::make_pair(current_var, type));
}
void parser_state_t::set_type_terminal(const std::string &type) {
current_type = type;
}
void parser_state_t::set_type_terminal_name(const std::string &name) {
grammar.term_types.insert(std::make_pair(symbol_t::make_term(current_var.c_str()), std::make_pair(current_type, name)));
}
}

View file

@ -1,83 +0,0 @@
/*
Copyright (c) 2015, Matthias Schiffer <mschiffer@universe-factory.net>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#include "grammar.hpp"
namespace solar {
class parser_state_t {
private:
grammar_t grammar;
item_t current;
std::vector<std::string> current_vars;
std::string current_var;
std::string current_type;
std::string current_extra_arg;
public:
parser_state_t() : current("") {}
const grammar_t & get_grammar() const {
return grammar;
}
void set_header_block(const std::string &value) {
grammar.header_block = value;
}
void set_source_block(const std::string &value) {
grammar.source_block = value;
}
void add_extra_arg(const std::string &type) {
current_extra_arg = type;
}
void set_extra_arg_name(const std::string &name) {
grammar.extra_args.emplace_back(current_extra_arg, name);
}
void new_rule(const std::string &nonterm);
void add_rule_nonterminal(const std::string &nonterm);
void add_rule_terminal(const std::string &term);
void add_rule_terminal(unsigned char term);
void add_rule(const std::string &action = "");
void add_rule_var(const std::string &var);
void add_type_nonterminal(const std::string &nonterm);
void add_type_terminal(const std::string &term);
void set_type_nonterminal(const std::string &type);
void set_type_terminal(const std::string &type);
void set_type_terminal_name(const std::string &name);
};
}

View file

@ -25,18 +25,19 @@
#include "lex.hpp" #include "lex.hpp"
#include "parser.hpp" #include "parse.hpp"
#include "generator_slr.hpp" #include "generator_slr.hpp"
#include "output_slr.hpp" #include "output_slr.hpp"
#include <cstdio> #include <cstdio>
#include <cstdlib>
#include <iostream>
#include <memory> #include <memory>
namespace solar { namespace solar {
bool read_grammar(const char *filename, parser_state_t *state) { bool read_grammar(const char *filename, grammar_t *grammar) {
FILE *file = fopen(filename, "r"); FILE *file = fopen(filename, "r");
if (!file) { if (!file) {
std::fprintf(stderr, "unable to open file %s\n", filename); std::fprintf(stderr, "unable to open file %s\n", filename);
@ -44,21 +45,21 @@ bool read_grammar(const char *filename, parser_state_t *state) {
} }
std::unique_ptr<lex_t> lexer(new lex_t(file)); std::unique_ptr<lex_t> lexer(new lex_t(file));
parser_t *parser = parser_alloc(); parse_context_t *parser = parse_alloc(std::malloc);
int ret; int ret;
do { do {
int token; int token;
parser_value_t value; parse_token_value_t value;
token = lexer->lex(&value); token = lexer->lex(&value);
if (token < 0) { if (token < 0) {
std::fprintf(stderr, "error: %s at %s:%i:%i\n", value.error, filename, std::fprintf(stderr, "error at %s:%i:%i\n", filename,
lexer->get_location().first_line, lexer->get_location().first_column); lexer->get_location().first_line, lexer->get_location().first_column);
return false; return false;
} }
ret = parser_push(parser, token, &value, state); ret = parse_push(parser, token, &value, grammar);
} while (ret > 0); } while (ret > 0);
if (ret < 0) { if (ret < 0) {
@ -67,7 +68,7 @@ bool read_grammar(const char *filename, parser_state_t *state) {
return false; return false;
} }
parser_free(parser); parse_free(parser, std::free);
return true; return true;
} }
@ -83,11 +84,11 @@ int main(int argc, char *argv[]) {
return 1; return 1;
} }
parser_state_t state; grammar_t grammar;
if (!read_grammar(argv[1], &state)) if (!read_grammar(argv[1], &grammar))
return 1; return 1;
generator_slr_t generator(state.get_grammar()); generator_slr_t generator(grammar);
output_slr_t output(&generator, argv[3], argv[2]); output_slr_t output(&generator, argv[3], argv[2]);
output.write(); output.write();