• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 }
131