Skip to content

Commit 14f2c80

Browse files
committed
feat(semantic): 支持浮点数解析.
1 parent 05380e9 commit 14f2c80

4 files changed

Lines changed: 99 additions & 16 deletions

File tree

script.exf

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,5 @@
11

2-
var num = 1 + 1 - 3;
2+
var num = .5138;
3+
var num1 = 1.2e-3;
4+
var num2 = 10.;
5+
var num3 = 3.14159265358979;

src/compiler/lexer.rs

Lines changed: 90 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::compiler::lexer::LexerError::{UnexpectedCharacter, Eof};
1+
use crate::compiler::lexer::LexerError::{Eof, UnexpectedCharacter};
22
use crate::compiler::lexer::TokenType::End;
33
use smol_str::{SmolStr, SmolStrBuilder};
44
use std::char;
@@ -32,6 +32,7 @@ pub enum LexerError {
3232
#[derive(Debug, Clone, Copy, PartialEq)]
3333
pub enum TokenType {
3434
Number,
35+
Float,
3536
LiteralString,
3637
Identifier,
3738
Semicolon,
@@ -92,6 +93,10 @@ impl Token {
9293
}
9394
}
9495

96+
pub fn value_float(&mut self) -> f64 {
97+
self.data.parse::<f64>().unwrap()
98+
}
99+
95100
pub fn value_number(&mut self) -> i64 {
96101
if let Some(hex) = self
97102
.data
@@ -226,13 +231,38 @@ impl LexerAnalysis {
226231
data_index: usize,
227232
) -> Result<Token, LexerError> {
228233
let mut data = SmolStrBuilder::new();
229-
let mut first_char = self.next_char();
230-
data.push(first_char);
234+
let mut is_float = false;
235+
236+
let first_char = self.next_char();
237+
238+
if first_char == '.' {
239+
let lookahead = self.next_char();
240+
241+
if lookahead.is_ascii_digit() {
242+
// 合法浮点:.123
243+
is_float = true;
244+
data.push('.');
245+
data.push(lookahead);
246+
} else {
247+
// 非法 .<num> 组合 → 返回分号,并缓存字符
248+
self.cache = Some(lookahead);
249+
return Ok(Token::new(
250+
".".into(),
251+
line,
252+
column,
253+
data_index,
254+
TokenType::Semicolon,
255+
));
256+
}
257+
} else {
258+
data.push(first_char);
259+
}
231260

232261
if first_char == '0' {
233-
first_char = self.next_char();
234-
data.push(first_char);
235-
match first_char {
262+
let next = self.next_char();
263+
data.push(next);
264+
265+
match next {
236266
'x' | 'X' => {
237267
loop {
238268
match self.next_char() {
@@ -243,6 +273,7 @@ impl LexerAnalysis {
243273
}
244274
}
245275
}
276+
246277
return Ok(Token::new(
247278
data.finish(),
248279
line,
@@ -255,13 +286,13 @@ impl LexerAnalysis {
255286
loop {
256287
match self.next_char() {
257288
c if c == '0' || c == '1' => data.push(c),
258-
'\0' => {
259-
self.cache = Some('\0');
289+
c => {
290+
self.cache = Some(c);
260291
break;
261292
}
262-
_ => break,
263293
}
264294
}
295+
265296
return Ok(Token::new(
266297
data.finish(),
267298
line,
@@ -271,15 +302,55 @@ impl LexerAnalysis {
271302
));
272303
}
273304
c if c.is_ascii_digit() => {}
305+
'.' => {
306+
is_float = true;
307+
}
274308
_ => return Err(LexerError::IllegalLiteral),
275309
}
276310
}
277311

312+
// ===== 小数 + 科学计数法解析 =====
278313
loop {
279314
match self.next_char() {
280315
c if c.is_ascii_digit() => {
281316
data.push(c);
282317
}
318+
'.' => {
319+
if is_float {
320+
return Err(LexerError::IllegalLiteral);
321+
}
322+
is_float = true;
323+
data.push('.');
324+
}
325+
'e' | 'E' => {
326+
is_float = true;
327+
data.push('e');
328+
329+
let sign = self.next_char();
330+
if sign == '+' || sign == '-' || sign.is_ascii_digit() {
331+
data.push(sign);
332+
} else {
333+
return Err(LexerError::IllegalLiteral);
334+
}
335+
336+
let mut has_exp_digit = false;
337+
loop {
338+
match self.next_char() {
339+
c if c.is_ascii_digit() => {
340+
has_exp_digit = true;
341+
data.push(c);
342+
}
343+
c => {
344+
if !has_exp_digit {
345+
return Err(LexerError::IllegalLiteral);
346+
}
347+
self.cache = Some(c);
348+
break;
349+
}
350+
}
351+
}
352+
break;
353+
}
283354
c => {
284355
self.cache = Some(c);
285356
break;
@@ -289,10 +360,14 @@ impl LexerAnalysis {
289360

290361
Ok(Token::new(
291362
data.finish(),
292-
self.now_line,
293-
self.now_column,
294-
self.data_index,
295-
TokenType::Number,
363+
line,
364+
column,
365+
data_index,
366+
if is_float {
367+
TokenType::Float
368+
} else {
369+
TokenType::Number
370+
},
296371
))
297372
}
298373

@@ -421,7 +496,7 @@ impl LexerAnalysis {
421496
}
422497

423498
fn is_sem(&self, c: char) -> bool {
424-
c == ',' || c == ':' || c == '?' || c == '.'
499+
c == ',' || c == ':' || c == '?'
425500
}
426501

427502
pub fn get_now_line(&self) -> usize {
@@ -447,7 +522,7 @@ impl LexerAnalysis {
447522
self.cache = Some(c);
448523
self.build_identifier(line, column, data_index)
449524
}
450-
c if c.is_ascii_digit() => {
525+
c if c.is_ascii_digit() || c == '.' => {
451526
self.cache = Some(c);
452527
self.build_number(line, column, data_index)
453528
}

src/compiler/parser/expression.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,7 @@ fn expr_bp(
196196
| TokenType::True
197197
| TokenType::False
198198
| TokenType::LiteralString
199+
| TokenType::Float
199200
| TokenType::Null => ASTExprTree::Literal(token),
200201
| TokenType::This => ASTExprTree::This(token),
201202
TokenType::Identifier => func_call_argument(token, parser, tokens)?,

src/compiler/semantic/expression.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,10 @@ fn lower_expr(
131131
let operand = Operand::ImmNum(tk_lit.value_number());
132132
Ok((operand.clone(), Number, vec![Push(operand)]))
133133
}
134+
TokenType::Float => {
135+
let operand = Operand::ImmFlot(tk_lit.value_float());
136+
Ok((operand.clone(), Float, vec![Push(operand)]))
137+
}
134138
TokenType::LiteralString => {
135139
let operand = Operand::ImmStr(tk_lit.value::<SmolStr>().unwrap());
136140
Ok((operand.clone(), String, vec![Push(operand)]))

0 commit comments

Comments
 (0)