diff options
Diffstat (limited to 'awkgram.y')
-rw-r--r-- | awkgram.y | 74 |
1 files changed, 71 insertions, 3 deletions
@@ -174,7 +174,7 @@ extern double fmod(double x, double y); %} %token FUNC_CALL NAME REGEXP FILENAME -%token YNUMBER YSTRING +%token YNUMBER YSTRING TYPED_REGEXP %token RELOP IO_OUT IO_IN %token ASSIGNOP ASSIGN MATCHOP CONCAT_OP %token SUBSCRIPT @@ -202,7 +202,7 @@ extern double fmod(double x, double y); %left MATCHOP %nonassoc RELOP '<' '>' IO_IN IO_OUT %left CONCAT_OP -%left YSTRING YNUMBER +%left YSTRING YNUMBER TYPED_REGEXP %left '+' '-' %left '*' '/' '%' %right '!' UNARY @@ -513,6 +513,35 @@ regexp } ; +typed_regexp + : TYPED_REGEXP + { + NODE *n, *exp, *n2; + char *re; + size_t len; + + re = $1->lextok; + $1->lextok = NULL; + len = strlen(re); + + exp = make_str_node(re, len, ALREADY_MALLOCED); + n = make_regnode(Node_regex, exp); + if (n == NULL) { + unref(exp); + YYABORT; + } + + n2 = make_string(re, len); + n2->typed_re = n; + n2->numbr = 0; + n2->flags |= NUMCUR|STRCUR|REGEX; + n2->flags &= ~(STRING|NUMBER); + + $$ = $1; + $$->opcode = Op_push_re; + $$->memory = n2; + } + a_slash : '/' { bcfree($1); } @@ -1252,6 +1281,12 @@ case_value $1->opcode = Op_push; $$ = $1; } + | typed_regexp + { + assert(($1->memory->flags & REGEX) == REGEX); + $1->opcode = Op_push_re; + $$ = $1; + } ; print @@ -1436,6 +1471,7 @@ fcall_expression_list fcall_exp : exp { $$ = $1; } + | typed_regexp { $$ = list_create($1); } ; /* Expressions, not including the comma operator. */ @@ -1447,10 +1483,27 @@ exp _("regular expression on right of assignment")); $$ = mk_assignment($1, $3, $2); } + | variable ASSIGN typed_regexp %prec ASSIGNOP + { + $$ = mk_assignment($1, list_create($3), $2); + } | exp LEX_AND exp { $$ = mk_boolean($1, $3, $2); } | exp LEX_OR exp { $$ = mk_boolean($1, $3, $2); } + | exp MATCHOP typed_regexp + { + if ($1->lasti->opcode == Op_match_rec) + warning_ln($2->source_line, + _("regular expression on left of `~' or `!~' operator")); + + assert($3->opcode == Op_push_re + && ($3->memory->flags & REGEX) != 0); + /* RHS is @/.../ */ + $2->memory = $3->memory; + bcfree($3); + $$ = list_append($1, $2); + } | exp MATCHOP exp { if ($1->lasti->opcode == Op_match_rec) @@ -3335,6 +3388,7 @@ yylex(void) bool inhex = false; bool intlstr = false; AWKNUM d; + bool collecting_typed_regexp = false; #define GET_INSTRUCTION(op) bcalloc(op, 1, sourceline) @@ -3370,6 +3424,7 @@ yylex(void) lexeme = lexptr; thisline = NULL; +collect_regexp: if (want_regexp) { int in_brack = 0; /* count brackets, [[:alnum:]] allowed */ int b_index = -1; @@ -3456,7 +3511,11 @@ end_regexp: peek); } } - lasttok = REGEXP; + if (collecting_typed_regexp) { + collecting_typed_regexp = false; + lasttok = TYPED_REGEXP; + } else + lasttok = REGEXP; return lasttok; case '\n': @@ -3516,6 +3575,13 @@ retry: return lasttok = NEWLINE; case '@': + c = nextc(true); + if (c == '/') { + want_regexp = true; + collecting_typed_regexp = true; + goto collect_regexp; + } + pushback(); at_seen = true; return lasttok = '@'; @@ -4573,6 +4639,8 @@ valinfo(NODE *n, Func_print print_func, FILE *fp) { if (n == Nnull_string) print_func(fp, "uninitialized scalar\n"); + else if ((n->flags & REGEX) != 0) + print_func(fp, "@/%.*s/\n", n->stlen, n->stptr); else if ((n->flags & STRING) != 0) { pp_string_fp(print_func, fp, n->stptr, n->stlen, '"', false); print_func(fp, "\n"); |