mirror of
https://github.com/yhirose/cpp-peglib.git
synced 2024-12-22 11:55:30 +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)
|
* `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
139
peglib.h
@ -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
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user