Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python grako的规则优先级问题_Python_Python 3.x_Ebnf_Peg_Grako - Fatal编程技术网

Python grako的规则优先级问题

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

我正在重做一种最初基于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{','@+: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