使用 pyparsing 解析表达式列表
Parse a list of expressions using pyparsing
我正在尝试使用 pyparsing 来解析简单的基本程序:
import pyparsing as pp
pp.ParserElement.setDefaultWhitespaceChars(" \t")
EOL = pp.LineEnd().suppress()
# Identifiers is a string + optional $
identifier = pp.Combine(pp.Word(pp.alphas) + pp.Optional("$"))
# Literals (number or double quoted string)
literal = pp.pyparsing_common.number | pp.dblQuotedString
line_number = pp.pyparsing_common.integer
function = pp.Forward()
operand = function | identifier | literal
expression = pp.infixNotation(operand, [
(pp.oneOf("* / %"), 2, pp.opAssoc.LEFT),
(pp.oneOf("+ -"), 2, pp.opAssoc.LEFT),
])
assignment = identifier + "=" + expression
# Keywords
PRINT = pp.CaselessKeyword("print")
FOR = pp.CaselessKeyword("for")
TO = pp.CaselessKeyword("to")
STEP = pp.CaselessKeyword("step")
NEXT = pp.CaselessKeyword("next")
CHRS = pp.CaselessKeyword("chr$")
statement = pp.Forward()
print_stmt = PRINT + pp.ZeroOrMore(expression | ";")
for_stmt = FOR + assignment + TO + expression + pp.Optional(STEP + expression)
next_stmt = NEXT
chrs_fn = CHRS + "(" + expression + ")"
function <<= chrs_fn
statement <<= print_stmt | for_stmt | next_stmt | assignment
code_line = pp.Group(line_number + statement + EOL)
program = pp.ZeroOrMore(code_line)
test = """\
10 print 123;
20 print 234; 567;
25 next
30 print 890
"""
print(program.parseString(test).dump())
除 print 子句外,我的其他所有东西都在工作。
这是输出:
[[10, 'print', 123, ';', 20, 'print', 234, ';', 567, ';', 25, 'next', 30, 'print', 890]]
[0]:
[10, 'print', 123, ';', 20, 'print', 234, ';', 567, ';', 25, 'next', 30, 'print', 890]
根据一些建议,我修改了我的解析器,但由于某种原因,解析器会泄漏到下一行。
如何正确定义要打印的项目列表?
这里发生了一件微妙的事情,在使用 ParserElement.setDefaultWhitespaceChars
时它有更好的文档记录。这只会更新 在 调用 setDefaultWhitespaceChars
之后创建的 pyparsing 表达式的空白字符。像 dblQuotedString
这样的内置表达式和 pyparsing_common
中的表达式都是在导入时定义的,因此要跳过标准的空白字符集,其中包括 '\n'。如果您使用 expr.copy()
或简单的 expr()
创建它们的新副本,您将获得使用更新的空白字符的新表达式。
变化:
literal = pp.pyparsing_common.number | pp.dblQuotedString
line_number = pp.pyparsing_common.integer
至:
literal = pp.pyparsing_common.number() | pp.dblQuotedString()
line_number = pp.pyparsing_common.integer()
而且我认为您的泄漏问题将得到解决。
我正在尝试使用 pyparsing 来解析简单的基本程序:
import pyparsing as pp
pp.ParserElement.setDefaultWhitespaceChars(" \t")
EOL = pp.LineEnd().suppress()
# Identifiers is a string + optional $
identifier = pp.Combine(pp.Word(pp.alphas) + pp.Optional("$"))
# Literals (number or double quoted string)
literal = pp.pyparsing_common.number | pp.dblQuotedString
line_number = pp.pyparsing_common.integer
function = pp.Forward()
operand = function | identifier | literal
expression = pp.infixNotation(operand, [
(pp.oneOf("* / %"), 2, pp.opAssoc.LEFT),
(pp.oneOf("+ -"), 2, pp.opAssoc.LEFT),
])
assignment = identifier + "=" + expression
# Keywords
PRINT = pp.CaselessKeyword("print")
FOR = pp.CaselessKeyword("for")
TO = pp.CaselessKeyword("to")
STEP = pp.CaselessKeyword("step")
NEXT = pp.CaselessKeyword("next")
CHRS = pp.CaselessKeyword("chr$")
statement = pp.Forward()
print_stmt = PRINT + pp.ZeroOrMore(expression | ";")
for_stmt = FOR + assignment + TO + expression + pp.Optional(STEP + expression)
next_stmt = NEXT
chrs_fn = CHRS + "(" + expression + ")"
function <<= chrs_fn
statement <<= print_stmt | for_stmt | next_stmt | assignment
code_line = pp.Group(line_number + statement + EOL)
program = pp.ZeroOrMore(code_line)
test = """\
10 print 123;
20 print 234; 567;
25 next
30 print 890
"""
print(program.parseString(test).dump())
除 print 子句外,我的其他所有东西都在工作。
这是输出:
[[10, 'print', 123, ';', 20, 'print', 234, ';', 567, ';', 25, 'next', 30, 'print', 890]]
[0]:
[10, 'print', 123, ';', 20, 'print', 234, ';', 567, ';', 25, 'next', 30, 'print', 890]
根据一些建议,我修改了我的解析器,但由于某种原因,解析器会泄漏到下一行。
如何正确定义要打印的项目列表?
这里发生了一件微妙的事情,在使用 ParserElement.setDefaultWhitespaceChars
时它有更好的文档记录。这只会更新 在 调用 setDefaultWhitespaceChars
之后创建的 pyparsing 表达式的空白字符。像 dblQuotedString
这样的内置表达式和 pyparsing_common
中的表达式都是在导入时定义的,因此要跳过标准的空白字符集,其中包括 '\n'。如果您使用 expr.copy()
或简单的 expr()
创建它们的新副本,您将获得使用更新的空白字符的新表达式。
变化:
literal = pp.pyparsing_common.number | pp.dblQuotedString
line_number = pp.pyparsing_common.integer
至:
literal = pp.pyparsing_common.number() | pp.dblQuotedString()
line_number = pp.pyparsing_common.integer()
而且我认为您的泄漏问题将得到解决。