| preludedrew | 38058dc | 2011-01-29 23:30:44 -0700 | [diff] [blame] | 1 | %{ | 
|  | 2 | /* | 
|  | 3 | * Copyright (C) 2009 The Android Open Source Project | 
|  | 4 | * | 
|  | 5 | * Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | 6 | * you may not use this file except in compliance with the License. | 
|  | 7 | * You may obtain a copy of the License at | 
|  | 8 | * | 
|  | 9 | *      http://www.apache.org/licenses/LICENSE-2.0 | 
|  | 10 | * | 
|  | 11 | * Unless required by applicable law or agreed to in writing, software | 
|  | 12 | * distributed under the License is distributed on an "AS IS" BASIS, | 
|  | 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | 14 | * See the License for the specific language governing permissions and | 
|  | 15 | * limitations under the License. | 
|  | 16 | */ | 
|  | 17 |  | 
|  | 18 | #include <stdio.h> | 
|  | 19 | #include <stdlib.h> | 
|  | 20 | #include <string.h> | 
|  | 21 |  | 
|  | 22 | #include "expr.h" | 
|  | 23 | #include "yydefs.h" | 
|  | 24 | #include "parser.h" | 
|  | 25 |  | 
|  | 26 | extern int gLine; | 
|  | 27 | extern int gColumn; | 
|  | 28 |  | 
|  | 29 | void yyerror(Expr** root, int* error_count, const char* s); | 
|  | 30 | int yyparse(Expr** root, int* error_count); | 
|  | 31 |  | 
|  | 32 | %} | 
|  | 33 |  | 
|  | 34 | %locations | 
|  | 35 |  | 
|  | 36 | %union { | 
|  | 37 | char* str; | 
|  | 38 | Expr* expr; | 
|  | 39 | struct { | 
|  | 40 | int argc; | 
|  | 41 | Expr** argv; | 
|  | 42 | } args; | 
|  | 43 | } | 
|  | 44 |  | 
|  | 45 | %token AND OR SUBSTR SUPERSTR EQ NE IF THEN ELSE ENDIF | 
|  | 46 | %token <str> STRING BAD | 
|  | 47 | %type <expr> expr | 
|  | 48 | %type <args> arglist | 
|  | 49 |  | 
|  | 50 | %parse-param {Expr** root} | 
|  | 51 | %parse-param {int* error_count} | 
|  | 52 | %error-verbose | 
|  | 53 |  | 
|  | 54 | /* declarations in increasing order of precedence */ | 
|  | 55 | %left ';' | 
|  | 56 | %left ',' | 
|  | 57 | %left OR | 
|  | 58 | %left AND | 
|  | 59 | %left EQ NE | 
|  | 60 | %left '+' | 
|  | 61 | %right '!' | 
|  | 62 |  | 
|  | 63 | %% | 
|  | 64 |  | 
|  | 65 | input:  expr           { *root = $1; } | 
|  | 66 | ; | 
|  | 67 |  | 
|  | 68 | expr:  STRING { | 
|  | 69 | $$ = malloc(sizeof(Expr)); | 
|  | 70 | $$->fn = Literal; | 
|  | 71 | $$->name = $1; | 
|  | 72 | $$->argc = 0; | 
|  | 73 | $$->argv = NULL; | 
|  | 74 | $$->start = @$.start; | 
|  | 75 | $$->end = @$.end; | 
|  | 76 | } | 
|  | 77 | |  '(' expr ')'                      { $$ = $2; $$->start=@$.start; $$->end=@$.end; } | 
|  | 78 | |  expr ';'                          { $$ = $1; $$->start=@1.start; $$->end=@1.end; } | 
|  | 79 | |  expr ';' expr                     { $$ = Build(SequenceFn, @$, 2, $1, $3); } | 
|  | 80 | |  error ';' expr                    { $$ = $3; $$->start=@$.start; $$->end=@$.end; } | 
|  | 81 | |  expr '+' expr                     { $$ = Build(ConcatFn, @$, 2, $1, $3); } | 
|  | 82 | |  expr EQ expr                      { $$ = Build(EqualityFn, @$, 2, $1, $3); } | 
|  | 83 | |  expr NE expr                      { $$ = Build(InequalityFn, @$, 2, $1, $3); } | 
|  | 84 | |  expr AND expr                     { $$ = Build(LogicalAndFn, @$, 2, $1, $3); } | 
|  | 85 | |  expr OR expr                      { $$ = Build(LogicalOrFn, @$, 2, $1, $3); } | 
|  | 86 | |  '!' expr                          { $$ = Build(LogicalNotFn, @$, 1, $2); } | 
|  | 87 | |  IF expr THEN expr ENDIF           { $$ = Build(IfElseFn, @$, 2, $2, $4); } | 
|  | 88 | |  IF expr THEN expr ELSE expr ENDIF { $$ = Build(IfElseFn, @$, 3, $2, $4, $6); } | 
|  | 89 | | STRING '(' arglist ')' { | 
|  | 90 | $$ = malloc(sizeof(Expr)); | 
|  | 91 | $$->fn = FindFunction($1); | 
|  | 92 | if ($$->fn == NULL) { | 
|  | 93 | char buffer[256]; | 
|  | 94 | snprintf(buffer, sizeof(buffer), "unknown function \"%s\"", $1); | 
|  | 95 | yyerror(root, error_count, buffer); | 
|  | 96 | YYERROR; | 
|  | 97 | } | 
|  | 98 | $$->name = $1; | 
|  | 99 | $$->argc = $3.argc; | 
|  | 100 | $$->argv = $3.argv; | 
|  | 101 | $$->start = @$.start; | 
|  | 102 | $$->end = @$.end; | 
|  | 103 | } | 
|  | 104 | ; | 
|  | 105 |  | 
|  | 106 | arglist:    /* empty */ { | 
|  | 107 | $$.argc = 0; | 
|  | 108 | $$.argv = NULL; | 
|  | 109 | } | 
|  | 110 | | expr { | 
|  | 111 | $$.argc = 1; | 
|  | 112 | $$.argv = malloc(sizeof(Expr*)); | 
|  | 113 | $$.argv[0] = $1; | 
|  | 114 | } | 
|  | 115 | | arglist ',' expr { | 
|  | 116 | $$.argc = $1.argc + 1; | 
|  | 117 | $$.argv = realloc($$.argv, $$.argc * sizeof(Expr*)); | 
|  | 118 | $$.argv[$$.argc-1] = $3; | 
|  | 119 | } | 
|  | 120 | ; | 
|  | 121 |  | 
|  | 122 | %% | 
|  | 123 |  | 
|  | 124 | void yyerror(Expr** root, int* error_count, const char* s) { | 
|  | 125 | if (strlen(s) == 0) { | 
|  | 126 | s = "syntax error"; | 
|  | 127 | } | 
|  | 128 | printf("line %d col %d: %s\n", gLine, gColumn, s); | 
|  | 129 | ++*error_count; | 
|  | 130 | } |