rc: move newline handling into parser

This commit is contained in:
Russ Cox 2020-05-04 22:52:27 -04:00
parent 47d4646eeb
commit 3caf5c238a
6 changed files with 67 additions and 24 deletions

View file

@ -9,6 +9,8 @@ fi
for i in $files for i in $files
do do
if ! diff <(./o.rc -DY $i 2>&1) <(./o.rc -D $i 2>&1); then
echo '#' $i echo '#' $i
diff <(./o.rc -DY $i 2>&1) <(./o.rc -D $i 2>&1) exit 1
fi
done done

View file

@ -102,15 +102,17 @@ pprompt(void)
doprompt = 0; doprompt = 0;
} }
void int
skipwhite(void) skipwhite(void)
{ {
int c; int c, skipped;
skipped = 0;
for(;;){ for(;;){
c = nextc(); c = nextc();
/* Why did this used to be if(!inquote && c=='#') ?? */ /* Why did this used to be if(!inquote && c=='#') ?? */
if(c=='#'){ if(c=='#'){
incomm = 1; incomm = 1;
skipped = 1;
for(;;){ for(;;){
c = nextc(); c = nextc();
if(c=='\n' || c==EOF) { if(c=='\n' || c==EOF) {
@ -120,9 +122,12 @@ skipwhite(void)
advance(); advance();
} }
} }
if(c==' ' || c=='\t') if(c==' ' || c=='\t') {
skipped = 1;
advance(); advance();
else return; }
else
return skipped;
} }
} }
@ -210,7 +215,8 @@ yylex(void)
} }
} }
inquote = 0; inquote = 0;
skipwhite(); if(skipwhite() && flag['Z'])
return SP;
switch(c = advance()){ switch(c = advance()){
case EOF: case EOF:
lastdol = 0; lastdol = 0;
@ -231,6 +237,7 @@ yylex(void)
case '&': case '&':
lastdol = 0; lastdol = 0;
if(nextis('&')){ if(nextis('&')){
if(flag['Y'])
skipnl(); skipnl();
strcpy(tok, "&&"); strcpy(tok, "&&");
return ANDAND; return ANDAND;
@ -240,6 +247,7 @@ yylex(void)
case '|': case '|':
lastdol = 0; lastdol = 0;
if(nextis(c)){ if(nextis(c)){
if(flag['Y'])
skipnl(); skipnl();
strcpy(tok, "||"); strcpy(tok, "||");
return OROR; return OROR;
@ -329,7 +337,7 @@ yylex(void)
} }
*w='\0'; *w='\0';
yylval.tree = t; yylval.tree = t;
if(t->type==PIPE) if(t->type==PIPE && flag['Y'])
skipnl(); skipnl();
if(t->type==REDIR) { if(t->type==REDIR) {
skipwhite(); skipwhite();

View file

@ -20,6 +20,14 @@ static tree* words(int tok, int *ptok);
static jmp_buf yyjmp; static jmp_buf yyjmp;
static int
dropnl(int tok)
{
while(tok == '\n')
tok = yylex();
return tok;
}
static void static void
syntax(int tok) syntax(int tok)
{ {
@ -191,13 +199,11 @@ cmd(int tok, int *ptok)
tok = yylex(); tok = yylex();
if(tok == NOT) { if(tok == NOT) {
t1 = yylval.tree; t1 = yylval.tree;
skipnl(); t2 = cmd(dropnl(yylex()), ptok);
t2 = cmd(yylex(), ptok);
return mung1(t1, t2); return mung1(t1, t2);
} }
t2 = paren(tok); t2 = paren(tok);
skipnl(); t3 = cmd(dropnl(yylex()), ptok);
t3 = cmd(yylex(), ptok);
return mung2(t1, t2, t3); return mung2(t1, t2, t3);
case FOR: case FOR:
@ -224,8 +230,7 @@ cmd(int tok, int *ptok)
syntax(tok); syntax(tok);
break; break;
} }
skipnl(); t4 = cmd(dropnl(yylex()), ptok);
t4 = cmd(yylex(), ptok);
return mung3(t1, t2, t3, t4); return mung3(t1, t2, t3, t4);
case WHILE: case WHILE:
@ -233,16 +238,14 @@ cmd(int tok, int *ptok)
// {$$=mung2($1, $2, $4);} // {$$=mung2($1, $2, $4);}
t1 = yylval.tree; t1 = yylval.tree;
t2 = paren(yylex()); t2 = paren(yylex());
skipnl(); t3 = cmd(dropnl(yylex()), ptok);
t3 = cmd(yylex(), ptok);
return mung2(t1, t2, t3); return mung2(t1, t2, t3);
case SWITCH: case SWITCH:
// | SWITCH word {skipnl();} brace // | SWITCH word {skipnl();} brace
// {$$=tree2(SWITCH, $2, $4);} // {$$=tree2(SWITCH, $2, $4);}
t1 = yyword(yylex(), &tok); t1 = yyword(yylex(), &tok);
while(tok == '\n') tok = dropnl(tok); // doesn't work in yacc grammar but works here!
tok = yylex();
t2 = brace(tok); t2 = brace(tok);
*ptok = yylex(); *ptok = yylex();
return tree2(SWITCH, t1, t2); return tree2(SWITCH, t1, t2);
@ -261,7 +264,7 @@ cmd2(int tok, int *ptok)
t1 = cmd3(tok, &tok); t1 = cmd3(tok, &tok);
while(tok == ANDAND || tok == OROR) { while(tok == ANDAND || tok == OROR) {
op = tok; op = tok;
t2 = cmd3(yylex(), &tok); t2 = cmd3(dropnl(yylex()), &tok);
t1 = tree2(op, t1, t2); t1 = tree2(op, t1, t2);
} }
*ptok = tok; *ptok = tok;
@ -277,7 +280,7 @@ cmd3(int tok, int *ptok)
t1 = cmd4(tok, &tok); t1 = cmd4(tok, &tok);
while(tok == PIPE) { while(tok == PIPE) {
t2 = yylval.tree; t2 = yylval.tree;
t3 = cmd4(yylex(), &tok); t3 = cmd4(dropnl(yylex()), &tok);
t1 = mung2(t2, t1, t3); t1 = mung2(t2, t1, t3);
} }
*ptok = tok; *ptok = tok;

View file

@ -244,6 +244,9 @@ pcmdu(io *f, tree *t) /* unambiguous */
pfmt(f, "[%d]", t->fd0); pfmt(f, "[%d]", t->fd0);
break; break;
} }
if(t->rtype == HERE)
pfmt(f, "HERE %u)", c1);
else
pfmt(f, "%u %u)", c0, c1); pfmt(f, "%u %u)", c0, c1);
break; break;
case '=': case '=':

View file

@ -1,4 +1,4 @@
%term FOR IN WHILE IF NOT TWIDDLE BANG SUBSHELL SWITCH FN %term FOR IN WHILE IF NOT TWIDDLE BANG SUBSHELL SWITCH FN SP
%term WORD REDIR REDIRW DUP PIPE SUB %term WORD REDIR REDIRW DUP PIPE SUB
%term SIMPLE ARGLIST WORDS BRACE PAREN PCMD PIPEFD /* not used in syntax */ %term SIMPLE ARGLIST WORDS BRACE PAREN PCMD PIPEFD /* not used in syntax */
/* operator priorities -- lowest first */ /* operator priorities -- lowest first */

View file

@ -36,3 +36,30 @@ $#$x
x for in while if not ~ ! @ switch fn x for in while if not ~ ! @ switch fn
x not$y x not$y
a;b;c a;b;c
if(x)
y
if(x)
{
y
}
if not
z
for(x)
y
for(x in y)
z
while(x)
y
# yacc doesn't accept a newline before the brace
# even though the rule is written as if it would
switch x {
}
switch (x) {
}
z
x &&
y
x ||
y
x |
y