【问题标题】:Multiline PLY parser多行 PLY 解析器
【发布时间】:2015-11-29 05:16:44
【问题描述】:

我正在使用 PLY 来解析跨越多行(或通过“;”分隔)的算术表达式。我不确定是否忽略换行符,因为我真的不需要它们。如果它们被忽略(在t_NEWLINE 中返回 None),是否有必要在制作中考虑它们?

def t_NEWLINE(self, t):
    r"""\n+|;+"""
    t.lexer.lineno += t.value.count("\n") + t.value.count(";")
    return t # or not

def p_expression(self, t):
    """ expression : ..."""

def p_expressions(self, t):
    """ expressions : expression
                    | expressions NEWLINE expression
    """
    # Do I need NEWLINE at all? How does the production figure out where expression ends without NEWLINE?

【问题讨论】:

    标签: python parsing ply


    【解决方案1】:

    这似乎是语言设计的问题,而不是实现的问题,当然,即使完全指定了设计,实现也可能并不明显。

    允许多个多行表达式的语言有几种可能的方法,我完全不清楚您有兴趣实现哪一种:

    1. Python 风格。表达式由; 或换行符终止,但括号表达式((...)[...]{...})内的换行符被忽略。

    2. ECMAscript 样式。表达式必须以; 结尾,但如果下一个标记不能扩展表达式,则会在行尾自动插入;

    3. 最大咀嚼。表达式是可以被解析为表达式的最长可能的标记流,但如有必要,; 可用于分隔表达式。

      我实际上并不知道实现此选项的通用语言。但是它(或一些变体)可以写成,例如,

      a = 3    b = 7    c = a + b
      

      这似乎应该是明确的。

    实施策略。

    1。括号隐藏换行符。

    在语言变得复杂之前,这很容易实现。对于简单的表达式,您只需要保留一个全局括号深度计数,它会随着(任何类型的)开括号而增加,并随着闭括号而减少;如果括号深度为 0,则 \n 规则返回 ;,否则吞下换行符。

    我个人觉得这种续行风格很烦人,尽管我每次回到 Python 编程时都很快习惯了。尽管如此,它总是有点你不能写:

    x = some * long * sub-expression       +
        another * long * sub-expression    +
        magical-constant
    

    这在 ECMAscript 中可以正常工作。

    2。自动分号

    事实证明,您可以在词法分析器中的 ECMAscript 中处理此问题,方法是查找一行中的第一个标记和合法标记对字典中的前一个标记。如果该标记对不在字典中,则返回一个分号标记而不是该行中的第一个标记;该标记被记住,以便下次对词法分析器的调用将返回它。构建合法标记对的字典并非易事,验证它是否正确更难,但只需要在每次更改语法时进行:)

    ECMAscript 实际上有一些规则例外,因此一些原本合法的表达式在用换行符分隔时会变为非法。这些异常可以通过从合法对的字典中删除一些标记对来实现(当它发生时)。例如,++ 后自增运算符不能用换行符与其操作数分隔,因此在下面插入分号:

    a
    ++b
    

    否则将是语法错误。 (前两个token会被解析为a++,然后b就无法解析了。)

    另一个有趣的案例是:

    a + b
    (c + d).format("x")
    

    这可以解析为函数调用:

    a + b(c + d).format("x")
    

    因此最好在b( 之间自动插入分号。

    3。最大咀嚼

    这实际上只是自动分号插入的一种变体,即使两个标记之间没有换行符,也可以插入分号。由于上述例外情况,您可能希望拥有两组不同的合法令牌对,或者将某些令牌对标记为仅在没有用换行符分隔时才有效。

    【讨论】:

    • 我对实现 Python 风格的语法很感兴趣,但每一行都是一个终止的表达式(在你的例子中没有换行)。我认为我需要明确说明 \n 令牌,否则 a = 3 b = 7 c = a + b 将是非法表达式(如果我要忽略每行末尾的 \n 令牌)。
    • @orange:要执行 python 样式的多行表达式,您需要有条件地返回换行符,正如我在第一段中描述的那样。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多