diff --git a/front/lexer/src/lexer/lexer.rs b/front/lexer/src/lexer/lexer.rs index 61164a36..16846280 100644 --- a/front/lexer/src/lexer/lexer.rs +++ b/front/lexer/src/lexer/lexer.rs @@ -477,6 +477,14 @@ impl<'a> Lexer<'a> { lexeme: ",".to_string(), line: self.line, }, + '\'' => { + let value = self.char_literal(); + Token { + token_type: TokenType::CharLiteral(value), + lexeme: format!("'{}'", value), + line: self.line, + } + }, '"' => { let string_value = self.string(); Token { @@ -758,6 +766,16 @@ impl<'a> Lexer<'a> { lexeme: "break".to_string(), line: self.line, }, + "true" => Token { + token_type: TokenType::BoolLiteral(true), + lexeme: "true".to_string(), + line: self.line, + }, + "false" => Token { + token_type: TokenType::BoolLiteral(false), + lexeme: "false".to_string(), + line: self.line, + }, _ => Token { token_type: TokenType::Identifier(identifier.clone()), lexeme: identifier, @@ -766,48 +784,43 @@ impl<'a> Lexer<'a> { } } '0'..='9' => { - let mut num_str = self.number().to_string(); // 첫 숫자만 읽음 - - // 16진수 접두사 체크 - if num_str == "0" && (self.peek() == 'x' || self.peek() == 'X') { - num_str.push(self.advance()); // 'x' 붙이기 + if c == '0' && (self.peek() == 'x' || self.peek() == 'X') { + self.advance(); // consume 'x' or 'X' + let mut hex_str = String::new(); while self.peek().is_ascii_hexdigit() { - num_str.push(self.advance()); + hex_str.push(self.advance()); } - let value = i64::from_str_radix(&num_str[2..], 16).unwrap_or(0); + let value = i64::from_str_radix(&hex_str, 16).unwrap_or(0); + return Token { token_type: TokenType::Number(value), - lexeme: num_str, + lexeme: format!("0x{}", hex_str), line: self.line, }; } - // float 처리 + let mut num_str = c.to_string(); + while self.peek().is_ascii_digit() { + num_str.push(self.advance()); + } + let is_float = if self.peek() == '.' { num_str.push('.'); self.advance(); - while self.peek().is_ascii_digit() { - num_str.push(self.advance()); // 소수점 뒤 숫자 + num_str.push(self.advance()); } true } else { false }; - // 일반 숫자/실수 토큰 결정 let token_type = if is_float { - num_str - .parse::() - .map(TokenType::Float) - .unwrap_or(TokenType::Float(0.0)) + num_str.parse::().map(TokenType::Float).unwrap() } else { - num_str - .parse::() - .map(TokenType::Number) - .unwrap_or(TokenType::Number(0)) + num_str.parse::().map(TokenType::Number).unwrap() }; Token { @@ -872,6 +885,32 @@ impl<'a> Lexer<'a> { string_literal } + fn char_literal(&mut self) -> char { + let c = if self.peek() == '\\' { + self.advance(); // consume '\' + let escaped = self.advance(); + match escaped { + 'n' => '\n', + 't' => '\t', + 'r' => '\r', + '\\' => '\\', + '\'' => '\'', + '"' => '"', + _ => panic!("Invalid escape sequence in char literal"), + } + } else { + self.advance() + }; + + if self.peek() != '\'' { + panic!("Unterminated or invalid char literal"); + } + + self.advance(); // closing ' + + c + } + fn identifier(&mut self) -> String { let start = if self.current > 0 { self.current - 1 diff --git a/front/lexer/src/lexer/token.rs b/front/lexer/src/lexer/token.rs index 028e58e9..e7d6e163 100644 --- a/front/lexer/src/lexer/token.rs +++ b/front/lexer/src/lexer/token.rs @@ -164,4 +164,6 @@ pub enum TokenType { Proto, Struct, TypeVoid, + CharLiteral(char), + BoolLiteral(bool), } diff --git a/front/parser/src/parser/ast.rs b/front/parser/src/parser/ast.rs index 4376c26e..71b34a30 100644 --- a/front/parser/src/parser/ast.rs +++ b/front/parser/src/parser/ast.rs @@ -133,6 +133,9 @@ pub enum Literal { Number(i64), Float(f64), String(String), + Bool(bool), + Char(char), + Byte(u8), } #[derive(Debug, Clone)] diff --git a/front/parser/src/parser/format.rs b/front/parser/src/parser/format.rs index 279f2158..8fcc665d 100644 --- a/front/parser/src/parser/format.rs +++ b/front/parser/src/parser/format.rs @@ -257,6 +257,14 @@ where 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(); diff --git a/llvm_temporary/src/llvm_temporary/expression.rs b/llvm_temporary/src/llvm_temporary/expression.rs index 5608801c..ab13a665 100644 --- a/llvm_temporary/src/llvm_temporary/expression.rs +++ b/llvm_temporary/src/llvm_temporary/expression.rs @@ -72,6 +72,24 @@ pub fn generate_expression_ir<'ctx>( gep.as_basic_value_enum() }, + Literal::Bool(v) => { + context + .bool_type() + .const_int(if *v { 1 } else { 0 }, false) + .as_basic_value_enum() + }, + Literal::Char(c) => { + context + .i8_type() + .const_int(*c as u64, false) + .as_basic_value_enum() + }, + Literal::Byte(b) => { + 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_backend.rs b/llvm_temporary/src/llvm_temporary/llvm_backend.rs index 1cc3ad0d..236c6909 100644 --- a/llvm_temporary/src/llvm_temporary/llvm_backend.rs +++ b/llvm_temporary/src/llvm_temporary/llvm_backend.rs @@ -13,7 +13,7 @@ pub fn compile_ir_to_object(ir: &str, file_stem: &str, opt_flag: &str) -> String .arg("-") .arg("-o") .arg(&object_path) - .stdin(std::process::Stdio::piped()) + .arg("-Wno-override-module") .stdin(std::process::Stdio::piped()) .spawn() .expect("Failed to execute clang"); diff --git a/llvm_temporary/src/llvm_temporary/statement.rs b/llvm_temporary/src/llvm_temporary/statement.rs index 6e53e9bc..0f713aed 100644 --- a/llvm_temporary/src/llvm_temporary/statement.rs +++ b/llvm_temporary/src/llvm_temporary/statement.rs @@ -111,10 +111,32 @@ pub fn generate_statement_ir<'ctx>( ( Expression::Literal(Literal::Float(value)), BasicTypeEnum::FloatType(float_type), - ) => { + ) + => { let init_value = float_type.const_float(*value); builder.build_store(alloca, init_value).unwrap(); } + ( + Expression::Literal(Literal::Bool(v)), + BasicTypeEnum::IntType(int_ty), + ) => { + let val = int_ty.const_int(if *v { 1 } else { 0 }, false); + builder.build_store(alloca, val).unwrap(); + } + ( + Expression::Literal(Literal::Char(c)), + BasicTypeEnum::IntType(int_ty), + ) => { + let val = int_ty.const_int(*c as u64, false); + builder.build_store(alloca, val).unwrap(); + } + ( + Expression::Literal(Literal::Byte(b)), + BasicTypeEnum::IntType(int_ty), + ) => { + let val = int_ty.const_int(*b as u64, false); + builder.build_store(alloca, val).unwrap(); + } (Expression::Literal(Literal::Float(value)), _) => { let float_value = context.f32_type().const_float(*value); diff --git a/test/test71.wave b/test/test71.wave new file mode 100644 index 00000000..3f3e119a --- /dev/null +++ b/test/test71.wave @@ -0,0 +1,12 @@ +fun main() { + var a: i32 = 10; + var b: u32 = 20; + var c: f32 = 10.1; + var d: str = "Wave"; + var e: bool = true; + var f: byte = 0xFF; + var g: char = 'A'; + var h: ptr = &a; + var i: array = [1, 2, 3, 4, 5]; + println("{}\n {}\n {}\n {}\n {}\n {}\n {}\n {}\n {}", a, b, c, d, e, f, g, h, i); +} \ No newline at end of file