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::().ok())] IntLiteral(u64), #[regex(r"[0-9]+\.[0-9]+", |lex| lex.slice().parse::().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))); } }