阶段3-3:新类型语法验证 + 修复(parse_primary 补字面量分支、负号折叠、NEG 指令)

- Parser:parse_primary 补 FLOAT_LIT/DATE_LIT/TOD_LIT/DT_LIT
  (表达式路径,此前仅初值路径支持)
- Typecheck:literal_range_ok 支持 Neg(LitInt/LitReal) 折叠负号
  (UINT := -1 → 'negative literal for unsigned type')
- Codegen:Neg → NEG 指令(RR 4B,func 按操作数类型)

验证通过:
- 19 类型声明 + 字面量:DINT/REAL(1.5)/LREAL(2.5e3)/BYTE(16#FF)/UINT(8#17)/
  WORD(2#1010)/DATE(D#2026-8-24)/TOD(TOD#12:30:00)/DT(DT#...)/BOOL/TIME(T#1s250ms)
- 负例:UINT:= -1 越域、INT:= DINT 禁隐式、BOOL:= 2 越界、
  DINT:= 16#FFFFFFFF 溢出、D#2026-13-40 日期非法
- ctest 12/14(vm/cases 待阶段 4)
This commit is contained in:
2026-08-26 09:35:39 +08:00
parent 316b252afc
commit 2c5852797a
3 changed files with 42 additions and 0 deletions
+9
View File
@@ -590,6 +590,15 @@ namespace {
E_rr(f, "NOT", rd, t);
return true;
}
if (e.kind == ExprKind::Neg) {
const uint8_t t = alloc_temp(f);
if (!compile_expr(f, *e.operand, t)) {
return false;
}
const size_t s = E_rr(f, "NEG", rd, t);
set_func(f.code.data() + s, expr_func(f, *e.operand, *e.operand));
return true;
}
if (e.kind == ExprKind::And || e.kind == ExprKind::Or) {
if (!compile_expr(f, *e.lhs, rd)) {
return false;
+20
View File
@@ -919,6 +919,26 @@ namespace {
e->int_value = cur().int_value;
advance();
return true;
case Tok::FLOAT_LIT:
e->kind = ExprKind::LitReal;
e->double_value = cur().double_value;
advance();
return true;
case Tok::DATE_LIT:
e->kind = ExprKind::LitDate;
e->int_value = cur().int_value;
advance();
return true;
case Tok::TOD_LIT:
e->kind = ExprKind::LitTod;
e->int_value = cur().int_value;
advance();
return true;
case Tok::DT_LIT:
e->kind = ExprKind::LitDt;
e->int_value = cur().int_value;
advance();
return true;
case Tok::TRUE:
e->kind = ExprKind::LitBool;
e->int_value = 1;
+13
View File
@@ -243,6 +243,19 @@ namespace {
* @return true 值域内;falseerr 已写)
*/
bool literal_range_ok(const std::string& file, const Expr& e, TType want) {
// 一元负 + 字面量:折叠负号后按负值检查(-1 赋无符号 → 越域)
if (e.kind == ExprKind::Neg && e.operand != nullptr &&
(e.operand->kind == ExprKind::LitInt ||
e.operand->kind == ExprKind::LitReal)) {
Expr folded;
folded.kind = e.operand->kind;
if (e.operand->kind == ExprKind::LitInt) {
folded.int_value = -e.operand->int_value;
} else {
folded.double_value = -e.operand->double_value;
}
return literal_range_ok(file, folded, want);
}
if (e.kind == ExprKind::LitInt) {
if (want == TType::Real || want == TType::Lreal) {
return true; // 整数字面量 → 浮点目标合法