Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/332.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层解析器_Python_Parsing_Yacc_Ply - Fatal编程技术网

Python层解析器

Python层解析器,python,parsing,yacc,ply,Python,Parsing,Yacc,Ply,我试着四处寻找这个问题的答案,但似乎找不到答案。 我正在尝试用Python编写一个解析器,使用PLY作为一种虚构的语言。我的BNF的简化版本如下所示: statement-list -> statement ',' statement-list | 'print' expr statement -> ident 'was' 'a' type | ident 'became' expr type -> 'number

我试着四处寻找这个问题的答案,但似乎找不到答案。 我正在尝试用Python编写一个解析器,使用PLY作为一种虚构的语言。我的BNF的简化版本如下所示:

statement-list -> statement ',' statement-list |
                 'print' expr

statement -> ident 'was' 'a' type |
             ident 'became' expr

type -> 'number' | 'letter'

expr -> factor |
       expr '+' factor |
       expr '-' factor

factor -> number | letter | ident
def p_statement_list_comma(p):
    'statement-list : statement COMMA statement-list'
    p[0] = [p[1]] + p[3]

def p_statement_print_expr(p):
    'statement-list : PRINT expr'
    p[0] = [p[2]]
def p_statement_list_comma(p):
    'statement-list : statement COMMA statement-list'
    p[0] = p[3]

def p_statement_print_expr(p):
    'statement-list : PRINT expr'
    p[0] = p[2]
其中数字和字母类似于int和char

Yacc文档()只显示了简单算术表达式的语法,其中明确了p[0]应该是什么

def p_expression_plus(p):
   'expression : expression PLUS term'
    p[0] = p[1] + p[3]
我的问题是,我该如何处理BNF中的语句列表?我有:

def p_statement_list_comma(p):
    'statement-list : statement COMMA statement-list'
但我真的不知道下一步该放什么。
任何帮助都将不胜感激

我不能支持PLY解决方案,但这里有一个使用pyparsing的解决方案。有时,pyparsing示例可能很有用,即使您最终想要使用其他库实现解析器,作为一个快速而肮脏的原型/练习。不幸的是,这个例子大量使用了
operatorPrecedence
方法,这埋下了很多中缀解析的魔法,所以我不知道翻译它有多容易。更传统的expr/term/factor解析器示例可以在pyparsing wiki的示例页面()中找到,标题为

bnf=”“”
语句列表->语句“,”语句列表
语句->标识“”是“”类型|
标识“变为”expr|
“打印”表达式|
“if”条件表达式语句
键入->“数字”|“字母”
expr->factor|
表达式'+'因子|
expr'-'因子
系数->数字字母识别
"""
从pyparsing导入(caselesskyword、Word、nums、alphas、alphanums、operatorrecessence、,
转发、匹配优先、opAssoc、其中之一、组、分隔符列表)
PRINT、WAS、A、been、NUMBER、字母、IF、ELSE、TRUE、FALSE和OR、NOT=map(
Caselesskyword,
“如果其他参数为真或假,则打印是一个数字字母”。upper().split())
关键字=MatchFirst([PRINT,WAS,A,Been,NUMBER,LETTER,IF,ELSE,TRUE,FALSE,AND,OR,NOT])
类型说明符=数字|字母
数字=字(nums)
ident=~关键字+单词(alphas,alphanums+“”)
操作数=数字|标识
expr=OperatorRecessence(操作数,
[
(“-”,1,opAssoc.右图),
(其中一个(“*/”),2,opAssoc.左),
(其中一个(+-),2,opAssoc.左),
])
comparisonExpr=操作员最近(expr,
[
(“!”,1,opAssoc.右),
(其中一个(“<>=!=”,2,opAssoc.左),
])
booleanExpr=OperatorRecessence(真|假|比较nexpr,
[
(不是,1,opAssoc.右),
(和,2,opAssoc.左),
(或,2,opAssoc.左),
])
语句=转发()
printsmt=PRINT+expr
wasaStmt=ident+WAS+A+类型说明符
becamesmt=ident+been+expr
ifStmt=IF+booleanExpr+语句
报表y打印1000
['IF',['5','>','y'],['PRINT','1000']]
如果y<10 y变为y+1,则打印y

[“如果”,['y','这实际上取决于你如何构造你的代码以及你想如何计算它。如果你在进行计算的同时,假设它以正确的顺序计算,你不想你可能不想在
p\u statement\u list\u comma
的docstring之后做任何事情,也就是说,就像你之前做的那样,这些语句将被计算是的,如果需要,您可以保存变量的全局字典或类似的东西来跟踪某些状态,例如标识符值

如果你想建立一个解析树,例如单独进行评估,如果你不喜欢ply的评估顺序,你可以这样做:

statement-list -> statement ',' statement-list |
                 'print' expr

statement -> ident 'was' 'a' type |
             ident 'became' expr

type -> 'number' | 'letter'

expr -> factor |
       expr '+' factor |
       expr '-' factor

factor -> number | letter | ident
def p_statement_list_comma(p):
    'statement-list : statement COMMA statement-list'
    p[0] = [p[1]] + p[3]

def p_statement_print_expr(p):
    'statement-list : PRINT expr'
    p[0] = [p[2]]
def p_statement_list_comma(p):
    'statement-list : statement COMMA statement-list'
    p[0] = p[3]

def p_statement_print_expr(p):
    'statement-list : PRINT expr'
    p[0] = p[2]
然后,这将为您提供一个语句列表,列表中的最后一个元素是表达式。为了简单起见,这使用了列表;如果您愿意,也可以使用您自己的类-只需将任何python对象分配给p[0],它将可用于上面的级别

如果希望从yacc.parse返回打印表达式的结果(解析树顶层的值将从yacc.parse返回),可以这样做:

statement-list -> statement ',' statement-list |
                 'print' expr

statement -> ident 'was' 'a' type |
             ident 'became' expr

type -> 'number' | 'letter'

expr -> factor |
       expr '+' factor |
       expr '-' factor

factor -> number | letter | ident
def p_statement_list_comma(p):
    'statement-list : statement COMMA statement-list'
    p[0] = [p[1]] + p[3]

def p_statement_print_expr(p):
    'statement-list : PRINT expr'
    p[0] = [p[2]]
def p_statement_list_comma(p):
    'statement-list : statement COMMA statement-list'
    p[0] = p[3]

def p_statement_print_expr(p):
    'statement-list : PRINT expr'
    p[0] = p[2]

我想,
'print'expr
将是另一种形式的语句,而不是语句列表。该程序以'print'expr结尾。而且这也不是家庭作业。如果你确实添加了'print'作为语句,你可以将其放在任何地方!你的答案总是很好!Paul!+1Pyparsing不再托管在wikispaces.com上。转到
p[0]=[p[1]]+p[3] 
是次优的,因为它会不断销毁和创建新的
列表。相反,请使用
p[1]。追加(p[3])
然后
p[0]=p[1]