@@ -355,3 +355,286 @@ fn lexer_test_unicode_escape_eight_digits() {
355355 & [ Token :: String ( b"2" . into( ) ) ]
356356 ) ;
357357}
358+
359+ #[ test]
360+ fn lexer_test_operators ( ) {
361+ let arena = Bump :: new ( ) ;
362+ let str = b"~ !~ | |& >> ** **= ^= += -= *= %= == != <= >= < > && || !" ;
363+ assert_eq ! (
364+ & lex( str , & arena, false , false ) ,
365+ & [
366+ Token :: Matching ,
367+ Token :: NotMatching ,
368+ Token :: Pipe ,
369+ Token :: DoublePipe ,
370+ Token :: AppendPipe ,
371+ Token :: Circumflex ,
372+ Token :: CaretAssign ,
373+ Token :: CaretAssign ,
374+ Token :: PlusAssign ,
375+ Token :: MinusAssign ,
376+ Token :: StarAssign ,
377+ Token :: PercentAssign ,
378+ Token :: EqualTo ,
379+ Token :: NotEqualTo ,
380+ Token :: LesserOrEqualThan ,
381+ Token :: GreaterOrEqualThan ,
382+ Token :: LesserThan ,
383+ Token :: GreaterThan ,
384+ Token :: BooleanAnd ,
385+ Token :: BooleanOr ,
386+ Token :: Negation ,
387+ ]
388+ ) ;
389+ }
390+
391+ #[ test]
392+ fn lexer_test_slash_assign ( ) {
393+ let arena = Bump :: new ( ) ;
394+ assert_eq ! (
395+ & lex( b"a/=1" , & arena, false , false ) ,
396+ & [
397+ Token :: Identifier ( Identifier { namespace: None , literal: "a" } ) ,
398+ Token :: SlashAssign ,
399+ Token :: SmallInt ( 1 ) ,
400+ ]
401+ ) ;
402+ }
403+
404+ #[ test]
405+ fn lexer_test_control_flow_keywords ( ) {
406+ let arena = Bump :: new ( ) ;
407+ let str = b"switch case default getline printf next nextfile exit return continue break" ;
408+ assert_eq ! (
409+ & lex( str , & arena, false , false ) ,
410+ & [
411+ Token :: Switch ,
412+ Token :: Case ,
413+ Token :: Default ,
414+ Token :: Getline ,
415+ Token :: Printf ,
416+ Token :: Next ,
417+ Token :: NextFile ,
418+ Token :: Exit ,
419+ Token :: Return ,
420+ Token :: Continue ,
421+ Token :: Break ,
422+ ]
423+ ) ;
424+ }
425+
426+ #[ test]
427+ fn lexer_test_builtin_variables ( ) {
428+ let arena = Bump :: new ( ) ;
429+ let str =
430+ b"NR NF FS RS OFS ORS FILENAME ARGC ARGV SUBSEP FNR ARGIND OFMT RSTART RLENGTH ENVIRON" ;
431+ assert_eq ! (
432+ & lex( str , & arena, false , false ) ,
433+ & [
434+ Token :: NrVariable ,
435+ Token :: NfVariable ,
436+ Token :: FsVariable ,
437+ Token :: RsVariable ,
438+ Token :: OfsVariable ,
439+ Token :: OrsVariable ,
440+ Token :: FilenameVariable ,
441+ Token :: ArgcVariable ,
442+ Token :: ArgvVariable ,
443+ Token :: SubsepVariable ,
444+ Token :: FnrVariable ,
445+ Token :: ArgindVariable ,
446+ Token :: OfmtVariable ,
447+ Token :: RstartVariable ,
448+ Token :: RlengthVariable ,
449+ Token :: EnvironVariable ,
450+ ]
451+ ) ;
452+ }
453+
454+ #[ test]
455+ fn lexer_test_typed_regex ( ) {
456+ let arena = Bump :: new ( ) ;
457+ assert_eq ! (
458+ & lex( b"@/pat/" , & arena, false , false ) ,
459+ & [ Token :: TypedRegex ( b"pat" . into( ) ) ]
460+ ) ;
461+ }
462+
463+ #[ test]
464+ fn lexer_test_comments ( ) {
465+ let arena = Bump :: new ( ) ;
466+ let str = b"print 1 # comment\n print 2" ;
467+ assert_eq ! (
468+ & lex( str , & arena, false , false ) ,
469+ & [
470+ Token :: Print ,
471+ Token :: SmallInt ( 1 ) ,
472+ Token :: Newline ,
473+ Token :: Print ,
474+ Token :: SmallInt ( 2 ) ,
475+ ]
476+ ) ;
477+ }
478+
479+ #[ test]
480+ fn lexer_test_indirect_call ( ) {
481+ let arena = Bump :: new ( ) ;
482+ assert_eq ! (
483+ & lex( b"@foo @ns::bar" , & arena, false , false ) ,
484+ & [
485+ Token :: IndirectCall ( Identifier { namespace: None , literal: "foo" } ) ,
486+ Token :: IndirectCall ( Identifier { namespace: Some ( "ns" ) , literal: "bar" } ) ,
487+ ]
488+ ) ;
489+ }
490+
491+ #[ test]
492+ #[ should_panic]
493+ fn lexer_test_indirect_call_posix ( ) {
494+ let arena = Bump :: new ( ) ;
495+ lex ( b"@foo" , & arena, true , false ) ;
496+ }
497+
498+ #[ test]
499+ fn lexer_test_concurrent_directive ( ) {
500+ let arena = Bump :: new ( ) ;
501+ assert_eq ! (
502+ & lex( b"@concurrent" , & arena, false , false ) ,
503+ & [ Token :: ConcurrentDirective ]
504+ ) ;
505+ }
506+
507+ #[ test]
508+ fn lexer_test_load_and_namespace_directives ( ) {
509+ let arena = Bump :: new ( ) ;
510+ assert_eq ! (
511+ & lex( br#"@load "lib.so" @namespace "ns""# , & arena, false , false ) ,
512+ & [
513+ Token :: LoadDirective ,
514+ Token :: String ( b"lib.so" . into( ) ) ,
515+ Token :: NamespaceDirective ,
516+ Token :: String ( b"ns" . into( ) ) ,
517+ ]
518+ ) ;
519+ }
520+
521+ #[ test]
522+ fn lexer_test_regex_literals ( ) {
523+ let arena = Bump :: new ( ) ;
524+ assert_eq ! (
525+ & lex( b"/abc/" , & arena, false , false ) ,
526+ & [ Token :: Regex ( b"abc" . into( ) ) ]
527+ ) ;
528+ assert_eq ! (
529+ & lex( b"/a\\ /b/" , & arena, false , false ) ,
530+ & [ Token :: Regex ( b"a/b" . into( ) ) ]
531+ ) ;
532+ assert_eq ! (
533+ & lex( b"x~/dot+/" , & arena, false , false ) ,
534+ & [
535+ Token :: Identifier ( Identifier { namespace: None , literal: "x" } ) ,
536+ Token :: Matching ,
537+ Token :: Regex ( b"dot+" . into( ) ) ,
538+ ]
539+ ) ;
540+ }
541+
542+ #[ test]
543+ fn lexer_test_switch_snippet ( ) {
544+ let arena = Bump :: new ( ) ;
545+ let str = br#"switch (x) { case 1: print; default: break }"# ;
546+ assert_eq ! (
547+ & lex( str , & arena, false , false ) ,
548+ & [
549+ Token :: Switch ,
550+ Token :: OpenParent ,
551+ Token :: Identifier ( Identifier { namespace: None , literal: "x" } ) ,
552+ Token :: ClosedParent ,
553+ Token :: OpenBrace ,
554+ Token :: Case ,
555+ Token :: SmallInt ( 1 ) ,
556+ Token :: Colon ,
557+ Token :: Print ,
558+ Token :: Semicolon ,
559+ Token :: Default ,
560+ Token :: Colon ,
561+ Token :: Break ,
562+ Token :: ClosedBrace ,
563+ ]
564+ ) ;
565+ }
566+
567+ #[ test]
568+ fn lexer_test_getline_redirection ( ) {
569+ let arena = Bump :: new ( ) ;
570+ let str = br#"getline getline x < "f" "cmd" | getline "cmd" |& getline"# ;
571+ assert_eq ! (
572+ & lex( str , & arena, false , false ) ,
573+ & [
574+ Token :: Getline ,
575+ Token :: Getline ,
576+ Token :: Identifier ( Identifier { namespace: None , literal: "x" } ) ,
577+ Token :: LesserThan ,
578+ Token :: String ( b"f" . into( ) ) ,
579+ Token :: String ( b"cmd" . into( ) ) ,
580+ Token :: Pipe ,
581+ Token :: Getline ,
582+ Token :: String ( b"cmd" . into( ) ) ,
583+ Token :: DoublePipe ,
584+ Token :: Getline ,
585+ ]
586+ ) ;
587+ }
588+
589+ #[ test]
590+ fn lexer_test_print_redirection ( ) {
591+ let arena = Bump :: new ( ) ;
592+ let str = br#"print > "out" print >> "out" print | "cmd" print |& "cmd""# ;
593+ assert_eq ! (
594+ & lex( str , & arena, false , false ) ,
595+ & [
596+ Token :: Print ,
597+ Token :: GreaterThan ,
598+ Token :: String ( b"out" . into( ) ) ,
599+ Token :: Print ,
600+ Token :: AppendPipe ,
601+ Token :: String ( b"out" . into( ) ) ,
602+ Token :: Print ,
603+ Token :: Pipe ,
604+ Token :: String ( b"cmd" . into( ) ) ,
605+ Token :: Print ,
606+ Token :: DoublePipe ,
607+ Token :: String ( b"cmd" . into( ) ) ,
608+ ]
609+ ) ;
610+ }
611+
612+ #[ test]
613+ fn lexer_test_func_keyword ( ) {
614+ let arena = Bump :: new ( ) ;
615+ assert_eq ! (
616+ & lex( b"func function" , & arena, false , false ) ,
617+ & [ Token :: Function , Token :: Function ]
618+ ) ;
619+ }
620+
621+ #[ test]
622+ fn lexer_test_func_keyword_posix ( ) {
623+ let arena = Bump :: new ( ) ;
624+ assert_eq ! (
625+ & lex( b"func" , & arena, true , false ) ,
626+ & [ Token :: Identifier ( Identifier {
627+ namespace: None ,
628+ literal: "func"
629+ } ) ]
630+ ) ;
631+ }
632+
633+ #[ test]
634+ fn lexer_test_backslash_escape_in_string ( ) {
635+ let arena = Bump :: new ( ) ;
636+ assert_eq ! (
637+ & lex( b"\" \\ n\\ t\\ \\ \" " , & arena, false , false ) ,
638+ & [ Token :: String ( b"\n \t \\ " . into( ) ) ]
639+ ) ;
640+ }
0 commit comments