Replace hand-written parser by one generated by solar itself :D
This commit is contained in:
parent
a5d1689bc7
commit
5a54699f18
11 changed files with 1762 additions and 575 deletions
|
@ -6,8 +6,7 @@ add_executable(solar
|
|||
output.cpp
|
||||
output_lr0.cpp
|
||||
output_slr.cpp
|
||||
parser.cpp
|
||||
parser_state.cpp
|
||||
parse.cpp
|
||||
solar.cpp
|
||||
)
|
||||
set_target_properties(solar PROPERTIES COMPILE_FLAGS "-std=c++11 -Wall")
|
||||
|
|
35
src/lex.cpp
35
src/lex.cpp
|
@ -101,20 +101,21 @@ void lex_t::consume(bool consume_needspace) {
|
|||
needspace = consume_needspace;
|
||||
}
|
||||
|
||||
int lex_t::io_error(parser_value_t *value) {
|
||||
value->error = "I/O error";
|
||||
int lex_t::io_error(parse_token_value_t *value) {
|
||||
//value->error = "I/O error";
|
||||
(void)value;
|
||||
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))
|
||||
return io_error(value);
|
||||
|
||||
value->error = "syntax error";
|
||||
//value->error = "syntax error";
|
||||
return -1;
|
||||
}
|
||||
|
||||
int lex_t::consume_comment(parser_value_t *value) {
|
||||
int lex_t::consume_comment(parse_token_value_t *value) {
|
||||
char prev = 0;
|
||||
|
||||
while (next(true)) {
|
||||
|
@ -130,20 +131,20 @@ int lex_t::consume_comment(parser_value_t *value) {
|
|||
if (std::ferror(file))
|
||||
return io_error(value);
|
||||
|
||||
value->error = "unterminated block comment";
|
||||
//value->error = "unterminated block comment";
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
int lex_t::unterminated_string(parser_value_t *value) {
|
||||
int lex_t::unterminated_string(parse_token_value_t *value) {
|
||||
if (ferror(file))
|
||||
return io_error(value);
|
||||
|
||||
value->error = "unterminated string";
|
||||
//value->error = "unterminated string";
|
||||
return -1;
|
||||
}
|
||||
|
||||
int lex_t::lex_string(parser_value_t *value) {
|
||||
int lex_t::lex_string(parse_token_value_t *value) {
|
||||
char *buf = NULL;
|
||||
size_t len = 1024;
|
||||
size_t pos = 0;
|
||||
|
@ -193,7 +194,7 @@ int lex_t::lex_string(parser_value_t *value) {
|
|||
return TOK_STRING;
|
||||
}
|
||||
|
||||
int lex_t::lex_number(parser_value_t *value) {
|
||||
int lex_t::lex_number(parse_token_value_t *value) {
|
||||
if (needspace)
|
||||
return syntax_error(value);
|
||||
|
||||
|
@ -223,7 +224,7 @@ int lex_t::lex_number(parser_value_t *value) {
|
|||
return TOK_UINT;
|
||||
}*/
|
||||
|
||||
int lex_t::lex_keyword(parser_value_t *value) {
|
||||
int lex_t::lex_keyword(parse_token_value_t *value) {
|
||||
if (needspace)
|
||||
return syntax_error(value);
|
||||
|
||||
|
@ -247,15 +248,15 @@ int lex_t::lex_keyword(parser_value_t *value) {
|
|||
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))
|
||||
return io_error(value);
|
||||
|
||||
value->error = "unterminated code block";
|
||||
//value->error = "unterminated code block";
|
||||
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;
|
||||
bool line_comment = false;
|
||||
bool block_comment = false;
|
||||
|
@ -326,7 +327,7 @@ int lex_t::lex_block(parser_value_t *value) {
|
|||
return TOK_BLOCK;
|
||||
}
|
||||
|
||||
int lex_t::lex_symbol(parser_value_t *value) {
|
||||
int lex_t::lex_symbol(parse_token_value_t *value) {
|
||||
if (needspace)
|
||||
return syntax_error(value);
|
||||
|
||||
|
@ -361,7 +362,7 @@ int lex_t::lex_symbol(parser_value_t *value) {
|
|||
return TOK_SYMBOL;
|
||||
}
|
||||
|
||||
int lex_t::lex(parser_value_t *value) {
|
||||
int lex_t::lex(parse_token_value_t *value) {
|
||||
int token;
|
||||
|
||||
while (end > start) {
|
||||
|
@ -416,7 +417,7 @@ int lex_t::lex(parser_value_t *value) {
|
|||
if (!next(true))
|
||||
return syntax_error(value);
|
||||
|
||||
value->number = current();
|
||||
value->c = current();
|
||||
|
||||
if (!next(true) || current() != '\'')
|
||||
return syntax_error(value);
|
||||
|
|
24
src/lex.hpp
24
src/lex.hpp
|
@ -26,7 +26,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "parser.hpp"
|
||||
#include "parse.hpp"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
|
@ -62,17 +62,17 @@ private:
|
|||
bool next(bool move);
|
||||
void consume(bool needspace);
|
||||
|
||||
int io_error(parser_value_t *value);
|
||||
int syntax_error(parser_value_t *value);
|
||||
int consume_comment(parser_value_t *value);
|
||||
int unterminated_block(parser_value_t *value);
|
||||
//int unterminated_string(parser_value_t *value);
|
||||
int io_error(parse_token_value_t *value);
|
||||
int syntax_error(parse_token_value_t *value);
|
||||
int consume_comment(parse_token_value_t *value);
|
||||
int unterminated_block(parse_token_value_t *value);
|
||||
//int unterminated_string(parse_token_value_t *value);
|
||||
|
||||
//int lex_string(parser_value_t *value);
|
||||
//int lex_number(parser_value_t *value);
|
||||
int lex_keyword(parser_value_t *value);
|
||||
int lex_block(parser_value_t *value);
|
||||
int lex_symbol(parser_value_t *value);
|
||||
//int lex_string(parse_token_value_t *value);
|
||||
//int lex_number(parse_token_value_t *value);
|
||||
int lex_keyword(parse_token_value_t *value);
|
||||
int lex_block(parse_token_value_t *value);
|
||||
int lex_symbol(parse_token_value_t *value);
|
||||
|
||||
char current() {
|
||||
return buffer[start + tok_len];
|
||||
|
@ -92,7 +92,7 @@ public:
|
|||
fclose(file);
|
||||
}
|
||||
|
||||
int lex(parser_value_t *value);
|
||||
int lex(parse_token_value_t *value);
|
||||
|
||||
const location_t & get_location() const {
|
||||
return loc;
|
||||
|
|
1548
src/parse.cpp
Normal file
1548
src/parse.cpp
Normal file
File diff suppressed because it is too large
Load diff
28
src/parse.hpp
Normal file
28
src/parse.hpp
Normal 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
143
src/parse.y
Normal 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;
|
||||
}
|
302
src/parser.cpp
302
src/parser.cpp
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
|
||||
}
|
|
@ -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)));
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
};
|
||||
|
||||
}
|
|
@ -25,18 +25,19 @@
|
|||
|
||||
|
||||
#include "lex.hpp"
|
||||
#include "parser.hpp"
|
||||
#include "parse.hpp"
|
||||
#include "generator_slr.hpp"
|
||||
#include "output_slr.hpp"
|
||||
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
|
||||
|
||||
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");
|
||||
if (!file) {
|
||||
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));
|
||||
parser_t *parser = parser_alloc();
|
||||
parse_context_t *parser = parse_alloc(std::malloc);
|
||||
int ret;
|
||||
|
||||
do {
|
||||
int token;
|
||||
parser_value_t value;
|
||||
parse_token_value_t value;
|
||||
|
||||
token = lexer->lex(&value);
|
||||
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);
|
||||
return false;
|
||||
}
|
||||
|
||||
ret = parser_push(parser, token, &value, state);
|
||||
ret = parse_push(parser, token, &value, grammar);
|
||||
} while (ret > 0);
|
||||
|
||||
if (ret < 0) {
|
||||
|
@ -67,7 +68,7 @@ bool read_grammar(const char *filename, parser_state_t *state) {
|
|||
return false;
|
||||
}
|
||||
|
||||
parser_free(parser);
|
||||
parse_free(parser, std::free);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -83,11 +84,11 @@ int main(int argc, char *argv[]) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
parser_state_t state;
|
||||
if (!read_grammar(argv[1], &state))
|
||||
grammar_t grammar;
|
||||
if (!read_grammar(argv[1], &grammar))
|
||||
return 1;
|
||||
|
||||
generator_slr_t generator(state.get_grammar());
|
||||
generator_slr_t generator(grammar);
|
||||
|
||||
output_slr_t output(&generator, argv[3], argv[2]);
|
||||
output.write();
|
||||
|
|
Reference in a new issue