mirror of
https://github.com/yhirose/cpp-peglib.git
synced 2024-12-22 11:55:30 +00:00
Throw operator support
This commit is contained in:
parent
d4aa6e7df5
commit
0dab91d8d9
File diff suppressed because one or more lines are too long
BIN
docs/native.wasm
BIN
docs/native.wasm
Binary file not shown.
22
peglib.h
22
peglib.h
@ -2918,7 +2918,8 @@ private:
|
||||
opt(g["Instruction"])));
|
||||
g["Expression"] <= seq(g["Sequence"], zom(seq(g["SLASH"], g["Sequence"])));
|
||||
g["Sequence"] <= zom(g["Prefix"]);
|
||||
g["Prefix"] <= seq(opt(cho(g["AND"], g["NOT"])), g["Suffix"]);
|
||||
g["Prefix"] <= seq(opt(cho(g["AND"], g["NOT"])), g["SuffixWithLabel"]);
|
||||
g["SuffixWithLabel"] <= seq(g["Suffix"], opt(seq(g["HAT"], g["Identifier"])));
|
||||
g["Suffix"] <= seq(g["Primary"], opt(g["Loop"]));
|
||||
g["Loop"] <= cho(g["QUESTION"], g["STAR"], g["PLUS"], g["Repetition"]);
|
||||
g["Primary"] <=
|
||||
@ -2991,6 +2992,7 @@ private:
|
||||
~g["PIPE"] <= seq(chr('|'), g["Spacing"]);
|
||||
g["AND"] <= seq(chr('&'), g["Spacing"]);
|
||||
g["NOT"] <= seq(chr('!'), g["Spacing"]);
|
||||
~g["HAT"] <= seq(chr('^'), g["Spacing"]);
|
||||
g["QUESTION"] <= seq(chr('?'), g["Spacing"]);
|
||||
g["STAR"] <= seq(chr('*'), g["Spacing"]);
|
||||
g["PLUS"] <= seq(chr('+'), g["Spacing"]);
|
||||
@ -3064,7 +3066,7 @@ private:
|
||||
|
||||
void setup_actions() {
|
||||
g["Definition"] = [&](const SemanticValues &vs, std::any &dt) {
|
||||
Data &data = *std::any_cast<Data *>(dt);
|
||||
auto &data = *std::any_cast<Data *>(dt);
|
||||
|
||||
auto is_macro = vs.choice() == 0;
|
||||
auto ignore = std::any_cast<bool>(vs[0]);
|
||||
@ -3150,6 +3152,20 @@ private:
|
||||
return ope;
|
||||
};
|
||||
|
||||
g["SuffixWithLabel"] = [&](const SemanticValues &vs, std::any &dt) {
|
||||
auto ope = std::any_cast<std::shared_ptr<Ope>>(vs[0]);
|
||||
if (vs.size() == 1) {
|
||||
return ope;
|
||||
} else {
|
||||
assert(vs.size() == 2);
|
||||
auto &data = *std::any_cast<Data *>(dt);
|
||||
const auto &ident = std::any_cast<std::string>(vs[1]);
|
||||
auto label = ref(*data.grammar, ident, vs.sv().data(), false, {});
|
||||
auto recovery = rec(ref(*data.grammar, RECOVER_DEFINITION_NAME, vs.sv().data(), true, {label}));
|
||||
return cho(ope, recovery);
|
||||
}
|
||||
};
|
||||
|
||||
struct Loop {
|
||||
enum class Type { opt = 0, zom, oom, rep };
|
||||
Type type;
|
||||
@ -3211,7 +3227,7 @@ private:
|
||||
};
|
||||
|
||||
g["Primary"] = [&](const SemanticValues &vs, std::any &dt) {
|
||||
Data &data = *std::any_cast<Data *>(dt);
|
||||
auto &data = *std::any_cast<Data *>(dt);
|
||||
|
||||
switch (vs.choice()) {
|
||||
case 0: // Macro Reference
|
||||
|
134
test/test2.cc
134
test/test2.cc
@ -1251,3 +1251,137 @@ R"(+ START
|
||||
+ ITEM/2
|
||||
)");
|
||||
}
|
||||
|
||||
TEST_CASE("Error recovery Java", "[error]") {
|
||||
parser pg(R"(
|
||||
Prog ← PUBLIC CLASS NAME LCUR PUBLIC STATIC VOID MAIN LPAR STRING LBRA RBRA NAME RPAR BlockStmt RCUR
|
||||
BlockStmt ← LCUR (Stmt)* RCUR^rcblk
|
||||
Stmt ← IfStmt / WhileStmt / PrintStmt / DecStmt / AssignStmt / BlockStmt
|
||||
IfStmt ← IF LPAR Exp RPAR Stmt (ELSE Stmt)?
|
||||
WhileStmt ← WHILE LPAR Exp RPAR Stmt
|
||||
DecStmt ← INT NAME (ASSIGN Exp)? SEMI
|
||||
AssignStmt ← NAME ASSIGN Exp SEMI^semia
|
||||
PrintStmt ← PRINTLN LPAR Exp RPAR SEMI
|
||||
Exp ← RelExp (EQ RelExp)*
|
||||
RelExp ← AddExp (LT AddExp)*
|
||||
AddExp ← MulExp ((PLUS / MINUS) MulExp)*
|
||||
MulExp ← AtomExp ((TIMES / DIV) AtomExp)*
|
||||
AtomExp ← LPAR Exp RPAR / NUMBER / NAME
|
||||
|
||||
NUMBER ← < [0-9]+ >
|
||||
NAME ← < [a-zA-Z_][a-zA-Z_0-9]* >
|
||||
|
||||
~LPAR ← '('
|
||||
~RPAR ← ')'
|
||||
~LCUR ← '{'
|
||||
~RCUR ← '}'
|
||||
~LBRA ← '['
|
||||
~RBRA ← ']'
|
||||
~SEMI ← ';'
|
||||
|
||||
~EQ ← '=='
|
||||
~LT ← '<'
|
||||
~ASSIGN ← '='
|
||||
|
||||
~IF ← 'if'
|
||||
~ELSE ← 'else'
|
||||
~WHILE ← 'while'
|
||||
|
||||
PLUS ← '+'
|
||||
MINUS ← '-'
|
||||
TIMES ← '*'
|
||||
DIV ← '/'
|
||||
|
||||
CLASS ← 'class'
|
||||
PUBLIC ← 'public'
|
||||
STATIC ← 'static'
|
||||
|
||||
VOID ← 'void'
|
||||
INT ← 'int'
|
||||
|
||||
MAIN ← 'main'
|
||||
STRING ← 'String'
|
||||
PRINTLN ← 'System.out.println'
|
||||
|
||||
%whitespace ← [ \t\n]*
|
||||
%word ← NAME
|
||||
|
||||
# Throw operator labels
|
||||
rcblk ← SkipToRCUR { message "missing end of block." }
|
||||
semia ← '' { message "missing simicolon in assignment." }
|
||||
|
||||
# Recovery expressions
|
||||
SkipToRCUR ← (!RCUR (LCUR SkipToRCUR / .))* RCUR
|
||||
)");
|
||||
|
||||
REQUIRE(!!pg); // OK
|
||||
|
||||
std::vector<std::string> errors{
|
||||
R"(8:5: missing simicolon in assignment.)",
|
||||
R"(8:6: missing end of block.)",
|
||||
};
|
||||
|
||||
size_t i = 0;
|
||||
pg.log = [&](size_t ln, size_t col, const std::string &msg) {
|
||||
std::stringstream ss;
|
||||
ss << ln << ":" << col << ": " << msg;
|
||||
REQUIRE(ss.str() == errors[i++]);
|
||||
};
|
||||
|
||||
pg.enable_ast();
|
||||
|
||||
std::shared_ptr<Ast> ast;
|
||||
REQUIRE_FALSE(pg.parse(R"(public class Example {
|
||||
public static void main(String[] args) {
|
||||
int n = 5;
|
||||
int f = 1;
|
||||
while(0 < n) {
|
||||
f = f * n;
|
||||
n = n - 1
|
||||
};
|
||||
System.out.println(f);
|
||||
}
|
||||
}
|
||||
)", ast));
|
||||
|
||||
ast = peg::AstOptimizer(true, {"ENTRIES"}).optimize(ast);
|
||||
|
||||
REQUIRE(ast_to_s(ast) ==
|
||||
R"(+ Prog
|
||||
- PUBLIC (public)
|
||||
- CLASS (class)
|
||||
- NAME (Example)
|
||||
- PUBLIC (public)
|
||||
- STATIC (static)
|
||||
- VOID (void)
|
||||
- MAIN (main)
|
||||
- STRING (String)
|
||||
- NAME (args)
|
||||
+ BlockStmt
|
||||
+ Stmt/3[DecStmt]
|
||||
- INT (int)
|
||||
- NAME (n)
|
||||
- Exp/0[NUMBER] (5)
|
||||
+ Stmt/3[DecStmt]
|
||||
- INT (int)
|
||||
- NAME (f)
|
||||
- Exp/0[NUMBER] (1)
|
||||
+ Stmt/1[WhileStmt]
|
||||
+ Exp/0[RelExp]
|
||||
- AddExp/0[NUMBER] (0)
|
||||
- AddExp/0[NAME] (n)
|
||||
+ Stmt/5[BlockStmt]
|
||||
+ Stmt/4[AssignStmt]
|
||||
- NAME (f)
|
||||
+ Exp/0[MulExp]
|
||||
- AtomExp/2[NAME] (f)
|
||||
- TIMES (*)
|
||||
- AtomExp/2[NAME] (n)
|
||||
+ Stmt/4[AssignStmt]
|
||||
- NAME (n)
|
||||
+ Exp/0[AddExp]
|
||||
- MulExp/0[NAME] (n)
|
||||
- MINUS (-)
|
||||
- MulExp/0[NUMBER] (1)
|
||||
)");
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user