识别lex中的关键字对

时间:2014-10-27 20:15:58

标签: python parsing yacc lex ply

我试图为使用关键字对(以空格分隔)的文件类型编写解析器,并且正在努力使用正确的方法来执行此操作。令牌的一些示例可能是:

angle spring
angle dampen
angle collision

还有结束该块的块定义和标记,例如:

dynamics
    angle spring 1.0
    angle dampen 0.0
    angle collision 0.0
    some 1 2 3
    more ['stuff' 'here']
    tokens "values can be strings, paths, etc"
end dynamics

换行符似乎很重要,我一直在使用它来确定我是在查看关键字还是仅查看常规旧字符串(关键字应该是每行上的第一个标记)。我是以正确的方式接近这个吗?在yacc阶段,我是否应该只是标记化所有内容并更严格地定义对?

谢谢你的时间!

1 个答案:

答案 0 :(得分:3)

问题在于您尝试将逻辑上的单个标记视为多个标记。如果关键字包含空格,则表示空格是关键字标记的一部分。

如果您定义关键字标记,包括您在解析器中无需处理它们的空格。这意味着您应该将关键字匹配与普通标识符匹配进行划分。

例如:

from ply.lex import TOKEN

KEYWORDS = [
    r'some', r'keyword',
    r'keyword with token',
    r'other keyword',
]

keyword = '|'.join(keyword.replace(' ', '\s+') for keyword in KEYWORDS)

@TOKEN(keyword)
def t_KEYWORD(t):
    # remove spaces
    value = ''.join(x for x in t.value if not x.isspace())
    return value.upper()

注意@TOKEN(keyword)行:您可以使用TOKEN装饰器动态设置函数的docstring。这允许复杂的正则表达式用于定义令牌,即使定义它们"需要"使用表达式而不是简单的字符串文字。


另一种方法是将空格分隔的关键字视为多个关键字。因此,您保留标识符和关键字的通常定义,并修改语法以使用多个关键字而不是一个。

例如,您的语法规则如下:

def p_dynamics(p):
    'DYNAMICS BLOCK END DYNAMICS'

而不是:

def p_dynamics(p):
    'DYNAMICS BLOCK END_DYNAMICS'

根据具体情况,您可以更轻松地实施一个解决方案。