将字母标记为运算符
Tokenizing a letter as an operator
我需要创建一种语言,其中包含变量,但它还需要字母 '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 不按出现顺序对标记变量进行优先级排序;相反,它按长度降序排列它们(最长的在前)。所以你的 t_NAME
模式将出现在 t_D
之前。 Ply manual 中对此进行了解释,并提供了一个具体示例来说明如何处理保留字(可能不适用于您的情况)。
如果我没理解错的话,字母d
不能是标识符,d
后跟数字也不能。我不完全清楚你是否期望 d2e
是一个合理的标识符,但为了简单起见,我假设答案是 "No",在这种情况下你可以轻松地限制 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_]*'
我需要创建一种语言,其中包含变量,但它还需要字母 '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 不按出现顺序对标记变量进行优先级排序;相反,它按长度降序排列它们(最长的在前)。所以你的 t_NAME
模式将出现在 t_D
之前。 Ply manual 中对此进行了解释,并提供了一个具体示例来说明如何处理保留字(可能不适用于您的情况)。
如果我没理解错的话,字母d
不能是标识符,d
后跟数字也不能。我不完全清楚你是否期望 d2e
是一个合理的标识符,但为了简单起见,我假设答案是 "No",在这种情况下你可以轻松地限制 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_]*'