From b47430153b6dc8e585d812bf86788810ef82cb13 Mon Sep 17 00:00:00 2001 From: Jaredan Date: Sat, 28 Dec 2024 07:35:54 +0000 Subject: [PATCH] Add BitwiseAnd and BitwiseOr operator and Add support for Reference and Dereference in lexer and parser (Not include the typer) --- src/ast/src/fmt.rs | 5 +++ src/ast/src/tree.rs | 7 +++- src/lexer/src/lib.rs | 6 ++- src/lexer/src/tokens.rs | 8 +++- src/parser/src/grammar.lalrpop | 72 +++++++++++++++++++++++++++++++- src/parser/src/lib.rs | 2 + test/phase1/basic/test_1_r07.out | 3 +- 7 files changed, 95 insertions(+), 8 deletions(-) diff --git a/src/ast/src/fmt.rs b/src/ast/src/fmt.rs index c551694..e592129 100644 --- a/src/ast/src/fmt.rs +++ b/src/ast/src/fmt.rs @@ -114,6 +114,7 @@ impl fmt::Display for Value { Value::Char(c) => write!(f, "{}: char", c), Value::Bool(b) => write!(f, "{}: bool", b), Value::Struct(s) => write!(f, "Struct({})", s), + Value::Pointer(p) => write!(f, "Pointer({})", p), Value::Null => write!(f, "null") } } @@ -131,6 +132,8 @@ impl fmt::Display for BinaryOperator { BinaryOperator::And => write!(f, "&&"), BinaryOperator::Or => write!(f, "||"), BinaryOperator::Error => write!(f, "[BinaryOperatorError]"), + BinaryOperator::BitwiseAnd => write!(f, "&"), + BinaryOperator::BitwiseOr => write!(f, "|"), } } } @@ -143,6 +146,8 @@ impl fmt::Display for UnaryOperator { UnaryOperator::Inc => write!(f, "++"), UnaryOperator::Dec => write!(f, "--"), UnaryOperator::Error => write!(f, "[UnaryOperatorError]"), + UnaryOperator::Ref => write!(f, "&"), + UnaryOperator::Deref => write!(f, "*"), } } } diff --git a/src/ast/src/tree.rs b/src/ast/src/tree.rs index 6638215..1bf9525 100644 --- a/src/ast/src/tree.rs +++ b/src/ast/src/tree.rs @@ -86,6 +86,7 @@ pub enum Value { Char(char), Bool(bool), Struct(String), + Pointer(Box), Null } @@ -99,6 +100,8 @@ pub enum BinaryOperator { Mod, // % And, // && Or, // || + BitwiseAnd, // & + BitwiseOr, // | Error } @@ -107,7 +110,9 @@ pub enum UnaryOperator { Not, // ! Inc, // ++ Dec, // -- - Error + Ref, //& + Deref, //* + Error, } #[derive(Clone, Debug, PartialEq)] diff --git a/src/lexer/src/lib.rs b/src/lexer/src/lib.rs index 84c3089..fcdf54b 100644 --- a/src/lexer/src/lib.rs +++ b/src/lexer/src/lib.rs @@ -197,7 +197,7 @@ mod test { fn operators() { assert_lex( " - ++ -- ! * / % ^ + - < <= > >= == != && || = + ++ -- ! * / % ^ + - < <= > >= == != && || = & | ", &[ (OpIncrement, "++"), @@ -217,7 +217,9 @@ mod test { (OpNotEqual, "!="), (OpAnd, "&&"), (OpOr, "||"), - (OpAssign, "=") + (OpAssign, "="), + (OpBitwiseAnd, "&"), + (OpBitwiseOr, "|"), ][..] ); } diff --git a/src/lexer/src/tokens.rs b/src/lexer/src/tokens.rs index 54e71ea..60f8ac0 100644 --- a/src/lexer/src/tokens.rs +++ b/src/lexer/src/tokens.rs @@ -90,9 +90,9 @@ pub enum Token { OpMod, #[token("^")] OpPow, - #[token("&&")] + #[token("&&", priority = 5)] OpAnd, - #[token("||")] + #[token("||", priority = 5)] OpOr, #[token("!")] OpNot, @@ -100,6 +100,10 @@ pub enum Token { OpIncrement, #[token("--")] OpDecrement, + #[token("&", priority = 3)] + OpBitwiseAnd, + #[token("|", priority = 3)] + OpBitwiseOr, // Punctuation #[token(".", priority = 5)] diff --git a/src/parser/src/grammar.lalrpop b/src/parser/src/grammar.lalrpop index 7dcea81..009182c 100644 --- a/src/parser/src/grammar.lalrpop +++ b/src/parser/src/grammar.lalrpop @@ -1211,12 +1211,55 @@ pub CompExpr: Box = { lhs, tree::BinaryOperator::Sub, rhs )) }, + + #[precedence(level="5")] #[assoc(side="left")] + "&" => { + let error = ErrorRecovery { + error: ParseError::User { + error: LexicalError::MissingLexeme(Span { + source: source.to_string(), + start: l, + end: l + 1 + }, "Exp after &".to_string()) + }, + dropped_tokens: Vec::new(), + }; + errors.push(error); + Box::new(tree::CompExpr::Error) + }, + "&" => { + Box::new(tree::CompExpr::BinaryOperation ( + lhs, tree::BinaryOperator::BitwiseAnd, rhs + )) + }, + "|" => { + let error = ErrorRecovery { + error: ParseError::User { + error: LexicalError::MissingLexeme(Span { + source: source.to_string(), + start: l, + end: l + 1 + }, "Exp after |".to_string()) + }, + dropped_tokens: Vec::new(), + }; + errors.push(error); + Box::new(tree::CompExpr::Error) + }, + "|" => { + Box::new(tree::CompExpr::BinaryOperation ( + lhs, tree::BinaryOperator::BitwiseOr, rhs + )) + }, } Specifier: tree::Value = { => tree::Value::Integer(0), + "*" => tree::Value::Pointer(Box::new(tree::Value::Integer(0))), => tree::Value::Float(0.0), + "*" => tree::Value::Pointer(Box::new(tree::Value::Float(0.0))), => tree::Value::Char(' '), + "*" => tree::Value::Pointer(Box::new(tree::Value::Char(' '))), => tree::Value::String(String::new()), => tree::Value::Null, "struct" => tree::Value::Struct(str) @@ -1262,7 +1305,32 @@ Term: Box = { => { Box::new(tree::CompExpr::Variable(tree::Variable::StructReference(Box::new(s)))) }, - + "&" => { + Box::new(tree::CompExpr::UnaryOperation( + tree::UnaryOperator::Ref, + Box::new( + tree::CompExpr::Variable( + tree::Variable::VarReference( + Box::new(ident), + Box::new(Vec::new()) + ) + ) + ) + )) + }, + "*" => { + Box::new(tree::CompExpr::UnaryOperation( + tree::UnaryOperator::Deref, + Box::new( + tree::CompExpr::Variable( + tree::Variable::VarReference( + Box::new(ident), + Box::new(Vec::new()) + ) + ), + ) + )) + }, // error recovery "(" ArgList? => { let error = ErrorRecovery { @@ -1362,6 +1430,8 @@ extern { "=" => Token::OpAssign, "++" => Token::OpIncrement, "--" => Token::OpDecrement, + "&" => Token::OpBitwiseAnd, + "|" => Token::OpBitwiseOr, "if" => Token::KeywordIf, "else" => Token::KeywordElse, "while" => Token::KeywordWhile, diff --git a/src/parser/src/lib.rs b/src/parser/src/lib.rs index f4ac71e..0e231ec 100644 --- a/src/parser/src/lib.rs +++ b/src/parser/src/lib.rs @@ -221,6 +221,8 @@ mod tests { "Struct: Struct Definition: obj with [Variable Declaration: a = [0: u32] with dimensions [], Variable Declaration: b = [ : char] with dimensions []]"); assert_parse(Parser::StmtParser, "#include \"../hi.h\"", "Include: ../hi.h"); assert_parse(Parser::StmtParser, "int a[1];", "GlobalVariable: [Variable Declaration: a = [0: u32] with dimensions [1: u32]]"); + assert_parse(Parser::ProgramParser, "int main(){ int a; int *b = &a; int c = *b;}", + "Functions: Function: main:[Body: [Variable Declaration: a = [0: u32] with dimensions [], Variable Declaration: b = [Pointer(0: u32)] with dimensions []; Variable Assignment: b = (& a), Variable Declaration: c = [0: u32] with dimensions []; Variable Assignment: c = (* b)]]"); } #[test] diff --git a/test/phase1/basic/test_1_r07.out b/test/phase1/basic/test_1_r07.out index 52f40df..153f506 100644 --- a/test/phase1/basic/test_1_r07.out +++ b/test/phase1/basic/test_1_r07.out @@ -1,2 +1 @@ -Error type A at Line 7: Unknown lexeme | -Error type A at Line 8: Unknown lexeme & +Functions: Function: test_1_r07:[Body: [Variable Declaration: a = [0: u32] with dimensions []; Variable Declaration: b = [0: u32] with dimensions []; Variable Declaration: c = [0: u32] with dimensions [], Variable Assignment: a = 1: u32, Variable Assignment: b = (a + 2: u32), Variable Assignment: c = (b - 3: u32), Variable Assignment: a = (c | 4: u32), Variable Assignment: b = (a & 5: u32)]] \ No newline at end of file