From d0ee32e585437b76f095379ec84fd753a5d30a3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bert=20M=C3=BCnnich?= Date: Sat, 27 Feb 2016 20:52:33 +0100 Subject: Parse equals sign as keyword The parser treats unexpected keyword tokens (eg. if, while, ~) as literals and not as syntax errors. It does not do this for the equals sign, but it could, as it only has a special meaning at the beginning of a command, much like the keywords. Doing this allows one to write commands like this: dd if'='/dev/zero of'='data bs'='1024 count'='1 without the quotes around the equals signs. All shells from the Bourne family do this. For this to work, the lexer must not automatically terminate words at equals signs, instead it has to generate a free caret around it like for the twiddle and other such special characters. In the parser's grammar we need to get rid of the left recursion in the rules for 'simple' to turn the reduce/reduce conflict at 'first' on '=' (empty -> 'optcaret' or 'first' -> 'simple') into a shift/reduce conflict, which then can be solved with precedence/associativity so that the reduction of the empty 'optcaret' wins over shifting '='. --- lex.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'lex.c') 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; -- cgit v1.2.3