diff --git a/grimoire/src/ast/expr.rs b/grimoire/src/ast/expr.rs index 89ad2fd0eb4ea2b744df945cf03ca42024cfe847..bfd3b87d9fc5c53b8104e9e969f55552605031f3 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 2185b01b7d845e887fb2e1bb4fd0c7aee8a6a9eb..331ef71f1f752bbf56f1b2eaf262755d70f4e9a1 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 cb91241aa98611e2c39c116fd8dfc53d1d9d755f..4fde857f9f91af45dfd371451886b49446af831c 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 0000000000000000000000000000000000000000..4ba2f7d7ac75c2b8147ecc43ee679db2618033fa --- /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 245e522113860f9efef2ce136d4ab06a9c87ffae..ea673b90694982f90a2bc957df13d225c6ffff92 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 dcdbb44a501c713098a365b48cbb27b37c4356b0..5b870a800c032220872b18447e666dfb98381cee 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) }