From 45ab0ed8dfd72666c4936a53b981f5f365c0e345 Mon Sep 17 00:00:00 2001 From: ghostlyzsh Date: Sat, 3 Aug 2024 12:04:03 -0500 Subject: [PATCH] ternary operators --- kabel/grammar.ebnf | 4 +- kabel/src/lexer.rs | 16 ++++- kabel/src/parser.rs | 167 +++++++++++++++++++++++++++++++++++++++----- 3 files changed, 167 insertions(+), 20 deletions(-) diff --git a/kabel/grammar.ebnf b/kabel/grammar.ebnf index 5a096b224a82433f46d0668b33fcc3718e823f0b..4356b8a1cac03f5e35327da8a8d076450a970d7d 100644 --- a/kabel/grammar.ebnf +++ b/kabel/grammar.ebnf @@ -23,7 +23,9 @@ expression = assignment | declaration ; declaration = "var" , identifier , "=" , expression ; assignment = ( identifier , ( "=" | "+=" | "-=" | "*=" - | "/=" | "%=" | "&=" | "^=" | "|=" ) , assignment ) | logical_or; + | "/=" | "%=" | "&=" | "^=" | "|=" ) , assignment ) | ternary ; + +ternary = logical_or [ , "?" , expression , ":" , expression ] ; logical_or = logical_and { , "||" , logical_and } ; diff --git a/kabel/src/lexer.rs b/kabel/src/lexer.rs index 0a6aca6b1a06246ed8e56aab9315af7f8baee94f..b04a304916f75cbfd7aa2e15139c75d16b0640e4 100644 --- a/kabel/src/lexer.rs +++ b/kabel/src/lexer.rs @@ -147,6 +147,14 @@ impl Lexer { self.output.push(token!(self, TokenType::Semicolon)); self.start = self.current; } + ':' => { + self.output.push(token!(self, TokenType::Colon)); + self.start = self.current; + } + '?' => { + self.output.push(token!(self, TokenType::Question)); + self.start = self.current; + } '^' => { if self.peek() == '=' { self.read_char(); @@ -360,9 +368,6 @@ pub enum TokenType { RightBrace, LeftSquare, RightSquare, - Period, - Comma, - Semicolon, Equal, EqualEqual, Bang, @@ -379,6 +384,11 @@ pub enum TokenType { OrOr, Caret, CaretEqual, + Period, + Comma, + Semicolon, + Colon, + Question, Ident(String), Str(String), diff --git a/kabel/src/parser.rs b/kabel/src/parser.rs index 8ad8935857452aa5a662f82b94795cbf8dcc878f..efd242950360862e7c05c3ad4916fdccaf30040d 100644 --- a/kabel/src/parser.rs +++ b/kabel/src/parser.rs @@ -382,7 +382,18 @@ impl Parser { ASTType::Binary( Box::new(lit!(Ident, name.clone(), ident)), BinOp::Asn, - Box::new(ast!(ASTType::Binary(Box::new(lit!(Ident, name, ident)), BinOp::Add, Box::new(expr.clone())), expr, expr).clone()) + Box::new( + ast!( + ASTType::Binary( + Box::new(lit!(Ident, name, ident)), + BinOp::Add, + Box::new(expr.clone()) + ), + expr, + expr + ) + .clone() + ) ), ident, expr @@ -392,7 +403,18 @@ impl Parser { ASTType::Binary( Box::new(lit!(Ident, name.clone(), ident)), BinOp::Asn, - Box::new(ast!(ASTType::Binary(Box::new(lit!(Ident, name, ident)), BinOp::Sub, Box::new(expr.clone())), expr, expr).clone()) + Box::new( + ast!( + ASTType::Binary( + Box::new(lit!(Ident, name, ident)), + BinOp::Sub, + Box::new(expr.clone()) + ), + expr, + expr + ) + .clone() + ) ), ident, expr @@ -402,7 +424,18 @@ impl Parser { ASTType::Binary( Box::new(lit!(Ident, name.clone(), ident)), BinOp::Asn, - Box::new(ast!(ASTType::Binary(Box::new(lit!(Ident, name, ident)), BinOp::Mul, Box::new(expr.clone())), expr, expr).clone()) + Box::new( + ast!( + ASTType::Binary( + Box::new(lit!(Ident, name, ident)), + BinOp::Mul, + Box::new(expr.clone()) + ), + expr, + expr + ) + .clone() + ) ), ident, expr @@ -412,7 +445,18 @@ impl Parser { ASTType::Binary( Box::new(lit!(Ident, name.clone(), ident)), BinOp::Asn, - Box::new(ast!(ASTType::Binary(Box::new(lit!(Ident, name.clone(), ident)), BinOp::Div, Box::new(expr.clone())), expr, expr).clone()) + Box::new( + ast!( + ASTType::Binary( + Box::new(lit!(Ident, name.clone(), ident)), + BinOp::Div, + Box::new(expr.clone()) + ), + expr, + expr + ) + .clone() + ) ), ident, expr @@ -422,7 +466,18 @@ impl Parser { ASTType::Binary( Box::new(lit!(Ident, name.clone(), ident)), BinOp::Asn, - Box::new(ast!(ASTType::Binary(Box::new(lit!(Ident, name, ident)), BinOp::Mod, Box::new(expr.clone())), expr, expr).clone()) + Box::new( + ast!( + ASTType::Binary( + Box::new(lit!(Ident, name, ident)), + BinOp::Mod, + Box::new(expr.clone()) + ), + expr, + expr + ) + .clone() + ) ), ident, expr @@ -432,7 +487,18 @@ impl Parser { ASTType::Binary( Box::new(lit!(Ident, name.clone(), ident)), BinOp::Asn, - Box::new(ast!(ASTType::Binary(Box::new(lit!(Ident, name, ident)), BinOp::BitAnd, Box::new(expr.clone())), expr, expr).clone()) + Box::new( + ast!( + ASTType::Binary( + Box::new(lit!(Ident, name, ident)), + BinOp::BitAnd, + Box::new(expr.clone()) + ), + expr, + expr + ) + .clone() + ) ), ident, expr @@ -442,7 +508,18 @@ impl Parser { ASTType::Binary( Box::new(lit!(Ident, name.clone(), ident)), BinOp::Asn, - Box::new(ast!(ASTType::Binary(Box::new(lit!(Ident, name, ident)), BinOp::BitXor, Box::new(expr.clone())), expr, expr).clone()) + Box::new( + ast!( + ASTType::Binary( + Box::new(lit!(Ident, name, ident)), + BinOp::BitXor, + Box::new(expr.clone()) + ), + expr, + expr + ) + .clone() + ) ), ident, expr @@ -452,7 +529,18 @@ impl Parser { ASTType::Binary( Box::new(lit!(Ident, name.clone(), ident)), BinOp::Asn, - Box::new(ast!(ASTType::Binary(Box::new(lit!(Ident, name, ident)), BinOp::BitOr, Box::new(expr.clone())), expr, expr).clone()) + Box::new( + ast!( + ASTType::Binary( + Box::new(lit!(Ident, name, ident)), + BinOp::BitOr, + Box::new(expr.clone()) + ), + expr, + expr + ) + .clone() + ) ), ident, expr @@ -460,10 +548,28 @@ impl Parser { } } self.current -= 1; - return self.logical_or(); + return self.ternary(); } - return self.logical_or(); + return self.ternary(); + } + + pub fn ternary(&mut self) -> Result { + let condition = self.logical_or()?; + + if let TokenType::Question = self.peek()?.token_type { + self.read_token()?; + let true_expr = self.expression()?; + if let TokenType::Colon = self.peek()?.token_type { + self.read_token()?; + let false_expr = self.expression()?; + return Ok(ast!(ASTType::Ternary(Box::new(condition.clone()), Box::new(true_expr), Box::new(false_expr.clone())), condition, false_expr)); + } else { + return Err(unexpected_token!(self, "Expected : found {}", self.token)); + } + } + + Ok(condition) } pub fn logical_or(&mut self) -> Result { @@ -837,13 +943,41 @@ impl Parser { if let TokenType::Ident(name) = ident.token_type { let oper = self.read_token()?; if oper.token_type == TokenType::PlusPlus { - return Ok(ast!(ASTType::Binary(Box::new(lit!(Ident, name.clone(), ident)), BinOp::Asn, - Box::new(ast!(ASTType::Binary(Box::new(lit!(Ident, name, ident)), BinOp::Add, - Box::new(lit!(Num, 1., oper))), oper, oper))), ident, oper)) + return Ok(ast!( + ASTType::Binary( + Box::new(lit!(Ident, name.clone(), ident)), + BinOp::Asn, + Box::new(ast!( + ASTType::Binary( + Box::new(lit!(Ident, name, ident)), + BinOp::Add, + Box::new(lit!(Num, 1., oper)) + ), + oper, + oper + )) + ), + ident, + oper + )); } else { - return Ok(ast!(ASTType::Binary(Box::new(lit!(Ident, name.clone(), ident)), BinOp::Asn, - Box::new(ast!(ASTType::Binary(Box::new(lit!(Ident, name, ident)), BinOp::Sub, - Box::new(lit!(Num, 1., oper))), oper, oper))), ident, oper)) + return Ok(ast!( + ASTType::Binary( + Box::new(lit!(Ident, name.clone(), ident)), + BinOp::Asn, + Box::new(ast!( + ASTType::Binary( + Box::new(lit!(Ident, name, ident)), + BinOp::Sub, + Box::new(lit!(Num, 1., oper)) + ), + oper, + oper + )) + ), + ident, + oper + )); } } panic!("Inc/dec logic broke"); @@ -942,6 +1076,7 @@ pub enum ASTType { // expressions Decl(Box, Box), // identifier, expression + Ternary(Box, Box, Box), Subscript(Box, Box), Binary(Box, BinOp, Box), Unary(UnOp, Box),