From 82818670e664c86a763cf89128ab10558ce27cd4 Mon Sep 17 00:00:00 2001 From: Kubat <maelle.martin@proton.me> Date: Thu, 1 May 2025 11:49:13 +0200 Subject: [PATCH] [PARSER] Add the reserved keyword check + assign tags to each operator --- grimoire/src/ast/expr.rs | 32 ++++++++++++++++---------------- grimoire/src/parser/error.rs | 9 ++++++--- grimoire/src/parser/expr.rs | 18 ++++++++++++------ grimoire/src/parser/keywords.rs | 26 ++++++++++++++++++++++++++ grimoire/src/parser/mod.rs | 1 + grimoire/src/parser/utils.rs | 8 ++++++-- 6 files changed, 67 insertions(+), 27 deletions(-) create mode 100644 grimoire/src/parser/keywords.rs diff --git a/grimoire/src/ast/expr.rs b/grimoire/src/ast/expr.rs index 89ad2fd..bfd3b87 100644 --- a/grimoire/src/ast/expr.rs +++ b/grimoire/src/ast/expr.rs @@ -37,8 +37,8 @@ pub enum UnOp { impl UnOp { pub fn as_str(&self) -> &'static str { match self { - UnOp::Not => todo!(), - UnOp::Neg => todo!(), + UnOp::Not => "!", + UnOp::Neg => "-", } } } @@ -70,20 +70,20 @@ pub enum BinOp { impl BinOp { pub fn as_str(&self) -> &'static str { match self { - BinOp::Add => todo!(), - BinOp::Sub => todo!(), - BinOp::Mul => todo!(), - BinOp::Div => todo!(), - BinOp::Mod => todo!(), - BinOp::CompGE => todo!(), - BinOp::CompGT => todo!(), - BinOp::CompLT => todo!(), - BinOp::CompLE => todo!(), - BinOp::Or => todo!(), - BinOp::And => todo!(), - BinOp::Xor => todo!(), - BinOp::CompEQ => todo!(), - BinOp::CompNEQ => todo!(), + BinOp::Add => "+", + BinOp::Sub => "-", + BinOp::Mul => "*", + BinOp::Div => "/", + BinOp::Mod => "%", + BinOp::CompGE => ">=", + BinOp::CompGT => ">", + BinOp::CompLT => "<=", + BinOp::CompLE => "<", + BinOp::Or => "|", + BinOp::And => "&", + BinOp::Xor => "^", + BinOp::CompEQ => "=", + BinOp::CompNEQ => "!=", } } } diff --git a/grimoire/src/parser/error.rs b/grimoire/src/parser/error.rs index 2185b01..331ef71 100644 --- a/grimoire/src/parser/error.rs +++ b/grimoire/src/parser/error.rs @@ -4,13 +4,16 @@ use std::num::{ParseFloatError, ParseIntError}; #[derive(Debug, thiserror::Error)] pub enum ParserError { - #[error("{0:?}, {1}")] + #[error("{0:?}: {1}")] ParseFloat(Location, ParseFloatError), - #[error("{0:?}, {1}")] + #[error("{0:?}: {1}")] ParseInt(Location, ParseIntError), - #[error("{0:?}, {1:?}")] + #[error("{0:?} use of a reserved keyword: '{1}'")] + UseOfReservedKeyword(Location, &'static str), + + #[error("{0:?}: nom error {1:?}")] Nom(Location, ErrorKind), } diff --git a/grimoire/src/parser/expr.rs b/grimoire/src/parser/expr.rs index cb91241..4fde857 100644 --- a/grimoire/src/parser/expr.rs +++ b/grimoire/src/parser/expr.rs @@ -2,21 +2,27 @@ use crate::{ ast::{AstSpan, expr::*}, parser::*, }; - use nom::{ - Parser, branch::alt, bytes::complete::tag, character::complete::multispace0, combinator::map, - multi::many0, sequence::preceded, + Parser, + branch::alt, + bytes::complete::tag, + character::complete::{char, multispace0}, + combinator::{map, value}, + multi::many0, + sequence::preceded, }; fn var_or_constant(s: Span) -> ParserResult<Expression> { + // Note: the order is important! utils::map_with_locaiton( alt(( map(utils::number, VarOrConstant::Int), map(utils::float, VarOrConstant::Flt), map(utils::string, VarOrConstant::Str), - map(utils::keyword("true"), |_| VarOrConstant::Bool(true)), - map(utils::keyword("false"), |_| VarOrConstant::Bool(false)), - map(utils::identifier, VarOrConstant::Var), + value(VarOrConstant::Bool(true), utils::keyword(keywords::TRUE)), + value(VarOrConstant::Bool(false), utils::keyword(keywords::FALSE)), + map(preceded(char('$'), utils::identifier), VarOrConstant::Var), + map(utils::identifier, VarOrConstant::Ident), )), Expression::Leaf, ) diff --git a/grimoire/src/parser/keywords.rs b/grimoire/src/parser/keywords.rs new file mode 100644 index 0000000..4ba2f7d --- /dev/null +++ b/grimoire/src/parser/keywords.rs @@ -0,0 +1,26 @@ +pub const TRUE: &str = "true"; +pub const FALSE: &str = "false"; + +pub fn check(keyword: &str) -> Result<&str, &'static str> { + const RESERVED: &[&str] = &[TRUE, FALSE]; + const _: () = { + let mut i = 0usize; + while i < RESERVED.len() { + let mut j = 0usize; + let reserved = RESERVED[i].as_bytes(); + while j < reserved.len() { + assert!( + u8::is_ascii_lowercase(&reserved[j]), + "reserved keyword must be ascii-lowercase composed..." + ); + j += 1; + } + i += 1; + } + }; + + match RESERVED.iter().find(|&&r| r == keyword.trim()) { + Some(&reserved) => Err(reserved), + None => Ok(keyword), + } +} diff --git a/grimoire/src/parser/mod.rs b/grimoire/src/parser/mod.rs index 245e522..ea673b9 100644 --- a/grimoire/src/parser/mod.rs +++ b/grimoire/src/parser/mod.rs @@ -1,5 +1,6 @@ mod error; mod expr; +pub mod keywords; mod location; mod span; pub mod utils; diff --git a/grimoire/src/parser/utils.rs b/grimoire/src/parser/utils.rs index dcdbb44..5b870a8 100644 --- a/grimoire/src/parser/utils.rs +++ b/grimoire/src/parser/utils.rs @@ -1,6 +1,6 @@ use crate::{ ast::AstSpan, - parser::{error::*, span::*}, + parser::{error::*, keywords, span::*}, }; use nom::{ Parser, @@ -68,7 +68,11 @@ pub fn identifier(s: Span) -> ParserResult<String> { alt((alpha1, tag("_"))), many0(alt((alphanumeric1, tag("_")))), )) - .map(String::from) + .map_res(|ident: Span| { + keywords::check(ident.into_fragment()) + .map_err(|reserved| ParserError::UseOfReservedKeyword(ident.into(), reserved)) + .map(String::from) + }) .parse(s) } -- GitLab