@@ -36,7 +36,7 @@ impl Parser {
3636
3737 pub fn parse ( & mut self , line : & str ) {
3838 self . err = "" . to_string ( ) ;
39- self . token = match tokens ( line) {
39+ self . token = match tokens ( line, false ) {
4040 Ok ( t) => t,
4141 Err ( e) => {
4242 self . err += & e;
@@ -55,6 +55,31 @@ impl Parser {
5555 }
5656 }
5757
58+ pub fn parse_double_quoted_string ( & mut self , line : & str ) -> Result < Vec < Argument > , String > {
59+ self . err = "" . to_string ( ) ;
60+ self . token = match tokens ( line, true ) {
61+ Ok ( t) => t,
62+ Err ( e) => {
63+ self . err += & e;
64+ Vec :: new ( )
65+ }
66+ } ;
67+
68+ let mut stringies: Vec < Argument > = Vec :: new ( ) ;
69+ while !self . current_is ( ShTokenType :: EndOfFile ) {
70+ let a = if self . current_is ( ShTokenType :: WhiteSpace ) {
71+ let r = Argument :: Name ( self . current ( ) . lexeme . clone ( ) ) ;
72+ self . next_token ( ) ;
73+ r
74+ } else {
75+ self . parse_double_argument ( ) ?
76+ . unwrap_or_else ( || Argument :: Name ( String :: default ( ) ) )
77+ } ;
78+ stringies. push ( a) ;
79+ }
80+ Ok ( stringies)
81+ }
82+
5883 // the results are a left-associative no precedence
5984 // list of and / or expressions.
6085 fn parse_andor_list ( & mut self ) -> Result < AndOrNode , String > {
@@ -465,33 +490,34 @@ impl Parser {
465490 Ok ( argument)
466491 }
467492
493+ fn parse_variable_name ( & mut self ) -> Result < Option < Argument > , String > {
494+ match self . current ( ) . token_type {
495+ ShTokenType :: Name => Ok ( Some ( Argument :: Variable ( VariableLookup {
496+ name : self . consume_current ( ) . lexeme . clone ( ) ,
497+ } ) ) ) ,
498+ ShTokenType :: LeftParen => Ok ( Some ( Argument :: SubShell ( SubShellExpr {
499+ shell : self . collect_matching ( ShTokenType :: LeftParen , ShTokenType :: RightParen ) ?,
500+ } ) ) ) ,
501+ ShTokenType :: LeftBrace => Ok ( Some ( Argument :: Expansion ( self . parse_expansion ( ) ?) ) ) ,
502+ ShTokenType :: DollarSign
503+ | ShTokenType :: Bang
504+ | ShTokenType :: Star
505+ | ShTokenType :: Pound
506+ | ShTokenType :: AtSign => Ok ( Some ( Argument :: Variable ( VariableLookup {
507+ name : self . consume_current ( ) . lexeme . clone ( ) ,
508+ } ) ) ) ,
509+ _ => Err ( "Expected some value after '$'" . to_string ( ) ) ,
510+ }
511+ }
512+
468513 // helper function for parse_argument that gets exactly one 'primitive' argument
469514 // which may be strung together to create
470515 fn _parse_argument ( & mut self ) -> Result < Option < Argument > , String > {
471516 match self . current ( ) . token_type {
472517 ShTokenType :: Name => Ok ( Some ( Argument :: Name ( self . consume_current ( ) . lexeme . clone ( ) ) ) ) ,
473518 ShTokenType :: DollarSign => {
474519 self . consume ( ShTokenType :: DollarSign ) ?;
475- match self . current ( ) . token_type {
476- ShTokenType :: Name => Ok ( Some ( Argument :: Variable ( VariableLookup {
477- name : self . consume_current ( ) . lexeme . clone ( ) ,
478- } ) ) ) ,
479- ShTokenType :: LeftParen => Ok ( Some ( Argument :: SubShell ( SubShellExpr {
480- shell : self
481- . collect_matching ( ShTokenType :: LeftParen , ShTokenType :: RightParen ) ?,
482- } ) ) ) ,
483- ShTokenType :: LeftBrace => {
484- Ok ( Some ( Argument :: Expansion ( self . parse_expansion ( ) ?) ) )
485- }
486- ShTokenType :: DollarSign
487- | ShTokenType :: Bang
488- | ShTokenType :: Star
489- | ShTokenType :: Pound
490- | ShTokenType :: AtSign => Ok ( Some ( Argument :: Variable ( VariableLookup {
491- name : self . consume_current ( ) . lexeme . clone ( ) ,
492- } ) ) ) ,
493- _ => Err ( "Expected some value after '$'" . to_string ( ) ) ,
494- }
520+ self . parse_variable_name ( )
495521 }
496522
497523 ShTokenType :: BackTickStr => Ok ( Some ( Argument :: SubShell ( SubShellExpr {
@@ -518,6 +544,41 @@ impl Parser {
518544 }
519545 }
520546
547+ pub fn parse_double_argument ( & mut self ) -> Result < Option < Argument > , String > {
548+ let mut argument: Option < Argument > = None ;
549+ while let Some ( a) = self . _parse_double_argument ( ) ? {
550+ // while we still have tokens in the assignment we need
551+ // to construct it at run time by creating MergeExprss
552+ // of the various types of arguments strung together.
553+ if argument. is_some ( ) {
554+ let l = argument. take ( ) . unwrap ( ) ;
555+ argument = Some ( Argument :: Merge ( MergeExpr {
556+ left : Box :: new ( l) ,
557+ right : Box :: new ( a) ,
558+ } ) ) ;
559+ } else {
560+ argument = Some ( a) ;
561+ }
562+ }
563+ Ok ( argument)
564+ }
565+
566+ // helper function for parse_argument that gets exactly one 'primitive' argument
567+ // which may be strung together to create
568+ fn _parse_double_argument ( & mut self ) -> Result < Option < Argument > , String > {
569+ match self . current ( ) . token_type {
570+ ShTokenType :: Name => Ok ( Some ( Argument :: Name ( self . consume_current ( ) . lexeme . clone ( ) ) ) ) ,
571+ ShTokenType :: DollarSign => {
572+ self . consume ( ShTokenType :: DollarSign ) ?;
573+ self . parse_variable_name ( )
574+ }
575+ ShTokenType :: BackTickStr => Ok ( Some ( Argument :: SubShell ( SubShellExpr {
576+ shell : self . consume_current ( ) . lexeme . clone ( ) ,
577+ } ) ) ) ,
578+ ShTokenType :: EndOfFile => Ok ( None ) ,
579+ _ => Ok ( Some ( Argument :: Name ( self . consume_current ( ) . lexeme . clone ( ) ) ) ) ,
580+ }
581+ }
521582 fn skip_whitespace ( & mut self ) {
522583 while self . current_is ( ShTokenType :: WhiteSpace ) {
523584 self . next_token ( ) ;
0 commit comments