Python grako的规则优先级问题
我正在重做一种最初基于Perl构建的小型语言(请参阅),但在应用语义时遇到了许多问题 :Python grako的规则优先级问题,python,python-3.x,ebnf,peg,grako,Python,Python 3.x,Ebnf,Peg,Grako,我正在重做一种最初基于Perl构建的小型语言(请参阅),但在应用语义时遇到了许多问题 : (*整数*) 十二月=/([1-9][0-9]*|0+/; int=/(0b[01]+|0o[0-7]+|0x[0-9a-fA-F]+)/| DEC; (*浮动*) 点浮点=/([0-9]*\.[0-9]+|[0-9]+\.)/; expfloat=/([0-9]+\.?|[0-9]*\.[eE][+-]?[0-9]+/; 浮点=点浮点| expfloat; list='['@+:atom{','@+:at
(*整数*)
十二月=/([1-9][0-9]*|0+/;
int=/(0b[01]+|0o[0-7]+|0x[0-9a-fA-F]+)/| DEC;
(*浮动*)
点浮点=/([0-9]*\.[0-9]+|[0-9]+\.)/;
expfloat=/([0-9]+\.?|[0-9]*\.[eE][+-]?[0-9]+/;
浮点=点浮点| expfloat;
list='['@+:atom{','@+:atom}*'];
(*原子*)
标识符=/[\uA-zA-Z][\uA-zA-Z0-9]*/;
符号=int|
浮动|
标识符|
列表
(*功能*)
arglist=@+:atom{','@+:atom}*;
函数=标识符“(“[arglist]”);
原子=函数|符号;
prec8='('atom')'| atom;
prec7=[(“+”|“-“|”~”)]prec8;
prec6=prec7['!'];
prec5=[prec6'**']prec6;
prec4=[prec5('*'|'/'|'%'|'d')]prec5;
prec3=[prec4(+''.'-')]prec4;
(*|分别为向左旋转和向右旋转。它们采用最接近的C大小。*)
prec2=[prec3(“|”|“)]prec3;
prec1=[prec2('&'|'|'|'|'^')]prec2;
expr=prec1$;
我遇到的问题是,d
运算符被拉入标识符规则,而该运算符和后面的任何字母数字字符串之间不存在空格。虽然语法本身是LL(2),但我不明白问题在哪里
例如,4d6
停止解析器,因为它被解释为4
d6
,其中d6
是一个标识符。应该发生的是,它被解释为4
d
6
,而d
是一个操作符。在LL解析器中,情况确实如此
一种可能的解决方案是不允许
d
开始一个标识符,但这将不允许像drop
这样的函数被命名为标识符。您的示例中的问题是Grako默认启用了nameguard
功能,当d6
在前面时,这将不允许只解析d
要禁用该功能,请实例化您自己的缓冲区
,并将其传递给生成的解析器的实例:
from grako.buffering import Buffer
from myparser import MyParser
# get the text
parser = MyParser()
parser.parse(Buffer(text, nameguard=False), 'expre')
Grako的tip版本在生成的解析器中添加了一个
--no-nameguard
命令行选项。在Perl中,您可以使用一个通用的BNF解析器,它支持具有现成关联性(以及更多)的通用优先级,例如
:start ::= Script
Script ::= Expression+ separator => comma
comma ~ [,]
Expression ::=
Number bless => primary
| '(' Expression ')' bless => paren assoc => group
|| Expression '**' Expression bless => exponentiate assoc => right
|| Expression '*' Expression bless => multiply
| Expression '/' Expression bless => divide
|| Expression '+' Expression bless => add
| Expression '-' Expression bless => subtract
完整的工作示例如下所示。至于编程语言,有一个问题
希望这有帮助。为了清楚起见,这是一个骰子机器人。我认为您的问题的答案可能在中,但请发布一个语法片段和示例输入,以形成一个有效的问题。我认为问题是相关的,但这里给出的答案与问题无关。事实上,至少对我来说,问题似乎是grako发出一个LR解析器,而我特别需要一个LL解析器。@Aerdan,grako发出一个PEG解析器,它是自顶向下的,因此类似于LL解析器,与LR解析器非常不同。请提供您遇到的问题的具体示例(一些语法规则和有问题的输入),以便论坛能够提供帮助。FWIW,我一直有意远离Perl。Grako的提示版本在生成的解析器中添加了一个
--no nameguard
命令行选项。这很有趣nameguard=False
修复了d
运算符,但它也会导致非十进制整数(0b1
,0o5
,0xF
等)解析失败。@Aerdan语言使用可能的标识符作为运算符肯定是不寻常的,否则我以前会看到它。如果您想使用无界d
运算符,PEG语法将允许您这样做,但这需要工作。您正在解析Perl吗?4d6
表达式是否按照您的要求进行解析?如果是这样,难怪。。。
:start ::= Script
Script ::= Expression+ separator => comma
comma ~ [,]
Expression ::=
Number bless => primary
| '(' Expression ')' bless => paren assoc => group
|| Expression '**' Expression bless => exponentiate assoc => right
|| Expression '*' Expression bless => multiply
| Expression '/' Expression bless => divide
|| Expression '+' Expression bless => add
| Expression '-' Expression bless => subtract