pull/232/head
yhirose 2 years ago
parent 5934f0abba
commit 030659aabc
  1. 8
      README.md
  2. 63
      peglib.h
  3. 80
      test/test2.cc

@ -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.

@ -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…
Cancel
Save