实现 12.4 词法:25 关键字、小写折叠、TIME 字面量、lex error。

- Lexer.h/cpp:关键字表(大小写不敏感折小写)、(* *) 注释不嵌套、整数/T# 段式字面量、最长匹配符号
- token 带 source_file + 行列(起始位置,修了消费后行列的偏差)
- lexer_test:75 断言(line1 三文件 token 流 21/34/27、大小写、符号、注释、行列、5 类负例)
- Doc/compiler/词法.md:设计文档 + 执行计划
This commit is contained in:
2026-08-21 10:51:45 +08:00
parent 9a07f938f9
commit d4e2c1ae7c
6 changed files with 786 additions and 2 deletions
+89
View File
@@ -0,0 +1,89 @@
/**
* @file Lexer.h
* @brief ST 子集词法分析
* @author
* @date 2026-08-21
*/
#pragma once
#include <cstdint>
#include <string>
#include <vector>
namespace compiler {
// token 类型。关键字与 token 集见 Doc/compiler/词法.md。
enum class Tok {
// 关键字(25 个,与 12.1 冻结表一致)
PROGRAM,
FUNCTION,
FUNCTION_BLOCK,
END_PROGRAM,
END_FUNCTION,
END_FUNCTION_BLOCK,
VAR,
VAR_INPUT,
VAR_OUTPUT,
VAR_GLOBAL,
VAR_EXTERNAL,
END_VAR,
BOOL,
INT,
TIME,
IF,
ELSIF,
ELSE,
END_IF,
WHILE,
END_WHILE,
AND,
OR,
NOT,
TRUE,
FALSE,
TON,
TOF,
CTU,
// 字面量
IDENT, // text = 小写名
INT_LIT, // int_value
TIME_LIT, // int_value = 毫秒
// 符号
ASSIGN, // :=
EQ, // =
NE, // <>
LT, // <
LE, // <=
GT, // >
GE, // >=
PLUS, // +
MINUS, // -
STAR, // *
SLASH, // /
LPAREN, // (
RPAREN, // )
COMMA, // ,
SEMI, // ;
COLON, // :
DOT, // .
END, // 文件结束
};
struct Token {
Tok type;
std::string text; // 标识符/关键字的小写文本;字面量原文
int64_t int_value; // INT_LIT / TIME_LIT(毫秒)
std::string source_file;
uint32_t line; // 从 1 起
uint32_t col; // 从 1 起
};
// 对源文本 lex 成 token 流(含末尾 END)。失败返回 false,
// err 前缀 "lex error",带文件与行列。
bool lex(const std::string& source_file, const std::string& content,
std::vector<Token>* out, std::string* err);
// 读文件后 lex(文件不存在 / 读取失败也算 lex error
bool lex_file(const std::string& path, std::vector<Token>* out, std::string* err);
}