blob: 58a8dec658e5e87a2371d8f7fde7e37bcabb993e [file] [log] [blame]
Doug Zongker37bee622009-06-08 17:35:39 -07001%{
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"
Doug Zongkerd9c9d102009-06-12 12:24:39 -070023#include "yydefs.h"
Doug Zongker37bee622009-06-08 17:35:39 -070024#include "parser.h"
25
26extern int gLine;
27extern int gColumn;
28
Doug Zongker8edb00c2009-06-11 17:21:44 -070029void yyerror(Expr** root, int* error_count, const char* s);
30int yyparse(Expr** root, int* error_count);
Doug Zongker37bee622009-06-08 17:35:39 -070031
Doug Zongker0d32f252014-02-13 15:07:56 -080032struct yy_buffer_state;
33void yy_switch_to_buffer(struct yy_buffer_state* new_buffer);
34struct yy_buffer_state* yy_scan_string(const char* yystr);
35
Tao Bao39119ad2016-10-10 22:52:18 -070036// Convenience function for building expressions with a fixed number
37// of arguments.
38static Expr* Build(Function fn, YYLTYPE loc, size_t count, ...) {
39 va_list v;
40 va_start(v, count);
41 Expr* e = static_cast<Expr*>(malloc(sizeof(Expr)));
42 e->fn = fn;
43 e->name = "(operator)";
44 e->argc = count;
45 e->argv = static_cast<Expr**>(malloc(count * sizeof(Expr*)));
46 for (size_t i = 0; i < count; ++i) {
47 e->argv[i] = va_arg(v, Expr*);
48 }
49 va_end(v);
50 e->start = loc.start;
51 e->end = loc.end;
52 return e;
53}
54
Doug Zongker37bee622009-06-08 17:35:39 -070055%}
56
Doug Zongkerd9c9d102009-06-12 12:24:39 -070057%locations
58
Doug Zongker37bee622009-06-08 17:35:39 -070059%union {
60 char* str;
61 Expr* expr;
62 struct {
63 int argc;
64 Expr** argv;
65 } args;
66}
67
68%token AND OR SUBSTR SUPERSTR EQ NE IF THEN ELSE ENDIF
69%token <str> STRING BAD
70%type <expr> expr
71%type <args> arglist
72
73%parse-param {Expr** root}
Doug Zongker8edb00c2009-06-11 17:21:44 -070074%parse-param {int* error_count}
Doug Zongker37bee622009-06-08 17:35:39 -070075%error-verbose
76
77/* declarations in increasing order of precedence */
78%left ';'
79%left ','
80%left OR
81%left AND
82%left EQ NE
83%left '+'
84%right '!'
85
86%%
87
88input: expr { *root = $1; }
89;
90
91expr: STRING {
Tao Bao39119ad2016-10-10 22:52:18 -070092 $$ = static_cast<Expr*>(malloc(sizeof(Expr)));
Doug Zongker37bee622009-06-08 17:35:39 -070093 $$->fn = Literal;
94 $$->name = $1;
95 $$->argc = 0;
96 $$->argv = NULL;
Doug Zongkerd9c9d102009-06-12 12:24:39 -070097 $$->start = @$.start;
98 $$->end = @$.end;
Doug Zongker37bee622009-06-08 17:35:39 -070099}
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700100| '(' expr ')' { $$ = $2; $$->start=@$.start; $$->end=@$.end; }
101| expr ';' { $$ = $1; $$->start=@1.start; $$->end=@1.end; }
102| expr ';' expr { $$ = Build(SequenceFn, @$, 2, $1, $3); }
103| error ';' expr { $$ = $3; $$->start=@$.start; $$->end=@$.end; }
104| expr '+' expr { $$ = Build(ConcatFn, @$, 2, $1, $3); }
105| expr EQ expr { $$ = Build(EqualityFn, @$, 2, $1, $3); }
106| expr NE expr { $$ = Build(InequalityFn, @$, 2, $1, $3); }
107| expr AND expr { $$ = Build(LogicalAndFn, @$, 2, $1, $3); }
108| expr OR expr { $$ = Build(LogicalOrFn, @$, 2, $1, $3); }
109| '!' expr { $$ = Build(LogicalNotFn, @$, 1, $2); }
110| IF expr THEN expr ENDIF { $$ = Build(IfElseFn, @$, 2, $2, $4); }
111| IF expr THEN expr ELSE expr ENDIF { $$ = Build(IfElseFn, @$, 3, $2, $4, $6); }
Doug Zongker37bee622009-06-08 17:35:39 -0700112| STRING '(' arglist ')' {
Tao Bao39119ad2016-10-10 22:52:18 -0700113 $$ = static_cast<Expr*>(malloc(sizeof(Expr)));
Doug Zongker37bee622009-06-08 17:35:39 -0700114 $$->fn = FindFunction($1);
Tao Bao39119ad2016-10-10 22:52:18 -0700115 if ($$->fn == nullptr) {
Doug Zongker37bee622009-06-08 17:35:39 -0700116 char buffer[256];
117 snprintf(buffer, sizeof(buffer), "unknown function \"%s\"", $1);
Doug Zongker8edb00c2009-06-11 17:21:44 -0700118 yyerror(root, error_count, buffer);
Doug Zongker37bee622009-06-08 17:35:39 -0700119 YYERROR;
120 }
121 $$->name = $1;
122 $$->argc = $3.argc;
123 $$->argv = $3.argv;
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700124 $$->start = @$.start;
125 $$->end = @$.end;
Doug Zongker37bee622009-06-08 17:35:39 -0700126}
127;
128
129arglist: /* empty */ {
130 $$.argc = 0;
131 $$.argv = NULL;
132}
133| expr {
134 $$.argc = 1;
Tao Bao39119ad2016-10-10 22:52:18 -0700135 $$.argv = static_cast<Expr**>(malloc(sizeof(Expr*)));
Doug Zongker37bee622009-06-08 17:35:39 -0700136 $$.argv[0] = $1;
137}
138| arglist ',' expr {
139 $$.argc = $1.argc + 1;
Tao Bao39119ad2016-10-10 22:52:18 -0700140 $$.argv = static_cast<Expr**>(realloc($$.argv, $$.argc * sizeof(Expr*)));
Doug Zongker37bee622009-06-08 17:35:39 -0700141 $$.argv[$$.argc-1] = $3;
142}
143;
144
145%%
146
Doug Zongker8edb00c2009-06-11 17:21:44 -0700147void yyerror(Expr** root, int* error_count, const char* s) {
Doug Zongker37bee622009-06-08 17:35:39 -0700148 if (strlen(s) == 0) {
149 s = "syntax error";
150 }
151 printf("line %d col %d: %s\n", gLine, gColumn, s);
Doug Zongker8edb00c2009-06-11 17:21:44 -0700152 ++*error_count;
Doug Zongker37bee622009-06-08 17:35:39 -0700153}
Doug Zongker0d32f252014-02-13 15:07:56 -0800154
155int parse_string(const char* str, Expr** root, int* error_count) {
156 yy_switch_to_buffer(yy_scan_string(str));
157 return yyparse(root, error_count);
158}