Expose all grammar compilation errors
This commit is contained in:
parent
e36d586817
commit
3a50171249
15 changed files with 79 additions and 49 deletions
|
|
@ -18,7 +18,7 @@
|
|||
#include "compiler/build_tables/first_set.h"
|
||||
|
||||
namespace tree_sitter {
|
||||
using std::pair;
|
||||
using std::tuple;
|
||||
using std::string;
|
||||
using std::map;
|
||||
using std::vector;
|
||||
|
|
@ -199,12 +199,12 @@ namespace tree_sitter {
|
|||
LexTable lex_table;
|
||||
};
|
||||
|
||||
pair<pair<ParseTable, LexTable>, vector<Conflict>>
|
||||
tuple<ParseTable, LexTable, vector<Conflict>>
|
||||
build_tables(const PreparedGrammar &grammar,
|
||||
const PreparedGrammar &lex_grammar) {
|
||||
TableBuilder builder(grammar, lex_grammar);
|
||||
builder.build();
|
||||
return { { builder.parse_table, builder.lex_table }, builder.conflicts() };
|
||||
return { builder.parse_table, builder.lex_table, builder.conflicts() };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ namespace tree_sitter {
|
|||
class PreparedGrammar;
|
||||
|
||||
namespace build_tables {
|
||||
std::pair<std::pair<ParseTable, LexTable>, std::vector<Conflict>>
|
||||
std::tuple<ParseTable, LexTable, std::vector<Conflict>>
|
||||
build_tables(const PreparedGrammar &grammar,
|
||||
const PreparedGrammar &lex_grammar);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ namespace tree_sitter {
|
|||
bool Item::is_done() const {
|
||||
return rule_can_be_blank(rule);
|
||||
}
|
||||
|
||||
|
||||
int Item::precedence() const {
|
||||
return get_metadata(rule, rules::PRECEDENCE);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,22 +5,27 @@
|
|||
#include "compiler/prepared_grammar.h"
|
||||
|
||||
namespace tree_sitter {
|
||||
using std::pair;
|
||||
using std::tuple;
|
||||
using std::string;
|
||||
using std::vector;
|
||||
using std::get;
|
||||
|
||||
pair<string, vector<Conflict>> compile(const Grammar &grammar, std::string name) {
|
||||
auto grammars = prepare_grammar::prepare_grammar(grammar);
|
||||
PreparedGrammar &syntax_grammar = grammars.first;
|
||||
PreparedGrammar &lexical_grammar = grammars.second;
|
||||
tuple<string, vector<Conflict>, const GrammarError *>
|
||||
compile(const Grammar &grammar, std::string name) {
|
||||
auto prepare_grammar_result = prepare_grammar::prepare_grammar(grammar);
|
||||
const PreparedGrammar &syntax_grammar = get<0>(prepare_grammar_result);
|
||||
const PreparedGrammar &lexical_grammar = get<1>(prepare_grammar_result);
|
||||
const GrammarError *error = get<2>(prepare_grammar_result);
|
||||
|
||||
if (error) return { "", vector<Conflict>(), error };
|
||||
|
||||
auto table_build_result = build_tables::build_tables(syntax_grammar, lexical_grammar);
|
||||
auto tables = table_build_result.first;
|
||||
auto conflicts = table_build_result.second;
|
||||
const ParseTable &parse_table = get<0>(table_build_result);
|
||||
const LexTable &lex_table = get<1>(table_build_result);
|
||||
const vector<Conflict> &conflicts = get<2>(table_build_result);
|
||||
|
||||
ParseTable &parse_table = tables.first;
|
||||
LexTable &lex_table = tables.second;
|
||||
string code = generate_code::c_code(name, parse_table, lex_table, syntax_grammar, lexical_grammar);
|
||||
|
||||
return { generate_code::c_code(name, parse_table, lex_table, syntax_grammar, lexical_grammar), conflicts };
|
||||
return { code, conflicts, nullptr };
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,4 +39,15 @@ namespace tree_sitter {
|
|||
}
|
||||
return stream << string("}>");
|
||||
}
|
||||
|
||||
GrammarError::GrammarError(GrammarErrorType type, std::string message) :
|
||||
type(type),
|
||||
message(message) {}
|
||||
|
||||
ostream& operator<<(ostream &stream, const GrammarError *error) {
|
||||
if (error)
|
||||
return stream << (string("#<grammar-error '") + error->message + "'>");
|
||||
else
|
||||
return stream << string("#<null>");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,12 +14,6 @@ namespace tree_sitter {
|
|||
using std::pair;
|
||||
using std::make_shared;
|
||||
|
||||
GrammarError::GrammarError(string rule_name) : rule_name(rule_name) {}
|
||||
|
||||
string GrammarError::message() const {
|
||||
return "Undefined rule '" + rule_name + "'";
|
||||
}
|
||||
|
||||
namespace prepare_grammar {
|
||||
class InternSymbols : public rules::IdentityRuleFn {
|
||||
const Grammar grammar;
|
||||
|
|
@ -54,7 +48,8 @@ namespace tree_sitter {
|
|||
if (!interner.missing_rule_name.empty())
|
||||
return {
|
||||
PreparedGrammar({}, {}),
|
||||
new GrammarError(interner.missing_rule_name)
|
||||
new GrammarError(GrammarErrorTypeUndefinedSymbol,
|
||||
"Undefined rule '" + interner.missing_rule_name + "'")
|
||||
};
|
||||
rules.push_back({ pair.first, new_rule });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,18 +3,12 @@
|
|||
|
||||
#include <utility>
|
||||
#include <string>
|
||||
#include "tree_sitter/compiler.h"
|
||||
|
||||
namespace tree_sitter {
|
||||
class Grammar;
|
||||
class PreparedGrammar;
|
||||
|
||||
class GrammarError {
|
||||
std::string rule_name;
|
||||
public:
|
||||
explicit GrammarError(std::string rule_name);
|
||||
std::string message() const;
|
||||
};
|
||||
|
||||
namespace prepare_grammar {
|
||||
std::pair<PreparedGrammar, const GrammarError *> intern_symbols(const Grammar &);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,18 +5,22 @@
|
|||
#include "compiler/prepare_grammar/intern_symbols.h"
|
||||
|
||||
namespace tree_sitter {
|
||||
using std::pair;
|
||||
using std::tuple;
|
||||
|
||||
namespace prepare_grammar {
|
||||
pair<PreparedGrammar, PreparedGrammar> prepare_grammar(const Grammar &input_grammar) {
|
||||
auto interned = intern_symbols(input_grammar);
|
||||
if (interned.second) {
|
||||
printf("Error! %s", interned.second->message().c_str());
|
||||
exit(1);
|
||||
}
|
||||
auto grammars = extract_tokens(interned.first);
|
||||
const auto &rule_grammar = expand_repeats(grammars.first);
|
||||
const auto &lex_grammar = grammars.second;
|
||||
tuple<PreparedGrammar, PreparedGrammar, const GrammarError *>
|
||||
prepare_grammar(const Grammar &input_grammar) {
|
||||
auto result = intern_symbols(input_grammar);
|
||||
const PreparedGrammar &grammar = result.first;
|
||||
const GrammarError *error = result.second;
|
||||
|
||||
if (error)
|
||||
return { PreparedGrammar({}, {}), PreparedGrammar({}, {}), error };
|
||||
|
||||
auto grammars = extract_tokens(grammar);
|
||||
const PreparedGrammar &rule_grammar = expand_repeats(grammars.first);
|
||||
const PreparedGrammar &lex_grammar = grammars.second;
|
||||
|
||||
return { rule_grammar, lex_grammar };
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,10 +5,12 @@
|
|||
|
||||
namespace tree_sitter {
|
||||
class Grammar;
|
||||
class GrammarError;
|
||||
class PreparedGrammar;
|
||||
|
||||
namespace prepare_grammar {
|
||||
std::pair<PreparedGrammar, PreparedGrammar> prepare_grammar(const Grammar &);
|
||||
std::tuple<PreparedGrammar, PreparedGrammar, const GrammarError *>
|
||||
prepare_grammar(const Grammar &);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ namespace tree_sitter {
|
|||
rule_ptr keyword(const string &value) {
|
||||
return metadata(make_shared<String>(value), { { PRECEDENCE, 100}, { IS_TOKEN, 1 } });
|
||||
}
|
||||
|
||||
|
||||
rule_ptr err(const rule_ptr &rule) {
|
||||
return choice({ rule, ERROR().copy() });
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue