diff --git a/example/hello_world.hyc b/example/hello_world.hyc index d907ef2..9efe307 100644 --- a/example/hello_world.hyc +++ b/example/hello_world.hyc @@ -10,4 +10,6 @@ func main :: () = { // Infix operator let n :: Bool = 2 == 2; + // Prefix operator + let m :: Bool = !n; }; diff --git a/src/front/model.rs b/src/front/model.rs index 163e3ef..07de247 100644 --- a/src/front/model.rs +++ b/src/front/model.rs @@ -138,6 +138,7 @@ pub struct Ident(pub String); #[derive(Clone, Debug, PartialEq)] pub enum Prefix { + Plus, Minus, Not, } diff --git a/src/front/parser.rs b/src/front/parser.rs index 7c29f9a..5d3dfa4 100644 --- a/src/front/parser.rs +++ b/src/front/parser.rs @@ -9,7 +9,7 @@ use nom::{ sequence::{terminated, tuple, pair, preceded, delimited}, error_position, }; -use super::model::{Token, Tokens, Precedence, Infix, Program, Stmt, Expr, Ident, Literal}; +use super::model::{Token, Tokens, Precedence, Infix, Program, Stmt, Expr, Ident, Literal, Prefix}; macro_rules! tag_token ( ($func_name:ident, $tag: expr) => ( @@ -25,6 +25,10 @@ tag_token!(tag_return, Token::Return); tag_token!(tag_if, Token::If); tag_token!(tag_else, Token::Else); +tag_token!(tag_plus, Token::Plus); +tag_token!(tag_minus, Token::Minus); +tag_token!(tag_not, Token::Not); + tag_token!(tag_assign, Token::Assign); tag_token!(tag_typehint, Token::Typehint); tag_token!(tag_semicolon, Token::Semicolon); @@ -73,10 +77,16 @@ fn parse_atom_expr(input: Tokens) -> IResult { alt(( parse_literal_expr, parse_ident_expr, + parse_prefix_expr, + parse_paren_expr, parse_if_expr, ))(input) } +fn parse_paren_expr(input: Tokens) -> IResult { + delimited(tag_lparen, parse_expr_lowest, tag_rparen)(input) +} + fn parse_ident(input: Tokens) -> IResult { let (i1, t1) = take(1usize)(input)?; if t1.tokens.is_empty() { Err(Err::Error(Error::new(input, ErrorKind::Tag))) } @@ -128,6 +138,20 @@ fn parse_infix_expr(input: Tokens, left: Expr) -> IResult { } } +fn parse_prefix_expr(input: Tokens) -> IResult { + let (i1, t1) = alt((tag_plus, tag_minus, tag_not))(input)?; + if t1.tokens.is_empty() { Err(Err::Error(error_position!(input, ErrorKind::Tag))) } + else { + let (i2, e) = parse_atom_expr(i1)?; + match t1.tokens[0].clone() { + Token::Plus => Ok((i2, Expr::Prefix(Prefix::Plus, Box::new(e)))), + Token::Minus => Ok((i2, Expr::Prefix(Prefix::Minus, Box::new(e)))), + Token::Not => Ok((i2, Expr::Prefix(Prefix::Not, Box::new(e)))), + _ => Err(Err::Error(error_position!(input, ErrorKind::Tag))), + } + } +} + fn parse_expr(input: Tokens, precedence: Precedence, left: Expr) -> IResult { let (i1, t1) = take(1usize)(input)?;