欢迎访问宙启技术站
智能推送

Python中的词法分析:lex()函数与语法分析器的协作应用

发布时间:2023-12-25 18:40:05

词法分析是编译器中的一个重要步骤,它的作用是将源代码拆分成一个个的“单词”,也称为“词法单元”或“记号”,然后将这些单词传递给语法分析器进行进一步处理。词法分析器通常使用正则表达式来定义每个记号的模式,然后从源代码中匹配这些模式。

在Python中,我们可以使用ply库(Python Lex-Yacc)来进行词法分析和语法分析。ply库提供了lex()和yacc()函数来实现词法分析器和语法分析器的协作。

首先,我们需要定义记号的模式。假设我们要解析一个简单的算术表达式,包括加法、减法、乘法、除法和数字。我们可以定义如下的模式:

# 定义记号的模式
tokens = (
   'NUMBER',
   'PLUS',
   'MINUS',
   'TIMES',
   'DIVIDE',
)

# 定义记号的具体规则
t_PLUS = r'\+'
t_MINUS = r'-'
t_TIMES = r'\*'
t_DIVIDE = r'/'

# 数字的规则,可以是整数或小数
def t_NUMBER(t):
    r'\d+(\.\d+)?'
    t.value = float(t.value) if '.' in t.value else int(t.value)
    return t

# 忽略空格和换行符
t_ignore = ' 
'

接下来,我们可以使用ply库中的lex()函数创建词法分析器:

from ply import lex

# 创建词法分析器
lexer = lex.lex()

创建词法分析器之后,我们可以使用lexer.input()方法将源代码传递给词法分析器,然后使用lexer.token()方法获取下一个记号:

# 将源代码传递给词法分析器
lexer.input('3 + 4 * 2')

# 获取下一个记号
token = lexer.token()
print(token)

输出结果为:

LexToken(NUMBER, 3, 1, 0)

这个记号表示数字3,在第1行第0列。

当我们想要获取所有的记号时,可以使用一个循环:

# 将源代码传递给词法分析器
lexer.input('3 + 4 * 2')

# 获取所有的记号
while True:
    token = lexer.token()
    if not token:
        break
    print(token)

输出结果为:

LexToken(NUMBER, 3, 1, 0)
LexToken(PLUS, '+', 1, 2)
LexToken(NUMBER, 4, 1, 4)
LexToken(TIMES, '*', 1, 6)
LexToken(NUMBER, 2, 1, 8)

这些记号分别表示数字3、加号、数字4、乘号和数字2。

注意:词法分析器使用的记号类型是一个特殊的类LexToken,它有四个属性:type(记号的类型)、value(记号的值)、lineno(记号在源代码中的行号)和lexpos(记号在源代码中的位置)。