summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lex.c6
-rw-r--r--parse.y16
-rw-r--r--rc.115
3 files changed, 25 insertions, 12 deletions
diff --git a/lex.c b/lex.c
index 92732f8..195e8f6 100644
--- a/lex.c
+++ b/lex.c
@@ -178,9 +178,9 @@ top: while ((c = gchar()) == ' ' || c == '\t')
y->word.q = FALSE;
return WORD;
}
- if (c == '`' || c == '!' || c == '@' || c == '~' || c == '$' || c == '\'') {
+ if (c == '`' || c == '!' || c == '@' || c == '~' || c == '$' || c == '\'' || c == '=') {
checkfreecaret;
- if (c == '!' || c == '@' || c == '~')
+ if (c == '!' || c == '@' || c == '~' || c == '=')
w = KW;
}
switch (c) {
@@ -255,9 +255,9 @@ top: while ((c = gchar()) == ' ' || c == '\t')
case ';':
case '^':
case ')':
- case '=':
case '{': case '}':
w = NW;
+ case '=':
return c;
case '&':
w = NW;
diff --git a/parse.y b/parse.y
index 8be65bb..bde299e 100644
--- a/parse.y
+++ b/parse.y
@@ -16,6 +16,7 @@ Node *parsetree; /* not using yylval because bison declares it as an auto */
%token ANDAND BACKBACK BANG CASE COUNT DUP ELSE END FLAT FN FOR IF IN
%token OROR PIPE REDIR SREDIR SUB SUBSHELL SWITCH TWIDDLE WHILE WORD HUH
+%left '^' '='
%left WHILE ')' ELSE
%left ANDAND OROR '\n'
%left BANG SUBSHELL
@@ -41,6 +42,7 @@ Node *parsetree; /* not using yylval because bison declares it as an auto */
%type <keyword> keyword
%type <node> assign body brace case cbody cmd cmdsa cmdsan comword epilog
first line nlwords paren redir sword simple iftail word words
+ arg args
%start rc
@@ -72,7 +74,7 @@ brace : '{' body '}' { $$ = $2; }
paren : '(' body ')' { $$ = $2; }
-assign : first '=' word { $$ = mk(nAssign,$1,$3); }
+assign : first optcaret '=' optcaret word { $$ = mk(nAssign,$1,$5); }
epilog : { $$ = NULL; }
| redir epilog { $$ = mk(nEpilog,$1,$2); }
@@ -115,12 +117,17 @@ cmd : /* empty */ %prec WHILE { $$ = NULL; }
| FN words brace { $$ = mk(nNewfn,$2,$3); }
| FN words { $$ = mk(nRmfn,$2); }
-optcaret : /* empty */
+optcaret : /* empty */ %prec '^'
| '^'
simple : first
- | simple word { $$ = ($2 != NULL ? mk(nArgs,$1,$2) : $1); }
- | simple redir { $$ = mk(nArgs,$1,$2); }
+ | first args { $$ = ($2 != NULL ? mk(nArgs,$1,$2) : $1); }
+
+args : arg
+ | args arg { $$ = ($2 != NULL ? mk(nArgs,$1,$2) : $1); }
+
+arg : word
+ | redir
first : comword
| first '^' sword { $$ = mk(nConcat,$1,$3); }
@@ -154,6 +161,7 @@ keyword : FOR { $$ = "for"; }
| TWIDDLE { $$ = "~"; }
| BANG { $$ = "!"; }
| SUBSHELL { $$ = "@"; }
+ | '=' { $$ = "="; }
words : { $$ = NULL; }
| words word { $$ = ($1 != NULL ? ($2 != NULL ? mk(nLappend,$1,$2) : $1) : $2); }
diff --git a/rc.1 b/rc.1
index 3a21bf5..3f16c74 100644
--- a/rc.1
+++ b/rc.1
@@ -395,7 +395,7 @@ interprets several characters specially; special characters
automatically terminate words.
The following characters are special:
.Ds
-.Cr "# ; & | ^ $ = \` ' { } ( ) < >"
+.Cr "# ; & | ^ $ \` ' { } ( ) < >"
.De
.PP
The single quote
@@ -1936,6 +1936,7 @@ grammar, edited to remove semantic actions.
%term ANDAND BACKBACK BANG CASE COUNT DUP ELSE END FLAT FN FOR IF IN
%term OROR PIPE REDIR SUB SUBSHELL SWITCH TWIDDLE WHILE WORD HUH
+%left '^' '='
%left WHILE ')' ELSE
%left ANDAND OROR '\en'
%left BANG SUBSHELL
@@ -1964,7 +1965,7 @@ brace: '{' body '}'
paren: '(' body ')'
-assign: first '=' word
+assign: first optcaret '=' optcaret word
epilog: /* empty */ | redir epilog
@@ -1996,9 +1997,13 @@ cmd : /* empty */ %prec WHILE
| FN words brace
| FN words
-optcaret: /* empty */ | '^'
+optcaret: /* empty */ %prec '^' | '^'
-simple: first | simple word | simple redir
+simple: first | first args
+
+args: arg | args arg
+
+arg: word | redir
first: comword | first '^' sword
@@ -2018,7 +2023,7 @@ comword: '$' sword
| WORD
keyword: FOR | IN | WHILE | IF | SWITCH
- | FN | ELSE | CASE | TWIDDLE | BANG | SUBSHELL
+ | FN | ELSE | CASE | TWIDDLE | BANG | SUBSHELL | '='
words: /* empty */ | words word