From af3fa90e8bb41c306c5fe2d2cf105db6bbabd1d9 Mon Sep 17 00:00:00 2001 From: Nicholas Noll Date: Tue, 19 Oct 2021 10:53:45 -0700 Subject: Feat: word operators and more robust crashing Added the length and concatenate operators. Slightly improved the robustness on syntax errors. --- sys/cmd/rc/code.c | 20 ++++ sys/cmd/rc/exec.c | 65 +++++++++++- sys/cmd/rc/exec.h | 5 +- sys/cmd/rc/input.c | 1 - sys/cmd/rc/lex.c | 25 ++++- sys/cmd/rc/parse.c | 296 ++++++++++++++++++++++++++++++---------------------- sys/cmd/rc/parse.h | 42 +++++--- sys/cmd/rc/prompt.c | 2 +- sys/cmd/rc/syntax.y | 35 +++++-- 9 files changed, 331 insertions(+), 160 deletions(-) (limited to 'sys') diff --git a/sys/cmd/rc/code.c b/sys/cmd/rc/code.c index d4dd6e1..c98cde2 100644 --- a/sys/cmd/rc/code.c +++ b/sys/cmd/rc/code.c @@ -51,6 +51,7 @@ walk(Tree *node) switch(node->type){ default: print(shell.err, "bad type %d in interpreter walk\n", node->type); + fatal("crashing\n"); break; case '$': @@ -59,6 +60,20 @@ walk(Tree *node) emitf(Xdollar); break; + case Tcount: + emitf(Xmark); + walk(node->child[0]); + emitf(Xcount); + break; + + case Tflat: + emitf(Xmark); + walk(node->child[0]); + emitf(Xflat); + break; + + case Tindex: + #if 0 case '&': emitf(Xasync); @@ -103,6 +118,11 @@ walk(Tree *node) emits(strdup(node->str)); break; + case Twords: + walk(node->child[1]); + walk(node->child[0]); + break; + case '=': for(n=node; node && node->type == '='; node = node->child[2]) ; diff --git a/sys/cmd/rc/exec.c b/sys/cmd/rc/exec.c index d78cb5d..87b6bb7 100644 --- a/sys/cmd/rc/exec.c +++ b/sys/cmd/rc/exec.c @@ -582,7 +582,11 @@ Xreadcmd(void) root = runner; if(yyparse()){ - exit(1); + // resource cleanup? + if(runner->flag.eof) + Xreturn(); + else + --root->code.i; }else{ --root->code.i; /* re-execute Xreadcmd after codebuf runs */ run(compiled, 1, root->local); @@ -670,9 +674,66 @@ Xbasic(void) foreground(runner, 0); // waits for child } +void +Xcount(void) +{ + Word *arg; + char *str, num[12]; + + if(count(runner->args->word) != 1){ + Xerror("variable name not a singleton\n"); + return; + } + + str = runner->args->word->str; + arg = var(str)->val; + poplist(); + + itoa(num, count(arg)); + pushword(num); +} + +void +Xflat(void) +{ + int len; + char *str; + Word *arg, *a; + + if(count(runner->args->word)!=1){ + Xerror("variable name is not a singleton\n"); + return; + } + + str = runner->args->word->str; + arg = var(str)->val; + poplist(); + + len = count(arg); + if(!len){ + pushword(""); + return; + } + + for(a=arg; a; a=a->link) + len += strlen(a->str); + + str = emalloc(len); + if(arg){ + strcpy(str, arg->str); + for(a = arg->link; a; a = a->link){ + strcat(str," "); + strcat(str,a->str); + } + }else + str[0] = 0; + + pushword(str); + efree(str); +} + void Xexit(void) { exit(shell.status); } - diff --git a/sys/cmd/rc/exec.h b/sys/cmd/rc/exec.h index ad53365..566c4a3 100644 --- a/sys/cmd/rc/exec.h +++ b/sys/cmd/rc/exec.h @@ -16,8 +16,11 @@ void Xreadcmd(void); void Xunlocal(void); void Xassign(void); void Xbasic(void); // Xbasic(args) run command and wait for result -void Xerror(char*); void Xword(void); +void Xcount(void); +void Xflat(void); + +void Xerror(char*); /* builtin commands */ void xfg(void); diff --git a/sys/cmd/rc/input.c b/sys/cmd/rc/input.c index 228b2d8..5e5fc78 100644 --- a/sys/cmd/rc/input.c +++ b/sys/cmd/rc/input.c @@ -1030,7 +1030,6 @@ readline(char *prompt) /* insert a newline character at the end */ put(&runner->cmd.io, '\n'); - printf("\n"); return 1; } diff --git a/sys/cmd/rc/lex.c b/sys/cmd/rc/lex.c index b4a2e8c..06737ba 100644 --- a/sys/cmd/rc/lex.c +++ b/sys/cmd/rc/lex.c @@ -2,6 +2,7 @@ #include "parse.h" static int advance(void); + // ----------------------------------------------------------------------- // lexer @@ -14,10 +15,14 @@ struct Lexer static struct Lexer lexer = { .c={0, EOF}, .doprompt=1 }; +#define put1(b) lexer.buf[0] = (b), lexer.buf[1] = 0; +#define put2(b0,b1) lexer.buf[0] = (b0), lexer.buf[1] = (b1), lexer.buf[2] = 0; +#define put3(b0,b1,b2) lexer.buf[0] = (b0), lexer.buf[1] = (b1), lexer.buf[2] = b2, lexer.buf[3] = 0; + void yyerror(const char *msg) { - print(shell.err, "\nrc:%d: ", runner->line); + print(shell.err, "rc:%d: ", runner->line); if(lexer.buf[0] && lexer.buf[0]!='\n') print(shell.err, "%q: ", lexer.buf); @@ -48,7 +53,6 @@ readc(void) exit(1); // XXX: hack for signal handling right now... c = get(runner->cmd.io); - lexer.doprompt = lexer.doprompt || c=='\n' || c==EOF; if(c==EOF) @@ -180,12 +184,25 @@ yylex(void) skipws(); switch(c=advance()){ case EOF: + put3('E','O','F'); return EOF; + case '&': - lexer.buf[0] = '&'; - lexer.buf[1] = 0; + put1('&'); return '&'; + case '$': + if(nextis('#')){ + put2('$','#'); + return Tcount; + } + if(nextis('^')){ + put2('$','^'); + return Tflat; + } + put1('$'); + return '$'; + default: ; } diff --git a/sys/cmd/rc/parse.c b/sys/cmd/rc/parse.c index 42834ed..b88e8ab 100644 --- a/sys/cmd/rc/parse.c +++ b/sys/cmd/rc/parse.c @@ -106,42 +106,47 @@ enum yysymbol_kind_t YYSYMBOL_YYerror = 1, /* error */ YYSYMBOL_YYUNDEF = 2, /* "invalid token" */ YYSYMBOL_Tword = 3, /* Tword */ - YYSYMBOL_Tif = 4, /* Tif */ - YYSYMBOL_Telse = 5, /* Telse */ - YYSYMBOL_Tbang = 6, /* Tbang */ - YYSYMBOL_Targs = 7, /* Targs */ - YYSYMBOL_Tbasic = 8, /* Tbasic */ - YYSYMBOL_Tparen = 9, /* Tparen */ - YYSYMBOL_Tblock = 10, /* Tblock */ - YYSYMBOL_Twhile = 11, /* Twhile */ - YYSYMBOL_12_n_ = 12, /* '\n' */ - YYSYMBOL_13_ = 13, /* '$' */ - YYSYMBOL_14_ = 14, /* '(' */ - YYSYMBOL_15_ = 15, /* ')' */ - YYSYMBOL_16_ = 16, /* '{' */ - YYSYMBOL_17_ = 17, /* '}' */ - YYSYMBOL_18_ = 18, /* ';' */ - YYSYMBOL_19_ = 19, /* '&' */ - YYSYMBOL_20_ = 20, /* '=' */ - YYSYMBOL_21_ = 21, /* '^' */ - YYSYMBOL_YYACCEPT = 22, /* $accept */ - YYSYMBOL_rc = 23, /* rc */ - YYSYMBOL_line = 24, /* line */ - YYSYMBOL_body = 25, /* body */ - YYSYMBOL_paren = 26, /* paren */ - YYSYMBOL_block = 27, /* block */ - YYSYMBOL_cmds = 28, /* cmds */ - YYSYMBOL_cmdsln = 29, /* cmdsln */ - YYSYMBOL_ifbody = 30, /* ifbody */ - YYSYMBOL_assign = 31, /* assign */ - YYSYMBOL_cmd = 32, /* cmd */ - YYSYMBOL_basic = 33, /* basic */ - YYSYMBOL_atom = 34, /* atom */ - YYSYMBOL_word = 35, /* word */ - YYSYMBOL_executable = 36, /* executable */ - YYSYMBOL_nonkeyword = 37, /* nonkeyword */ - YYSYMBOL_keyword = 38, /* keyword */ - YYSYMBOL_nl = 39 /* nl */ + YYSYMBOL_Twords = 4, /* Twords */ + YYSYMBOL_Tif = 5, /* Tif */ + YYSYMBOL_Telse = 6, /* Telse */ + YYSYMBOL_Tbang = 7, /* Tbang */ + YYSYMBOL_Targs = 8, /* Targs */ + YYSYMBOL_Tindex = 9, /* Tindex */ + YYSYMBOL_Tbasic = 10, /* Tbasic */ + YYSYMBOL_Tparen = 11, /* Tparen */ + YYSYMBOL_Tblock = 12, /* Tblock */ + YYSYMBOL_Twhile = 13, /* Twhile */ + YYSYMBOL_14_n_ = 14, /* '\n' */ + YYSYMBOL_15_ = 15, /* '$' */ + YYSYMBOL_Tcount = 16, /* Tcount */ + YYSYMBOL_Tflat = 17, /* Tflat */ + YYSYMBOL_18_ = 18, /* '(' */ + YYSYMBOL_19_ = 19, /* ')' */ + YYSYMBOL_20_ = 20, /* '{' */ + YYSYMBOL_21_ = 21, /* '}' */ + YYSYMBOL_22_ = 22, /* ';' */ + YYSYMBOL_23_ = 23, /* '&' */ + YYSYMBOL_24_ = 24, /* '=' */ + YYSYMBOL_25_ = 25, /* '^' */ + YYSYMBOL_YYACCEPT = 26, /* $accept */ + YYSYMBOL_rc = 27, /* rc */ + YYSYMBOL_line = 28, /* line */ + YYSYMBOL_body = 29, /* body */ + YYSYMBOL_paren = 30, /* paren */ + YYSYMBOL_block = 31, /* block */ + YYSYMBOL_cmds = 32, /* cmds */ + YYSYMBOL_cmdsln = 33, /* cmdsln */ + YYSYMBOL_ifbody = 34, /* ifbody */ + YYSYMBOL_assign = 35, /* assign */ + YYSYMBOL_cmd = 36, /* cmd */ + YYSYMBOL_basic = 37, /* basic */ + YYSYMBOL_atom = 38, /* atom */ + YYSYMBOL_word = 39, /* word */ + YYSYMBOL_executable = 40, /* executable */ + YYSYMBOL_nonkeyword = 41, /* nonkeyword */ + YYSYMBOL_keyword = 42, /* keyword */ + YYSYMBOL_wordsnl = 43, /* wordsnl */ + YYSYMBOL_nl = 44 /* nl */ }; typedef enum yysymbol_kind_t yysymbol_kind_t; @@ -467,21 +472,21 @@ union yyalloc #endif /* !YYCOPY_NEEDED */ /* YYFINAL -- State number of the termination state. */ -#define YYFINAL 25 +#define YYFINAL 31 /* YYLAST -- Last index in YYTABLE. */ -#define YYLAST 53 +#define YYLAST 91 /* YYNTOKENS -- Number of terminals. */ -#define YYNTOKENS 22 +#define YYNTOKENS 26 /* YYNNTS -- Number of nonterminals. */ -#define YYNNTS 18 +#define YYNNTS 19 /* YYNRULES -- Number of rules. */ -#define YYNRULES 35 +#define YYNRULES 41 /* YYNSTATES -- Number of states. */ -#define YYNSTATES 52 +#define YYNSTATES 61 /* YYMAXUTOK -- Last valid token kind. */ -#define YYMAXUTOK 266 +#define YYMAXUTOK 270 /* YYTRANSLATE(TOKEN-NUM) -- Symbol number corresponding to TOKEN-NUM @@ -496,18 +501,18 @@ union yyalloc static const yytype_int8 yytranslate[] = { 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 12, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 14, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 13, 2, 19, 2, - 14, 15, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 18, - 2, 20, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 15, 2, 23, 2, + 18, 19, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 22, + 2, 24, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 21, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 25, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 16, 2, 17, 2, 2, 2, 2, + 2, 2, 2, 20, 2, 21, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, @@ -521,7 +526,8 @@ static const yytype_int8 yytranslate[] = 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, - 5, 6, 7, 8, 9, 10, 11 + 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, + 17 }; #if YYDEBUG @@ -531,7 +537,8 @@ static const yytype_int8 yyrline[] = 0, 36, 36, 37, 40, 41, 44, 45, 48, 51, 54, 55, 58, 59, 62, 63, 66, 69, 70, 71, 72, 73, 76, 77, 86, 87, 90, 91, 94, 95, - 98, 99, 102, 102, 104, 106 + 98, 99, 100, 101, 102, 106, 106, 113, 114, 115, + 117, 119 }; #endif @@ -547,12 +554,12 @@ static const char *yysymbol_name (yysymbol_kind_t yysymbol) YY_ATTRIBUTE_UNUSED; First, the terminals, then, starting at YYNTOKENS, nonterminals. */ static const char *const yytname[] = { - "\"end of file\"", "error", "\"invalid token\"", "Tword", "Tif", - "Telse", "Tbang", "Targs", "Tbasic", "Tparen", "Tblock", "Twhile", - "'\\n'", "'$'", "'('", "')'", "'{'", "'}'", "';'", "'&'", "'='", "'^'", - "$accept", "rc", "line", "body", "paren", "block", "cmds", "cmdsln", - "ifbody", "assign", "cmd", "basic", "atom", "word", "executable", - "nonkeyword", "keyword", "nl", YY_NULLPTR + "\"end of file\"", "error", "\"invalid token\"", "Tword", "Twords", + "Tif", "Telse", "Tbang", "Targs", "Tindex", "Tbasic", "Tparen", "Tblock", + "Twhile", "'\\n'", "'$'", "Tcount", "Tflat", "'('", "')'", "'{'", "'}'", + "';'", "'&'", "'='", "'^'", "$accept", "rc", "line", "body", "paren", + "block", "cmds", "cmdsln", "ifbody", "assign", "cmd", "basic", "atom", + "word", "executable", "nonkeyword", "keyword", "wordsnl", "nl", YY_NULLPTR }; static const char * @@ -562,7 +569,7 @@ yysymbol_name (yysymbol_kind_t yysymbol) } #endif -#define YYPACT_NINF (-14) +#define YYPACT_NINF (-22) #define yypact_value_is_default(Yyn) \ ((Yyn) == YYPACT_NINF) @@ -576,12 +583,13 @@ yysymbol_name (yysymbol_kind_t yysymbol) STATE-NUM. */ static const yytype_int8 yypact[] = { - 3, -14, -13, 24, 10, 5, 19, -14, 10, 10, - 28, 24, -3, -14, 10, -14, -14, -14, -14, -14, - -14, -2, -14, 10, 26, -14, -14, -14, -14, -14, - -14, -14, 21, 24, 24, 25, 8, -14, -14, -14, - 24, 21, -14, -14, -14, 38, -14, -14, -14, -14, - 8, -14 + 14, -22, -17, 73, 73, 73, -22, 52, 10, 2, + -22, 52, 52, 1, 73, 16, -22, 52, -22, -22, + -22, -22, -22, -22, -22, -22, 68, 7, -22, 52, + 13, -22, -22, -22, -22, -22, -22, -22, -5, 73, + 73, 18, 46, -22, -22, -5, -22, -22, -22, 73, + -5, -22, -22, -22, 27, -22, -22, -22, -22, 46, + -22 }; /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM. @@ -589,26 +597,27 @@ static const yytype_int8 yypact[] = means the default is an error. */ static const yytype_int8 yydefact[] = { - 17, 30, 0, 0, 17, 0, 0, 19, 17, 17, - 4, 18, 22, 28, 17, 34, 32, 33, 31, 24, - 25, 0, 12, 17, 6, 1, 3, 5, 20, 10, - 11, 26, 23, 0, 0, 0, 17, 9, 7, 13, - 0, 16, 29, 8, 35, 19, 21, 14, 27, 34, - 17, 15 + 17, 30, 0, 0, 0, 0, 37, 17, 0, 0, + 19, 17, 17, 4, 18, 22, 28, 17, 40, 35, + 36, 31, 24, 25, 33, 34, 0, 0, 12, 17, + 6, 1, 3, 5, 20, 10, 11, 26, 23, 0, + 0, 0, 17, 38, 32, 39, 9, 7, 13, 0, + 16, 29, 8, 41, 19, 21, 14, 27, 40, 17, + 15 }; /* YYPGOTO[NTERM-NUM]. */ static const yytype_int8 yypgoto[] = { - -14, -14, 40, 11, -14, 13, 22, -14, -14, -14, - 0, -14, 1, 18, -14, -1, -14, 4 + -22, -22, 11, -8, -22, 4, 15, -22, -22, -22, + 0, -22, 3, -21, -22, -1, -22, -22, -14 }; /* YYDEFGOTO[NTERM-NUM]. */ static const yytype_int8 yydefgoto[] = { - 0, 5, 6, 21, 15, 7, 22, 23, 46, 9, - 24, 11, 31, 32, 12, 13, 20, 36 + 0, 8, 9, 27, 18, 10, 28, 29, 55, 12, + 30, 14, 37, 38, 15, 16, 23, 26, 42 }; /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If @@ -616,43 +625,53 @@ static const yytype_int8 yydefgoto[] = number is the opposite. If YYTABLE_NINF, syntax error. */ static const yytype_int8 yytable[] = { - 10, 14, 19, -2, 18, 25, 1, 2, 10, 28, - 19, 1, 2, 1, 2, 37, 3, 33, 34, 4, - 44, 3, 8, 3, 4, 35, 4, 1, 16, 17, - 8, 26, 19, 19, 38, 42, 47, 3, 39, 19, - 43, 48, 40, 49, 29, 30, 29, 30, 27, 45, - 51, 41, 0, 50 + 13, 17, 22, 22, 22, 45, 21, 24, 25, 41, + 31, 13, 34, 22, -2, 11, 32, 1, 50, 2, + 49, 47, 33, 35, 36, 22, 11, 48, 46, 3, + 4, 5, 6, 58, 7, 35, 36, 52, 22, 22, + 39, 40, 56, 51, 59, 0, 54, 0, 22, 1, + 0, 2, 57, 0, 0, 1, 0, 2, 0, 60, + 53, 3, 4, 5, 6, 0, 7, 3, 4, 5, + 6, 1, 7, 19, 20, 0, 1, 0, 19, 20, + 0, 0, 43, 3, 4, 5, 6, 44, 3, 4, + 5, 6 }; static const yytype_int8 yycheck[] = { - 0, 14, 3, 0, 3, 0, 3, 4, 8, 9, - 11, 3, 4, 3, 4, 17, 13, 20, 21, 16, - 12, 13, 0, 13, 16, 14, 16, 3, 4, 5, - 8, 12, 33, 34, 23, 34, 36, 13, 12, 40, - 15, 40, 21, 5, 18, 19, 18, 19, 8, 36, - 50, 33, -1, 49 + 0, 18, 3, 4, 5, 26, 3, 4, 5, 17, + 0, 11, 12, 14, 0, 0, 14, 3, 39, 5, + 25, 29, 11, 22, 23, 26, 11, 14, 21, 15, + 16, 17, 18, 6, 20, 22, 23, 19, 39, 40, + 24, 25, 42, 40, 58, -1, 42, -1, 49, 3, + -1, 5, 49, -1, -1, 3, -1, 5, -1, 59, + 14, 15, 16, 17, 18, -1, 20, 15, 16, 17, + 18, 3, 20, 5, 6, -1, 3, -1, 5, 6, + -1, -1, 14, 15, 16, 17, 18, 19, 15, 16, + 17, 18 }; /* YYSTOS[STATE-NUM] -- The symbol kind of the accessing symbol of state STATE-NUM. */ static const yytype_int8 yystos[] = { - 0, 3, 4, 13, 16, 23, 24, 27, 28, 31, - 32, 33, 36, 37, 14, 26, 4, 5, 34, 37, - 38, 25, 28, 29, 32, 0, 12, 24, 32, 18, - 19, 34, 35, 20, 21, 25, 39, 17, 25, 12, - 21, 35, 34, 15, 12, 27, 30, 32, 34, 5, - 39, 32 + 0, 3, 5, 15, 16, 17, 18, 20, 27, 28, + 31, 32, 35, 36, 37, 40, 41, 18, 30, 5, + 6, 38, 41, 42, 38, 38, 43, 29, 32, 33, + 36, 0, 14, 28, 36, 22, 23, 38, 39, 24, + 25, 29, 44, 14, 19, 39, 21, 29, 14, 25, + 39, 38, 19, 14, 31, 34, 36, 38, 6, 44, + 36 }; /* YYR1[RULE-NUM] -- Symbol kind of the left-hand side of rule RULE-NUM. */ static const yytype_int8 yyr1[] = { - 0, 22, 23, 23, 24, 24, 25, 25, 26, 27, - 28, 28, 29, 29, 30, 30, 31, 32, 32, 32, - 32, 32, 33, 33, 34, 34, 35, 35, 36, 36, - 37, 37, 38, 38, 39, 39 + 0, 26, 27, 27, 28, 28, 29, 29, 30, 31, + 32, 32, 33, 33, 34, 34, 35, 36, 36, 36, + 36, 36, 37, 37, 38, 38, 39, 39, 40, 40, + 41, 41, 41, 41, 41, 42, 42, 43, 43, 43, + 44, 44 }; /* YYR2[RULE-NUM] -- Number of symbols on the right-hand side of rule RULE-NUM. */ @@ -661,7 +680,8 @@ static const yytype_int8 yyr2[] = 0, 2, 0, 2, 1, 2, 1, 2, 3, 3, 2, 2, 1, 2, 1, 4, 3, 0, 1, 1, 2, 4, 1, 2, 1, 1, 1, 3, 1, 3, - 1, 2, 1, 1, 0, 2 + 1, 2, 3, 2, 2, 1, 1, 0, 2, 2, + 0, 2 }; @@ -1397,119 +1417,149 @@ yyreduce: case 2: /* rc: %empty */ #line 36 "sys/cmd/rc/syntax.y" { return 0; } -#line 1401 "sys/cmd/rc/parse.c" +#line 1421 "sys/cmd/rc/parse.c" break; case 3: /* rc: line '\n' */ #line 37 "sys/cmd/rc/syntax.y" { return compile((yyvsp[-1].tree)); } -#line 1407 "sys/cmd/rc/parse.c" +#line 1427 "sys/cmd/rc/parse.c" break; case 5: /* line: cmds line */ #line 41 "sys/cmd/rc/syntax.y" { (yyval.tree) = maketree2(';', (yyvsp[-1].tree), (yyvsp[0].tree)); } -#line 1413 "sys/cmd/rc/parse.c" +#line 1433 "sys/cmd/rc/parse.c" break; case 7: /* body: cmdsln body */ #line 45 "sys/cmd/rc/syntax.y" { (yyval.tree) = maketree2(';', (yyvsp[-1].tree), (yyvsp[0].tree)); } -#line 1419 "sys/cmd/rc/parse.c" +#line 1439 "sys/cmd/rc/parse.c" break; case 8: /* paren: '(' body ')' */ #line 48 "sys/cmd/rc/syntax.y" { (yyval.tree) = maketree1(Tparen, (yyvsp[-1].tree)); } -#line 1425 "sys/cmd/rc/parse.c" +#line 1445 "sys/cmd/rc/parse.c" break; case 9: /* block: '{' body '}' */ #line 51 "sys/cmd/rc/syntax.y" { (yyval.tree) = maketree1(Tblock, (yyvsp[-1].tree)); } -#line 1431 "sys/cmd/rc/parse.c" +#line 1451 "sys/cmd/rc/parse.c" break; case 11: /* cmds: cmd '&' */ #line 55 "sys/cmd/rc/syntax.y" { (yyval.tree) = maketree1('&', (yyvsp[-1].tree)); } -#line 1437 "sys/cmd/rc/parse.c" +#line 1457 "sys/cmd/rc/parse.c" break; case 14: /* ifbody: cmd */ #line 62 "sys/cmd/rc/syntax.y" { (yyval.tree) = maketree2(Tif, nil, (yyvsp[0].tree)); } -#line 1443 "sys/cmd/rc/parse.c" +#line 1463 "sys/cmd/rc/parse.c" break; case 15: /* ifbody: block Telse nl cmd */ #line 63 "sys/cmd/rc/syntax.y" { (yyval.tree) = maketree3(Tif, nil, (yyvsp[-3].tree), (yyvsp[-2].tree)); } -#line 1449 "sys/cmd/rc/parse.c" +#line 1469 "sys/cmd/rc/parse.c" break; case 16: /* assign: executable '=' word */ #line 66 "sys/cmd/rc/syntax.y" { (yyval.tree) = maketree2('=', (yyvsp[-2].tree), (yyvsp[0].tree)); } -#line 1455 "sys/cmd/rc/parse.c" +#line 1475 "sys/cmd/rc/parse.c" break; case 17: /* cmd: %empty */ #line 69 "sys/cmd/rc/syntax.y" { (yyval.tree) = nil; } -#line 1461 "sys/cmd/rc/parse.c" +#line 1481 "sys/cmd/rc/parse.c" break; case 18: /* cmd: basic */ #line 70 "sys/cmd/rc/syntax.y" { (yyval.tree) = maketree1(Tbasic, (yyvsp[0].tree)); } -#line 1467 "sys/cmd/rc/parse.c" +#line 1487 "sys/cmd/rc/parse.c" break; case 20: /* cmd: assign cmd */ #line 72 "sys/cmd/rc/syntax.y" { (yyval.tree) = hangchild1((yyvsp[-1].tree), (yyvsp[0].tree), 2); } -#line 1473 "sys/cmd/rc/parse.c" +#line 1493 "sys/cmd/rc/parse.c" break; case 21: /* cmd: Tif paren nl ifbody */ #line 73 "sys/cmd/rc/syntax.y" { (yyval.tree) = hangchild1((yyvsp[-2].tree), (yyvsp[-3].tree), 0); } -#line 1479 "sys/cmd/rc/parse.c" +#line 1499 "sys/cmd/rc/parse.c" break; case 23: /* basic: basic word */ #line 77 "sys/cmd/rc/syntax.y" - { (yyval.tree) = maketree2(Targs, (yyvsp[-1].tree), (yyvsp[0].tree)); } -#line 1485 "sys/cmd/rc/parse.c" + { (yyval.tree) = maketree2(Targs, (yyvsp[-1].tree), (yyvsp[0].tree)); } +#line 1505 "sys/cmd/rc/parse.c" break; case 25: /* atom: keyword */ #line 87 "sys/cmd/rc/syntax.y" - { (yyval.tree) = maketree1(Tword, (yyvsp[0].tree)); } -#line 1491 "sys/cmd/rc/parse.c" + { (yyval.tree) = maketree1(Tword, (yyvsp[0].tree)); } +#line 1511 "sys/cmd/rc/parse.c" break; case 27: /* word: word '^' atom */ #line 91 "sys/cmd/rc/syntax.y" - { (yyval.tree) = maketree2('^', (yyvsp[-2].tree), (yyvsp[0].tree)); } -#line 1497 "sys/cmd/rc/parse.c" + { (yyval.tree) = maketree2('^', (yyvsp[-2].tree), (yyvsp[0].tree)); } +#line 1517 "sys/cmd/rc/parse.c" break; case 29: /* executable: executable '^' atom */ #line 95 "sys/cmd/rc/syntax.y" { (yyval.tree) = maketree2('^', (yyvsp[-2].tree), (yyvsp[0].tree)); } -#line 1503 "sys/cmd/rc/parse.c" +#line 1523 "sys/cmd/rc/parse.c" break; case 31: /* nonkeyword: '$' atom */ #line 99 "sys/cmd/rc/syntax.y" - { (yyval.tree) = maketree1('$', (yyvsp[0].tree)); } -#line 1509 "sys/cmd/rc/parse.c" + { (yyval.tree) = maketree1('$', (yyvsp[0].tree)); } +#line 1529 "sys/cmd/rc/parse.c" + break; + + case 32: /* nonkeyword: '(' wordsnl ')' */ +#line 100 "sys/cmd/rc/syntax.y" + { (yyval.tree) = (yyvsp[-1].tree); } +#line 1535 "sys/cmd/rc/parse.c" + break; + + case 33: /* nonkeyword: Tcount atom */ +#line 101 "sys/cmd/rc/syntax.y" + { (yyval.tree) = maketree1(Tcount, (yyvsp[0].tree)); } +#line 1541 "sys/cmd/rc/parse.c" + break; + + case 34: /* nonkeyword: Tflat atom */ +#line 102 "sys/cmd/rc/syntax.y" + { (yyval.tree) = maketree1(Tflat, (yyvsp[0].tree)); } +#line 1547 "sys/cmd/rc/parse.c" + break; + + case 37: /* wordsnl: %empty */ +#line 113 "sys/cmd/rc/syntax.y" + { (yyval.tree) = nil; } +#line 1553 "sys/cmd/rc/parse.c" + break; + + case 39: /* wordsnl: wordsnl word */ +#line 115 "sys/cmd/rc/syntax.y" + {(yyval.tree) = (!(yyvsp[-1].tree)) ? ((!(yyvsp[0].tree)) ? nil : (yyvsp[0].tree)) : ((!(yyvsp[0].tree)) ? (yyvsp[-1].tree) : maketree2(Twords, (yyvsp[-1].tree), (yyvsp[0].tree))); } +#line 1559 "sys/cmd/rc/parse.c" break; -#line 1513 "sys/cmd/rc/parse.c" +#line 1563 "sys/cmd/rc/parse.c" default: break; } @@ -1733,5 +1783,5 @@ yyreturnlab: return yyresult; } -#line 107 "sys/cmd/rc/syntax.y" +#line 120 "sys/cmd/rc/syntax.y" diff --git a/sys/cmd/rc/parse.h b/sys/cmd/rc/parse.h index 8fc661f..85be043 100644 --- a/sys/cmd/rc/parse.h +++ b/sys/cmd/rc/parse.h @@ -55,14 +55,18 @@ extern int yydebug; YYerror = 256, /* error */ YYUNDEF = 257, /* "invalid token" */ Tword = 258, /* Tword */ - Tif = 259, /* Tif */ - Telse = 260, /* Telse */ - Tbang = 261, /* Tbang */ - Targs = 262, /* Targs */ - Tbasic = 263, /* Tbasic */ - Tparen = 264, /* Tparen */ - Tblock = 265, /* Tblock */ - Twhile = 266 /* Twhile */ + Twords = 259, /* Twords */ + Tif = 260, /* Tif */ + Telse = 261, /* Telse */ + Tbang = 262, /* Tbang */ + Targs = 263, /* Targs */ + Tindex = 264, /* Tindex */ + Tbasic = 265, /* Tbasic */ + Tparen = 266, /* Tparen */ + Tblock = 267, /* Tblock */ + Twhile = 268, /* Twhile */ + Tcount = 269, /* Tcount */ + Tflat = 270 /* Tflat */ }; typedef enum yytokentype yytoken_kind_t; #endif @@ -72,14 +76,18 @@ extern int yydebug; #define YYerror 256 #define YYUNDEF 257 #define Tword 258 -#define Tif 259 -#define Telse 260 -#define Tbang 261 -#define Targs 262 -#define Tbasic 263 -#define Tparen 264 -#define Tblock 265 -#define Twhile 266 +#define Twords 259 +#define Tif 260 +#define Telse 261 +#define Tbang 262 +#define Targs 263 +#define Tindex 264 +#define Tbasic 265 +#define Tparen 266 +#define Tblock 267 +#define Twhile 268 +#define Tcount 269 +#define Tflat 270 /* Value type. */ #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED @@ -89,7 +97,7 @@ union YYSTYPE struct Tree *tree; -#line 93 "sys/cmd/rc/parse.h" +#line 101 "sys/cmd/rc/parse.h" }; typedef union YYSTYPE YYSTYPE; diff --git a/sys/cmd/rc/prompt.c b/sys/cmd/rc/prompt.c index 94022ca..3d05e41 100644 --- a/sys/cmd/rc/prompt.c +++ b/sys/cmd/rc/prompt.c @@ -9,7 +9,7 @@ prompt(ushort *flag) runner->flag.eof = 1; return 0; } - + printf("\n"); runner->line++; *flag = 0; } diff --git a/sys/cmd/rc/syntax.y b/sys/cmd/rc/syntax.y index a580cb0..469260f 100644 --- a/sys/cmd/rc/syntax.y +++ b/sys/cmd/rc/syntax.y @@ -1,5 +1,5 @@ -%token Tword Tif Telse Tbang -%token Targs +%token Tword Twords Tif Telse Tbang +%token Targs Tindex %token Tbasic Tparen Tblock %define parse.error verbose @@ -12,18 +12,18 @@ %} /* operator precendence: lowest first */ -%right Telse -%left Twhile +%left Twhile Telse %left '\n' %left Tbang -%right '$' +%right '$' Tcount Tflat +%right Tindex /* semantic types */ %union{ struct Tree *tree; } %type line cmds cmdsln body paren block ifbody assign; -%type cmd basic executable nonkeyword keyword word atom arg args; +%type cmd basic executable nonkeyword keyword word words wordsnl atom arg args; %type Tbang; %type Tword Tif Telse; @@ -74,21 +74,21 @@ cmd: basic: executable -| basic word { $$ = maketree2(Targs, $1, $2); } +| basic word { $$ = maketree2(Targs, $1, $2); } arg: word args: arg -| args arg { $$ = maketree2(Targs, $1, $2); } +| args arg { $$ = maketree2(Targs, $1, $2); } atom: nonkeyword -| keyword { $$ = maketree1(Tword, $1); } +| keyword { $$ = maketree1(Tword, $1); } word: atom -| word '^' atom { $$ = maketree2('^', $1, $3); } +| word '^' atom { $$ = maketree2('^', $1, $3); } executable: nonkeyword @@ -96,11 +96,24 @@ executable: nonkeyword: Tword -| '$' atom { $$ = maketree1('$', $2); } +| '$' atom { $$ = maketree1('$', $2); } +| '(' wordsnl ')' { $$ = $2; } +| Tcount atom { $$ = maketree1(Tcount, $2); } +| Tflat atom { $$ = maketree1(Tflat, $2); } +//| '`' block { $$ = maketree1('`', $2); } keyword: Tif|Telse +words: +/* empty */ { $$ = nil; } +| words word { $$ = maketree2(Twords, $1, $2); } + +wordsnl: +/* empty */ { $$ = nil; } +| wordsnl '\n' /* empty */ +| wordsnl word {$$ = (!$1) ? ((!$2) ? nil : $2) : ((!$2) ? $1 : maketree2(Twords, $1, $2)); } + nl: /*empty*/ | nl '\n' -- cgit v1.2.1