首页 > 解决方案 > 将字母标记为运算符

问题描述

我需要制作一种包含变量的语言,但它还需要字母“d”作为操作数,右侧有一个数字,左边可能有一个数字。我认为确保词法分析器首先检查字母会给它优先级,但这并没有发生,我不知道为什么。

from ply import lex, yacc

tokens=['INT', 'D', 'PLUS', 'MINUS', 'LPAR', 'RPAR', 'BIGGEST', 'SMALLEST', 'EQ', 'NAME']

t_PLUS     = r'\+'
t_MINUS    = r'\-'
t_LPAR     = r'\('
t_RPAR     = r'\)'
t_BIGGEST  = r'\!'
t_SMALLEST = r'\#'
t_D        = r'[dD]'
t_EQ       = r'\='
t_NAME     = r'[a-zA-Z_][a-zA-Z0-9_]*'

def t_INT(t):
    r'[0-9]\d*'
    t.value = int(t.value)
    return t


def t_newline(t):
    r'\n+'
    t.lexer.lineno += 1


t_ignore = ' \t'

def t_error(t):
    print("Not recognized by the lexer:", t.value)
    t.lexer.skip(1)

lexer = lex.lex()

while True:
    try: s = input(">> ")
    except EOFError: break
    lexer.input(s)
    while True:
        t = lexer.token()
        if not t: break
        print(t)

如果我写: 3d4 它输出:

LexToken(INT,3,1,0)
LexToken(NAME,'d4',1,1)

我不知道如何解决它。

标签: ply

解决方案


Ply 不按出现顺序优先标记变量;相反,它按长度降序排列它们(最长的在前)。所以你的t_NAME模式会出现在前面t_D。这在Ply 手册中进行了解释,以及如何处理保留字的具体示例(可能不适用于您的情况)。

如果我理解正确,字母d不能是标识符,d后面也不能是数字。我并不完全清楚您是否希望d2e成为一个合理的标识符,但为简单起见,我假设答案是“否”,在这种情况下,您可以通过要求一个首字母后跟另一个来轻松地限制t_NAME正则表达式d信:

t_NAME = '([a-ce-zA-CE-Z_]|[dD][a-zA-Z_])[a-zA-Z0-9_]*'

如果你想允许d2e成为一个名字,那么你可以选择:

t_NAME = '([a-ce-zA-CE-Z_]|[dD][0-9]*[a-zA-Z_])[a-zA-Z0-9_]*'

推荐阅读