- isa:CAL_* 操作码连续占 24..31(CALL/RET 后移为 32/33,kOpCount=34);disasm 支持 5 个新操作码 - 词法/语法/链接:新 8 个关键字与冻结布局(TP=in/pt/q/et、CTD=cd/ld/pv/q/cv、 CTUD=cu/cd/r/lu/pv/qu/qd/cv、R_TRIG/F_TRIG=clk/q) - VM:do_cal 全 8 个语义(TP 脉冲、CTD 递减、CTUD 双向+装载、R_TRIG 上升沿、F_TRIG 下降沿); edge_prev_ 每槽 2 字节存边沿上次输入;exec_one 分发补 5 个新操作码 - 验证:TP 30ms 脉冲 2 周期、CTD 装载+递减到 q=1、CTUD cu/cd 双向、R/F_TRIG 交替; ctest 11/11 全绿 - 文档:指令与映像/词法/初步计划/符号表与链接/指令执行/扫描周期/使用说明 同步
4.7 KiB
4.7 KiB
词法(12.4)
compiler 模块的词法分析。输入:单个 .st 源文件内容;输出:稳定 token 流(带 source_file + 行列)。语法与字段表见 初步计划.md 12.1、12.4。
做 / 不做
做
(* *)注释、标识符、关键字、整数、TIME字面量、:=、比较符、括号- 关键字与标识符统一折成小写内部形(与 IEC 一致,大小写不敏感)
- 每个 token 带
source_file+ 行列,供以后报错 - 非法字符 →
lex error硬错误(带行列)
不做(第一版)
- 字符串字面量、
REAL字面量、十六进制/科学计数 - 注释嵌套(
(*到第一个*)结束,未闭合报错) - 浮点数、
_数字分隔符
关键字表(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 TP CTU CTD CTUD R_TRIG F_TRIG
12.5 修订:
THEN、DO补入关键字表(IF ... THEN/WHILE ... DO语法需要), 与 12.1 原表合并,其余不变。 12.11 修订:内置 FB 扩为 8 个(TON/TOF/TP/CTU/CTD/CTUD/R_TRIG/F_TRIG)。
其余单词一律当标识符;VAR_IN_OUT、REF、CLASS 等由语法层(12.5)出明确错误。
Token
enum class Tok {
// 关键字(25 个,逐一对应上表)
...
// 字面量
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 起
};
规则
大小写
- 关键字匹配大小写不敏感(
program/PROGRAM/Program同义) - 标识符统一折小写存入
text(内部形);原始大小写不保留(v1 无字符串字面量,报错靠行列定位)
字面量
- 整数:
[0-9]+,int64_t存储;超INT64_MAX→lex error TIME:T#(不敏感)+ 一个或多个<整数><单位>段,单位不敏感:ms s m h d,累加为毫秒:T#10ms→ 10T#1s250ms→ 1250T#2h→ 7200000- 缺单位 / 未知单位 / 空段 →
lex error
- 负数不是字面量:
-5是MINUS+ 整数,由语法层处理
符号
:=优先于:;<>优先于</>;<=/>=单独匹配
注释
(* ... *),不嵌套;未闭合 →lex error- 注释内不产 token
错误
稳定前缀 lex error,带文件与行列:
lex error: illegal character '@' (motor.st, line 3, col 7)
lex error: unterminated comment (main.st, line 1, col 1)
lex error: bad time literal 'T#3q' (main.st, line 4, col 10)
完成标准
- 第 11 节三个文件(
examples/line1/*.st)lex 成稳定 token 流;lexer_test断言数量、类型、小写化、行列、END收尾 - 非法字符 / 未闭合注释 / 坏 TIME 字面量 →
lex error负例过 - 全部构建 +
ctest无回归
执行计划(单步确认)
-
Lexer.h(新建compiler/include/compiler/Lexer.h)Tok枚举:25 关键字 +IDENT/INT_LIT/TIME_LIT+ 符号(:= = <> < <= > >= + - * / ( ) , ; : .)+ENDToken { type, text, int_value, source_file, line, col }(行列从 1 起)bool lex_file(path, out, err)/bool lex(source_file, content, out, err)
-
Lexer.cpp(重写占位)- 25 关键字小写映射表,大小写不敏感,标识符统一折小写
(* *)注释不嵌套、未闭合报错;非法字符报错- 整数
[0-9]+(超INT64_MAX报错);T#<int><单位>段式解析累加毫秒(ms s m h d) :=/<>/<=/>=最长匹配优先- 错误前缀
lex error,带 file/line/col
-
lexer_test(tests/src/lexer_test.cpp+ CMake,链compiler库)- line1 三文件:token 数量 / 类型序列 / 小写化 / 行列 /
END收尾断言 - 负例:
@非法字符、未闭合注释、T#3q坏字面量、超大整数 →lex error类别
- line1 三文件:token 数量 / 类型序列 / 小写化 / 行列 /
-
验证:
cmake --build+ctest(新增lexer_test后 5/5 全绿) -
提交:
Lexer.h/cpp+lexer_test+ 文档