【问题标题】:Parse a list of expressions using pyparsing使用 pyparsing 解析表达式列表
【发布时间】:2019-09-01 08:13:27
【问题描述】:

我正在尝试使用 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())

除了打印子句之外,我确实有其他一切工作。

这是输出:

[[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(" \t"),但看起来像ZeroOrMore(),当遇到新行时只是通过它。如果我将换行符添加为stopOn,则可以正常工作
  • 您输入了Keyword,但您必须使用CaselessKeyword 来解析示例文本。另外,expr 是否包含其尾随的“;”?如果是这样,您可能需要重新考虑。你写过BNF吗?尝试“Be The Parser”并按照 BNF 手动完成您的问题陈述,然后按照 pyparsing 代码。要解决“泄漏到下一行”问题,您需要发布更多实际的解析器代码。有趣的项目,做得很好。
  • Keyword("PRINT") + Optional(delimitedList(expr, delim=';')) + Optional(';') 呢?
  • 你有一些可选的换行符作为你的解析器的一部分吗?这可能是泄漏到下一行的罪魁祸首。

标签: expression pyparsing basic


【解决方案1】:

这里发生了一件微妙的事情,使用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()

而且我认为您的泄漏问题将得到解决。

【讨论】:

  • 这个“功能”早就在我的脑海里整顿了。我将在即将发布的 3.0 版本中对其进行修复,以便不再需要这些额外的副本。
  • 太棒了。如此简单的修复... :) 非常感谢。完成后,我会将我的项目作为 OSS 放到 github 上
猜你喜欢
  • 2011-05-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多