gpt4 book ai didi

Python PLY 解析器

转载 作者:行者123 更新时间:2023-11-28 19:58:36 26 4
gpt4 key购买 nike

我试图四处寻找这个问题的答案,但似乎找不到。我正在尝试使用 PLY 在 Python 中编写一个解析器作为一种编造的语言。我的 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

其中数字和字母类似于 int 和 char。

Yacc 文档 ( http://www.dabeaz.com/ply/ply.html#ply_nn23 ) 仅显示了简单算术表达式的语法,其中明确了 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 示例可能很有用,即使您最终想使用其他一些库来实现您的解析器,作为一个快速而肮脏的原型(prototype)/练习。不幸的是,这个例子大量使用了 operatorPrecedence 方法,它隐藏了很多中缀解析魔法,所以我不知道你能多容易地翻译它。可以在示例页面 ( http://pyparsing.wikispaces.com/Examples ) 的 pyparsing wiki 上找到更传统的 expr/term/factor 解析器示例,标题为 fourFn.py .

bnf = """
statement-list -> statement ',' statement-list

statement -> ident 'was' 'a' type |
ident 'became' expr |
'print' expr |
'if' conditional-expr statement

type -> 'number' | 'letter'

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

factor -> number | letter | ident
"""

from pyparsing import (CaselessKeyword, Word, nums, alphas, alphanums, operatorPrecedence,
Forward, MatchFirst, opAssoc, oneOf, Group, delimitedList)

PRINT, WAS, A, BECAME, NUMBER, LETTER, IF, ELSE, TRUE, FALSE, AND, OR, NOT = map(
CaselessKeyword,
"print was a became number letter if else true false and or not".upper().split())
keyword = MatchFirst([PRINT, WAS, A, BECAME, NUMBER, LETTER, IF, ELSE, TRUE, FALSE, AND, OR, NOT])

typeSpecifier = NUMBER | LETTER

number = Word(nums)
ident = ~keyword + Word(alphas, alphanums+'_')
operand = number | ident

expr = operatorPrecedence(operand,
[
('-', 1, opAssoc.RIGHT),
(oneOf('* /'), 2, opAssoc.LEFT),
(oneOf('+ -'), 2, opAssoc.LEFT),
])

comparisonExpr = operatorPrecedence(expr,
[
("!", 1, opAssoc.RIGHT),
(oneOf("< > = <= >= !="), 2, opAssoc.LEFT),
])

booleanExpr = operatorPrecedence(TRUE | FALSE | comparisonExpr,
[
(NOT, 1, opAssoc.RIGHT),
(AND, 2, opAssoc.LEFT),
(OR, 2, opAssoc.LEFT),
])

statement = Forward()
printStmt = PRINT + expr
wasaStmt = ident + WAS + A + typeSpecifier
becameStmt = ident + BECAME + expr
ifStmt = IF + booleanExpr + statement
statement << Group(printStmt | wasaStmt | becameStmt | ifStmt)

statementList = delimitedList(statement)

tests = """\
x was a number
y became 2+5
print y
print 100*(5+2)
print 100*5+2
if 5 > y print 1000
if y < 10 y became y+1, print y
""".splitlines()[:-1]

for t in tests:
print t.strip()
for s in statementList.parseString(t).asList():
print(s)
print

打印:

x was a number
['x', 'WAS', 'A', 'NUMBER']

y became 2+5
['y', 'BECAME', ['2', '+', '5']]

print y
['PRINT', 'y']

print 100*(5+2)
['PRINT', ['100', '*', ['5', '+', '2']]]

print 100*5+2
['PRINT', [['100', '*', '5'], '+', '2']]

if 5 > y print 1000
['IF', ['5', '>', 'y'], ['PRINT', '1000']]

if y < 10 y became y+1, print y
['IF', ['y', '<', '10'], ['y', 'BECAME', ['y', '+', '1']]
['PRINT', 'y']

我冒昧地将 print 添加为一种语句,这样它就可以出现在程序主体的任何位置。另外,我尝试添加一个 IF-THEN 语句,这个确实展示了添加这样一个控制流语句如何开始带你走上编写递归语法的道路(不需要递归只是为了"is"、“成为”和“打印”)。

关于Python PLY 解析器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7908898/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com