mirror of
https://github.com/yhirose/cpp-peglib.git
synced 2024-12-22 20:05:31 +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
|
```peg
|
||||||
S <- (Decl / Ref)*
|
S <- (Decl / Ref)*
|
||||||
Decl <- 'decl' symbol(Name)
|
Decl <- 'decl' symbol
|
||||||
Ref <- 'ref' is_symbol(Name)
|
Ref <- 'ref' is_symbol
|
||||||
Name <- < [a-zA-Z]+ >
|
Name <- < [a-zA-Z]+ >
|
||||||
%whitespace <- [ \t\r\n]*
|
%whitespace <- [ \t\r\n]*
|
||||||
|
|
||||||
# 'var_table' is a table name.
|
# 'var_table' is a table name.
|
||||||
symbol(s) <- s { declare_symbol var_table } # Declare symbol instruction
|
symbol <- Name { declare_symbol var_table } # Declare symbol instruction
|
||||||
is_symbol(s) <- s { check_symbol var_table } # Check 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.
|
If we parse the following text with the above grammar, it will fail.
|
||||||
|
61
peglib.h
61
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_);
|
c.rule_stack.push_back(outer_);
|
||||||
auto len = ope_->parse(s, n, vs, c, dt);
|
auto len = ope_->parse(s, n, vs, c, dt);
|
||||||
c.rule_stack.pop_back();
|
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;
|
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;
|
c.error_info.message = msg;
|
||||||
}
|
}
|
||||||
len = static_cast<size_t>(-1);
|
len = static_cast<size_t>(-1);
|
||||||
|
} 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 {
|
} 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);
|
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) {
|
TEST(SymbolTableTest, symbol_instruction_test) {
|
||||||
parser parser(R"(
|
parser parser(R"(
|
||||||
S <- (Decl / Ref)*
|
S <- (Decl / Ref)*
|
||||||
Decl <- 'decl' symbol(Name)
|
Decl <- 'decl' symbol
|
||||||
Ref <- 'ref' is_symbol(Name)
|
Ref <- 'ref' is_symbol
|
||||||
Name <- < [a-zA-Z]+ >
|
Name <- < [a-zA-Z]+ >
|
||||||
%whitespace <- [ \t\r\n]*
|
%whitespace <- [ \t\r\n]*
|
||||||
|
|
||||||
symbol(s) <- s { declare_symbol var_table }
|
symbol <- Name { declare_symbol var_table }
|
||||||
is_symbol(s) <- s { check_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"(
|
parser parser(R"(
|
||||||
S <- (Decl / Ref)*
|
S <- (Decl / Ref)*
|
||||||
Decl <- 'decl' symbol(Name)
|
Decl <- 'decl' symbol
|
||||||
Ref <- 'ref' is_symbol(Name)
|
Ref <- 'ref' is_symbol
|
||||||
Name <- < [a-zA-Z]+ >
|
Name <- < [a-zA-Z]+ >
|
||||||
%whitespace <- [ \t\r\n]*
|
%whitespace <- [ \t\r\n]*
|
||||||
|
|
||||||
# These must be tokens.
|
# These must be tokens.
|
||||||
symbol(s) <- < s >
|
symbol <- < Name >
|
||||||
is_symbol(s) <- < s >
|
is_symbol <- < Name >
|
||||||
)");
|
)");
|
||||||
|
|
||||||
std::set<std::string> dic;
|
std::set<std::string> dic;
|
||||||
|
Loading…
Reference in New Issue
Block a user