blob: 97205fe3ba15f03bc847e18be84b8b8fb57a7ab4 [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
Tianjie Xuc4447322017-03-06 14:44:59 -080022#include <memory>
23#include <string>
24#include <vector>
25
Doug Zongker37bee622009-06-08 17:35:39 -070026#include "expr.h"
Doug Zongkerd9c9d102009-06-12 12:24:39 -070027#include "yydefs.h"
Doug Zongker37bee622009-06-08 17:35:39 -070028#include "parser.h"
29
30extern int gLine;
31extern int gColumn;
32
Tianjie Xuc4447322017-03-06 14:44:59 -080033void yyerror(std::unique_ptr<Expr>* root, int* error_count, const char* s);
34int yyparse(std::unique_ptr<Expr>* root, int* error_count);
Doug Zongker37bee622009-06-08 17:35:39 -070035
Doug Zongker0d32f252014-02-13 15:07:56 -080036struct yy_buffer_state;
37void yy_switch_to_buffer(struct yy_buffer_state* new_buffer);
38struct yy_buffer_state* yy_scan_string(const char* yystr);
39
Tao Bao39119ad2016-10-10 22:52:18 -070040// Convenience function for building expressions with a fixed number
41// of arguments.
42static Expr* Build(Function fn, YYLTYPE loc, size_t count, ...) {
43 va_list v;
44 va_start(v, count);
Tianjie Xuc4447322017-03-06 14:44:59 -080045 Expr* e = new Expr(fn, "(operator)", loc.start, loc.end);
Tao Bao39119ad2016-10-10 22:52:18 -070046 for (size_t i = 0; i < count; ++i) {
Tianjie Xuc4447322017-03-06 14:44:59 -080047 e->argv.emplace_back(va_arg(v, Expr*));
Tao Bao39119ad2016-10-10 22:52:18 -070048 }
49 va_end(v);
Tao Bao39119ad2016-10-10 22:52:18 -070050 return e;
51}
52
Doug Zongker37bee622009-06-08 17:35:39 -070053%}
54
Doug Zongkerd9c9d102009-06-12 12:24:39 -070055%locations
56
Doug Zongker37bee622009-06-08 17:35:39 -070057%union {
58 char* str;
59 Expr* expr;
Tianjie Xuc4447322017-03-06 14:44:59 -080060 std::vector<std::unique_ptr<Expr>>* args;
Doug Zongker37bee622009-06-08 17:35:39 -070061}
62
63%token AND OR SUBSTR SUPERSTR EQ NE IF THEN ELSE ENDIF
64%token <str> STRING BAD
65%type <expr> expr
66%type <args> arglist
67
Tianjie Xuc4447322017-03-06 14:44:59 -080068%destructor { delete $$; } expr
69%destructor { delete $$; } arglist
70
71%parse-param {std::unique_ptr<Expr>* root}
Doug Zongker8edb00c2009-06-11 17:21:44 -070072%parse-param {int* error_count}
Doug Zongker37bee622009-06-08 17:35:39 -070073%error-verbose
74
75/* declarations in increasing order of precedence */
76%left ';'
77%left ','
78%left OR
79%left AND
80%left EQ NE
81%left '+'
82%right '!'
83
84%%
85
Tianjie Xuc4447322017-03-06 14:44:59 -080086input: expr { root->reset($1); }
Doug Zongker37bee622009-06-08 17:35:39 -070087;
88
89expr: STRING {
Tianjie Xuc4447322017-03-06 14:44:59 -080090 $$ = new Expr(Literal, $1, @$.start, @$.end);
Doug Zongker37bee622009-06-08 17:35:39 -070091}
Doug Zongkerd9c9d102009-06-12 12:24:39 -070092| '(' expr ')' { $$ = $2; $$->start=@$.start; $$->end=@$.end; }
93| expr ';' { $$ = $1; $$->start=@1.start; $$->end=@1.end; }
94| expr ';' expr { $$ = Build(SequenceFn, @$, 2, $1, $3); }
95| error ';' expr { $$ = $3; $$->start=@$.start; $$->end=@$.end; }
96| expr '+' expr { $$ = Build(ConcatFn, @$, 2, $1, $3); }
97| expr EQ expr { $$ = Build(EqualityFn, @$, 2, $1, $3); }
98| expr NE expr { $$ = Build(InequalityFn, @$, 2, $1, $3); }
99| expr AND expr { $$ = Build(LogicalAndFn, @$, 2, $1, $3); }
100| expr OR expr { $$ = Build(LogicalOrFn, @$, 2, $1, $3); }
101| '!' expr { $$ = Build(LogicalNotFn, @$, 1, $2); }
102| IF expr THEN expr ENDIF { $$ = Build(IfElseFn, @$, 2, $2, $4); }
103| IF expr THEN expr ELSE expr ENDIF { $$ = Build(IfElseFn, @$, 3, $2, $4, $6); }
Doug Zongker37bee622009-06-08 17:35:39 -0700104| STRING '(' arglist ')' {
Tianjie Xuc4447322017-03-06 14:44:59 -0800105 Function fn = FindFunction($1);
106 if (fn == nullptr) {
107 std::string msg = "unknown function \"" + std::string($1) + "\"";
108 yyerror(root, error_count, msg.c_str());
Doug Zongker37bee622009-06-08 17:35:39 -0700109 YYERROR;
110 }
Tianjie Xuc4447322017-03-06 14:44:59 -0800111 $$ = new Expr(fn, $1, @$.start, @$.end);
112 $$->argv = std::move(*$3);
Doug Zongker37bee622009-06-08 17:35:39 -0700113}
114;
115
116arglist: /* empty */ {
Tianjie Xuc4447322017-03-06 14:44:59 -0800117 $$ = new std::vector<std::unique_ptr<Expr>>;
Doug Zongker37bee622009-06-08 17:35:39 -0700118}
119| expr {
Tianjie Xuc4447322017-03-06 14:44:59 -0800120 $$ = new std::vector<std::unique_ptr<Expr>>;
121 $$->emplace_back($1);
Doug Zongker37bee622009-06-08 17:35:39 -0700122}
123| arglist ',' expr {
Tianjie Xuc4447322017-03-06 14:44:59 -0800124 $$->push_back(std::unique_ptr<Expr>($3));
Doug Zongker37bee622009-06-08 17:35:39 -0700125}
126;
127
128%%
129
Tianjie Xuc4447322017-03-06 14:44:59 -0800130void yyerror(std::unique_ptr<Expr>* root, int* error_count, const char* s) {
Doug Zongker37bee622009-06-08 17:35:39 -0700131 if (strlen(s) == 0) {
132 s = "syntax error";
133 }
134 printf("line %d col %d: %s\n", gLine, gColumn, s);
Doug Zongker8edb00c2009-06-11 17:21:44 -0700135 ++*error_count;
Doug Zongker37bee622009-06-08 17:35:39 -0700136}
Doug Zongker0d32f252014-02-13 15:07:56 -0800137
Tianjie Xuc4447322017-03-06 14:44:59 -0800138int parse_string(const char* str, std::unique_ptr<Expr>* root, int* error_count) {
Doug Zongker0d32f252014-02-13 15:07:56 -0800139 yy_switch_to_buffer(yy_scan_string(str));
140 return yyparse(root, error_count);
141}