///| IEC 61131-3 结构化文本 (ST) 语法分析器 (Parser)
///|
/// Parser 状态
pub(all) struct Parser {
tokens : Array[Token]
len : Int
mut pos : Int
} derive(Debug)
///|
/// 创建 Parser
pub fn Parser::new(tokens : Array[Token]) -> Parser {
{ tokens, len: tokens.length(), pos: 0, }
}
///|
/// 从源代码直接创建 Parser
pub fn Parser::from_source(src : String) -> Parser {
let lexer = Lexer::new(src)
Parser::new(lexer.tokenize())
}
///|
/// 查看当前 Token
fn Parser::peek(self : Parser) -> Token {
if self.pos < self.len {
self.tokens[self.pos]
} else {
Token::EOF
}
}
///|
/// 查看下一个 Token
pub fn Parser::peek_next(self : Parser) -> Token {
if self.pos + 1 < self.len {
self.tokens[self.pos + 1]
} else {
Token::EOF
}
}
///|
/// 消耗当前 Token
fn Parser::advance(self : Parser) -> Token {
let tok = self.peek()
self.pos = self.pos + 1
tok
}
///|
/// 检查当前 Token 是否匹配预期
fn Parser::check(self : Parser, tok : Token) -> Bool {
self.peek() == tok
}
///|
/// 消耗指定类型的 Token,否则返回 false
fn Parser::match_token(self : Parser, tok : Token) -> Bool {
if self.check(tok) {
let _ = self.advance()
true
} else {
false
}
}
// ------------------- 表达式解析 -------------------
///|
/// 解析原子表达式
fn Parser::parse_primary(self : Parser) -> Expr {
match self.peek() {
Token::BoolLit(b) => {
let _ = self.advance()
Expr::Literal(PlcValue::Bool(b))
}
Token::IntLit(i) => {
let _ = self.advance()
Expr::Literal(PlcValue::Int(i))
}
Token::RealLit(r) => {
let _ = self.advance()
Expr::Literal(PlcValue::Real(r))
}
Token::TimeLit(t) => {
let _ = self.advance()
Expr::Literal(PlcValue::Time(t))
}
Token::StringLit(s) => {
let _ = self.advance()
Expr::Literal(PlcValue::String(s))
}
Token::DirectAddr(addr) => {
let _ = self.advance()
Expr::DirectAddress(addr)
}
Token::Ident(name) => {
let _ = self.advance()
// 检查是否是结构体/功能块属性访问 name.field
if self.check(Token::Dot) {
let _ = self.advance()
match self.peek() {
Token::Ident(field) => {
let _ = self.advance()
Expr::FieldAccess(name, field)
}
_ => Expr::Variable(name)
}
} else {
Expr::Variable(name)
}
}
Token::LParen => {
let _ = self.advance()
let expr = self.parse_expr()
let _ = self.match_token(Token::RParen)
expr
}
_ => {
let _ = self.advance()
Expr::Literal(PlcValue::Null)
}
}
}
///|
/// 解析一元表达式 (NOT, -)
fn Parser::parse_unary(self : Parser) -> Expr {
if self.match_token(Token::KwNot) {
let expr = self.parse_unary()
return Expr::Unary(UnaryOp::Not, expr)
}
if self.match_token(Token::Minus) {
let expr = self.parse_unary()
return Expr::Unary(UnaryOp::Neg, expr)
}
self.parse_primary()
}
///|
/// 解析乘除模 (*, /, MOD)
fn Parser::parse_multiplicative(self : Parser) -> Expr {
let mut left = self.parse_unary()
while true {
if self.match_token(Token::Star) {
let right = self.parse_unary()
left = Expr::Binary(left, BinaryOp::Mul, right)
} else if self.match_token(Token::Slash) {
let right = self.parse_unary()
left = Expr::Binary(left, BinaryOp::Div, right)
} else if self.match_token(Token::KwMod) {
let right = self.parse_unary()
left = Expr::Binary(left, BinaryOp::Mod, right)
} else {
break
}
}
left
}
///|
/// 解析加减 (+, -)
fn Parser::parse_additive(self : Parser) -> Expr {
let mut left = self.parse_multiplicative()
while true {
if self.match_token(Token::Plus) {
let right = self.parse_multiplicative()
left = Expr::Binary(left, BinaryOp::Add, right)
} else if self.match_token(Token::Minus) {
let right = self.parse_multiplicative()
left = Expr::Binary(left, BinaryOp::Sub, right)
} else {
break
}
}
left
}
///|
/// 解析比较运算 (=, <>, <, <=, >, >=)
fn Parser::parse_comparison(self : Parser) -> Expr {
let mut left = self.parse_additive()
while true {
if self.match_token(Token::Equal) {
let right = self.parse_additive()
left = Expr::Binary(left, BinaryOp::Eq, right)
} else if self.match_token(Token::NotEqual) {
let right = self.parse_additive()
left = Expr::Binary(left, BinaryOp::Neq, right)
} else if self.match_token(Token::LessThan) {
let right = self.parse_additive()
left = Expr::Binary(left, BinaryOp::Lt, right)
} else if self.match_token(Token::LessThanEqual) {
let right = self.parse_additive()
left = Expr::Binary(left, BinaryOp::Lte, right)
} else if self.match_token(Token::GreaterThan) {
let right = self.parse_additive()
left = Expr::Binary(left, BinaryOp::Gt, right)
} else if self.match_token(Token::GreaterThanEqual) {
let right = self.parse_additive()
left = Expr::Binary(left, BinaryOp::Gte, right)
} else {
break
}
}
left
}
///|
/// 解析逻辑与 (AND)
fn Parser::parse_logical_and(self : Parser) -> Expr {
let mut left = self.parse_comparison()
while self.match_token(Token::KwAnd) {
let right = self.parse_comparison()
left = Expr::Binary(left, BinaryOp::And, right)
}
left
}
///|
/// 解析逻辑或/异或 (OR, XOR)
fn Parser::parse_logical_or(self : Parser) -> Expr {
let mut left = self.parse_logical_and()
while true {
if self.match_token(Token::KwOr) {
let right = self.parse_logical_and()
left = Expr::Binary(left, BinaryOp::Or, right)
} else if self.match_token(Token::KwXor) {
let right = self.parse_logical_and()
left = Expr::Binary(left, BinaryOp::Xor, right)
} else {
break
}
}
left
}
///|
/// 表达式解析入口
pub fn Parser::parse_expr(self : Parser) -> Expr {
self.parse_logical_or()
}
// ------------------- 语句解析 -------------------
///|
/// 解析单个语句
pub fn Parser::parse_statement(self : Parser) -> Stmt {
// IF 语句
if self.match_token(Token::KwIf) {
let cond = self.parse_expr()
let _ = self.match_token(Token::KwThen)
let then_stmts = self.parse_statement_list()
let elsifs = []
while self.match_token(Token::KwElsif) {
let elsif_cond = self.parse_expr()
let _ = self.match_token(Token::KwThen)
let elsif_stmts = self.parse_statement_list()
elsifs.push((elsif_cond, elsif_stmts))
}
let else_stmts = if self.match_token(Token::KwElse) {
self.parse_statement_list()
} else {
[]
}
let _ = self.match_token(Token::KwEndIf)
let _ = self.match_token(Token::Semicolon)
return Stmt::If(cond, then_stmts, elsifs, else_stmts)
}
// WHILE 语句
if self.match_token(Token::KwWhile) {
let cond = self.parse_expr()
let _ = self.match_token(Token::KwDo)
let body = self.parse_statement_list()
let _ = self.match_token(Token::KwEndWhile)
let _ = self.match_token(Token::Semicolon)
return Stmt::While(cond, body)
}
// FOR 语句
if self.match_token(Token::KwFor) {
let var_name = match self.peek() {
Token::Ident(name) => {
let _ = self.advance()
name
}
_ => "i"
}
let _ = self.match_token(Token::Assign)
let start_expr = self.parse_expr()
let _ = self.match_token(Token::KwTo)
let end_expr = self.parse_expr()
let step_expr = if self.match_token(Token::KwBy) {
Some(self.parse_expr())
} else {
None
}
let _ = self.match_token(Token::KwDo)
let body = self.parse_statement_list()
let _ = self.match_token(Token::KwEndFor)
let _ = self.match_token(Token::Semicolon)
return Stmt::For(var_name, start_expr, end_expr, step_expr, body)
}
// 直接物理地址赋值 %QX0.0 := expr;
match self.peek() {
Token::DirectAddr(addr) => {
let _ = self.advance()
if self.match_token(Token::Assign) {
let expr = self.parse_expr()
let _ = self.match_token(Token::Semicolon)
return Stmt::AssignAddress(addr, expr)
}
return Stmt::Empty
}
_ => ()
}
// 标识符开头:可能是变量赋值、结构体字段赋值或功能块调用
match self.peek() {
Token::Ident(name) => {
let _ = self.advance()
// 1. 结构体/功能块字段赋值 name.field := expr;
if self.match_token(Token::Dot) {
match self.peek() {
Token::Ident(field) => {
let _ = self.advance()
if self.match_token(Token::Assign) {
let expr = self.parse_expr()
let _ = self.match_token(Token::Semicolon)
return Stmt::AssignField(name, field, expr)
}
}
_ => ()
}
}
// 2. 普通变量赋值 name := expr;
if self.match_token(Token::Assign) {
let expr = self.parse_expr()
let _ = self.match_token(Token::Semicolon)
return Stmt::Assign(name, expr)
}
// 3. 功能块调用 name(IN := expr, PT := expr);
if self.match_token(Token::LParen) {
let args = []
while !self.check(Token::RParen) && !self.check(Token::EOF) {
match self.peek() {
Token::Ident(arg_name) => {
let _ = self.advance()
if self.match_token(Token::Assign) {
let arg_val = self.parse_expr()
args.push((arg_name, arg_val))
}
}
_ => {
let _ = self.advance()
()
}
}
let _ = self.match_token(Token::Comma)
}
let _ = self.match_token(Token::RParen)
let _ = self.match_token(Token::Semicolon)
return Stmt::FbCall(name, "", args)
}
let _ = self.match_token(Token::Semicolon)
return Stmt::Empty
}
_ => ()
}
// 跳过其他无用标记或空语句
if self.match_token(Token::Semicolon) {
return Stmt::Empty
}
let _ = self.advance()
Stmt::Empty
}
///|
/// 解析语句列表 (直到遇到 END_*, ELSE, ELSIF, EOF)
pub fn Parser::parse_statement_list(self : Parser) -> Array[Stmt] {
let stmts = []
while true {
let tok = self.peek()
if tok == Token::EOF ||
tok == Token::KwEndIf ||
tok == Token::KwElse ||
tok == Token::KwElsif ||
tok == Token::KwEndWhile ||
tok == Token::KwEndFor ||
tok == Token::KwEndProgram {
break
}
let s = self.parse_statement()
match s {
Stmt::Empty => ()
_ => stmts.push(s)
}
}
stmts
}
// ------------------- 变量声明段与完整 POU -------------------
///|
/// 解析 VAR ... END_VAR 块
pub fn Parser::parse_var_block(self : Parser) -> Array[VarDecl] {
let decls = []
let _ = self.advance() // 吃掉 VAR / VAR_INPUT / VAR_OUTPUT
while !self.check(Token::KwEndVar) && !self.check(Token::EOF) {
let name = match self.peek() {
Token::Ident(n) => {
let _ = self.advance()
n
}
_ => {
let _ = self.advance()
continue
}
}
// 可选:AT %IX0.0
let located_at = if self.match_token(Token::KwAt) {
match self.peek() {
Token::DirectAddr(addr) => {
let _ = self.advance()
Some(addr)
}
_ => None
}
} else {
None
}
// 冒号与类型
let _ = self.match_token(Token::Colon)
let var_type = match self.peek() {
Token::Ident(t) => {
let _ = self.advance()
t
}
_ => "BOOL"
}
// 可选:初始值 := ...
let init_val = if self.match_token(Token::Assign) {
match self.peek() {
Token::BoolLit(b) => {
let _ = self.advance()
Some(PlcValue::Bool(b))
}
Token::IntLit(i) => {
let _ = self.advance()
Some(PlcValue::Int(i))
}
Token::RealLit(r) => {
let _ = self.advance()
Some(PlcValue::Real(r))
}
Token::TimeLit(t) => {
let _ = self.advance()
Some(PlcValue::Time(t))
}
Token::StringLit(s) => {
let _ = self.advance()
Some(PlcValue::String(s))
}
_ => {
let _ = self.advance()
None
}
}
} else {
None
}
let _ = self.match_token(Token::Semicolon)
decls.push({ name, var_type, init_val, located_at, })
}
let _ = self.match_token(Token::KwEndVar)
decls
}
///|
/// 解析完整 PROGRAM 程序
pub fn Parser::parse_program(self : Parser) -> Program {
let mut prog_name = "Main"
if self.match_token(Token::KwProgram) {
match self.peek() {
Token::Ident(n) => {
let _ = self.advance()
prog_name = n
}
_ => ()
}
}
let variables = []
while self.check(Token::KwVar) ||
self.check(Token::KwVarInput) ||
self.check(Token::KwVarOutput) {
let block = self.parse_var_block()
for v in block {
variables.push(v)
}
}
let statements = self.parse_statement_list()
let _ = self.match_token(Token::KwEndProgram)
{ name: prog_name, variables, statements, }
}