diff --git a/Cargo.toml b/Cargo.toml index a5e5e948..972fa43c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wavec" -version = "0.1.5-pre-beta" +version = "0.1.6-pre-beta" edition = "2021" [lib] diff --git a/front/lexer/src/lexer/common.rs b/front/lexer/src/lexer/common.rs deleted file mode 100644 index 4e26bf66..00000000 --- a/front/lexer/src/lexer/common.rs +++ /dev/null @@ -1,2 +0,0 @@ -use crate::*; -use std::str::FromStr; \ No newline at end of file diff --git a/front/lexer/src/lexer/core.rs b/front/lexer/src/lexer/core.rs index 4506283a..29f784fb 100644 --- a/front/lexer/src/lexer/core.rs +++ b/front/lexer/src/lexer/core.rs @@ -1,5 +1,4 @@ use crate::token::TokenType; -use super::common::*; #[derive(Debug, Clone)] pub struct Token { @@ -39,7 +38,7 @@ impl<'a> Lexer<'a> { pub fn tokenize(&mut self) -> Vec { let mut tokens = Vec::new(); loop { - let token = self.next_token(); // scan.rs에 구현 + let token = self.next_token(); if token.token_type == TokenType::Eof { tokens.push(token); break; diff --git a/front/lexer/src/lexer/ident.rs b/front/lexer/src/lexer/ident.rs index 1eff7f1a..acb13075 100644 --- a/front/lexer/src/lexer/ident.rs +++ b/front/lexer/src/lexer/ident.rs @@ -1,5 +1,4 @@ use crate::token::*; -use super::common::*; use super::{Lexer, Token}; impl<'a> Lexer<'a> { @@ -19,9 +18,6 @@ impl<'a> Lexer<'a> { } pub(crate) fn keyword_or_ident_token(&self, ident: String) -> Token { - // 여기엔 기존 match identifier.as_str() { ... } 통째로 옮겨와 - // 단, Token { token_type: ..., lexeme: ..., line: self.line } 형태 그대로 유지 - // 마지막 default는 Identifier(ident.clone()) match ident.as_str() { "fun" => Token { token_type: TokenType::Fun, diff --git a/front/lexer/src/lexer/mod.rs b/front/lexer/src/lexer/mod.rs index fa6b54ab..4f78d27b 100644 --- a/front/lexer/src/lexer/mod.rs +++ b/front/lexer/src/lexer/mod.rs @@ -17,7 +17,6 @@ clippy::new_without_default )] -mod common; mod core; mod cursor; mod trivia; diff --git a/front/lexer/src/lexer/scan.rs b/front/lexer/src/lexer/scan.rs index e32c6115..d32d25c6 100644 --- a/front/lexer/src/lexer/scan.rs +++ b/front/lexer/src/lexer/scan.rs @@ -1,5 +1,4 @@ use crate::token::*; -use super::common::*; use super::{Lexer, Token}; impl<'a> Lexer<'a> { diff --git a/front/parser/src/expr/assign.rs b/front/parser/src/expr/assign.rs new file mode 100644 index 00000000..b48108fd --- /dev/null +++ b/front/parser/src/expr/assign.rs @@ -0,0 +1,41 @@ +use lexer::Token; +use lexer::token::TokenType; +use crate::ast::{AssignOperator, Expression}; +use crate::expr::binary::parse_logical_or_expression; + +pub fn parse_expression<'a, T>(tokens: &mut std::iter::Peekable) -> Option +where + T: Iterator, +{ + parse_assignment_expression(tokens) +} + +pub fn parse_assignment_expression<'a, T>(tokens: &mut std::iter::Peekable) -> Option +where + T: Iterator, +{ + let left = parse_logical_or_expression(tokens)?; + + if let Some(token) = tokens.peek() { + let op = match token.token_type { + TokenType::Equal => AssignOperator::Assign, + TokenType::PlusEq => AssignOperator::AddAssign, + TokenType::MinusEq => AssignOperator::SubAssign, + TokenType::StarEq => AssignOperator::MulAssign, + TokenType::DivEq => AssignOperator::DivAssign, + TokenType::RemainderEq => AssignOperator::RemAssign, + _ => return Some(left), + }; + + tokens.next(); // consume op + + let right = parse_assignment_expression(tokens)?; + return Some(Expression::AssignOperation { + target: Box::new(left), + operator: op, + value: Box::new(right), + }); + } + + Some(left) +} \ No newline at end of file diff --git a/front/parser/src/expr/binary.rs b/front/parser/src/expr/binary.rs new file mode 100644 index 00000000..83b84f72 --- /dev/null +++ b/front/parser/src/expr/binary.rs @@ -0,0 +1,223 @@ +use lexer::Token; +use lexer::token::TokenType; +use crate::ast::{Expression, Operator}; +use crate::expr::unary::parse_unary_expression; + +pub fn parse_logical_or_expression<'a, T>(tokens: &mut std::iter::Peekable) -> Option +where + T: Iterator, +{ + let mut left = parse_logical_and_expression(tokens)?; + + while matches!(tokens.peek().map(|t| &t.token_type), Some(TokenType::LogicalOr)) { + tokens.next(); + let right = parse_logical_and_expression(tokens)?; + left = Expression::BinaryExpression { + left: Box::new(left), + operator: Operator::LogicalOr, + right: Box::new(right), + }; + } + + Some(left) +} + +pub fn parse_logical_and_expression<'a, T>(tokens: &mut std::iter::Peekable) -> Option +where + T: Iterator, +{ + let mut left = parse_bitwise_or_expression(tokens)?; + + while matches!(tokens.peek().map(|t| &t.token_type), Some(TokenType::LogicalAnd)) { + tokens.next(); + let right = parse_bitwise_or_expression(tokens)?; + left = Expression::BinaryExpression { + left: Box::new(left), + operator: Operator::LogicalAnd, + right: Box::new(right), + }; + } + + Some(left) +} + +pub fn parse_bitwise_or_expression<'a, T>(tokens: &mut std::iter::Peekable) -> Option +where + T: Iterator, +{ + let mut left = parse_bitwise_xor_expression(tokens)?; + + while matches!(tokens.peek().map(|t| &t.token_type), Some(TokenType::BitwiseOr)) { + tokens.next(); + let right = parse_bitwise_xor_expression(tokens)?; + left = Expression::BinaryExpression { + left: Box::new(left), + operator: Operator::BitwiseOr, + right: Box::new(right), + }; + } + + Some(left) +} + +pub fn parse_bitwise_xor_expression<'a, T>(tokens: &mut std::iter::Peekable) -> Option +where + T: Iterator, +{ + let mut left = parse_bitwise_and_expression(tokens)?; + + while matches!(tokens.peek().map(|t| &t.token_type), Some(TokenType::Xor)) { + tokens.next(); + let right = parse_bitwise_and_expression(tokens)?; + left = Expression::BinaryExpression { + left: Box::new(left), + operator: Operator::BitwiseXor, + right: Box::new(right), + }; + } + + Some(left) +} + +pub fn parse_bitwise_and_expression<'a, T>(tokens: &mut std::iter::Peekable) -> Option +where + T: Iterator, +{ + let mut left = parse_equality_expression(tokens)?; + + while matches!(tokens.peek().map(|t| &t.token_type), Some(TokenType::AddressOf)) { + tokens.next(); + let right = parse_equality_expression(tokens)?; + left = Expression::BinaryExpression { + left: Box::new(left), + operator: Operator::BitwiseAnd, + right: Box::new(right), + }; + } + + Some(left) +} + +pub fn parse_equality_expression<'a, T>(tokens: &mut std::iter::Peekable) -> Option +where + T: Iterator, +{ + let mut left = parse_relational_expression(tokens)?; + + while let Some(token) = tokens.peek() { + let op = match token.token_type { + TokenType::EqualTwo => Operator::Equal, + TokenType::NotEqual => Operator::NotEqual, + _ => break, + }; + tokens.next(); + let right = parse_relational_expression(tokens)?; + left = Expression::BinaryExpression { + left: Box::new(left), + operator: op, + right: Box::new(right), + }; + } + + Some(left) +} + +pub fn parse_relational_expression<'a, T>(tokens: &mut std::iter::Peekable) -> Option +where + T: Iterator, +{ + let mut left = parse_shift_expression(tokens)?; + + while let Some(token) = tokens.peek() { + let op = match token.token_type { + TokenType::Rchevr => Operator::Greater, + TokenType::RchevrEq => Operator::GreaterEqual, + TokenType::Lchevr => Operator::Less, + TokenType::LchevrEq => Operator::LessEqual, + _ => break, + }; + tokens.next(); + let right = parse_shift_expression(tokens)?; + left = Expression::BinaryExpression { + left: Box::new(left), + operator: op, + right: Box::new(right), + }; + } + + Some(left) +} + +pub fn parse_shift_expression<'a, T>(tokens: &mut std::iter::Peekable) -> Option +where + T: Iterator, +{ + let mut left = parse_additive_expression(tokens)?; + + while let Some(token) = tokens.peek() { + let op = match token.token_type { + TokenType::Rol => Operator::ShiftLeft, + TokenType::Ror => Operator::ShiftRight, + _ => break, + }; + + tokens.next(); + let right = parse_additive_expression(tokens)?; + left = Expression::BinaryExpression { + left: Box::new(left), + operator: op, + right: Box::new(right), + }; + } + + Some(left) +} + +pub fn parse_additive_expression<'a, T>(tokens: &mut std::iter::Peekable) -> Option +where + T: Iterator, +{ + let mut left = parse_multiplicative_expression(tokens)?; + + while let Some(token) = tokens.peek() { + let op = match token.token_type { + TokenType::Plus => Operator::Add, + TokenType::Minus => Operator::Subtract, + _ => break, + }; + tokens.next(); + let right = parse_multiplicative_expression(tokens)?; + left = Expression::BinaryExpression { + left: Box::new(left), + operator: op, + right: Box::new(right), + }; + } + + Some(left) +} + +pub fn parse_multiplicative_expression<'a, T>(tokens: &mut std::iter::Peekable) -> Option +where + T: Iterator, +{ + let mut left = parse_unary_expression(tokens)?; + + while let Some(token) = tokens.peek() { + let op = match token.token_type { + TokenType::Star => Operator::Multiply, + TokenType::Div => Operator::Divide, + TokenType::Remainder => Operator::Remainder, + _ => break, + }; + tokens.next(); + let right = parse_unary_expression(tokens)?; + left = Expression::BinaryExpression { + left: Box::new(left), + operator: op, + right: Box::new(right), + }; + } + + Some(left) +} \ No newline at end of file diff --git a/front/parser/src/expr/helpers.rs b/front/parser/src/expr/helpers.rs new file mode 100644 index 00000000..b84f87a3 --- /dev/null +++ b/front/parser/src/expr/helpers.rs @@ -0,0 +1,39 @@ +use std::iter::Peekable; +use std::slice::Iter; +use lexer::Token; +use lexer::token::TokenType; +use crate::ast::Expression; +pub fn is_assignable(expr: &Expression) -> bool { + match expr { + Expression::Variable(_) => true, + Expression::Deref(_) => true, + Expression::FieldAccess { .. } => true, + Expression::IndexAccess { .. } => true, + + Expression::Grouped(inner) => is_assignable(inner), + + _ => false, + } +} + +pub fn parse_expression_from_token( + first_token: &Token, + tokens: &mut Peekable>, +) -> Option { + match &first_token.token_type { + TokenType::Identifier(name) => Some(Expression::Variable(name.clone())), + + TokenType::Deref => { + if let Some(next_token) = tokens.next() { + if let TokenType::Identifier(name) = &next_token.token_type { + return Some(Expression::Deref(Box::new(Expression::Variable( + name.clone(), + )))); + } + } + None + } + + _ => None, + } +} diff --git a/front/parser/src/expr/mod.rs b/front/parser/src/expr/mod.rs new file mode 100644 index 00000000..35b43b03 --- /dev/null +++ b/front/parser/src/expr/mod.rs @@ -0,0 +1,9 @@ +mod helpers; +mod primary; +mod postfix; +mod unary; +mod binary; +mod assign; + +pub use helpers::*; +pub use assign::parse_expression; diff --git a/front/parser/src/expr/postfix.rs b/front/parser/src/expr/postfix.rs new file mode 100644 index 00000000..ea4e7346 --- /dev/null +++ b/front/parser/src/expr/postfix.rs @@ -0,0 +1,147 @@ +use std::iter::Peekable; + +use lexer::token::TokenType; +use lexer::Token; + +use crate::ast::{Expression, IncDecKind}; +use crate::expr::{is_assignable, parse_expression}; + +pub fn parse_postfix_expression<'a, T>( + tokens: &mut Peekable, + mut expr: Expression, +) -> Option +where + T: Iterator, +{ + loop { + match tokens.peek().map(|t| &t.token_type) { + Some(TokenType::Dot) => { + tokens.next(); // consume '.' + + let name = if let Some(Token { + token_type: TokenType::Identifier(name), + .. + }) = tokens.next() + { + name.clone() + } else { + println!("Error: Expected identifier after '.'"); + return None; + }; + + if let Some(Token { + token_type: TokenType::Lparen, + .. + }) = tokens.peek() + { + // ----- MethodCall ----- + tokens.next(); // consume '(' + + let mut args = Vec::new(); + if tokens + .peek() + .map_or(false, |t| t.token_type != TokenType::Rparen) + { + loop { + let arg = parse_expression(tokens)?; + args.push(arg); + + if let Some(Token { + token_type: TokenType::Comma, + .. + }) = tokens.peek() + { + tokens.next(); // consume ',' + } else { + break; + } + } + } + + if tokens + .peek() + .map_or(true, |t| t.token_type != TokenType::Rparen) + { + println!("Error: Expected ')' after method call arguments"); + return None; + } + tokens.next(); // consume ')' + + let base_expr = expr; + expr = Expression::MethodCall { + object: Box::new(base_expr), + name, + args, + }; + } else { + // ----- FieldAccess ----- + let base_expr = expr; + expr = Expression::FieldAccess { + object: Box::new(base_expr), + field: name, + }; + } + } + + Some(TokenType::Lbrack) => { + tokens.next(); // consume '[' + + let index_expr = parse_expression(tokens)?; + if tokens + .peek() + .map_or(true, |t| t.token_type != TokenType::Rbrack) + { + println!("Error: Expected ']' after index"); + return None; + } + tokens.next(); // consume ']' + + let base_expr = expr; + expr = Expression::IndexAccess { + target: Box::new(base_expr), + index: Box::new(index_expr), + }; + } + + Some(TokenType::Increment) => { + let line = tokens.peek().unwrap().line; + tokens.next(); // consume '++' + + if !is_assignable(&expr) { + println!("Error: postfix ++ target must be assignable (line {})", line); + return None; + } + + let base = expr; + expr = Expression::IncDec { + kind: IncDecKind::PostInc, + target: Box::new(base), + }; + + return Some(expr); + } + + Some(TokenType::Decrement) => { + let line = tokens.peek().unwrap().line; + tokens.next(); // consume '--' + + if !is_assignable(&expr) { + println!("Error: postfix -- target must be assignable (line {})", line); + return None; + } + + let base = expr; + expr = Expression::IncDec { + kind: IncDecKind::PostDec, + target: Box::new(base), + }; + + return Some(expr); + } + + _ => break, + } + } + + Some(expr) +} diff --git a/front/parser/src/expr/primary.rs b/front/parser/src/expr/primary.rs new file mode 100644 index 00000000..28dd213d --- /dev/null +++ b/front/parser/src/expr/primary.rs @@ -0,0 +1,254 @@ +use std::iter::Peekable; + +use lexer::token::TokenType; +use lexer::Token; + +use crate::asm::parse_asm_inout_clause; +use crate::ast::{Expression, Literal}; +use crate::expr::parse_expression; +use crate::expr::postfix::parse_postfix_expression; + +pub fn parse_primary_expression<'a, T>(tokens: &mut Peekable) -> Option +where + T: Iterator, +{ + let token = (*tokens.peek()?).clone(); + + let expr = match &token.token_type { + TokenType::IntLiteral(s) => { + tokens.next(); + Some(Expression::Literal(Literal::Int(s.clone()))) + } + TokenType::Float(value) => { + tokens.next(); + Some(Expression::Literal(Literal::Float(*value))) + } + TokenType::CharLiteral(c) => { + tokens.next(); + Some(Expression::Literal(Literal::Char(*c))) + } + TokenType::BoolLiteral(b) => { + tokens.next(); + Some(Expression::Literal(Literal::Bool(*b))) + } + TokenType::Identifier(name) => { + let name = name.clone(); + tokens.next(); + + let expr = if let Some(peeked_token) = tokens.peek() { + match &peeked_token.token_type { + TokenType::Lparen => { + tokens.next(); + + let mut args = vec![]; + if tokens + .peek() + .map_or(false, |t| t.token_type != TokenType::Rparen) + { + loop { + let arg = parse_expression(tokens)?; + args.push(arg); + + if let Some(Token { + token_type: TokenType::Comma, + .. + }) = tokens.peek() + { + tokens.next(); + } else { + break; + } + } + } + + if tokens + .peek() + .map_or(true, |t| t.token_type != TokenType::Rparen) + { + println!("Error: Expected ')' after function call arguments"); + return None; + } + tokens.next(); + + Expression::FunctionCall { name, args } + } + TokenType::Lbrace => { + tokens.next(); + let mut fields = vec![]; + + while tokens + .peek() + .map_or(false, |t| t.token_type != TokenType::Rbrace) + { + let field_name = if let Some(Token { + token_type: TokenType::Identifier(n), + .. + }) = tokens.next() + { + n.clone() + } else { + println!("Error: Expected field name in struct literal."); + return None; + }; + + if tokens + .peek() + .map_or(true, |t| t.token_type != TokenType::Colon) + { + println!("Error: Expected ':' after field name '{}'", field_name); + return None; + } + tokens.next(); + + let value = parse_expression(tokens)?; + fields.push((field_name, value)); + + if let Some(Token { + token_type: TokenType::Comma, + .. + }) = tokens.peek() + { + tokens.next(); + } else { + break; + } + } + + if tokens + .peek() + .map_or(true, |t| t.token_type != TokenType::Rbrace) + { + println!("Error: Expected '}}' to close struct literal"); + return None; + } + tokens.next(); + + Expression::StructLiteral { name, fields } + } + _ => Expression::Variable(name), + } + } else { + Expression::Variable(name) + }; + + Some(expr) + } + TokenType::Lparen => { + tokens.next(); + let inner_expr = parse_expression(tokens)?; + if tokens + .peek() + .map_or(true, |t| t.token_type != TokenType::Rparen) + { + println!("Error: Expected ')' to close grouped expression"); + return None; + } + tokens.next(); + Some(Expression::Grouped(Box::new(inner_expr))) + } + TokenType::String(value) => { + tokens.next(); + Some(Expression::Literal(Literal::String(value.clone()))) + } + TokenType::Lbrack => { + tokens.next(); + let mut elements = vec![]; + if tokens + .peek() + .map_or(false, |t| t.token_type != TokenType::Rbrack) + { + loop { + elements.push(parse_expression(tokens)?); + if let Some(Token { + token_type: TokenType::Comma, + .. + }) = tokens.peek() + { + tokens.next(); + } else { + break; + } + } + } + if tokens + .peek() + .map_or(true, |t| t.token_type != TokenType::Rbrack) + { + println!("Error: Expected ']' to close array literal"); + return None; + } + tokens.next(); + Some(Expression::ArrayLiteral(elements)) + } + TokenType::Asm => { + tokens.next(); + if tokens.peek()?.token_type != TokenType::Lbrace { + println!("Expected '{{' after 'asm'"); + return None; + } + tokens.next(); + + let mut instructions = vec![]; + let mut inputs = vec![]; + let mut outputs = vec![]; + + while let Some(token) = tokens.peek() { + match &token.token_type { + TokenType::Rbrace => { + tokens.next(); + break; + } + + TokenType::In => { + tokens.next(); + parse_asm_inout_clause(tokens, true, &mut inputs, &mut outputs)?; + } + + TokenType::Out => { + tokens.next(); + parse_asm_inout_clause(tokens, false, &mut inputs, &mut outputs)?; + } + + TokenType::Identifier(s) if s == "in" => { + tokens.next(); + parse_asm_inout_clause(tokens, true, &mut inputs, &mut outputs)?; + } + + TokenType::Identifier(s) if s == "out" => { + tokens.next(); + parse_asm_inout_clause(tokens, false, &mut inputs, &mut outputs)?; + } + + TokenType::String(s) => { + instructions.push(s.clone()); + tokens.next(); + } + + other => { + println!("Unexpected token in asm expression: {:?}", other); + tokens.next(); + } + } + } + + Some(Expression::AsmBlock { + instructions, + inputs, + outputs, + }) + } + _ => match token.token_type { + TokenType::Continue | TokenType::Break | TokenType::Return | TokenType::SemiColon => None, + _ => { + println!("Error: Expected primary expression, found {:?}", token.token_type); + println!("Error: Expected primary expression, found {:?}", token.lexeme); + println!("Error: Expected primary expression, found {:?}", token.line); + None + } + }, + }; + + let base = expr?; + + parse_postfix_expression(tokens, base) +} diff --git a/front/parser/src/expr/unary.rs b/front/parser/src/expr/unary.rs new file mode 100644 index 00000000..4bca96b1 --- /dev/null +++ b/front/parser/src/expr/unary.rs @@ -0,0 +1,91 @@ +use lexer::Token; +use lexer::token::TokenType; +use crate::ast::{Expression, IncDecKind, Literal, Operator}; +use crate::expr::is_assignable; +use crate::expr::primary::parse_primary_expression; + +pub fn parse_unary_expression<'a, T>(tokens: &mut std::iter::Peekable) -> Option +where + T: Iterator, +{ + if let Some(token) = tokens.peek() { + match token.token_type { + TokenType::Not => { + tokens.next(); + let inner = parse_unary_expression(tokens)?; + return Some(Expression::Unary { + operator: Operator::Not, + expr: Box::new(inner), + }); + } + TokenType::BitwiseNot => { + tokens.next(); + let inner = parse_unary_expression(tokens)?; + return Some(Expression::Unary { + operator: Operator::BitwiseNot, + expr: Box::new(inner), + }); + } + TokenType::AddressOf => { + tokens.next(); + let inner = parse_unary_expression(tokens)?; + return Some(Expression::AddressOf(Box::new(inner))); + } + TokenType::Deref => { + tokens.next(); + let inner = parse_unary_expression(tokens)?; + return Some(Expression::Deref(Box::new(inner))); + } + TokenType::Increment => { + let tok = tokens.next()?; // '++' + let inner = parse_unary_expression(tokens)?; + if !is_assignable(&inner) { + println!("Error: ++ target must be assignable (line {})", tok.line); + return None; + } + return Some(Expression::IncDec { + kind: IncDecKind::PreInc, + target: Box::new(inner), + }); + } + TokenType::Decrement => { + let tok = tokens.next()?; // '--' + let inner = parse_unary_expression(tokens)?; + if !is_assignable(&inner) { + println!("Error: -- target must be assignable (line {})", tok.line); + return None; + } + return Some(Expression::IncDec { + kind: IncDecKind::PreDec, + target: Box::new(inner), + }); + } + TokenType::Minus => { + let tok = tokens.next()?; // '-' + let inner = parse_unary_expression(tokens)?; + + match inner { + Expression::Literal(Literal::Int(s)) => { + return Some(Expression::Literal(Literal::Int(format!("-{}", s)))); + } + Expression::Literal(Literal::Float(f)) => { + return Some(Expression::Literal(Literal::Float(-f))); + } + _ => { + println!("Error: unary '-' only supports numeric literals (line {})", tok.line); + return None; + } + } + } + + TokenType::Plus => { + tokens.next(); // consume '+' + let inner = parse_unary_expression(tokens)?; + return Some(inner); + } + _ => {} + } + } + + parse_primary_expression(tokens) +} \ No newline at end of file diff --git a/front/parser/src/format.rs b/front/parser/src/format.rs index 04383e1b..1f0c539c 100644 --- a/front/parser/src/format.rs +++ b/front/parser/src/format.rs @@ -1,10 +1,4 @@ -use crate::ast::Expression::Variable; -use crate::ast::{AssignOperator, Expression, FormatPart, IncDecKind, Literal, Operator}; -use lexer::Token; -use lexer::token::TokenType; -use std::iter::Peekable; -use std::slice::Iter; -use crate::asm::{parse_asm_inout_clause, parse_asm_operand}; +use crate::ast::FormatPart; pub fn parse_format_string(s: &str) -> Vec { let mut parts = Vec::new(); @@ -34,816 +28,3 @@ pub fn parse_format_string(s: &str) -> Vec { parts } - -pub fn is_assignable(expr: &Expression) -> bool { - match expr { - Expression::Variable(_) => true, - Expression::Deref(_) => true, - Expression::FieldAccess { .. } => true, - Expression::IndexAccess { .. } => true, - - Expression::Grouped(inner) => is_assignable(inner), - - _ => false, - } -} - -fn desugar_incdec(line: usize, target: Expression, is_inc: bool) -> Option { - if !is_assignable(&target) { - println!("Error: ++/-- target must bee assignable (line {})", line); - return None; - } - - Some(Expression::AssignOperation { - target: Box::new(target), - operator: if is_inc { - AssignOperator::AddAssign - } else { - AssignOperator::SubAssign - }, - value: Box::new(Expression::Literal(Literal::Int("1".to_string()))), - }) -} - -pub fn parse_expression<'a, T>(tokens: &mut std::iter::Peekable) -> Option -where - T: Iterator, -{ - parse_assignment_expression(tokens) -} - -pub fn parse_assignment_expression<'a, T>(tokens: &mut std::iter::Peekable) -> Option -where - T: Iterator, -{ - let left = parse_logical_or_expression(tokens)?; - - if let Some(token) = tokens.peek() { - let op = match token.token_type { - TokenType::Equal => AssignOperator::Assign, - TokenType::PlusEq => AssignOperator::AddAssign, - TokenType::MinusEq => AssignOperator::SubAssign, - TokenType::StarEq => AssignOperator::MulAssign, - TokenType::DivEq => AssignOperator::DivAssign, - TokenType::RemainderEq => AssignOperator::RemAssign, - _ => return Some(left), - }; - - tokens.next(); // consume op - - let right = parse_assignment_expression(tokens)?; - return Some(Expression::AssignOperation { - target: Box::new(left), - operator: op, - value: Box::new(right), - }); - } - - Some(left) -} - -fn parse_logical_or_expression<'a, T>(tokens: &mut std::iter::Peekable) -> Option -where - T: Iterator, -{ - let mut left = parse_logical_and_expression(tokens)?; - - while matches!(tokens.peek().map(|t| &t.token_type), Some(TokenType::LogicalOr)) { - tokens.next(); - let right = parse_logical_and_expression(tokens)?; - left = Expression::BinaryExpression { - left: Box::new(left), - operator: Operator::LogicalOr, - right: Box::new(right), - }; - } - - Some(left) -} - -fn parse_logical_and_expression<'a, T>(tokens: &mut std::iter::Peekable) -> Option -where - T: Iterator, -{ - let mut left = parse_bitwise_or_expression(tokens)?; - - while matches!(tokens.peek().map(|t| &t.token_type), Some(TokenType::LogicalAnd)) { - tokens.next(); - let right = parse_bitwise_or_expression(tokens)?; - left = Expression::BinaryExpression { - left: Box::new(left), - operator: Operator::LogicalAnd, - right: Box::new(right), - }; - } - - Some(left) -} - -fn parse_bitwise_or_expression<'a, T>(tokens: &mut std::iter::Peekable) -> Option -where - T: Iterator, -{ - let mut left = parse_bitwise_xor_expression(tokens)?; - - while matches!(tokens.peek().map(|t| &t.token_type), Some(TokenType::BitwiseOr)) { - tokens.next(); - let right = parse_bitwise_xor_expression(tokens)?; - left = Expression::BinaryExpression { - left: Box::new(left), - operator: Operator::BitwiseOr, - right: Box::new(right), - }; - } - - Some(left) -} - -fn parse_bitwise_xor_expression<'a, T>(tokens: &mut std::iter::Peekable) -> Option -where - T: Iterator, -{ - let mut left = parse_bitwise_and_expression(tokens)?; - - while matches!(tokens.peek().map(|t| &t.token_type), Some(TokenType::Xor)) { - tokens.next(); - let right = parse_bitwise_and_expression(tokens)?; - left = Expression::BinaryExpression { - left: Box::new(left), - operator: Operator::BitwiseXor, - right: Box::new(right), - }; - } - - Some(left) -} - -fn parse_bitwise_and_expression<'a, T>(tokens: &mut std::iter::Peekable) -> Option -where - T: Iterator, -{ - let mut left = parse_equality_expression(tokens)?; - - while matches!(tokens.peek().map(|t| &t.token_type), Some(TokenType::AddressOf)) { - tokens.next(); - let right = parse_equality_expression(tokens)?; - left = Expression::BinaryExpression { - left: Box::new(left), - operator: Operator::BitwiseAnd, - right: Box::new(right), - }; - } - - Some(left) -} - -fn parse_equality_expression<'a, T>(tokens: &mut std::iter::Peekable) -> Option -where - T: Iterator, -{ - let mut left = parse_relational_expression(tokens)?; - - while let Some(token) = tokens.peek() { - let op = match token.token_type { - TokenType::EqualTwo => Operator::Equal, - TokenType::NotEqual => Operator::NotEqual, - _ => break, - }; - tokens.next(); - let right = parse_relational_expression(tokens)?; - left = Expression::BinaryExpression { - left: Box::new(left), - operator: op, - right: Box::new(right), - }; - } - - Some(left) -} - -pub fn parse_relational_expression<'a, T>(tokens: &mut std::iter::Peekable) -> Option -where - T: Iterator, -{ - let mut left = parse_shift_expression(tokens)?; - - while let Some(token) = tokens.peek() { - let op = match token.token_type { - TokenType::Rchevr => Operator::Greater, - TokenType::RchevrEq => Operator::GreaterEqual, - TokenType::Lchevr => Operator::Less, - TokenType::LchevrEq => Operator::LessEqual, - _ => break, - }; - tokens.next(); - let right = parse_shift_expression(tokens)?; - left = Expression::BinaryExpression { - left: Box::new(left), - operator: op, - right: Box::new(right), - }; - } - - Some(left) -} - -pub fn parse_shift_expression<'a, T>(tokens: &mut std::iter::Peekable) -> Option -where - T: Iterator, -{ - let mut left = parse_additive_expression(tokens)?; - - while let Some(token) = tokens.peek() { - let op = match token.token_type { - TokenType::Rol => Operator::ShiftLeft, - TokenType::Ror => Operator::ShiftRight, - _ => break, - }; - - tokens.next(); - let right = parse_additive_expression(tokens)?; - left = Expression::BinaryExpression { - left: Box::new(left), - operator: op, - right: Box::new(right), - }; - } - - Some(left) -} - -pub fn parse_additive_expression<'a, T>(tokens: &mut std::iter::Peekable) -> Option -where - T: Iterator, -{ - let mut left = parse_multiplicative_expression(tokens)?; - - while let Some(token) = tokens.peek() { - let op = match token.token_type { - TokenType::Plus => Operator::Add, - TokenType::Minus => Operator::Subtract, - _ => break, - }; - tokens.next(); - let right = parse_multiplicative_expression(tokens)?; - left = Expression::BinaryExpression { - left: Box::new(left), - operator: op, - right: Box::new(right), - }; - } - - Some(left) -} - -pub fn parse_multiplicative_expression<'a, T>(tokens: &mut std::iter::Peekable) -> Option -where - T: Iterator, -{ - let mut left = parse_unary_expression(tokens)?; - - while let Some(token) = tokens.peek() { - let op = match token.token_type { - TokenType::Star => Operator::Multiply, - TokenType::Div => Operator::Divide, - TokenType::Remainder => Operator::Remainder, - _ => break, - }; - tokens.next(); - let right = parse_unary_expression(tokens)?; - left = Expression::BinaryExpression { - left: Box::new(left), - operator: op, - right: Box::new(right), - }; - } - - Some(left) -} - -fn parse_unary_expression<'a, T>(tokens: &mut std::iter::Peekable) -> Option -where - T: Iterator, -{ - if let Some(token) = tokens.peek() { - match token.token_type { - TokenType::Not => { - tokens.next(); - let inner = parse_unary_expression(tokens)?; - return Some(Expression::Unary { - operator: Operator::Not, - expr: Box::new(inner), - }); - } - TokenType::BitwiseNot => { - tokens.next(); - let inner = parse_unary_expression(tokens)?; - return Some(Expression::Unary { - operator: Operator::BitwiseNot, - expr: Box::new(inner), - }); - } - TokenType::AddressOf => { - tokens.next(); - let inner = parse_unary_expression(tokens)?; - return Some(Expression::AddressOf(Box::new(inner))); - } - TokenType::Deref => { - tokens.next(); - let inner = parse_unary_expression(tokens)?; - return Some(Expression::Deref(Box::new(inner))); - } - TokenType::Increment => { - let tok = tokens.next()?; // '++' - let inner = parse_unary_expression(tokens)?; - if !is_assignable(&inner) { - println!("Error: ++ target must be assignable (line {})", tok.line); - return None; - } - return Some(Expression::IncDec { - kind: IncDecKind::PreInc, - target: Box::new(inner), - }); - } - TokenType::Decrement => { - let tok = tokens.next()?; // '--' - let inner = parse_unary_expression(tokens)?; - if !is_assignable(&inner) { - println!("Error: -- target must be assignable (line {})", tok.line); - return None; - } - return Some(Expression::IncDec { - kind: IncDecKind::PreDec, - target: Box::new(inner), - }); - } - TokenType::Minus => { - let tok = tokens.next()?; // '-' - let inner = parse_unary_expression(tokens)?; - - match inner { - Expression::Literal(Literal::Int(s)) => { - return Some(Expression::Literal(Literal::Int(format!("-{}", s)))); - } - Expression::Literal(Literal::Float(f)) => { - return Some(Expression::Literal(Literal::Float(-f))); - } - _ => { - println!("Error: unary '-' only supports numeric literals (line {})", tok.line); - return None; - } - } - } - - TokenType::Plus => { - tokens.next(); // consume '+' - let inner = parse_unary_expression(tokens)?; - return Some(inner); - } - _ => {} - } - } - - parse_primary_expression(tokens) -} - -pub fn parse_primary_expression<'a, T>(tokens: &mut Peekable) -> Option -where - T: Iterator, -{ - let token = (*tokens.peek()?).clone(); - - let mut expr = match &token.token_type { - TokenType::IntLiteral(s) => { - tokens.next(); - Some(Expression::Literal(Literal::Int(s.clone()))) - } - TokenType::Float(value) => { - tokens.next(); - Some(Expression::Literal(Literal::Float(*value))) - } - TokenType::CharLiteral(c) => { - tokens.next(); - Some(Expression::Literal(Literal::Char(*c))) - } - TokenType::BoolLiteral(b) => { - tokens.next(); - Some(Expression::Literal(Literal::Bool(*b))) - } - TokenType::Identifier(name) => { - let name = name.clone(); - tokens.next(); - - let expr = if let Some(peeked_token) = tokens.peek() { - match &peeked_token.token_type { - TokenType::Lparen => { - tokens.next(); - - let mut args = vec![]; - if tokens - .peek() - .map_or(false, |t| t.token_type != TokenType::Rparen) - { - loop { - let arg = parse_expression(tokens)?; - args.push(arg); - - if let Some(Token { - token_type: TokenType::Comma, - .. - }) = tokens.peek() - { - tokens.next(); - } else { - break; - } - } - } - - if tokens - .peek() - .map_or(true, |t| t.token_type != TokenType::Rparen) - { - println!("Error: Expected ')' after function call arguments"); - return None; - } - tokens.next(); - - Expression::FunctionCall { name, args } - } - TokenType::Lbrace => { - tokens.next(); - let mut fields = vec![]; - - while tokens - .peek() - .map_or(false, |t| t.token_type != TokenType::Rbrace) - { - let field_name = if let Some(Token { - token_type: TokenType::Identifier(n), - .. - }) = tokens.next() - { - n.clone() - } else { - println!("Error: Expected field name in struct literal."); - return None; - }; - - if tokens - .peek() - .map_or(true, |t| t.token_type != TokenType::Colon) - { - println!("Error: Expected ':' after field name '{}'", field_name); - return None; - } - tokens.next(); - - let value = parse_expression(tokens)?; - fields.push((field_name, value)); - - if let Some(Token { - token_type: TokenType::Comma, - .. - }) = tokens.peek() - { - tokens.next(); - } else { - break; - } - } - - if tokens - .peek() - .map_or(true, |t| t.token_type != TokenType::Rbrace) - { - println!("Error: Expected '}}' to close struct literal"); - return None; - } - tokens.next(); - - Expression::StructLiteral { name, fields } - } - _ => Expression::Variable(name), - } - } else { - Expression::Variable(name) - }; - - Some(expr) - } - TokenType::Lparen => { - tokens.next(); - let inner_expr = parse_expression(tokens)?; - if tokens - .peek() - .map_or(true, |t| t.token_type != TokenType::Rparen) - { - println!("Error: Expected ')' to close grouped expression"); - return None; - } - tokens.next(); - Some(Expression::Grouped(Box::new(inner_expr))) - } - TokenType::String(value) => { - tokens.next(); // consume the string token - Some(Expression::Literal(Literal::String(value.clone()))) - } - TokenType::Lbrack => { - tokens.next(); - let mut elements = vec![]; - if tokens - .peek() - .map_or(false, |t| t.token_type != TokenType::Rbrack) - { - loop { - elements.push(parse_expression(tokens)?); - if let Some(Token { - token_type: TokenType::Comma, - .. - }) = tokens.peek() - { - tokens.next(); - } else { - break; - } - } - } - if tokens - .peek() - .map_or(true, |t| t.token_type != TokenType::Rbrack) - { - println!("Error: Expected ']' to close array literal"); - return None; - } - tokens.next(); - Some(Expression::ArrayLiteral(elements)) - } - TokenType::Asm => { - tokens.next(); // consume 'asm' - if tokens.peek()?.token_type != TokenType::Lbrace { - println!("Expected '{{' after 'asm'"); - return None; - } - tokens.next(); // consume '{' - - let mut instructions = vec![]; - let mut inputs = vec![]; - let mut outputs = vec![]; - - while let Some(token) = tokens.peek() { - match &token.token_type { - TokenType::Rbrace => { - tokens.next(); - break; - } - - TokenType::In => { - tokens.next(); // consume 'in' - parse_asm_inout_clause(tokens, true, &mut inputs, &mut outputs)?; - } - - TokenType::Out => { - tokens.next(); // consume 'out' - parse_asm_inout_clause(tokens, false, &mut inputs, &mut outputs)?; - } - - - TokenType::Identifier(s) if s == "in" => { - tokens.next(); // consume identifier 'in' - parse_asm_inout_clause(tokens, true, &mut inputs, &mut outputs)?; - } - - TokenType::Identifier(s) if s == "out" => { - tokens.next(); // consume identifier 'out' - parse_asm_inout_clause(tokens, false, &mut inputs, &mut outputs)?; - } - - TokenType::String(s) => { - instructions.push(s.clone()); - tokens.next(); - } - - other => { - println!("Unexpected token in asm expression: {:?}", other); - tokens.next(); - } - } - } - - Some(Expression::AsmBlock { - instructions, - inputs, - outputs, - }) - } - _ => match token.token_type { - TokenType::Continue | TokenType::Break | TokenType::Return | TokenType::SemiColon => { - None - } - _ => { - println!( - "Error: Expected primary expression, found {:?}", - token.token_type - ); - println!( - "Error: Expected primary expression, found {:?}", - token.lexeme - ); - println!("Error: Expected primary expression, found {:?}", token.line); - None - } - }, - }; - - if expr.is_none() { - return None; - } - - loop { - match tokens.peek().map(|t| &t.token_type) { - Some(TokenType::Dot) => { - tokens.next(); // consume '.' - - let name = if let Some(Token { - token_type: TokenType::Identifier(name), - .. - }) = tokens.next() - { - name.clone() - } else { - println!("Error: Expected identifier after '.'"); - return None; - }; - - let base_expr = match expr.take() { - Some(e) => e, - None => { - println!("Internal parser error: missing base expression before '.'"); - return None; - } - }; - - if let Some(Token { - token_type: TokenType::Lparen, - .. - }) = tokens.peek() - { - // ----- MethodCall ----- - tokens.next(); // consume '(' - - let mut args = Vec::new(); - if tokens - .peek() - .map_or(false, |t| t.token_type != TokenType::Rparen) - { - loop { - let arg = parse_expression(tokens)?; - args.push(arg); - - if let Some(Token { - token_type: TokenType::Comma, - .. - }) = tokens.peek() - { - tokens.next(); // consume ',' - } else { - break; - } - } - } - - if tokens - .peek() - .map_or(true, |t| t.token_type != TokenType::Rparen) - { - println!("Error: Expected ')' after method call arguments"); - return None; - } - tokens.next(); // consume ')' - - expr = Some(Expression::MethodCall { - object: Box::new(base_expr), - name, - args, - }); - } else { - // ----- FieldAccess ----- - expr = Some(Expression::FieldAccess { - object: Box::new(base_expr), - field: name, - }); - } - } - - Some(TokenType::Lbrack) => { - tokens.next(); // consume '[' - - let index_expr = parse_expression(tokens)?; - if tokens - .peek() - .map_or(true, |t| t.token_type != TokenType::Rbrack) - { - println!("Error: Expected ']' after index"); - return None; - } - tokens.next(); // consume ']' - - let base_expr = match expr.take() { - Some(e) => e, - None => { - println!("Internal parser error: missing base expression before '['"); - return None; - } - }; - - expr = Some(Expression::IndexAccess { - target: Box::new(base_expr), - index: Box::new(index_expr), - }); - } - - Some(TokenType::Increment) => { - let line = tokens.peek().unwrap().line; - tokens.next(); // consume '++' - - let base = expr.take()?; - if !is_assignable(&base) { - println!("Error: postfix ++ target must be assignable (line {})", line); - return None; - } - - expr = Some(Expression::IncDec { - kind: IncDecKind::PostInc, - target: Box::new(base), - }); - break; - } - - Some(TokenType::Decrement) => { - let line = tokens.peek().unwrap().line; - tokens.next(); // consume '--' - - let base = expr.take()?; - if !is_assignable(&base) { - println!("Error: postfix -- target must be assignable (line {})", line); - return None; - } - - expr = Some(Expression::IncDec { - kind: IncDecKind::PostDec, - target: Box::new(base), - }); - break; - } - - _ => break, - } - } - - expr -} - -pub fn parse_parenthesized_expression<'a, T>(tokens: &mut Peekable) -> Option -where - T: Iterator, -{ - // Ensure the next token is '(' - if tokens.next()?.token_type != TokenType::Lparen { - println!("Error: Expected '('"); - return None; - } - - // Parse the inner expression - let expr = parse_expression(tokens)?; - - // Ensure the next token is ')' - if tokens.next()?.token_type != TokenType::Rparen { - println!("Error: Expected ')'"); - return None; - } - - Some(expr) -} - -pub fn parse_expression_from_token( - first_token: &Token, - tokens: &mut Peekable>, -) -> Option { - match &first_token.token_type { - TokenType::Identifier(name) => Some(Expression::Variable(name.clone())), - - TokenType::Deref => { - if let Some(next_token) = tokens.next() { - if let TokenType::Identifier(name) = &next_token.token_type { - return Some(Expression::Deref(Box::new(Expression::Variable( - name.clone(), - )))); - } - } - None - } - - _ => None, - } -} diff --git a/front/parser/src/lib.rs b/front/parser/src/lib.rs index c3ff1342..a638fc68 100644 --- a/front/parser/src/lib.rs +++ b/front/parser/src/lib.rs @@ -3,7 +3,7 @@ pub mod ast; pub mod format; pub mod import; pub mod stdlib; -pub mod type_system; pub mod verification; +pub mod expr; pub use parser::*; diff --git a/front/parser/src/parser/asm.rs b/front/parser/src/parser/asm.rs index e86a4d5e..1a502950 100644 --- a/front/parser/src/parser/asm.rs +++ b/front/parser/src/parser/asm.rs @@ -3,7 +3,7 @@ use std::slice::Iter; use lexer::Token; use lexer::token::TokenType; use crate::ast::{ASTNode, Expression, Literal, StatementNode}; -use crate::format::is_assignable; +use crate::expr::is_assignable; pub fn parse_asm_block(tokens: &mut Peekable>) -> Option { if tokens.peek()?.token_type != TokenType::Lbrace { @@ -27,7 +27,7 @@ pub fn parse_asm_block(tokens: &mut Peekable>) -> Option { - tokens.next(); // 구분자 스킵 + tokens.next(); } TokenType::String(s) => { @@ -45,7 +45,6 @@ pub fn parse_asm_block(tokens: &mut Peekable>) -> Option { tokens.next(); parse_asm_inout_clause(tokens, true, &mut inputs, &mut outputs)?; diff --git a/front/parser/src/parser/control.rs b/front/parser/src/parser/control.rs index 5e6128a1..ffa9fe8f 100644 --- a/front/parser/src/parser/control.rs +++ b/front/parser/src/parser/control.rs @@ -3,7 +3,7 @@ use std::slice::Iter; use lexer::Token; use lexer::token::TokenType; use crate::ast::{ASTNode, Expression, StatementNode}; -use crate::format::parse_expression; +use crate::expr::parse_expression; use crate::parser::stmt::parse_block; pub fn parse_if(tokens: &mut Peekable>) -> Option { diff --git a/front/parser/src/parser/decl.rs b/front/parser/src/parser/decl.rs index bdb85bc4..26420075 100644 --- a/front/parser/src/parser/decl.rs +++ b/front/parser/src/parser/decl.rs @@ -3,7 +3,7 @@ use std::slice::Iter; use lexer::Token; use lexer::token::TokenType; use crate::ast::{ASTNode, Expression, Mutability, VariableNode, WaveType}; -use crate::format::parse_expression; +use crate::expr::parse_expression; use crate::parser::types::{parse_type, token_type_to_wave_type}; fn collect_generic_inner(tokens: &mut Peekable>) -> Option { @@ -11,7 +11,6 @@ fn collect_generic_inner(tokens: &mut Peekable>) -> Option { depth += 1; @@ -29,7 +28,6 @@ fn collect_generic_inner(tokens: &mut Peekable>) -> Option {} } - // ✅ 2) 그 외는 문자열(lexeme 또는 Identifier 이름)을 스캔해서 <, > 처리 let text: &str = if !t.lexeme.is_empty() { t.lexeme.as_str() } else if let TokenType::Identifier(name) = &t.token_type { diff --git a/front/parser/src/parser/expr.rs b/front/parser/src/parser/expr.rs index fa7cb1ca..aee2b17b 100644 --- a/front/parser/src/parser/expr.rs +++ b/front/parser/src/parser/expr.rs @@ -3,7 +3,7 @@ use std::slice::Iter; use lexer::Token; use lexer::token::TokenType; use crate::ast::Expression; -use crate::format::parse_expression; +use crate::expr::parse_expression; pub fn parse_function_call( name: Option, diff --git a/front/parser/src/parser/functions.rs b/front/parser/src/parser/functions.rs index f22c04dd..a808f2df 100644 --- a/front/parser/src/parser/functions.rs +++ b/front/parser/src/parser/functions.rs @@ -4,7 +4,7 @@ use std::slice::Iter; use lexer::Token; use lexer::token::TokenType; use crate::ast::{ASTNode, FunctionNode, ParameterNode, StatementNode, Value}; -use crate::format::parse_expression; +use crate::expr::parse_expression; use crate::parser::asm::*; use crate::parser::control::*; use crate::parser::decl::*; diff --git a/front/parser/src/parser/io.rs b/front/parser/src/parser/io.rs index afc766ec..5e74185d 100644 --- a/front/parser/src/parser/io.rs +++ b/front/parser/src/parser/io.rs @@ -4,7 +4,7 @@ use utils::formatx::*; use lexer::Token; use lexer::token::TokenType; use crate::ast::{ASTNode, StatementNode}; -use crate::format::parse_expression; +use crate::expr::parse_expression; // PRINTLN parsing pub fn parse_println(tokens: &mut Peekable>) -> Option { diff --git a/front/parser/src/parser/stmt.rs b/front/parser/src/parser/stmt.rs index e5dd49cd..9dc67055 100644 --- a/front/parser/src/parser/stmt.rs +++ b/front/parser/src/parser/stmt.rs @@ -3,7 +3,7 @@ use std::slice::Iter; use lexer::Token; use lexer::token::TokenType; use crate::ast::{ASTNode, AssignOperator, Expression, Operator, StatementNode}; -use crate::format::{parse_expression, parse_expression_from_token}; +use crate::expr::{parse_expression, parse_expression_from_token}; use crate::parser::control::{parse_for, parse_if, parse_while}; use crate::parser::decl::parse_var; use crate::parser::io::*; @@ -228,13 +228,3 @@ pub fn parse_statement(tokens: &mut Peekable>) -> Option { node } - -fn skip_whitespace(tokens: &mut Peekable>) { - while let Some(token) = tokens.peek() { - if token.token_type == TokenType::Whitespace { - tokens.next(); - } else { - break; - } - } -} diff --git a/front/parser/src/type_system.rs b/front/parser/src/type_system.rs deleted file mode 100644 index 344ec13e..00000000 --- a/front/parser/src/type_system.rs +++ /dev/null @@ -1,7 +0,0 @@ -use crate::ast::WaveType; -use crate::*; -use lexer::Token; -use lexer::token::TokenType; -use std::iter::Peekable; -use std::slice::Iter; - diff --git a/llvm_temporary/src/llvm_temporary/expression/lvalue.rs b/llvm_temporary/src/llvm_temporary/expression/lvalue.rs index 489fd1fa..7cf9ff5b 100644 --- a/llvm_temporary/src/llvm_temporary/expression/lvalue.rs +++ b/llvm_temporary/src/llvm_temporary/expression/lvalue.rs @@ -4,7 +4,6 @@ use inkwell::{ module::Module, types::StructType, values::{BasicValueEnum, PointerValue}, - AddressSpace, }; use std::collections::HashMap; use parser::ast::Expression; diff --git a/llvm_temporary/src/llvm_temporary/expression/rvalue/literals.rs b/llvm_temporary/src/llvm_temporary/expression/rvalue/literals.rs index ee4e073a..021b38e2 100644 --- a/llvm_temporary/src/llvm_temporary/expression/rvalue/literals.rs +++ b/llvm_temporary/src/llvm_temporary/expression/rvalue/literals.rs @@ -1,5 +1,5 @@ use super::ExprGenEnv; -use inkwell::types::{BasicType, BasicTypeEnum, StringRadix}; +use inkwell::types::{BasicTypeEnum, StringRadix}; use inkwell::values::{BasicValue, BasicValueEnum}; use parser::ast::Literal; @@ -138,7 +138,5 @@ pub(crate) fn gen<'ctx, 'a>( Literal::Char(c) => env.context.i8_type().const_int(*c as u64, false).as_basic_value_enum(), Literal::Byte(b) => env.context.i8_type().const_int(*b as u64, false).as_basic_value_enum(), - - _ => unimplemented!("Unsupported literal type"), } } diff --git a/llvm_temporary/src/llvm_temporary/llvm_codegen/ir.rs b/llvm_temporary/src/llvm_temporary/llvm_codegen/ir.rs index b1dd3a01..67ff1ed8 100644 --- a/llvm_temporary/src/llvm_temporary/llvm_codegen/ir.rs +++ b/llvm_temporary/src/llvm_temporary/llvm_codegen/ir.rs @@ -1,7 +1,7 @@ use inkwell::context::Context; use inkwell::passes::{PassManager, PassManagerBuilder}; use inkwell::types::{BasicMetadataTypeEnum, BasicType, BasicTypeEnum}; -use inkwell::values::{BasicValue, BasicValueEnum, FunctionValue}; +use inkwell::values::{BasicValueEnum, FunctionValue}; use inkwell::OptimizationLevel; use parser::ast::{ASTNode, FunctionNode, Mutability, VariableNode, WaveType}; diff --git a/llvm_temporary/src/llvm_temporary/llvm_codegen/mod.rs b/llvm_temporary/src/llvm_temporary/llvm_codegen/mod.rs index 3b18630a..c1b60047 100644 --- a/llvm_temporary/src/llvm_temporary/llvm_codegen/mod.rs +++ b/llvm_temporary/src/llvm_temporary/llvm_codegen/mod.rs @@ -10,5 +10,4 @@ pub use format::{wave_format_to_c, wave_format_to_scanf}; pub use ir::generate_ir; pub use types::{wave_type_to_llvm_type, VariableInfo}; -// legacy (TokenType 기반) - 아직 참조하는 곳 있으면 쓰고, 없으면 지워도 됨 pub use legacy::{create_alloc, get_llvm_type}; diff --git a/llvm_temporary/src/llvm_temporary/llvm_codegen/types.rs b/llvm_temporary/src/llvm_temporary/llvm_codegen/types.rs index 309267d4..d40dea8f 100644 --- a/llvm_temporary/src/llvm_temporary/llvm_codegen/types.rs +++ b/llvm_temporary/src/llvm_temporary/llvm_codegen/types.rs @@ -44,9 +44,6 @@ pub fn wave_type_to_llvm_type<'ctx>( .unwrap_or_else(|| panic!("Struct type '{}' not found", name)); struct_ty.as_basic_type_enum() } - _ => { - panic!("Unsupported wave type type"); - } } } diff --git a/llvm_temporary/src/llvm_temporary/statement/io.rs b/llvm_temporary/src/llvm_temporary/statement/io.rs index 870a2d20..3d1d0eac 100644 --- a/llvm_temporary/src/llvm_temporary/statement/io.rs +++ b/llvm_temporary/src/llvm_temporary/statement/io.rs @@ -87,7 +87,7 @@ pub(super) fn gen_print_format_ir<'ctx>( struct_types: &HashMap>, struct_field_indices: &HashMap>, ) { - // ⚠️ 원본은 args를 2번 평가했는데(부작용 가능), 여기선 1번만 평가하도록 고쳤어. + // NOTE: Avoid evaluating arguments twice to prevent side effects let mut arg_vals: Vec> = Vec::with_capacity(args.len()); let mut arg_types = Vec::with_capacity(args.len()); @@ -181,7 +181,6 @@ pub(super) fn gen_input_ir<'ctx>( struct_types: &HashMap>, struct_field_indices: &HashMap>, ) { - // lvalue도 2번 만들 필요 없어서 1번만 만들도록 정리 let mut ptrs = Vec::with_capacity(args.len()); let mut arg_types = Vec::with_capacity(args.len()); diff --git a/llvm_temporary/src/llvm_temporary/statement/variable.rs b/llvm_temporary/src/llvm_temporary/statement/variable.rs index ba36b76f..1a103cf7 100644 --- a/llvm_temporary/src/llvm_temporary/statement/variable.rs +++ b/llvm_temporary/src/llvm_temporary/statement/variable.rs @@ -1,10 +1,9 @@ use crate::llvm_temporary::expression::rvalue::generate_expression_ir; use crate::llvm_temporary::llvm_codegen::{wave_type_to_llvm_type, VariableInfo}; -use inkwell::module::{Linkage, Module}; -use inkwell::types::{AnyTypeEnum, BasicType, BasicTypeEnum, StructType}; +use inkwell::module::{Module}; +use inkwell::types::{BasicTypeEnum, StructType}; use inkwell::values::{BasicValue, BasicValueEnum}; -use inkwell::{AddressSpace}; -use parser::ast::{Expression, Literal, VariableNode, WaveType}; +use parser::ast::{Expression, VariableNode, WaveType}; use std::collections::HashMap; #[derive(Copy, Clone, Debug)]