词法分析:测试
约 309 字大约 1 分钟
2025-12-21
测试
我们之前的测试,都是通过 REPL 实现的。但是,随着功能越来越多,我们需要一个更系统的测试方法。
- 对于新的功能,我们需要编写测试代码来验证它的正确性。
- 我们也希望添加的新代码不会影响已经存在的功能。
行号和列号
为了后续的错误定位,我们在词法分析器中添加了行号和列号。在 L5-L6 中,我们添加了 line 和 column 两个属性。随之,初始化的参数也需要更新。
class Token:
def __init__(
self, token_type: TokenType, literal: str, line: int, column: int
) -> None:
self.type: TokenType = token_type
self.literal: str = literal
self.line: int = line
self.column: int = column比较两个 token 是否相等
def __eq__(self, other: object) -> bool:
if not isinstance(other, Token):
return False
return (
self.type == other.type
and self.literal == other.literal
and self.line == other.line
and self.column == other.column通常情况下,两个 token 相等,当且仅当它们以下所有条件都相等:
- 类型
- 字面量
- 行号
- 列号
测试用例
测试的逻辑很简单,让 Lexer 解析一个字符串,然后检查解析出的 token 是否与预期的 token 相等。
def test_lexer(src_code: str, expected_tokens: List[Token]) -> None:
lexer = Lexer(src_code)
for expected in expected_tokens:
actual = lexer.next_token()
assert expected == actual, f"expected={expected}, got={actual}"在函数 test_lexer 中,我们测试了 12 + 34\n56+78 这个表达式。我们期望解析出 5 个 token:12、+、34、\n、56、+、78,以及其中的 WHITESPACE 和最后的 EOF.
(
"12 + 34\n56+78",
[
Token(TokenType.INT, "12", 1, 1),
Token(TokenType.WHITESPACE, " ", 1, 3),
Token(TokenType.PLUS, "+", 1, 4),
Token(TokenType.WHITESPACE, " ", 1, 5),
Token(TokenType.INT, "34", 1, 6),
Token(TokenType.NEWLINE, "\n", 1, 8),
Token(TokenType.INT, "56", 2, 1),
Token(TokenType.PLUS, "+", 2, 3),
Token(TokenType.INT, "78", 2, 4),
Token(TokenType.EOF, "", 2, 6),
],
),