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