阶段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:
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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; // 整数字面量 → 浮点目标合法
|
||||
|
||||
Reference in New Issue
Block a user