1*acea8879SAndroid Build Coastguard Worker%{ 2*acea8879SAndroid Build Coastguard Worker/* 3*acea8879SAndroid Build Coastguard Worker * Copyright (C) 2009 The Android Open Source Project 4*acea8879SAndroid Build Coastguard Worker * 5*acea8879SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 6*acea8879SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 7*acea8879SAndroid Build Coastguard Worker * You may obtain a copy of the License at 8*acea8879SAndroid Build Coastguard Worker * 9*acea8879SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 10*acea8879SAndroid Build Coastguard Worker * 11*acea8879SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 12*acea8879SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 13*acea8879SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14*acea8879SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 15*acea8879SAndroid Build Coastguard Worker * limitations under the License. 16*acea8879SAndroid Build Coastguard Worker */ 17*acea8879SAndroid Build Coastguard Worker 18*acea8879SAndroid Build Coastguard Worker#include <stdarg.h> 19*acea8879SAndroid Build Coastguard Worker#include <stdio.h> 20*acea8879SAndroid Build Coastguard Worker#include <stdlib.h> 21*acea8879SAndroid Build Coastguard Worker#include <string.h> 22*acea8879SAndroid Build Coastguard Worker 23*acea8879SAndroid Build Coastguard Worker#include <memory> 24*acea8879SAndroid Build Coastguard Worker#include <string> 25*acea8879SAndroid Build Coastguard Worker#include <vector> 26*acea8879SAndroid Build Coastguard Worker 27*acea8879SAndroid Build Coastguard Worker#include <android-base/macros.h> 28*acea8879SAndroid Build Coastguard Worker 29*acea8879SAndroid Build Coastguard Worker#include "edify/expr.h" 30*acea8879SAndroid Build Coastguard Worker#include "yydefs.h" 31*acea8879SAndroid Build Coastguard Worker#include "parser.h" 32*acea8879SAndroid Build Coastguard Worker 33*acea8879SAndroid Build Coastguard Workerextern int gLine; 34*acea8879SAndroid Build Coastguard Workerextern int gColumn; 35*acea8879SAndroid Build Coastguard Worker 36*acea8879SAndroid Build Coastguard Workervoid yyerror(std::unique_ptr<Expr>* root, int* error_count, const char* s); 37*acea8879SAndroid Build Coastguard Workerint yyparse(std::unique_ptr<Expr>* root, int* error_count); 38*acea8879SAndroid Build Coastguard Worker 39*acea8879SAndroid Build Coastguard Workerstruct yy_buffer_state; 40*acea8879SAndroid Build Coastguard Workervoid yy_switch_to_buffer(struct yy_buffer_state* new_buffer); 41*acea8879SAndroid Build Coastguard Workerstruct yy_buffer_state* yy_scan_string(const char* yystr); 42*acea8879SAndroid Build Coastguard Worker 43*acea8879SAndroid Build Coastguard Worker// Convenience function for building expressions with a fixed number 44*acea8879SAndroid Build Coastguard Worker// of arguments. 45*acea8879SAndroid Build Coastguard Workerstatic Expr* Build(Function fn, YYLTYPE loc, size_t count, ...) { 46*acea8879SAndroid Build Coastguard Worker va_list v; 47*acea8879SAndroid Build Coastguard Worker va_start(v, count); 48*acea8879SAndroid Build Coastguard Worker Expr* e = new Expr(fn, "(operator)", loc.start, loc.end); 49*acea8879SAndroid Build Coastguard Worker for (size_t i = 0; i < count; ++i) { 50*acea8879SAndroid Build Coastguard Worker e->argv.emplace_back(va_arg(v, Expr*)); 51*acea8879SAndroid Build Coastguard Worker } 52*acea8879SAndroid Build Coastguard Worker va_end(v); 53*acea8879SAndroid Build Coastguard Worker return e; 54*acea8879SAndroid Build Coastguard Worker} 55*acea8879SAndroid Build Coastguard Worker 56*acea8879SAndroid Build Coastguard Worker%} 57*acea8879SAndroid Build Coastguard Worker 58*acea8879SAndroid Build Coastguard Worker%locations 59*acea8879SAndroid Build Coastguard Worker 60*acea8879SAndroid Build Coastguard Worker%union { 61*acea8879SAndroid Build Coastguard Worker char* str; 62*acea8879SAndroid Build Coastguard Worker Expr* expr; 63*acea8879SAndroid Build Coastguard Worker std::vector<std::unique_ptr<Expr>>* args; 64*acea8879SAndroid Build Coastguard Worker} 65*acea8879SAndroid Build Coastguard Worker 66*acea8879SAndroid Build Coastguard Worker%token AND OR SUBSTR SUPERSTR EQ NE IF THEN ELSE ENDIF 67*acea8879SAndroid Build Coastguard Worker%token <str> STRING BAD 68*acea8879SAndroid Build Coastguard Worker%type <expr> expr 69*acea8879SAndroid Build Coastguard Worker%type <args> arglist 70*acea8879SAndroid Build Coastguard Worker 71*acea8879SAndroid Build Coastguard Worker%destructor { delete $$; } expr 72*acea8879SAndroid Build Coastguard Worker%destructor { delete $$; } arglist 73*acea8879SAndroid Build Coastguard Worker 74*acea8879SAndroid Build Coastguard Worker%parse-param {std::unique_ptr<Expr>* root} 75*acea8879SAndroid Build Coastguard Worker%parse-param {int* error_count} 76*acea8879SAndroid Build Coastguard Worker%define parse.error verbose 77*acea8879SAndroid Build Coastguard Worker 78*acea8879SAndroid Build Coastguard Worker/* declarations in increasing order of precedence */ 79*acea8879SAndroid Build Coastguard Worker%left ';' 80*acea8879SAndroid Build Coastguard Worker%left ',' 81*acea8879SAndroid Build Coastguard Worker%left OR 82*acea8879SAndroid Build Coastguard Worker%left AND 83*acea8879SAndroid Build Coastguard Worker%left EQ NE 84*acea8879SAndroid Build Coastguard Worker%left '+' 85*acea8879SAndroid Build Coastguard Worker%right '!' 86*acea8879SAndroid Build Coastguard Worker 87*acea8879SAndroid Build Coastguard Worker%% 88*acea8879SAndroid Build Coastguard Worker 89*acea8879SAndroid Build Coastguard Workerinput: expr { root->reset($1); } 90*acea8879SAndroid Build Coastguard Worker; 91*acea8879SAndroid Build Coastguard Worker 92*acea8879SAndroid Build Coastguard Workerexpr: STRING { 93*acea8879SAndroid Build Coastguard Worker $$ = new Expr(Literal, $1, @$.start, @$.end); 94*acea8879SAndroid Build Coastguard Worker} 95*acea8879SAndroid Build Coastguard Worker| '(' expr ')' { $$ = $2; $$->start=@$.start; $$->end=@$.end; } 96*acea8879SAndroid Build Coastguard Worker| expr ';' { $$ = $1; $$->start=@1.start; $$->end=@1.end; } 97*acea8879SAndroid Build Coastguard Worker| expr ';' expr { $$ = Build(SequenceFn, @$, 2, $1, $3); } 98*acea8879SAndroid Build Coastguard Worker| error ';' expr { $$ = $3; $$->start=@$.start; $$->end=@$.end; } 99*acea8879SAndroid Build Coastguard Worker| expr '+' expr { $$ = Build(ConcatFn, @$, 2, $1, $3); } 100*acea8879SAndroid Build Coastguard Worker| expr EQ expr { $$ = Build(EqualityFn, @$, 2, $1, $3); } 101*acea8879SAndroid Build Coastguard Worker| expr NE expr { $$ = Build(InequalityFn, @$, 2, $1, $3); } 102*acea8879SAndroid Build Coastguard Worker| expr AND expr { $$ = Build(LogicalAndFn, @$, 2, $1, $3); } 103*acea8879SAndroid Build Coastguard Worker| expr OR expr { $$ = Build(LogicalOrFn, @$, 2, $1, $3); } 104*acea8879SAndroid Build Coastguard Worker| '!' expr { $$ = Build(LogicalNotFn, @$, 1, $2); } 105*acea8879SAndroid Build Coastguard Worker| IF expr THEN expr ENDIF { $$ = Build(IfElseFn, @$, 2, $2, $4); } 106*acea8879SAndroid Build Coastguard Worker| IF expr THEN expr ELSE expr ENDIF { $$ = Build(IfElseFn, @$, 3, $2, $4, $6); } 107*acea8879SAndroid Build Coastguard Worker| STRING '(' arglist ')' { 108*acea8879SAndroid Build Coastguard Worker Function fn = FindFunction($1); 109*acea8879SAndroid Build Coastguard Worker if (fn == nullptr) { 110*acea8879SAndroid Build Coastguard Worker std::string msg = "unknown function \"" + std::string($1) + "\""; 111*acea8879SAndroid Build Coastguard Worker yyerror(root, error_count, msg.c_str()); 112*acea8879SAndroid Build Coastguard Worker YYERROR; 113*acea8879SAndroid Build Coastguard Worker } 114*acea8879SAndroid Build Coastguard Worker $$ = new Expr(fn, $1, @$.start, @$.end); 115*acea8879SAndroid Build Coastguard Worker $$->argv = std::move(*$3); 116*acea8879SAndroid Build Coastguard Worker} 117*acea8879SAndroid Build Coastguard Worker; 118*acea8879SAndroid Build Coastguard Worker 119*acea8879SAndroid Build Coastguard Workerarglist: /* empty */ { 120*acea8879SAndroid Build Coastguard Worker $$ = new std::vector<std::unique_ptr<Expr>>; 121*acea8879SAndroid Build Coastguard Worker} 122*acea8879SAndroid Build Coastguard Worker| expr { 123*acea8879SAndroid Build Coastguard Worker $$ = new std::vector<std::unique_ptr<Expr>>; 124*acea8879SAndroid Build Coastguard Worker $$->emplace_back($1); 125*acea8879SAndroid Build Coastguard Worker} 126*acea8879SAndroid Build Coastguard Worker| arglist ',' expr { 127*acea8879SAndroid Build Coastguard Worker UNUSED($1); 128*acea8879SAndroid Build Coastguard Worker $$->push_back(std::unique_ptr<Expr>($3)); 129*acea8879SAndroid Build Coastguard Worker} 130*acea8879SAndroid Build Coastguard Worker; 131*acea8879SAndroid Build Coastguard Worker 132*acea8879SAndroid Build Coastguard Worker%% 133*acea8879SAndroid Build Coastguard Worker 134*acea8879SAndroid Build Coastguard Workervoid yyerror(std::unique_ptr<Expr>* root, int* error_count, const char* s) { 135*acea8879SAndroid Build Coastguard Worker if (strlen(s) == 0) { 136*acea8879SAndroid Build Coastguard Worker s = "syntax error"; 137*acea8879SAndroid Build Coastguard Worker } 138*acea8879SAndroid Build Coastguard Worker printf("line %d col %d: %s\n", gLine, gColumn, s); 139*acea8879SAndroid Build Coastguard Worker ++*error_count; 140*acea8879SAndroid Build Coastguard Worker} 141*acea8879SAndroid Build Coastguard Worker 142*acea8879SAndroid Build Coastguard Workerint ParseString(const std::string& str, std::unique_ptr<Expr>* root, int* error_count) { 143*acea8879SAndroid Build Coastguard Worker yy_switch_to_buffer(yy_scan_string(str.c_str())); 144*acea8879SAndroid Build Coastguard Worker return yyparse(root, error_count); 145*acea8879SAndroid Build Coastguard Worker} 146