You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Python词法分析:按行输出分类Token的问题求助

解决词法分析的分类与顺序输出问题

看起来你在实现一个简单的词法分析器时遇到了顺序混乱、重复输出、跨行打印的问题,核心原因是你的代码没有保留原文本的token顺序,而是把所有同类别元素集中收集,同时打印逻辑没有针对单行处理。下面是完整的解决方案:

核心思路

要实现按原文本顺序输出每个token及其类别,我们需要:

  1. 逐行读取文本,只处理当前行的内容
  2. 按文本顺序逐个识别每个token(包括分隔符),同时记录其类别
  3. 对每个token仅处理一次,避免重复输出

完整代码实现

import re

# 定义token分类函数:根据token内容判断所属词法类
def classify_token(token):
    # 标识符:字母开头,后续可跟字母/数字
    if re.fullmatch(r'[a-zA-Z][a-zA-Z0-9]*', token):
        return 'identifiers'
    # 常量:整数、浮点数,支持科学计数法(可选)
    elif re.fullmatch(r'[-+]?\d+\.?\d*|\.\d+([eE][-+]?\d+)?', token):
        return 'constants'
    # 操作符:匹配你定义的=、+、/
    elif token in ('=', '+', '/'):
        return 'operators'
    # 分隔符:空白字符(空格、换行等)
    elif re.fullmatch(r'\s+', token):
        return 'separators'
    # 未知类型(可选处理)
    else:
        return 'unknown'

# 读取目标文本文件
with open('your_file.txt', 'r') as file:
    lines = file.readlines()

# 逐行处理并按要求格式输出
for line_idx, line in enumerate(lines, start=1):
    print(f'Line {line_idx}:')
    # 用正则匹配当前行的所有token(按原顺序)
    token_matches = re.finditer(
        r'([a-zA-Z][a-zA-Z0-9]*|[-+]?\d+\.?\d*|\.\d+([eE][-+]?\d+)?|=|\+|/|\s+)',
        line
    )
    output_segments = []
    for match in token_matches:
        token = match.group(0)
        # 可选:跳过换行符(如果不需要输出换行符的话)
        if token == '\n':
            continue
        category = classify_token(token)
        # 按要求格式生成每个token的输出片段
        output_segments.append(f"('{token}', {category})")
    # 拼接所有片段并打印
    print(' '.join(output_segments))
    print()

代码说明

  1. 分类函数classify_token:清晰定义了每个词法类的判断规则,你可以根据需求轻松扩展(比如添加更多操作符或关键字)
  2. 逐行处理:通过readlines()读取所有行,再用enumerate跟踪行号,确保只处理当前行的内容
  3. 顺序匹配token:使用re.finditer按文本顺序匹配所有token,完全保留原文本的元素顺序
  4. 避免重复输出:每个token仅被匹配和处理一次,不会出现重复添加的问题

针对你原代码问题的分析

  1. 顺序混乱:你之前把所有identifiers、operators等分别收集到独立列表,再合并,完全打乱了原文本的顺序,导致输出时先所有标识符,再操作符,不符合要求
  2. 重复输出:使用extend添加元素时,若正则匹配逻辑有问题(比如重复匹配同一元素),会导致列表中出现重复项
  3. 跨行打印:你的打印逻辑遍历了所有行的tokens,所以每一行都会输出整个文件的所有元素,而不是当前行的内容
  4. 正则错误:原常量正则中包含多余空格(比如[+-]? *(?:\d+),导致无法正确识别常量

测试输出

用你提供的文本内容测试,输出会完全符合你的要求:

Line 1:
('a273', identifiers) (' ', separators) ('=', operators) (' ', separators) ('4', constants) (' ', separators) ('+', operators) (' ', separators) ('1337', constants)

Line 2:
('variable', identifiers) (' ', separators) ('=', operators) (' ', separators) ('50.123132123', constants) (' ', separators) ('+', operators) (' ', separators) ('3.123123132', constants) (' ', separators) ('/', operators) (' ', separators) ('23.121212', constants)

内容的提问来源于stack exchange,提问作者Marko Markusevic

火山引擎 最新活动