mirror of
https://github.com/yhirose/cpp-peglib.git
synced 2024-12-22 11:55:30 +00:00
Fix a bug in #228
This commit is contained in:
parent
5934f0abba
commit
030659aabc
@ -466,14 +466,14 @@ Simple symbol table support is available with `declare_symbol` and `check_symbol
|
||||
|
||||
```peg
|
||||
S <- (Decl / Ref)*
|
||||
Decl <- 'decl' symbol(Name)
|
||||
Ref <- 'ref' is_symbol(Name)
|
||||
Decl <- 'decl' symbol
|
||||
Ref <- 'ref' is_symbol
|
||||
Name <- < [a-zA-Z]+ >
|
||||
%whitespace <- [ \t\r\n]*
|
||||
|
||||
# 'var_table' is a table name.
|
||||
symbol(s) <- s { declare_symbol var_table } # Declare symbol instruction
|
||||
is_symbol(s) <- s { check_symbol var_table } # Check symbol instruction
|
||||
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.
|
||||
|
63
peglib.h
63
peglib.h
@ -2695,42 +2695,6 @@ inline size_t Holder::parse_core(const char *s, size_t n, SemanticValues &vs,
|
||||
c.rule_stack.push_back(outer_);
|
||||
auto len = ope_->parse(s, n, vs, c, dt);
|
||||
c.rule_stack.pop_back();
|
||||
|
||||
std::string msg;
|
||||
|
||||
if (success(len)) {
|
||||
if (outer_->predicate && !outer_->predicate(vs, dt, msg)) {
|
||||
len = static_cast<size_t>(-1);
|
||||
} else if (outer_->declare_symbol) {
|
||||
assert(outer_->is_token());
|
||||
auto symbol = vs.token_to_string();
|
||||
auto &table = c.symbol_tables[outer_->symbol_table_name];
|
||||
auto ret = table.find(symbol) != table.end();
|
||||
if (ret) {
|
||||
msg = "'" + symbol + "' already exists.";
|
||||
len = static_cast<size_t>(-1);
|
||||
} else {
|
||||
table.insert(symbol);
|
||||
}
|
||||
} else if (outer_->check_symbol) {
|
||||
assert(outer_->is_token());
|
||||
auto symbol = vs.token_to_string();
|
||||
auto &table = c.symbol_tables[outer_->symbol_table_name];
|
||||
auto ret = table.find(symbol) != table.end();
|
||||
if (!ret) {
|
||||
msg = "'" + symbol + "' doesn't exist.";
|
||||
len = static_cast<size_t>(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (fail(len)) {
|
||||
if (c.log && !msg.empty() && c.error_info.message_pos < s) {
|
||||
c.error_info.message_pos = s;
|
||||
c.error_info.message = msg;
|
||||
}
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
@ -2768,8 +2732,33 @@ 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);
|
||||
} else {
|
||||
} else if (outer_->declare_symbol) {
|
||||
assert(outer_->is_token());
|
||||
auto symbol = chldvs.token_to_string();
|
||||
auto &table = c.symbol_tables[outer_->symbol_table_name];
|
||||
if (table.find(symbol) != table.end()) {
|
||||
msg = "'" + symbol + "' already exists.";
|
||||
len = static_cast<size_t>(-1);
|
||||
} else {
|
||||
table.insert(symbol);
|
||||
}
|
||||
} else if (outer_->check_symbol) {
|
||||
assert(outer_->is_token());
|
||||
auto symbol = chldvs.token_to_string();
|
||||
auto &table = c.symbol_tables[outer_->symbol_table_name];
|
||||
if (table.find(symbol) == table.end()) {
|
||||
msg = "'" + symbol + "' doesn't exist.";
|
||||
len = static_cast<size_t>(-1);
|
||||
}
|
||||
}
|
||||
|
||||
if (success(len)) {
|
||||
a_val = reduce(chldvs, dt);
|
||||
} else {
|
||||
if (c.log && !msg.empty() && c.error_info.message_pos < s) {
|
||||
c.error_info.message_pos = s;
|
||||
c.error_info.message = msg;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -864,13 +864,13 @@ TEST(PredicateTest, Semantic_predicate_test) {
|
||||
TEST(SymbolTableTest, symbol_instruction_test) {
|
||||
parser parser(R"(
|
||||
S <- (Decl / Ref)*
|
||||
Decl <- 'decl' symbol(Name)
|
||||
Ref <- 'ref' is_symbol(Name)
|
||||
Decl <- 'decl' symbol
|
||||
Ref <- 'ref' is_symbol
|
||||
Name <- < [a-zA-Z]+ >
|
||||
%whitespace <- [ \t\r\n]*
|
||||
|
||||
symbol(s) <- s { declare_symbol var_table }
|
||||
is_symbol(s) <- s { check_symbol var_table }
|
||||
symbol <- Name { declare_symbol var_table }
|
||||
is_symbol <- Name { check_symbol var_table }
|
||||
)");
|
||||
|
||||
{
|
||||
@ -900,17 +900,65 @@ decl aaa
|
||||
}
|
||||
}
|
||||
|
||||
TEST(SymbolTableTest, with_predicate_test) {
|
||||
TEST(SymbolTableTest, typedef_test) {
|
||||
parser parser(R"(
|
||||
S <- (Decl / TypeDef)*
|
||||
Decl <- 'decl' type
|
||||
TypeDef <- 'typedef' type_ref type ';'
|
||||
type <- Name { declare_symbol type_table }
|
||||
type_ref <- Name { check_symbol type_table }
|
||||
|
||||
Name <- < [a-zA-Z0-9_]+ >
|
||||
%whitespace <- [ \t\r\n]*
|
||||
)");
|
||||
|
||||
{
|
||||
const auto source = R"(decl long
|
||||
typedef long __off64_t;
|
||||
typedef __off64_t __loff_t;
|
||||
)";
|
||||
EXPECT_TRUE(parser.parse(source));
|
||||
}
|
||||
|
||||
{
|
||||
const auto source = R"(decl long
|
||||
typedef long __off64_t;
|
||||
typedef __off64_T __loff_t;
|
||||
)";
|
||||
parser.log = [](size_t line, size_t col, const std::string &msg) {
|
||||
EXPECT_EQ(3, line);
|
||||
EXPECT_EQ(9, col);
|
||||
EXPECT_EQ("'__off64_T' doesn't exist.", msg);
|
||||
};
|
||||
EXPECT_FALSE(parser.parse(source));
|
||||
}
|
||||
|
||||
{
|
||||
const auto source = R"(decl long
|
||||
typedef long __off64_t;
|
||||
typedef __off64_t __loff_t;
|
||||
typedef __off64_t __loff_t;
|
||||
)";
|
||||
parser.log = [](size_t line, size_t col, const std::string &msg) {
|
||||
EXPECT_EQ(4, line);
|
||||
EXPECT_EQ(19, col);
|
||||
EXPECT_EQ("'__loff_t' already exists.", msg);
|
||||
};
|
||||
EXPECT_FALSE(parser.parse(source));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(SymbolTableTest, predicate_test) {
|
||||
parser parser(R"(
|
||||
S <- (Decl / Ref)*
|
||||
Decl <- 'decl' symbol(Name)
|
||||
Ref <- 'ref' is_symbol(Name)
|
||||
Decl <- 'decl' symbol
|
||||
Ref <- 'ref' is_symbol
|
||||
Name <- < [a-zA-Z]+ >
|
||||
%whitespace <- [ \t\r\n]*
|
||||
|
||||
# These must be tokens.
|
||||
symbol(s) <- < s >
|
||||
is_symbol(s) <- < s >
|
||||
symbol <- < Name >
|
||||
is_symbol <- < Name >
|
||||
)");
|
||||
|
||||
std::set<std::string> dic;
|
||||
@ -1096,13 +1144,13 @@ TEST(MacroTest, Macro_invalid_macro_reference_error) {
|
||||
TEST(MacroTest, Macro_calculator) {
|
||||
// Create a PEG parser
|
||||
parser parser(R"(
|
||||
# Grammar for simple calculator...
|
||||
EXPRESSION <- _ LIST(TERM, TERM_OPERATOR)
|
||||
TERM <- LIST(FACTOR, FACTOR_OPERATOR)
|
||||
FACTOR <- NUMBER / T('(') EXPRESSION T(')')
|
||||
TERM_OPERATOR <- T([-+])
|
||||
FACTOR_OPERATOR <- T([*/])
|
||||
NUMBER <- T([0-9]+)
|
||||
# Grammar for simple calculator...
|
||||
EXPRESSION <- _ LIST(TERM, TERM_OPERATOR)
|
||||
TERM <- LIST(FACTOR, FACTOR_OPERATOR)
|
||||
FACTOR <- NUMBER / T('(') EXPRESSION T(')')
|
||||
TERM_OPERATOR <- T([-+])
|
||||
FACTOR_OPERATOR <- T([*/])
|
||||
NUMBER <- T([0-9]+)
|
||||
~_ <- [ \t]*
|
||||
LIST(I, D) <- I (D I)*
|
||||
T(S) <- < S > _
|
||||
|
Loading…
Reference in New Issue
Block a user