1- use crate :: compiler:: lexer:: LexerError :: { UnexpectedCharacter , Eof } ;
1+ use crate :: compiler:: lexer:: LexerError :: { Eof , UnexpectedCharacter } ;
22use crate :: compiler:: lexer:: TokenType :: End ;
33use smol_str:: { SmolStr , SmolStrBuilder } ;
44use std:: char;
@@ -32,6 +32,7 @@ pub enum LexerError {
3232#[ derive( Debug , Clone , Copy , PartialEq ) ]
3333pub 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 }
0 commit comments