@@ -38,9 +38,12 @@ pub(crate) enum Statement<'src> {
3838 expr : Expression < ' src > ,
3939 lines : Lines < ' src > ,
4040 } ,
41+ Return {
42+ expr : Option < Expression < ' src > > ,
43+ } ,
4144}
4245
43- #[ derive( Debug ) ]
46+ #[ derive( Debug , PartialEq ) ]
4447pub ( crate ) enum Atom < ' src > {
4548 Name ( & ' src str ) ,
4649 Real ( Real ) ,
@@ -156,11 +159,19 @@ impl<'src> Function<'src> {
156159 None => err ! ( UnexpectedEOL , 0 , 0 ) ,
157160 }
158161
159- let parameters = Vec :: new ( ) ;
162+ let mut parameters = Vec :: new ( ) ;
160163 loop {
161164 match skip_whitespace ( tokens) {
162165 Some ( ( Token :: BracketRoundClose , _, _) ) => break ,
163- _ => todo ! ( ) ,
166+ Some ( ( Token :: Name ( a) , l, c) ) => {
167+ parameters. push ( a) ;
168+ match skip_whitespace ( tokens) {
169+ Some ( ( Token :: BracketRoundClose , ..) ) => break ,
170+ Some ( ( Token :: Comma , ..) ) => ( ) ,
171+ e => todo ! ( "{:?}" , e) ,
172+ }
173+ }
174+ e => todo ! ( "{:?}" , e) ,
164175 }
165176 }
166177
@@ -216,8 +227,8 @@ impl<'src> Function<'src> {
216227 let ( expr, last_tk) = Expression :: parse ( pre, tokens) ?;
217228 args. push ( expr) ;
218229 match last_tk {
219- Token :: Comma => ( ) ,
220- Token :: BracketRoundClose => break ,
230+ Some ( Token :: Comma ) => ( ) ,
231+ Some ( Token :: BracketRoundClose ) => break ,
221232 tk => {
222233 panic ! ( "Expression did not parse all tokens: {:?}" , tk)
223234 }
@@ -249,7 +260,7 @@ impl<'src> Function<'src> {
249260 Some ( ( tk, ..) ) => Expression :: parse ( tk, tokens) ?,
250261 None => err ! ( UnexpectedEOL , line, column) ,
251262 } ;
252- if tk == Token :: EOL {
263+ if tk == Some ( Token :: EOL ) {
253264 let expected_indent = expected_indent + 1 ;
254265 ' eol: loop {
255266 for i in 0 ..expected_indent {
@@ -279,10 +290,18 @@ impl<'src> Function<'src> {
279290 }
280291 }
281292 Some ( ( Token :: Pass , ..) ) => ( ) ,
282- Some ( ( tk, ..) ) => {
283- dbg ! ( tk) ;
284- todo ! ( )
285- }
293+ Some ( ( Token :: Return , l, c) ) => {
294+ if let Some ( ( tk, l, c) ) = skip_whitespace ( tokens) {
295+ let expr = match Expression :: parse ( tk, tokens) {
296+ Ok ( expr) => Some ( expr. 0 ) ,
297+ e => todo ! ( "{:?}" , e) ,
298+ } ;
299+ lines. push ( Statement :: Return { expr } ) ;
300+ } else {
301+ err ! ( UnexpectedEOL , l, c) ;
302+ }
303+ }
304+ Some ( ( tk, ..) ) => todo ! ( "{:?}" , tk) ,
286305 None => return Ok ( ( lines, 0 ) ) ,
287306 } ;
288307 }
@@ -293,44 +312,108 @@ impl<'src> Expression<'src> {
293312 fn parse (
294313 pre : Token < ' src > ,
295314 tokens : & mut impl Iterator < Item = ( Token < ' src > , usize , usize ) > ,
296- ) -> Result < ( Self , Token < ' src > ) , Error > {
315+ ) -> Result < ( Self , Option < Token < ' src > > ) , Error > {
297316 let ( lhs, last_tk) = match pre {
298317 Token :: BracketRoundOpen => match skip_whitespace ( tokens) {
299- Some ( ( pre, ..) ) => Self :: parse ( pre, tokens) . map ( |( e, t) | ( e, Some ( t ) ) ) ?,
318+ Some ( ( pre, ..) ) => Self :: parse ( pre, tokens) . map ( |( e, t) | ( e, t ) ) ?,
300319 None => err ! ( UnexpectedEOL , 0 , 0 ) ,
301320 } ,
302321 Token :: String ( s) => ( Expression :: Atom ( Atom :: String ( s) ) , None ) ,
303322 Token :: Number ( n) => (
304323 Expression :: Atom ( if let Ok ( n) = parse_integer ( n) {
305- Atom :: Integer ( n)
306- } else if let Ok ( n) = Real :: from_str ( n) {
307- Atom :: Real ( n)
324+ n
308325 } else {
309- dbg ! ( n) ;
310326 err ! ( NotANumber , 0 , 0 ) ;
311327 } ) ,
312328 None ,
313329 ) ,
314- e => {
315- dbg ! ( e) ;
316- todo ! ( )
317- }
330+ Token :: Name ( name) => {
331+ match skip_whitespace ( tokens) {
332+ Some ( ( Token :: BracketRoundOpen , ..) ) => {
333+ let mut arguments = Vec :: new ( ) ;
334+ loop {
335+ match skip_whitespace ( tokens) {
336+ Some ( ( Token :: Number ( n) , l, c) ) => {
337+ if let Ok ( n) = parse_integer ( n) {
338+ arguments. push ( Expression :: Atom ( n) ) ;
339+ } else {
340+ err ! ( NotANumber , l, c) ;
341+ }
342+ } ,
343+ e => todo ! ( "{:?}" , e) ,
344+ }
345+ match skip_whitespace ( tokens) {
346+ Some ( ( Token :: Comma , ..) ) => ( ) ,
347+ Some ( ( Token :: BracketRoundClose , ..) ) => break ,
348+ Some ( ( _, l, c) ) => err ! ( UnexpectedToken , l, c) ,
349+ None => err ! ( UnexpectedEOL , 0 , 0 ) ,
350+ }
351+ }
352+ ( Expression :: Function { name, arguments } , None )
353+ }
354+ Some ( ( tk, ..) ) => ( Expression :: Atom ( Atom :: Name ( name) ) , Some ( tk) ) ,
355+ e => todo ! ( "{:?}" , e) ,
356+ }
357+ }
358+ e => todo ! ( "{:?}" , e) ,
318359 } ;
319- match skip_whitespace ( tokens) {
320- Some ( ( Token :: BracketRoundClose , ..) ) => return Ok ( ( lhs, Token :: BracketRoundClose ) ) ,
321- Some ( ( Token :: Comma , ..) ) => return Ok ( ( lhs, Token :: Comma ) ) ,
322- Some ( ( Token :: EOL , ..) ) => return Ok ( ( lhs, Token :: EOL ) ) ,
323- Some ( ( tk, ..) ) => todo ! ( "{:?}" , tk) ,
324- None => todo ! ( "none" ) ,
325- }
326- /*
327- let lhs = match skip_whitespace(tokens) {
328- Some((Token::BracketRoundOpen, ..)) => Self::parse(tokens)?,
329- Some((Token::String(s), ..)) => Expression::Atom(Atom::String(s)),
330- Some(e) => { dbg!(e); todo!() },
331- None => todo!(),
332- };
333- */
360+ if let Some ( last_tk) = last_tk {
361+ match last_tk {
362+ Token :: Op ( opl) => {
363+ match skip_whitespace ( tokens) {
364+ Some ( ( Token :: Name ( mid) , ..) ) => {
365+ let mid = Expression :: Atom ( Atom :: Name ( mid) ) ;
366+ match skip_whitespace ( tokens) {
367+ Some ( ( Token :: Op ( opr) , ..) ) => {
368+ match skip_whitespace ( tokens) {
369+ Some ( ( Token :: Name ( rhs) , ..) ) => {
370+ let ( left, op, right) = if opl >= opr {
371+ let rhs = Expression :: parse ( Token :: Name ( rhs) , tokens) ?. 0 ;
372+ let lhs = Expression :: Operation {
373+ op : opl,
374+ left : Box :: new ( lhs) ,
375+ right : Box :: new ( mid) ,
376+ } ;
377+ ( lhs, opr, rhs)
378+ } else {
379+ let rhs = Expression :: Atom ( Atom :: Name ( rhs) ) ;
380+ let rhs = Expression :: Operation {
381+ op : opr,
382+ left : Box :: new ( mid) ,
383+ right : Box :: new ( rhs) ,
384+ } ;
385+ ( lhs, opl, rhs)
386+ } ;
387+ let ( left, right) = ( Box :: new ( left) , Box :: new ( right) ) ;
388+ Ok ( ( Expression :: Operation { left, op, right } , skip_whitespace ( tokens) . map ( |v| v. 0 ) ) )
389+ }
390+ e => todo ! ( "{:?}" , e) ,
391+ }
392+ }
393+ Some ( ( tk, ..) ) if tk == Token :: BracketRoundClose || tk == Token :: EOL => {
394+ Ok ( ( Expression :: Operation {
395+ left : Box :: new ( lhs) ,
396+ op : opl,
397+ right : Box :: new ( mid) ,
398+ } , Some ( tk) ) )
399+ }
400+ e => todo ! ( "{:?}" , e) ,
401+ }
402+ }
403+ e => todo ! ( "{:?}" , e) ,
404+ }
405+ }
406+ e => todo ! ( "{:?}" , e) ,
407+ }
408+ } else {
409+ match skip_whitespace ( tokens) {
410+ Some ( ( Token :: BracketRoundClose , ..) ) => return Ok ( ( lhs, Some ( Token :: BracketRoundClose ) ) ) ,
411+ Some ( ( Token :: Comma , ..) ) => return Ok ( ( lhs, Some ( Token :: Comma ) ) ) ,
412+ Some ( ( Token :: EOL , ..) ) => return Ok ( ( lhs, Some ( Token :: EOL ) ) ) ,
413+ Some ( ( tk, ..) ) => todo ! ( "{:?}" , tk) ,
414+ None => todo ! ( "none" ) ,
415+ }
416+ }
334417 }
335418}
336419
@@ -344,45 +427,100 @@ impl Error {
344427 }
345428}
346429
430+ #[ derive( Debug , PartialEq ) ]
347431enum NumberParseError {
348432 InvalidBase ,
349433 InvalidDigit ,
350434 Empty ,
435+ SeparatorInWrongPosition ,
351436}
352437
353- /// Custom integer parsing function that allows underscores
354- fn parse_integer ( s : & str ) -> Result < Integer , NumberParseError > {
438+ /// Custom number parsing function that allows underscores
439+ fn parse_integer ( s : & str ) -> Result < Atom , NumberParseError > {
355440 let mut chars = s. chars ( ) ;
356441 let ( mut chars, base) = if chars. next ( ) == Some ( '0' ) {
357442 if let Some ( c) = chars. next ( ) {
358- let b = match c {
359- 'x' => 16 ,
360- 'b' => 2 ,
361- 'o' => 8 ,
443+ if let Some ( b) = match c {
444+ 'x' => Some ( 16 ) ,
445+ 'b' => Some ( 2 ) ,
446+ 'o' => Some ( 8 ) ,
447+ '0' | '.' => None ,
362448 _ => return Err ( NumberParseError :: InvalidBase ) ,
363- } ;
364- ( chars, b)
449+ } {
450+ ( chars, b)
451+ } else {
452+ ( s. chars ( ) , 10 )
453+ }
365454 } else {
366- return Ok ( 0 ) ;
455+ return Ok ( Atom :: Integer ( 0 ) ) ;
367456 }
368457 } else {
369458 ( s. chars ( ) , 10 )
370459 } ;
371460 if s == "" {
372461 Err ( NumberParseError :: Empty )
373462 } else {
374- let mut chars = chars. peekable ( ) ;
375- let neg = if chars. peek ( ) == Some ( & '-' ) {
376- chars. next ( ) ;
377- true
378- } else {
379- false
380- } ;
381- let mut n = 0 ;
382- for c in chars. filter ( |& c| c != '_' ) {
383- n *= base as Integer ;
384- n += c. to_digit ( base) . ok_or ( NumberParseError :: InvalidDigit ) ? as isize ;
385- }
386- Ok ( if neg { -n } else { n } )
463+ let mut chars = chars. peekable ( ) ;
464+ let neg = if chars. peek ( ) == Some ( & '-' ) {
465+ chars. next ( ) ;
466+ true
467+ } else {
468+ false
469+ } ;
470+ let mut chars = chars. filter ( |& c| c != '_' ) . peekable ( ) ;
471+ // Real numbers and integers have to be processed separately as the range of a real can
472+ // exceed that of an integer
473+ if s. contains ( '.' ) {
474+ // Don't accept '.0', '0.' or even '.'. While many languages accept the former two,
475+ // I believe they are a poor choice for readability, hence they are disallowed.
476+ if chars. peek ( ) . unwrap ( ) == & '.' {
477+ return Err ( NumberParseError :: SeparatorInWrongPosition ) ;
478+ }
479+ let mut n = 0.0 ;
480+ loop {
481+ let c = chars. next ( ) . unwrap ( ) ;
482+ if c == '.' {
483+ break ;
484+ }
485+ n *= base as Real ;
486+ n += c. to_digit ( base) . ok_or ( NumberParseError :: InvalidDigit ) ? as Real ;
487+ }
488+ if chars. peek ( ) == None {
489+ return Err ( NumberParseError :: SeparatorInWrongPosition ) ;
490+ }
491+ let mut i = 1.0 / base as Real ;
492+ for c in chars {
493+ n += ( c. to_digit ( base) . ok_or ( NumberParseError :: InvalidDigit ) ? as Real ) * i;
494+ i /= base as Real ;
495+ }
496+ Ok ( Atom :: Real ( if neg { -n } else { n } ) )
497+ } else {
498+ let mut n = 0 ;
499+ for c in chars {
500+ n *= base as Integer ;
501+ // Negative numbers have a larger range than positive numbers (e.g. i8 has range -128..127)
502+ n -= c. to_digit ( base) . ok_or ( NumberParseError :: InvalidDigit ) ? as Integer ;
503+ }
504+ Ok ( Atom :: Integer ( if neg { n } else { -n } ) )
505+ }
387506 }
388507}
508+
509+ #[ cfg( test) ]
510+ mod test {
511+ use super :: * ;
512+
513+ #[ test]
514+ fn number ( ) {
515+ assert_eq ! ( parse_integer( "0" ) , Ok ( Atom :: Integer ( 0 ) ) ) ;
516+ assert_eq ! ( parse_integer( "32" ) , Ok ( Atom :: Integer ( 32 ) ) ) ;
517+ assert_eq ! ( parse_integer( "0.0" ) , Ok ( Atom :: Real ( 0.0 ) ) ) ;
518+ match parse_integer ( "13.37" ) {
519+ Ok ( Atom :: Real ( f) ) => assert ! ( ( f - 13.37 ) . abs( ) <= Real :: EPSILON * 13.37 ) ,
520+ r => panic ! ( "{:?}" , r) ,
521+ }
522+ assert_eq ! ( parse_integer( "." ) , Err ( NumberParseError :: SeparatorInWrongPosition ) ) ;
523+ assert_eq ! ( parse_integer( "0." ) , Err ( NumberParseError :: SeparatorInWrongPosition ) ) ;
524+ assert_eq ! ( parse_integer( ".0" ) , Err ( NumberParseError :: SeparatorInWrongPosition ) ) ;
525+ }
526+ }
0 commit comments