mirror of
https://github.com/yhirose/cpp-peglib.git
synced 2024-12-22 03:55:29 +00:00
Resolve #239
This commit is contained in:
parent
eaef1725d7
commit
978a8dc274
34
README.md
34
README.md
@ -35,11 +35,6 @@ The PEG syntax is well described on page 2 in the [document](http://www.brynosau
|
||||
* `label { message "..." }` (Error message instruction)
|
||||
* `{ no_ast_opt }` (No AST node optimazation instruction)
|
||||
|
||||
The following syntax is available with `CPPPEGLIB_SYMBOL_TABLE_SUPPORT`.
|
||||
|
||||
* `{ declare_symbol "..." }` (Declare symbol instruction)
|
||||
* `{ check_symbol "..." }` (Check symbol instruction)
|
||||
|
||||
'End of Input' check will be done as default. In order to disable the check, please call `disable_eoi_check`.
|
||||
|
||||
This library supports the linear-time parsing known as the [*Packrat*](http://pdos.csail.mit.edu/~baford/packrat/thesis/thesis.pdf) parsing.
|
||||
@ -462,35 +457,6 @@ It internally calls `peg::AstOptimizer` to do the job. You can make your own AST
|
||||
|
||||
See actual usages in the [AST calculator example](https://github.com/yhirose/cpp-peglib/blob/master/example/calc3.cc) and [PL/0 language example](https://github.com/yhirose/cpp-peglib/blob/master/pl0/pl0.cc).
|
||||
|
||||
Symbol Table
|
||||
------------
|
||||
|
||||
NOTE: This feature is available with `CPPPEGLIB_SYMBOL_TABLE_SUPPORT`, and has [some limitations](https://github.com/yhirose/cpp-peglib/issues/231#issuecomment-1173215709).
|
||||
|
||||
Simple symbol table support is available with `declare_symbol` and `check_symbol` instructions.
|
||||
|
||||
```peg
|
||||
S <- (Decl / Ref)*
|
||||
Decl <- 'decl' symbol
|
||||
Ref <- 'ref' is_symbol
|
||||
Name <- < [a-zA-Z]+ >
|
||||
%whitespace <- [ \t\r\n]*
|
||||
|
||||
# 'var_table' is a table name.
|
||||
symbol <- Name { declare_symbol var_table } # Declare symbol instruction
|
||||
is_symbol <- Name { check_symbol var_table } # Check symbol instruction
|
||||
```
|
||||
|
||||
If we parse the following text with the above grammar, it will fail.
|
||||
|
||||
```
|
||||
decl aaa
|
||||
ref aaa
|
||||
ref bbb
|
||||
```
|
||||
|
||||
It is because the line 3 references undeclared 'bbb'.
|
||||
|
||||
Make a parser with parser combinators
|
||||
-------------------------------------
|
||||
|
||||
|
139
peglib.h
139
peglib.h
@ -778,12 +778,6 @@ public:
|
||||
|
||||
std::vector<bool> cut_stack;
|
||||
|
||||
#ifdef CPPPEGLIB_SYMBOL_TABLE_SUPPORT
|
||||
std::vector<std::map<std::string, std::unordered_set<std::string>>>
|
||||
symbol_tables_stack;
|
||||
size_t symbol_tables_stack_size = 0;
|
||||
#endif
|
||||
|
||||
const size_t def_count;
|
||||
const bool enablePackratParsing;
|
||||
std::vector<bool> cache_registered;
|
||||
@ -813,10 +807,6 @@ public:
|
||||
|
||||
push_args({});
|
||||
push_capture_scope();
|
||||
|
||||
#ifdef CPPPEGLIB_SYMBOL_TABLE_SUPPORT
|
||||
push_symbol_tables();
|
||||
#endif
|
||||
}
|
||||
|
||||
~Context() {
|
||||
@ -825,11 +815,6 @@ public:
|
||||
assert(!value_stack_size);
|
||||
assert(!capture_scope_stack_size);
|
||||
assert(cut_stack.empty());
|
||||
|
||||
#ifdef CPPPEGLIB_SYMBOL_TABLE_SUPPORT
|
||||
pop_symbol_tables();
|
||||
assert(!symbol_tables_stack_size);
|
||||
#endif
|
||||
}
|
||||
|
||||
Context(const Context &) = delete;
|
||||
@ -870,18 +855,12 @@ public:
|
||||
|
||||
SemanticValues &push() {
|
||||
push_capture_scope();
|
||||
#ifdef CPPPEGLIB_SYMBOL_TABLE_SUPPORT
|
||||
push_symbol_tables();
|
||||
#endif
|
||||
return push_semantic_values_scope();
|
||||
}
|
||||
|
||||
void pop() {
|
||||
pop_capture_scope();
|
||||
pop_semantic_values_scope();
|
||||
#ifdef CPPPEGLIB_SYMBOL_TABLE_SUPPORT
|
||||
pop_symbol_tables();
|
||||
#endif
|
||||
}
|
||||
|
||||
// Semantic values
|
||||
@ -944,53 +923,6 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CPPPEGLIB_SYMBOL_TABLE_SUPPORT
|
||||
// Symbol tables
|
||||
void push_symbol_tables() {
|
||||
assert(symbol_tables_stack_size <= symbol_tables_stack.size());
|
||||
if (symbol_tables_stack_size == symbol_tables_stack.size()) {
|
||||
symbol_tables_stack.emplace_back(
|
||||
std::map<std::string, std::unordered_set<std::string>>());
|
||||
} else {
|
||||
auto &tables = symbol_tables_stack[symbol_tables_stack_size];
|
||||
if (!tables.empty()) { tables.clear(); }
|
||||
}
|
||||
symbol_tables_stack_size++;
|
||||
}
|
||||
|
||||
void pop_symbol_tables() { symbol_tables_stack_size--; }
|
||||
|
||||
void shift_symbol_tables() {
|
||||
assert(symbol_tables_stack_size >= 2);
|
||||
auto curr = &symbol_tables_stack[symbol_tables_stack_size - 1];
|
||||
auto prev = curr - 1;
|
||||
for (const auto &[k, v] : *curr) {
|
||||
(*prev)[k].insert(v.begin(), v.end());
|
||||
}
|
||||
}
|
||||
|
||||
void declare_symbol(const std::string &table_name,
|
||||
const std::string &symbol) {
|
||||
assert(symbol_tables_stack_size >= 1);
|
||||
auto &table = symbol_tables_stack[symbol_tables_stack_size - 1][table_name];
|
||||
table.insert(symbol);
|
||||
}
|
||||
|
||||
bool check_symbol(const std::string &table_name, const std::string &symbol) {
|
||||
int i = symbol_tables_stack_size - 1;
|
||||
while (i >= 0) {
|
||||
const auto &tables = symbol_tables_stack[i];
|
||||
if (auto it = tables.find(table_name); it != tables.end()) {
|
||||
if (const auto &table = it->second; table.find(symbol) != table.end()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
i--;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Error
|
||||
void set_error_pos(const char *a_s, const char *literal = nullptr);
|
||||
|
||||
@ -1082,9 +1014,6 @@ public:
|
||||
vs.choice_count_ = opes_.size();
|
||||
vs.choice_ = id;
|
||||
c.shift_capture_values();
|
||||
#ifdef CPPPEGLIB_SYMBOL_TABLE_SUPPORT
|
||||
c.shift_symbol_tables();
|
||||
#endif
|
||||
break;
|
||||
} else if (!c.cut_stack.empty() && c.cut_stack.back()) {
|
||||
break;
|
||||
@ -1124,9 +1053,6 @@ public:
|
||||
if (success(len)) {
|
||||
vs.append(chvs);
|
||||
c.shift_capture_values();
|
||||
#ifdef CPPPEGLIB_SYMBOL_TABLE_SUPPORT
|
||||
c.shift_symbol_tables();
|
||||
#endif
|
||||
} else {
|
||||
return len;
|
||||
}
|
||||
@ -1143,9 +1069,6 @@ public:
|
||||
if (success(len)) {
|
||||
vs.append(chvs);
|
||||
c.shift_capture_values();
|
||||
#ifdef CPPPEGLIB_SYMBOL_TABLE_SUPPORT
|
||||
c.shift_symbol_tables();
|
||||
#endif
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
@ -2426,12 +2349,6 @@ public:
|
||||
|
||||
bool eoi_check = true;
|
||||
|
||||
#ifdef CPPPEGLIB_SYMBOL_TABLE_SUPPORT
|
||||
bool declare_symbol = false;
|
||||
bool check_symbol = false;
|
||||
std::string symbol_table_name;
|
||||
#endif
|
||||
|
||||
private:
|
||||
friend class Reference;
|
||||
friend class ParserGenerator;
|
||||
@ -2808,24 +2725,6 @@ inline size_t Holder::parse_core(const char *s, size_t n, SemanticValues &vs,
|
||||
c.error_info.message = msg;
|
||||
}
|
||||
len = static_cast<size_t>(-1);
|
||||
#ifdef CPPPEGLIB_SYMBOL_TABLE_SUPPORT
|
||||
} else if (outer_->declare_symbol) {
|
||||
assert(outer_->is_token());
|
||||
auto symbol = chvs.token_to_string();
|
||||
if (c.check_symbol(outer_->symbol_table_name, symbol)) {
|
||||
msg = "'" + symbol + "' already exists.";
|
||||
len = static_cast<size_t>(-1);
|
||||
} else {
|
||||
c.declare_symbol(outer_->symbol_table_name, symbol);
|
||||
}
|
||||
} else if (outer_->check_symbol) {
|
||||
assert(outer_->is_token());
|
||||
auto symbol = chvs.token_to_string();
|
||||
if (!c.check_symbol(outer_->symbol_table_name, symbol)) {
|
||||
msg = "'" + symbol + "' doesn't exist.";
|
||||
len = static_cast<size_t>(-1);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (success(len)) {
|
||||
@ -3485,10 +3384,6 @@ private:
|
||||
g["EndBlacket"]);
|
||||
g["InstructionItem"] <= cho(g["PrecedenceClimbing"], g["ErrorMessage"],
|
||||
g["NoAstOpt"]
|
||||
#ifdef CPPPEGLIB_SYMBOL_TABLE_SUPPORT
|
||||
,
|
||||
g["DeclareSymbol"], g["CheckSymbol"]
|
||||
#endif
|
||||
);
|
||||
~g["InstructionItemSeparator"] <= seq(chr(';'), g["Spacing"]);
|
||||
|
||||
@ -3522,14 +3417,6 @@ private:
|
||||
// No Ast node optimazation instruction
|
||||
g["NoAstOpt"] <= seq(lit("no_ast_opt"), g["SpacesZom"]);
|
||||
|
||||
#ifdef CPPPEGLIB_SYMBOL_TABLE_SUPPORT
|
||||
// Symbol table instruction
|
||||
g["DeclareSymbol"] <= seq(lit("declare_symbol"), g["SpacesZom"],
|
||||
g["Identifier"], g["SpacesZom"]);
|
||||
g["CheckSymbol"] <= seq(lit("check_symbol"), g["SpacesZom"],
|
||||
g["Identifier"], g["SpacesZom"]);
|
||||
#endif
|
||||
|
||||
// Set definition names
|
||||
for (auto &x : g) {
|
||||
x.second.name = x.first;
|
||||
@ -3932,24 +3819,6 @@ private:
|
||||
return instruction;
|
||||
};
|
||||
|
||||
#ifdef CPPPEGLIB_SYMBOL_TABLE_SUPPORT
|
||||
g["DeclareSymbol"] = [](const SemanticValues &vs) {
|
||||
Instruction instruction;
|
||||
instruction.type = "declare_symbol";
|
||||
instruction.data = std::string("default");
|
||||
instruction.sv = vs.sv();
|
||||
return instruction;
|
||||
};
|
||||
|
||||
g["CheckSymbol"] = [](const SemanticValues &vs) {
|
||||
Instruction instruction;
|
||||
instruction.type = "check_symbol";
|
||||
instruction.data = std::string("default");
|
||||
instruction.sv = vs.sv();
|
||||
return instruction;
|
||||
};
|
||||
#endif
|
||||
|
||||
g["Instruction"] = [](const SemanticValues &vs) {
|
||||
return vs.transform<Instruction>();
|
||||
};
|
||||
@ -4200,14 +4069,6 @@ private:
|
||||
rule.error_message = std::any_cast<std::string>(instruction.data);
|
||||
} else if (instruction.type == "no_ast_opt") {
|
||||
rule.no_ast_opt = true;
|
||||
#ifdef CPPPEGLIB_SYMBOL_TABLE_SUPPORT
|
||||
} else if (instruction.type == "declare_symbol") {
|
||||
rule.declare_symbol = true;
|
||||
rule.symbol_table_name = std::any_cast<std::string>(instruction.data);
|
||||
} else if (instruction.type == "check_symbol") {
|
||||
rule.check_symbol = true;
|
||||
rule.symbol_table_name = std::any_cast<std::string>(instruction.data);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user