NAC_Blockchain/cnnl-compiler/src/lexer/token.rs

301 lines
7.7 KiB
Rust

use logos::Logos;
use std::fmt;
/// CNNL词法Token定义
#[derive(Logos, Debug, Clone, PartialEq)]
#[logos(skip r"[ \t\n\f]+")] // 跳过空白字符
#[logos(skip r"//[^\n]*")] // 跳过单行注释
#[logos(skip r"/\*([^*]|\*[^/])*\*/")] // 跳过多行注释
pub enum Token {
// 关键字 - 条款结构
#[token("clause")]
Clause,
#[token("level")]
Level,
#[token("title")]
Title,
#[token("depends_on")]
DependsOn,
// 关键字 - 条款层级
#[token("eternal")]
Eternal,
#[token("strategic")]
Strategic,
#[token("tactical")]
Tactical,
// 关键字 - 参数和谓词
#[token("parameter")]
Parameter,
#[token("predicate")]
Predicate,
#[token("obligation")]
Obligation,
// 关键字 - 义务属性
#[token("frequency")]
Frequency,
#[token("enforcer")]
Enforcer,
#[token("penalty")]
Penalty,
// 关键字 - 频率值
#[token("continuous")]
Continuous,
#[token("periodic")]
Periodic,
#[token("on_demand")]
OnDemand,
// 关键字 - 控制流
#[token("if")]
If,
#[token("else")]
Else,
#[token("return")]
Return,
// 类型关键字
#[token("bool")]
Bool,
#[token("u64")]
U64,
#[token("u32")]
U32,
#[token("f64")]
F64,
#[token("string")]
String_,
// 字面量
#[regex(r"[0-9]+", |lex| lex.slice().parse::<u64>().ok())]
IntLiteral(u64),
#[regex(r"[0-9]+\.[0-9]+", |lex| lex.slice().parse::<f64>().ok())]
FloatLiteral(f64),
#[token("true", |_| true)]
#[token("false", |_| false)]
BoolLiteral(bool),
#[regex(r#""([^"\\]|\\.)*""#, |lex| {
let s = lex.slice();
Some(s[1..s.len()-1].to_string())
})]
StringLiteral(String),
// 标识符
#[regex(r"[A-Z][A-Z0-9_]+", |lex| lex.slice().to_string())]
ConstantIdent(String), // 全大写标识符(常量)
#[regex(r"[a-z_][a-z0-9_]*", |lex| lex.slice().to_string())]
Ident(String), // 小写标识符
// 运算符
#[token("+")]
Plus,
#[token("-")]
Minus,
#[token("*")]
Star,
#[token("/")]
Slash,
#[token("%")]
Percent,
#[token("==")]
Eq,
#[token("!=")]
Ne,
#[token("<")]
Lt,
#[token("<=")]
Le,
#[token(">")]
Gt,
#[token(">=")]
Ge,
#[token("&&")]
And,
#[token("||")]
Or,
#[token("!")]
Not,
// 分隔符
#[token("(")]
LParen,
#[token(")")]
RParen,
#[token("{")]
LBrace,
#[token("}")]
RBrace,
#[token("[")]
LBracket,
#[token("]")]
RBracket,
#[token(":")]
Colon,
#[token(",")]
Comma,
#[token("=")]
Assign,
#[token("->")]
Arrow,
}
impl fmt::Display for Token {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Token::Clause => write!(f, "clause"),
Token::Level => write!(f, "level"),
Token::Title => write!(f, "title"),
Token::DependsOn => write!(f, "depends_on"),
Token::Eternal => write!(f, "eternal"),
Token::Strategic => write!(f, "strategic"),
Token::Tactical => write!(f, "tactical"),
Token::Parameter => write!(f, "parameter"),
Token::Predicate => write!(f, "predicate"),
Token::Obligation => write!(f, "obligation"),
Token::Frequency => write!(f, "frequency"),
Token::Enforcer => write!(f, "enforcer"),
Token::Penalty => write!(f, "penalty"),
Token::Continuous => write!(f, "continuous"),
Token::Periodic => write!(f, "periodic"),
Token::OnDemand => write!(f, "on_demand"),
Token::If => write!(f, "if"),
Token::Else => write!(f, "else"),
Token::Return => write!(f, "return"),
Token::Bool => write!(f, "bool"),
Token::U64 => write!(f, "u64"),
Token::U32 => write!(f, "u32"),
Token::F64 => write!(f, "f64"),
Token::String_ => write!(f, "string"),
Token::IntLiteral(n) => write!(f, "{}", n),
Token::FloatLiteral(n) => write!(f, "{}", n),
Token::BoolLiteral(b) => write!(f, "{}", b),
Token::StringLiteral(s) => write!(f, "\"{}\"", s),
Token::ConstantIdent(s) => write!(f, "{}", s),
Token::Ident(s) => write!(f, "{}", s),
Token::Plus => write!(f, "+"),
Token::Minus => write!(f, "-"),
Token::Star => write!(f, "*"),
Token::Slash => write!(f, "/"),
Token::Percent => write!(f, "%"),
Token::Eq => write!(f, "=="),
Token::Ne => write!(f, "!="),
Token::Lt => write!(f, "<"),
Token::Le => write!(f, "<="),
Token::Gt => write!(f, ">"),
Token::Ge => write!(f, ">="),
Token::And => write!(f, "&&"),
Token::Or => write!(f, "||"),
Token::Not => write!(f, "!"),
Token::LParen => write!(f, "("),
Token::RParen => write!(f, ")"),
Token::LBrace => write!(f, "{{"),
Token::RBrace => write!(f, "}}"),
Token::LBracket => write!(f, "["),
Token::RBracket => write!(f, "]"),
Token::Colon => write!(f, ":"),
Token::Comma => write!(f, ","),
Token::Assign => write!(f, "="),
Token::Arrow => write!(f, "->"),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_keywords() {
let mut lex = Token::lexer("clause level eternal parameter predicate");
assert_eq!(lex.next(), Some(Ok(Token::Clause)));
assert_eq!(lex.next(), Some(Ok(Token::Level)));
assert_eq!(lex.next(), Some(Ok(Token::Eternal)));
assert_eq!(lex.next(), Some(Ok(Token::Parameter)));
assert_eq!(lex.next(), Some(Ok(Token::Predicate)));
}
#[test]
fn test_literals() {
let mut lex = Token::lexer("123 3.14 true false \"hello\"");
assert_eq!(lex.next(), Some(Ok(Token::IntLiteral(123))));
assert_eq!(lex.next(), Some(Ok(Token::FloatLiteral(3.14))));
assert_eq!(lex.next(), Some(Ok(Token::BoolLiteral(true))));
assert_eq!(lex.next(), Some(Ok(Token::BoolLiteral(false))));
assert_eq!(lex.next(), Some(Ok(Token::StringLiteral("hello".to_string()))));
}
#[test]
fn test_identifiers() {
let mut lex = Token::lexer("XTZH_GOLD_COVERAGE check_coverage");
assert_eq!(lex.next(), Some(Ok(Token::ConstantIdent("XTZH_GOLD_COVERAGE".to_string()))));
assert_eq!(lex.next(), Some(Ok(Token::Ident("check_coverage".to_string()))));
}
#[test]
fn test_operators() {
let mut lex = Token::lexer("+ - * / >= <= == !=");
assert_eq!(lex.next(), Some(Ok(Token::Plus)));
assert_eq!(lex.next(), Some(Ok(Token::Minus)));
assert_eq!(lex.next(), Some(Ok(Token::Star)));
assert_eq!(lex.next(), Some(Ok(Token::Slash)));
assert_eq!(lex.next(), Some(Ok(Token::Ge)));
assert_eq!(lex.next(), Some(Ok(Token::Le)));
assert_eq!(lex.next(), Some(Ok(Token::Eq)));
assert_eq!(lex.next(), Some(Ok(Token::Ne)));
}
#[test]
fn test_comments() {
let mut lex = Token::lexer("clause // comment\nlevel /* block comment */ eternal");
assert_eq!(lex.next(), Some(Ok(Token::Clause)));
assert_eq!(lex.next(), Some(Ok(Token::Level)));
assert_eq!(lex.next(), Some(Ok(Token::Eternal)));
}
}