实现 12.5 递归下降语法:AST + 拒绝清单。

- Parser.h/cpp:POU 外壳(PROGRAM/FUNCTION/FUNCTION_BLOCK)、变量段、语句(赋值/IF/WHILE/FB 调用)、表达式优先级爬升(NOT/AND/OR 短路/比较/算术/函数调用/负号)
- Unit 结构:顶层 VAR_GLOBAL 段(GVL 文件形态)+ POU 列表
- 拒绝:VAR_IN_OUT/REF/CLASS/ANY 等保留名、链式比较、FB 字段赋值、顶层非 GVL 段
- THEN/DO 补入关键字表(12.5 修订,同步 12.1 与词法文档)
- parser_test:98 断言(line1 三文件 AST、FUNCTION 调用、IF/WHILE/TON、9 类负例),ctest 6/6
This commit is contained in:
2026-08-21 11:07:34 +08:00
parent d4e2c1ae7c
commit 4ba44459e2
11 changed files with 1387 additions and 1 deletions
+2
View File
@@ -37,6 +37,8 @@ namespace compiler {
END_IF,
WHILE,
END_WHILE,
THEN, // 12.5 修订:IF/WHILE 语法需要,补入关键字表
DO, // 同上
AND,
OR,
NOT,
+133
View File
@@ -0,0 +1,133 @@
/**
* @file Parser.h
* @brief ST 子集递归下降语法分析(AST 定义 + 入口)
* @author
* @date 2026-08-21
*/
#pragma once
#include <cstdint>
#include <memory>
#include <string>
#include <vector>
namespace compiler {
// ---- 类型引用 ----
enum class TypeKind { Bool, Int, Time, FbBuiltin, FbUser };
struct TypeRef {
TypeKind kind = TypeKind::Bool;
std::string name; // FbUser 时为用户 FB 类型名(小写)
};
// ---- 变量段 ----
struct VarDecl {
std::string name;
TypeRef type;
bool has_init = false; // 可选初值(v1 仅字面量)
int64_t init_value = 0; // BOOL 0/1、INT 值、TIME 毫秒
uint32_t line = 0;
uint32_t col = 0;
};
enum class VarSection { Local, Input, Output, Global, External };
struct VarBlock {
VarSection section = VarSection::Local;
std::vector<VarDecl> vars;
};
// ---- 表达式 ----
enum class ExprKind {
LitBool, // int_value 0/1
LitInt, // int_value
LitTime, // int_value 毫秒
VarRef, // name
Field, // name.field
Not, // operand
And, Or, // lhs, rhs(短路语义保留到 12.8
Cmp, Add, Sub, Mul, Div, // lhs, rhsop
Neg, // operand(一元负号)
Call, // name + args(函数调用,有返回值)
};
enum class BinOp { Eq, Ne, Lt, Le, Gt, Ge, Add, Sub, Mul, Div };
struct Expr {
ExprKind kind = ExprKind::LitBool;
BinOp op = BinOp::Eq; // 二目运算
std::string name; // VarRef / Field 对象 / Call 函数名
std::string field; // Field 字段名
int64_t int_value = 0; // 字面量值
std::unique_ptr<Expr> lhs;
std::unique_ptr<Expr> rhs;
std::unique_ptr<Expr> operand; // Not / Neg
std::vector<std::unique_ptr<Expr>> args; // Call 实参
};
// ---- 语句 ----
enum class StmtKind { Assign, If, While, FbCall };
struct Stmt; // 前置声明(IfBranch / Stmt 相互引用)
struct FbArg {
std::string name;
std::unique_ptr<Expr> value;
};
struct IfBranch {
std::unique_ptr<Expr> cond;
std::vector<Stmt> body;
};
// 前置声明:Stmt 内部自引用
struct Stmt {
StmtKind kind = StmtKind::Assign;
// Assign
std::string target; // 左值标识符
bool target_is_field = false; // 左值 fb.field(v1 禁止赋值,语法层拒绝)
std::string field;
std::unique_ptr<Expr> value;
// If / While
std::unique_ptr<Expr> cond;
std::vector<Stmt> body;
std::vector<IfBranch> elsifs;
std::vector<Stmt> else_body;
// FbCall
std::string instance;
std::vector<FbArg> args;
};
// ---- POU ----
enum class PouKind { Program, Function, FunctionBlock };
struct POU {
PouKind kind = PouKind::Program;
std::string name;
TypeRef result_type; // FUNCTION 才有
std::vector<VarBlock> blocks;
std::vector<Stmt> body;
std::string source_file;
};
// 一个 .st 文件的解析结果:GVL 文件形态(无 POU)时只有 globals 非空
struct Unit {
std::vector<VarBlock> globals; // 顶层 VAR_GLOBAL 段(仅 GVL 文件)
std::vector<POU> pous;
};
// 解析一个 .st 文件的全部内容(顶层 VAR_GLOBAL 段或 POU)。
// 失败返回 falseerr 前缀 "syntax error",带文件与行列。
bool parse_pous(const std::string& source_file, const std::string& content,
Unit* out, std::string* err);
// 读文件后解析
bool parse_pous_file(const std::string& path, Unit* out, std::string* err);
}