This commit is contained in:
yhirose 2022-08-19 23:11:02 -04:00
parent eaef1725d7
commit 978a8dc274
2 changed files with 0 additions and 173 deletions

View File

@ -35,11 +35,6 @@ The PEG syntax is well described on page 2 in the [document](http://www.brynosau
* `label { message "..." }` (Error message instruction) * `label { message "..." }` (Error message instruction)
* `{ no_ast_opt }` (No AST node optimazation 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`. '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. 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). 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 Make a parser with parser combinators
------------------------------------- -------------------------------------

139
peglib.h
View File

@ -778,12 +778,6 @@ public:
std::vector<bool> cut_stack; 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 size_t def_count;
const bool enablePackratParsing; const bool enablePackratParsing;
std::vector<bool> cache_registered; std::vector<bool> cache_registered;
@ -813,10 +807,6 @@ public:
push_args({}); push_args({});
push_capture_scope(); push_capture_scope();
#ifdef CPPPEGLIB_SYMBOL_TABLE_SUPPORT
push_symbol_tables();
#endif
} }
~Context() { ~Context() {
@ -825,11 +815,6 @@ public:
assert(!value_stack_size); assert(!value_stack_size);
assert(!capture_scope_stack_size); assert(!capture_scope_stack_size);
assert(cut_stack.empty()); assert(cut_stack.empty());
#ifdef CPPPEGLIB_SYMBOL_TABLE_SUPPORT
pop_symbol_tables();
assert(!symbol_tables_stack_size);
#endif
} }
Context(const Context &) = delete; Context(const Context &) = delete;
@ -870,18 +855,12 @@ public:
SemanticValues &push() { SemanticValues &push() {
push_capture_scope(); push_capture_scope();
#ifdef CPPPEGLIB_SYMBOL_TABLE_SUPPORT
push_symbol_tables();
#endif
return push_semantic_values_scope(); return push_semantic_values_scope();
} }
void pop() { void pop() {
pop_capture_scope(); pop_capture_scope();
pop_semantic_values_scope(); pop_semantic_values_scope();
#ifdef CPPPEGLIB_SYMBOL_TABLE_SUPPORT
pop_symbol_tables();
#endif
} }
// Semantic values // 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 // Error
void set_error_pos(const char *a_s, const char *literal = nullptr); void set_error_pos(const char *a_s, const char *literal = nullptr);
@ -1082,9 +1014,6 @@ public:
vs.choice_count_ = opes_.size(); vs.choice_count_ = opes_.size();
vs.choice_ = id; vs.choice_ = id;
c.shift_capture_values(); c.shift_capture_values();
#ifdef CPPPEGLIB_SYMBOL_TABLE_SUPPORT
c.shift_symbol_tables();
#endif
break; break;
} else if (!c.cut_stack.empty() && c.cut_stack.back()) { } else if (!c.cut_stack.empty() && c.cut_stack.back()) {
break; break;
@ -1124,9 +1053,6 @@ public:
if (success(len)) { if (success(len)) {
vs.append(chvs); vs.append(chvs);
c.shift_capture_values(); c.shift_capture_values();
#ifdef CPPPEGLIB_SYMBOL_TABLE_SUPPORT
c.shift_symbol_tables();
#endif
} else { } else {
return len; return len;
} }
@ -1143,9 +1069,6 @@ public:
if (success(len)) { if (success(len)) {
vs.append(chvs); vs.append(chvs);
c.shift_capture_values(); c.shift_capture_values();
#ifdef CPPPEGLIB_SYMBOL_TABLE_SUPPORT
c.shift_symbol_tables();
#endif
} else { } else {
break; break;
} }
@ -2426,12 +2349,6 @@ public:
bool eoi_check = true; bool eoi_check = true;
#ifdef CPPPEGLIB_SYMBOL_TABLE_SUPPORT
bool declare_symbol = false;
bool check_symbol = false;
std::string symbol_table_name;
#endif
private: private:
friend class Reference; friend class Reference;
friend class ParserGenerator; 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; c.error_info.message = msg;
} }
len = static_cast<size_t>(-1); 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)) { if (success(len)) {
@ -3485,10 +3384,6 @@ private:
g["EndBlacket"]); g["EndBlacket"]);
g["InstructionItem"] <= cho(g["PrecedenceClimbing"], g["ErrorMessage"], g["InstructionItem"] <= cho(g["PrecedenceClimbing"], g["ErrorMessage"],
g["NoAstOpt"] g["NoAstOpt"]
#ifdef CPPPEGLIB_SYMBOL_TABLE_SUPPORT
,
g["DeclareSymbol"], g["CheckSymbol"]
#endif
); );
~g["InstructionItemSeparator"] <= seq(chr(';'), g["Spacing"]); ~g["InstructionItemSeparator"] <= seq(chr(';'), g["Spacing"]);
@ -3522,14 +3417,6 @@ private:
// No Ast node optimazation instruction // No Ast node optimazation instruction
g["NoAstOpt"] <= seq(lit("no_ast_opt"), g["SpacesZom"]); 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 // Set definition names
for (auto &x : g) { for (auto &x : g) {
x.second.name = x.first; x.second.name = x.first;
@ -3932,24 +3819,6 @@ private:
return instruction; 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) { g["Instruction"] = [](const SemanticValues &vs) {
return vs.transform<Instruction>(); return vs.transform<Instruction>();
}; };
@ -4200,14 +4069,6 @@ private:
rule.error_message = std::any_cast<std::string>(instruction.data); rule.error_message = std::any_cast<std::string>(instruction.data);
} else if (instruction.type == "no_ast_opt") { } else if (instruction.type == "no_ast_opt") {
rule.no_ast_opt = true; 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
} }
} }
} }