From 2c5852797ad9d2898a14c4328d243c9aac81b8fc Mon Sep 17 00:00:00 2001 From: chentianya Date: Wed, 26 Aug 2026 09:35:39 +0800 Subject: [PATCH] =?UTF-8?q?=E9=98=B6=E6=AE=B53-3=EF=BC=9A=E6=96=B0?= =?UTF-8?q?=E7=B1=BB=E5=9E=8B=E8=AF=AD=E6=B3=95=E9=AA=8C=E8=AF=81=20+=20?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D=EF=BC=88parse=5Fprimary=20=E8=A1=A5=E5=AD=97?= =?UTF-8?q?=E9=9D=A2=E9=87=8F=E5=88=86=E6=94=AF=E3=80=81=E8=B4=9F=E5=8F=B7?= =?UTF-8?q?=E6=8A=98=E5=8F=A0=E3=80=81NEG=20=E6=8C=87=E4=BB=A4=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 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) --- compiler/src/Codegen.cpp | 9 +++++++++ compiler/src/Parser.cpp | 20 ++++++++++++++++++++ compiler/src/Typecheck.cpp | 13 +++++++++++++ 3 files changed, 42 insertions(+) diff --git a/compiler/src/Codegen.cpp b/compiler/src/Codegen.cpp index 9d9c4a1..f4a824c 100644 --- a/compiler/src/Codegen.cpp +++ b/compiler/src/Codegen.cpp @@ -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; diff --git a/compiler/src/Parser.cpp b/compiler/src/Parser.cpp index cf6e684..d918be2 100644 --- a/compiler/src/Parser.cpp +++ b/compiler/src/Parser.cpp @@ -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; diff --git a/compiler/src/Typecheck.cpp b/compiler/src/Typecheck.cpp index b1839f2..50f652f 100644 --- a/compiler/src/Typecheck.cpp +++ b/compiler/src/Typecheck.cpp @@ -243,6 +243,19 @@ namespace { * @return true 值域内;false(err 已写) */ 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; // 整数字面量 → 浮点目标合法