我已经写了这个 - 效果很好:
use Grammar::Tracer;
my grammar Lambda {
token TOP { <signature> <body> ' as ' <r-type> }
rule signature { '|' <a-sig> [',' <b-sig>]? '|' }
rule a-sig { 'a:' <a-type> }
rule b-sig { 'b:' <b-type> }
token body { '(' <expr> ')' <?before ' as '> }
token expr { <-[()]>* }
token a-type { @types }
token b-type { @types }
token r-type { @types }
}
Lambda.parse("|a: i32, b: i32| (a + b) as i32");
Run Code Online (Sandbox Code Playgroud)
给出我需要的:
TOP
| signature
| | a-sig
| | | a-type
| | | * MATCH "i32"
| | * MATCH "a: i32"
| | b-sig
| | | b-type
| | | * MATCH "i32"
| | * MATCH "b: i32"
| * MATCH "|a: i32, b: i32| "
| body
| | expr
| | * MATCH "a + b"
| * MATCH "(a + b)"
| r-type
| * MATCH "i32"
* MATCH "|a: i32, b: i32| (a + b) as i32"
Run Code Online (Sandbox Code Playgroud)
但我想做这个字符串(和类似的):
|a: str, b: i32| (a.len() as i32 + b) as i32
我想找到某种方法将匹配“固定”为字符串末尾之前“as type”的最后一个有效匹配
以及如何匹配但不只捕获其他括号。
请
经过一番尝试和错误后,我设法解决了这个问题(Grammar::Tracer 太有帮助了!)
这是工作语法
my @types = <bool i32 i64 u32 u64 f32 f64 str>;
my grammar Lambda {
rule TOP { <signature> <body> <as-type> }
rule signature { '|' <a-sig> [',' <b-sig>]? '|' }
rule a-sig { 'a:' <a-type> }
rule b-sig { 'b:' <b-type> }
rule as-type { 'as' <r-type> }
rule body { '(' <expr> ')' <?before <as-type>> }
rule expr { .* <?before ')'> }
token a-type { @types }
token b-type { @types }
token r-type { @types }
}
Run Code Online (Sandbox Code Playgroud)
我所做的改变是:
<as-type>将返回类型捆绑为 TOP 中的单个匹配器,以便它始终在末尾匹配<body>有一个前瞻断言,所以总是在<as-type><expr>有一个先行断言,所以总是在 ')' 之前