Loading edify/edify_parser.cpp +5 −4 Original line number Diff line number Diff line Loading @@ -27,18 +27,19 @@ #include <errno.h> #include <stdio.h> #include <memory> #include <string> #include <android-base/file.h> #include "expr.h" static void ExprDump(int depth, const Expr* n, const std::string& script) { static void ExprDump(int depth, const std::unique_ptr<Expr>& n, const std::string& script) { printf("%*s", depth*2, ""); printf("%s %p (%d-%d) \"%s\"\n", n->name == NULL ? "(NULL)" : n->name, n->fn, n->start, n->end, n->name.c_str(), n->fn, n->start, n->end, script.substr(n->start, n->end - n->start).c_str()); for (int i = 0; i < n->argc; ++i) { for (size_t i = 0; i < n->argv.size(); ++i) { ExprDump(depth+1, n->argv[i], script); } } Loading @@ -57,7 +58,7 @@ int main(int argc, char** argv) { return 1; } Expr* root; std::unique_ptr<Expr> root; int error_count = 0; int error = parse_string(buffer.data(), &root, &error_count); printf("parse returned %d; %d errors encountered\n", error, error_count); Loading edify/expr.cpp +75 −44 Original line number Diff line number Diff line Loading @@ -40,12 +40,12 @@ static bool BooleanString(const std::string& s) { return !s.empty(); } bool Evaluate(State* state, Expr* expr, std::string* result) { bool Evaluate(State* state, const std::unique_ptr<Expr>& expr, std::string* result) { if (result == nullptr) { return false; } std::unique_ptr<Value> v(expr->fn(expr->name, state, expr->argc, expr->argv)); std::unique_ptr<Value> v(expr->fn(expr->name.c_str(), state, expr->argv)); if (!v) { return false; } Loading @@ -58,8 +58,8 @@ bool Evaluate(State* state, Expr* expr, std::string* result) { return true; } Value* EvaluateValue(State* state, Expr* expr) { return expr->fn(expr->name, state, expr->argc, expr->argv); Value* EvaluateValue(State* state, const std::unique_ptr<Expr>& expr) { return expr->fn(expr->name.c_str(), state, expr->argv); } Value* StringValue(const char* str) { Loading @@ -73,12 +73,12 @@ Value* StringValue(const std::string& str) { return StringValue(str.c_str()); } Value* ConcatFn(const char* name, State* state, int argc, Expr* argv[]) { if (argc == 0) { Value* ConcatFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { if (argv.empty()) { return StringValue(""); } std::string result; for (int i = 0; i < argc; ++i) { for (size_t i = 0; i < argv.size(); ++i) { std::string str; if (!Evaluate(state, argv[i], &str)) { return nullptr; Loading @@ -89,8 +89,8 @@ Value* ConcatFn(const char* name, State* state, int argc, Expr* argv[]) { return StringValue(result); } Value* IfElseFn(const char* name, State* state, int argc, Expr* argv[]) { if (argc != 2 && argc != 3) { Value* IfElseFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { if (argv.size() != 2 && argv.size() != 3) { state->errmsg = "ifelse expects 2 or 3 arguments"; return nullptr; } Loading @@ -102,16 +102,16 @@ Value* IfElseFn(const char* name, State* state, int argc, Expr* argv[]) { if (!cond.empty()) { return EvaluateValue(state, argv[1]); } else if (argc == 3) { } else if (argv.size() == 3) { return EvaluateValue(state, argv[2]); } return StringValue(""); } Value* AbortFn(const char* name, State* state, int argc, Expr* argv[]) { Value* AbortFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { std::string msg; if (argc > 0 && Evaluate(state, argv[0], &msg)) { if (!argv.empty() && Evaluate(state, argv[0], &msg)) { state->errmsg = msg; } else { state->errmsg = "called abort()"; Loading @@ -119,8 +119,8 @@ Value* AbortFn(const char* name, State* state, int argc, Expr* argv[]) { return nullptr; } Value* AssertFn(const char* name, State* state, int argc, Expr* argv[]) { for (int i = 0; i < argc; ++i) { Value* AssertFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { for (size_t i = 0; i < argv.size(); ++i) { std::string result; if (!Evaluate(state, argv[i], &result)) { return nullptr; Loading @@ -134,7 +134,7 @@ Value* AssertFn(const char* name, State* state, int argc, Expr* argv[]) { return StringValue(""); } Value* SleepFn(const char* name, State* state, int argc, Expr* argv[]) { Value* SleepFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { std::string val; if (!Evaluate(state, argv[0], &val)) { return nullptr; Loading @@ -149,8 +149,8 @@ Value* SleepFn(const char* name, State* state, int argc, Expr* argv[]) { return StringValue(val); } Value* StdoutFn(const char* name, State* state, int argc, Expr* argv[]) { for (int i = 0; i < argc; ++i) { Value* StdoutFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { for (size_t i = 0; i < argv.size(); ++i) { std::string v; if (!Evaluate(state, argv[i], &v)) { return nullptr; Loading @@ -161,7 +161,7 @@ Value* StdoutFn(const char* name, State* state, int argc, Expr* argv[]) { } Value* LogicalAndFn(const char* name, State* state, int argc, Expr* argv[]) { const std::vector<std::unique_ptr<Expr>>& argv) { std::string left; if (!Evaluate(state, argv[0], &left)) { return nullptr; Loading @@ -174,7 +174,7 @@ Value* LogicalAndFn(const char* name, State* state, } Value* LogicalOrFn(const char* name, State* state, int argc, Expr* argv[]) { const std::vector<std::unique_ptr<Expr>>& argv) { std::string left; if (!Evaluate(state, argv[0], &left)) { return nullptr; Loading @@ -187,7 +187,7 @@ Value* LogicalOrFn(const char* name, State* state, } Value* LogicalNotFn(const char* name, State* state, int argc, Expr* argv[]) { const std::vector<std::unique_ptr<Expr>>& argv) { std::string val; if (!Evaluate(state, argv[0], &val)) { return nullptr; Loading @@ -197,7 +197,7 @@ Value* LogicalNotFn(const char* name, State* state, } Value* SubstringFn(const char* name, State* state, int argc, Expr* argv[]) { const std::vector<std::unique_ptr<Expr>>& argv) { std::string needle; if (!Evaluate(state, argv[0], &needle)) { return nullptr; Loading @@ -212,7 +212,7 @@ Value* SubstringFn(const char* name, State* state, return StringValue(result); } Value* EqualityFn(const char* name, State* state, int argc, Expr* argv[]) { Value* EqualityFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { std::string left; if (!Evaluate(state, argv[0], &left)) { return nullptr; Loading @@ -226,7 +226,8 @@ Value* EqualityFn(const char* name, State* state, int argc, Expr* argv[]) { return StringValue(result); } Value* InequalityFn(const char* name, State* state, int argc, Expr* argv[]) { Value* InequalityFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { std::string left; if (!Evaluate(state, argv[0], &left)) { return nullptr; Loading @@ -240,7 +241,7 @@ Value* InequalityFn(const char* name, State* state, int argc, Expr* argv[]) { return StringValue(result); } Value* SequenceFn(const char* name, State* state, int argc, Expr* argv[]) { Value* SequenceFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { std::unique_ptr<Value> left(EvaluateValue(state, argv[0])); if (!left) { return nullptr; Loading @@ -248,14 +249,15 @@ Value* SequenceFn(const char* name, State* state, int argc, Expr* argv[]) { return EvaluateValue(state, argv[1]); } Value* LessThanIntFn(const char* name, State* state, int argc, Expr* argv[]) { if (argc != 2) { Value* LessThanIntFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { if (argv.size() != 2) { state->errmsg = "less_than_int expects 2 arguments"; return nullptr; } std::vector<std::string> args; if (!ReadArgs(state, 2, argv, &args)) { if (!ReadArgs(state, argv, &args)) { return nullptr; } Loading @@ -276,20 +278,34 @@ Value* LessThanIntFn(const char* name, State* state, int argc, Expr* argv[]) { } Value* GreaterThanIntFn(const char* name, State* state, int argc, Expr* argv[]) { if (argc != 2) { const std::vector<std::unique_ptr<Expr>>& argv) { if (argv.size() != 2) { state->errmsg = "greater_than_int expects 2 arguments"; return nullptr; } Expr* temp[2]; temp[0] = argv[1]; temp[1] = argv[0]; std::vector<std::string> args; if (!ReadArgs(state, argv, &args)) { return nullptr; } // Parse up to at least long long or 64-bit integers. int64_t l_int; if (!android::base::ParseInt(args[0].c_str(), &l_int)) { state->errmsg = "failed to parse int in " + args[0]; return nullptr; } int64_t r_int; if (!android::base::ParseInt(args[1].c_str(), &r_int)) { state->errmsg = "failed to parse int in " + args[1]; return nullptr; } return LessThanIntFn(name, state, 2, temp); return StringValue(l_int > r_int ? "t" : ""); } Value* Literal(const char* name, State* state, int argc, Expr* argv[]) { Value* Literal(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { return StringValue(name); } Loading Loading @@ -329,14 +345,22 @@ void RegisterBuiltins() { // convenience methods for functions // ----------------------------------------------------------------- // Evaluate the expressions in argv, and put the results of strings in // args. If any expression evaluates to nullptr, free the rest and return // false. Return true on success. bool ReadArgs(State* state, int argc, Expr* argv[], std::vector<std::string>* args) { // Evaluate the expressions in argv, and put the results of strings in args. If any expression // evaluates to nullptr, return false. Return true on success. bool ReadArgs(State* state, const std::vector<std::unique_ptr<Expr>>& argv, std::vector<std::string>* args) { return ReadArgs(state, argv, args, 0, argv.size()); } bool ReadArgs(State* state, const std::vector<std::unique_ptr<Expr>>& argv, std::vector<std::string>* args, size_t start, size_t len) { if (args == nullptr) { return false; } for (int i = 0; i < argc; ++i) { if (len == 0 || start + len > argv.size()) { return false; } for (size_t i = start; i < start + len; ++i) { std::string var; if (!Evaluate(state, argv[i], &var)) { args->clear(); Loading @@ -347,15 +371,22 @@ bool ReadArgs(State* state, int argc, Expr* argv[], std::vector<std::string>* ar return true; } // Evaluate the expressions in argv, and put the results of Value* in // args. If any expression evaluate to nullptr, free the rest and return // false. Return true on success. bool ReadValueArgs(State* state, int argc, Expr* argv[], // Evaluate the expressions in argv, and put the results of Value* in args. If any expression // evaluate to nullptr, return false. Return true on success. bool ReadValueArgs(State* state, const std::vector<std::unique_ptr<Expr>>& argv, std::vector<std::unique_ptr<Value>>* args) { return ReadValueArgs(state, argv, args, 0, argv.size()); } bool ReadValueArgs(State* state, const std::vector<std::unique_ptr<Expr>>& argv, std::vector<std::unique_ptr<Value>>* args, size_t start, size_t len) { if (args == nullptr) { return false; } for (int i = 0; i < argc; ++i) { if (len == 0 || start + len > argv.size()) { return false; } for (size_t i = start; i < start + len; ++i) { std::unique_ptr<Value> v(EvaluateValue(state, argv[i])); if (!v) { args->clear(); Loading edify/expr.h +46 −37 Original line number Diff line number Diff line Loading @@ -18,7 +18,10 @@ #define _EXPRESSION_H #include <unistd.h> #include <memory> #include <string> #include <vector> #include "error_code.h" Loading Loading @@ -65,47 +68,49 @@ struct Value { struct Expr; using Function = Value* (*)(const char* name, State* state, int argc, Expr* argv[]); using Function = Value* (*)(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv); struct Expr { Function fn; const char* name; int argc; Expr** argv; std::string name; std::vector<std::unique_ptr<Expr>> argv; int start, end; Expr(Function fn, const std::string& name, int start, int end) : fn(fn), name(name), start(start), end(end) {} }; // Take one of the Expr*s passed to the function as an argument, // evaluate it, return the resulting Value. The caller takes // ownership of the returned Value. Value* EvaluateValue(State* state, Expr* expr); // Evaluate the input expr, return the resulting Value. Value* EvaluateValue(State* state, const std::unique_ptr<Expr>& expr); // Take one of the Expr*s passed to the function as an argument, // evaluate it, assert that it is a string, and update the result // parameter. This function returns true if the evaluation succeeds. // This is a convenience function for older functions that want to // deal only with strings. bool Evaluate(State* state, Expr* expr, std::string* result); // Evaluate the input expr, assert that it is a string, and update the result parameter. This // function returns true if the evaluation succeeds. This is a convenience function for older // functions that want to deal only with strings. bool Evaluate(State* state, const std::unique_ptr<Expr>& expr, std::string* result); // Glue to make an Expr out of a literal. Value* Literal(const char* name, State* state, int argc, Expr* argv[]); Value* Literal(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv); // Functions corresponding to various syntactic sugar operators. // ("concat" is also available as a builtin function, to concatenate // more than two strings.) Value* ConcatFn(const char* name, State* state, int argc, Expr* argv[]); Value* LogicalAndFn(const char* name, State* state, int argc, Expr* argv[]); Value* LogicalOrFn(const char* name, State* state, int argc, Expr* argv[]); Value* LogicalNotFn(const char* name, State* state, int argc, Expr* argv[]); Value* SubstringFn(const char* name, State* state, int argc, Expr* argv[]); Value* EqualityFn(const char* name, State* state, int argc, Expr* argv[]); Value* InequalityFn(const char* name, State* state, int argc, Expr* argv[]); Value* SequenceFn(const char* name, State* state, int argc, Expr* argv[]); Value* ConcatFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv); Value* LogicalAndFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv); Value* LogicalOrFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv); Value* LogicalNotFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv); Value* SubstringFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv); Value* EqualityFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv); Value* InequalityFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv); Value* SequenceFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv); // Global builtins, registered by RegisterBuiltins(). Value* IfElseFn(const char* name, State* state, int argc, Expr* argv[]); Value* AssertFn(const char* name, State* state, int argc, Expr* argv[]); Value* AbortFn(const char* name, State* state, int argc, Expr* argv[]); Value* IfElseFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv); Value* AssertFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv); Value* AbortFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv); // Register a new function. The same Function may be registered under // multiple names, but a given name should only be used once. Loading @@ -120,15 +125,19 @@ Function FindFunction(const std::string& name); // --- convenience functions for use in functions --- // Evaluate the expressions in argv, and put the results of strings in // args. If any expression evaluates to nullptr, free the rest and return // false. Return true on success. bool ReadArgs(State* state, int argc, Expr* argv[], std::vector<std::string>* args); // Evaluate the expressions in argv, and put the results of strings in args. If any expression // evaluates to nullptr, return false. Return true on success. bool ReadArgs(State* state, const std::vector<std::unique_ptr<Expr>>& argv, std::vector<std::string>* args); bool ReadArgs(State* state, const std::vector<std::unique_ptr<Expr>>& argv, std::vector<std::string>* args, size_t start, size_t len); // Evaluate the expressions in argv, and put the results of Value* in // args. If any expression evaluate to nullptr, free the rest and return // false. Return true on success. bool ReadValueArgs(State* state, int argc, Expr* argv[], std::vector<std::unique_ptr<Value>>* args); // Evaluate the expressions in argv, and put the results of Value* in args. If any // expression evaluate to nullptr, return false. Return true on success. bool ReadValueArgs(State* state, const std::vector<std::unique_ptr<Expr>>& argv, std::vector<std::unique_ptr<Value>>* args); bool ReadValueArgs(State* state, const std::vector<std::unique_ptr<Expr>>& argv, std::vector<std::unique_ptr<Value>>* args, size_t start, size_t len); // Use printf-style arguments to compose an error message to put into // *state. Returns NULL. Loading @@ -145,6 +154,6 @@ Value* StringValue(const char* str); Value* StringValue(const std::string& str); int parse_string(const char* str, Expr** root, int* error_count); int parse_string(const char* str, std::unique_ptr<Expr>* root, int* error_count); #endif // _EXPRESSION_H edify/parser.yy +27 −44 Original line number Diff line number Diff line Loading @@ -19,6 +19,10 @@ #include <stdlib.h> #include <string.h> #include <memory> #include <string> #include <vector> #include "expr.h" #include "yydefs.h" #include "parser.h" Loading @@ -26,8 +30,8 @@ extern int gLine; extern int gColumn; void yyerror(Expr** root, int* error_count, const char* s); int yyparse(Expr** root, int* error_count); void yyerror(std::unique_ptr<Expr>* root, int* error_count, const char* s); int yyparse(std::unique_ptr<Expr>* root, int* error_count); struct yy_buffer_state; void yy_switch_to_buffer(struct yy_buffer_state* new_buffer); Loading @@ -38,17 +42,11 @@ struct yy_buffer_state* yy_scan_string(const char* yystr); static Expr* Build(Function fn, YYLTYPE loc, size_t count, ...) { va_list v; va_start(v, count); Expr* e = static_cast<Expr*>(malloc(sizeof(Expr))); e->fn = fn; e->name = "(operator)"; e->argc = count; e->argv = static_cast<Expr**>(malloc(count * sizeof(Expr*))); Expr* e = new Expr(fn, "(operator)", loc.start, loc.end); for (size_t i = 0; i < count; ++i) { e->argv[i] = va_arg(v, Expr*); e->argv.emplace_back(va_arg(v, Expr*)); } va_end(v); e->start = loc.start; e->end = loc.end; return e; } Loading @@ -59,10 +57,7 @@ static Expr* Build(Function fn, YYLTYPE loc, size_t count, ...) { %union { char* str; Expr* expr; struct { int argc; Expr** argv; } args; std::vector<std::unique_ptr<Expr>>* args; } %token AND OR SUBSTR SUPERSTR EQ NE IF THEN ELSE ENDIF Loading @@ -70,7 +65,10 @@ static Expr* Build(Function fn, YYLTYPE loc, size_t count, ...) { %type <expr> expr %type <args> arglist %parse-param {Expr** root} %destructor { delete $$; } expr %destructor { delete $$; } arglist %parse-param {std::unique_ptr<Expr>* root} %parse-param {int* error_count} %error-verbose Loading @@ -85,17 +83,11 @@ static Expr* Build(Function fn, YYLTYPE loc, size_t count, ...) { %% input: expr { *root = $1; } input: expr { root->reset($1); } ; expr: STRING { $$ = static_cast<Expr*>(malloc(sizeof(Expr))); $$->fn = Literal; $$->name = $1; $$->argc = 0; $$->argv = NULL; $$->start = @$.start; $$->end = @$.end; $$ = new Expr(Literal, $1, @$.start, @$.end); } | '(' expr ')' { $$ = $2; $$->start=@$.start; $$->end=@$.end; } | expr ';' { $$ = $1; $$->start=@1.start; $$->end=@1.end; } Loading @@ -110,41 +102,32 @@ expr: STRING { | IF expr THEN expr ENDIF { $$ = Build(IfElseFn, @$, 2, $2, $4); } | IF expr THEN expr ELSE expr ENDIF { $$ = Build(IfElseFn, @$, 3, $2, $4, $6); } | STRING '(' arglist ')' { $$ = static_cast<Expr*>(malloc(sizeof(Expr))); $$->fn = FindFunction($1); if ($$->fn == nullptr) { char buffer[256]; snprintf(buffer, sizeof(buffer), "unknown function \"%s\"", $1); yyerror(root, error_count, buffer); Function fn = FindFunction($1); if (fn == nullptr) { std::string msg = "unknown function \"" + std::string($1) + "\""; yyerror(root, error_count, msg.c_str()); YYERROR; } $$->name = $1; $$->argc = $3.argc; $$->argv = $3.argv; $$->start = @$.start; $$->end = @$.end; $$ = new Expr(fn, $1, @$.start, @$.end); $$->argv = std::move(*$3); } ; arglist: /* empty */ { $$.argc = 0; $$.argv = NULL; $$ = new std::vector<std::unique_ptr<Expr>>; } | expr { $$.argc = 1; $$.argv = static_cast<Expr**>(malloc(sizeof(Expr*))); $$.argv[0] = $1; $$ = new std::vector<std::unique_ptr<Expr>>; $$->emplace_back($1); } | arglist ',' expr { $$.argc = $1.argc + 1; $$.argv = static_cast<Expr**>(realloc($$.argv, $$.argc * sizeof(Expr*))); $$.argv[$$.argc-1] = $3; $$->push_back(std::unique_ptr<Expr>($3)); } ; %% void yyerror(Expr** root, int* error_count, const char* s) { void yyerror(std::unique_ptr<Expr>* root, int* error_count, const char* s) { if (strlen(s) == 0) { s = "syntax error"; } Loading @@ -152,7 +135,7 @@ void yyerror(Expr** root, int* error_count, const char* s) { ++*error_count; } int parse_string(const char* str, Expr** root, int* error_count) { int parse_string(const char* str, std::unique_ptr<Expr>* root, int* error_count) { yy_switch_to_buffer(yy_scan_string(str)); return yyparse(root, error_count); } tests/component/edify_test.cpp +3 −2 Original line number Diff line number Diff line Loading @@ -14,6 +14,7 @@ * limitations under the License. */ #include <memory> #include <string> #include <gtest/gtest.h> Loading @@ -21,7 +22,7 @@ #include "edify/expr.h" static void expect(const char* expr_str, const char* expected) { Expr* e; std::unique_ptr<Expr> e; int error_count = 0; EXPECT_EQ(0, parse_string(expr_str, &e, &error_count)); EXPECT_EQ(0, error_count); Loading Loading @@ -152,7 +153,7 @@ TEST_F(EdifyTest, big_string) { TEST_F(EdifyTest, unknown_function) { // unknown function const char* script1 = "unknown_function()"; Expr* expr; std::unique_ptr<Expr> expr; int error_count = 0; EXPECT_EQ(1, parse_string(script1, &expr, &error_count)); EXPECT_EQ(1, error_count); Loading Loading
edify/edify_parser.cpp +5 −4 Original line number Diff line number Diff line Loading @@ -27,18 +27,19 @@ #include <errno.h> #include <stdio.h> #include <memory> #include <string> #include <android-base/file.h> #include "expr.h" static void ExprDump(int depth, const Expr* n, const std::string& script) { static void ExprDump(int depth, const std::unique_ptr<Expr>& n, const std::string& script) { printf("%*s", depth*2, ""); printf("%s %p (%d-%d) \"%s\"\n", n->name == NULL ? "(NULL)" : n->name, n->fn, n->start, n->end, n->name.c_str(), n->fn, n->start, n->end, script.substr(n->start, n->end - n->start).c_str()); for (int i = 0; i < n->argc; ++i) { for (size_t i = 0; i < n->argv.size(); ++i) { ExprDump(depth+1, n->argv[i], script); } } Loading @@ -57,7 +58,7 @@ int main(int argc, char** argv) { return 1; } Expr* root; std::unique_ptr<Expr> root; int error_count = 0; int error = parse_string(buffer.data(), &root, &error_count); printf("parse returned %d; %d errors encountered\n", error, error_count); Loading
edify/expr.cpp +75 −44 Original line number Diff line number Diff line Loading @@ -40,12 +40,12 @@ static bool BooleanString(const std::string& s) { return !s.empty(); } bool Evaluate(State* state, Expr* expr, std::string* result) { bool Evaluate(State* state, const std::unique_ptr<Expr>& expr, std::string* result) { if (result == nullptr) { return false; } std::unique_ptr<Value> v(expr->fn(expr->name, state, expr->argc, expr->argv)); std::unique_ptr<Value> v(expr->fn(expr->name.c_str(), state, expr->argv)); if (!v) { return false; } Loading @@ -58,8 +58,8 @@ bool Evaluate(State* state, Expr* expr, std::string* result) { return true; } Value* EvaluateValue(State* state, Expr* expr) { return expr->fn(expr->name, state, expr->argc, expr->argv); Value* EvaluateValue(State* state, const std::unique_ptr<Expr>& expr) { return expr->fn(expr->name.c_str(), state, expr->argv); } Value* StringValue(const char* str) { Loading @@ -73,12 +73,12 @@ Value* StringValue(const std::string& str) { return StringValue(str.c_str()); } Value* ConcatFn(const char* name, State* state, int argc, Expr* argv[]) { if (argc == 0) { Value* ConcatFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { if (argv.empty()) { return StringValue(""); } std::string result; for (int i = 0; i < argc; ++i) { for (size_t i = 0; i < argv.size(); ++i) { std::string str; if (!Evaluate(state, argv[i], &str)) { return nullptr; Loading @@ -89,8 +89,8 @@ Value* ConcatFn(const char* name, State* state, int argc, Expr* argv[]) { return StringValue(result); } Value* IfElseFn(const char* name, State* state, int argc, Expr* argv[]) { if (argc != 2 && argc != 3) { Value* IfElseFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { if (argv.size() != 2 && argv.size() != 3) { state->errmsg = "ifelse expects 2 or 3 arguments"; return nullptr; } Loading @@ -102,16 +102,16 @@ Value* IfElseFn(const char* name, State* state, int argc, Expr* argv[]) { if (!cond.empty()) { return EvaluateValue(state, argv[1]); } else if (argc == 3) { } else if (argv.size() == 3) { return EvaluateValue(state, argv[2]); } return StringValue(""); } Value* AbortFn(const char* name, State* state, int argc, Expr* argv[]) { Value* AbortFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { std::string msg; if (argc > 0 && Evaluate(state, argv[0], &msg)) { if (!argv.empty() && Evaluate(state, argv[0], &msg)) { state->errmsg = msg; } else { state->errmsg = "called abort()"; Loading @@ -119,8 +119,8 @@ Value* AbortFn(const char* name, State* state, int argc, Expr* argv[]) { return nullptr; } Value* AssertFn(const char* name, State* state, int argc, Expr* argv[]) { for (int i = 0; i < argc; ++i) { Value* AssertFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { for (size_t i = 0; i < argv.size(); ++i) { std::string result; if (!Evaluate(state, argv[i], &result)) { return nullptr; Loading @@ -134,7 +134,7 @@ Value* AssertFn(const char* name, State* state, int argc, Expr* argv[]) { return StringValue(""); } Value* SleepFn(const char* name, State* state, int argc, Expr* argv[]) { Value* SleepFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { std::string val; if (!Evaluate(state, argv[0], &val)) { return nullptr; Loading @@ -149,8 +149,8 @@ Value* SleepFn(const char* name, State* state, int argc, Expr* argv[]) { return StringValue(val); } Value* StdoutFn(const char* name, State* state, int argc, Expr* argv[]) { for (int i = 0; i < argc; ++i) { Value* StdoutFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { for (size_t i = 0; i < argv.size(); ++i) { std::string v; if (!Evaluate(state, argv[i], &v)) { return nullptr; Loading @@ -161,7 +161,7 @@ Value* StdoutFn(const char* name, State* state, int argc, Expr* argv[]) { } Value* LogicalAndFn(const char* name, State* state, int argc, Expr* argv[]) { const std::vector<std::unique_ptr<Expr>>& argv) { std::string left; if (!Evaluate(state, argv[0], &left)) { return nullptr; Loading @@ -174,7 +174,7 @@ Value* LogicalAndFn(const char* name, State* state, } Value* LogicalOrFn(const char* name, State* state, int argc, Expr* argv[]) { const std::vector<std::unique_ptr<Expr>>& argv) { std::string left; if (!Evaluate(state, argv[0], &left)) { return nullptr; Loading @@ -187,7 +187,7 @@ Value* LogicalOrFn(const char* name, State* state, } Value* LogicalNotFn(const char* name, State* state, int argc, Expr* argv[]) { const std::vector<std::unique_ptr<Expr>>& argv) { std::string val; if (!Evaluate(state, argv[0], &val)) { return nullptr; Loading @@ -197,7 +197,7 @@ Value* LogicalNotFn(const char* name, State* state, } Value* SubstringFn(const char* name, State* state, int argc, Expr* argv[]) { const std::vector<std::unique_ptr<Expr>>& argv) { std::string needle; if (!Evaluate(state, argv[0], &needle)) { return nullptr; Loading @@ -212,7 +212,7 @@ Value* SubstringFn(const char* name, State* state, return StringValue(result); } Value* EqualityFn(const char* name, State* state, int argc, Expr* argv[]) { Value* EqualityFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { std::string left; if (!Evaluate(state, argv[0], &left)) { return nullptr; Loading @@ -226,7 +226,8 @@ Value* EqualityFn(const char* name, State* state, int argc, Expr* argv[]) { return StringValue(result); } Value* InequalityFn(const char* name, State* state, int argc, Expr* argv[]) { Value* InequalityFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { std::string left; if (!Evaluate(state, argv[0], &left)) { return nullptr; Loading @@ -240,7 +241,7 @@ Value* InequalityFn(const char* name, State* state, int argc, Expr* argv[]) { return StringValue(result); } Value* SequenceFn(const char* name, State* state, int argc, Expr* argv[]) { Value* SequenceFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { std::unique_ptr<Value> left(EvaluateValue(state, argv[0])); if (!left) { return nullptr; Loading @@ -248,14 +249,15 @@ Value* SequenceFn(const char* name, State* state, int argc, Expr* argv[]) { return EvaluateValue(state, argv[1]); } Value* LessThanIntFn(const char* name, State* state, int argc, Expr* argv[]) { if (argc != 2) { Value* LessThanIntFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { if (argv.size() != 2) { state->errmsg = "less_than_int expects 2 arguments"; return nullptr; } std::vector<std::string> args; if (!ReadArgs(state, 2, argv, &args)) { if (!ReadArgs(state, argv, &args)) { return nullptr; } Loading @@ -276,20 +278,34 @@ Value* LessThanIntFn(const char* name, State* state, int argc, Expr* argv[]) { } Value* GreaterThanIntFn(const char* name, State* state, int argc, Expr* argv[]) { if (argc != 2) { const std::vector<std::unique_ptr<Expr>>& argv) { if (argv.size() != 2) { state->errmsg = "greater_than_int expects 2 arguments"; return nullptr; } Expr* temp[2]; temp[0] = argv[1]; temp[1] = argv[0]; std::vector<std::string> args; if (!ReadArgs(state, argv, &args)) { return nullptr; } // Parse up to at least long long or 64-bit integers. int64_t l_int; if (!android::base::ParseInt(args[0].c_str(), &l_int)) { state->errmsg = "failed to parse int in " + args[0]; return nullptr; } int64_t r_int; if (!android::base::ParseInt(args[1].c_str(), &r_int)) { state->errmsg = "failed to parse int in " + args[1]; return nullptr; } return LessThanIntFn(name, state, 2, temp); return StringValue(l_int > r_int ? "t" : ""); } Value* Literal(const char* name, State* state, int argc, Expr* argv[]) { Value* Literal(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { return StringValue(name); } Loading Loading @@ -329,14 +345,22 @@ void RegisterBuiltins() { // convenience methods for functions // ----------------------------------------------------------------- // Evaluate the expressions in argv, and put the results of strings in // args. If any expression evaluates to nullptr, free the rest and return // false. Return true on success. bool ReadArgs(State* state, int argc, Expr* argv[], std::vector<std::string>* args) { // Evaluate the expressions in argv, and put the results of strings in args. If any expression // evaluates to nullptr, return false. Return true on success. bool ReadArgs(State* state, const std::vector<std::unique_ptr<Expr>>& argv, std::vector<std::string>* args) { return ReadArgs(state, argv, args, 0, argv.size()); } bool ReadArgs(State* state, const std::vector<std::unique_ptr<Expr>>& argv, std::vector<std::string>* args, size_t start, size_t len) { if (args == nullptr) { return false; } for (int i = 0; i < argc; ++i) { if (len == 0 || start + len > argv.size()) { return false; } for (size_t i = start; i < start + len; ++i) { std::string var; if (!Evaluate(state, argv[i], &var)) { args->clear(); Loading @@ -347,15 +371,22 @@ bool ReadArgs(State* state, int argc, Expr* argv[], std::vector<std::string>* ar return true; } // Evaluate the expressions in argv, and put the results of Value* in // args. If any expression evaluate to nullptr, free the rest and return // false. Return true on success. bool ReadValueArgs(State* state, int argc, Expr* argv[], // Evaluate the expressions in argv, and put the results of Value* in args. If any expression // evaluate to nullptr, return false. Return true on success. bool ReadValueArgs(State* state, const std::vector<std::unique_ptr<Expr>>& argv, std::vector<std::unique_ptr<Value>>* args) { return ReadValueArgs(state, argv, args, 0, argv.size()); } bool ReadValueArgs(State* state, const std::vector<std::unique_ptr<Expr>>& argv, std::vector<std::unique_ptr<Value>>* args, size_t start, size_t len) { if (args == nullptr) { return false; } for (int i = 0; i < argc; ++i) { if (len == 0 || start + len > argv.size()) { return false; } for (size_t i = start; i < start + len; ++i) { std::unique_ptr<Value> v(EvaluateValue(state, argv[i])); if (!v) { args->clear(); Loading
edify/expr.h +46 −37 Original line number Diff line number Diff line Loading @@ -18,7 +18,10 @@ #define _EXPRESSION_H #include <unistd.h> #include <memory> #include <string> #include <vector> #include "error_code.h" Loading Loading @@ -65,47 +68,49 @@ struct Value { struct Expr; using Function = Value* (*)(const char* name, State* state, int argc, Expr* argv[]); using Function = Value* (*)(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv); struct Expr { Function fn; const char* name; int argc; Expr** argv; std::string name; std::vector<std::unique_ptr<Expr>> argv; int start, end; Expr(Function fn, const std::string& name, int start, int end) : fn(fn), name(name), start(start), end(end) {} }; // Take one of the Expr*s passed to the function as an argument, // evaluate it, return the resulting Value. The caller takes // ownership of the returned Value. Value* EvaluateValue(State* state, Expr* expr); // Evaluate the input expr, return the resulting Value. Value* EvaluateValue(State* state, const std::unique_ptr<Expr>& expr); // Take one of the Expr*s passed to the function as an argument, // evaluate it, assert that it is a string, and update the result // parameter. This function returns true if the evaluation succeeds. // This is a convenience function for older functions that want to // deal only with strings. bool Evaluate(State* state, Expr* expr, std::string* result); // Evaluate the input expr, assert that it is a string, and update the result parameter. This // function returns true if the evaluation succeeds. This is a convenience function for older // functions that want to deal only with strings. bool Evaluate(State* state, const std::unique_ptr<Expr>& expr, std::string* result); // Glue to make an Expr out of a literal. Value* Literal(const char* name, State* state, int argc, Expr* argv[]); Value* Literal(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv); // Functions corresponding to various syntactic sugar operators. // ("concat" is also available as a builtin function, to concatenate // more than two strings.) Value* ConcatFn(const char* name, State* state, int argc, Expr* argv[]); Value* LogicalAndFn(const char* name, State* state, int argc, Expr* argv[]); Value* LogicalOrFn(const char* name, State* state, int argc, Expr* argv[]); Value* LogicalNotFn(const char* name, State* state, int argc, Expr* argv[]); Value* SubstringFn(const char* name, State* state, int argc, Expr* argv[]); Value* EqualityFn(const char* name, State* state, int argc, Expr* argv[]); Value* InequalityFn(const char* name, State* state, int argc, Expr* argv[]); Value* SequenceFn(const char* name, State* state, int argc, Expr* argv[]); Value* ConcatFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv); Value* LogicalAndFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv); Value* LogicalOrFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv); Value* LogicalNotFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv); Value* SubstringFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv); Value* EqualityFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv); Value* InequalityFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv); Value* SequenceFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv); // Global builtins, registered by RegisterBuiltins(). Value* IfElseFn(const char* name, State* state, int argc, Expr* argv[]); Value* AssertFn(const char* name, State* state, int argc, Expr* argv[]); Value* AbortFn(const char* name, State* state, int argc, Expr* argv[]); Value* IfElseFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv); Value* AssertFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv); Value* AbortFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv); // Register a new function. The same Function may be registered under // multiple names, but a given name should only be used once. Loading @@ -120,15 +125,19 @@ Function FindFunction(const std::string& name); // --- convenience functions for use in functions --- // Evaluate the expressions in argv, and put the results of strings in // args. If any expression evaluates to nullptr, free the rest and return // false. Return true on success. bool ReadArgs(State* state, int argc, Expr* argv[], std::vector<std::string>* args); // Evaluate the expressions in argv, and put the results of strings in args. If any expression // evaluates to nullptr, return false. Return true on success. bool ReadArgs(State* state, const std::vector<std::unique_ptr<Expr>>& argv, std::vector<std::string>* args); bool ReadArgs(State* state, const std::vector<std::unique_ptr<Expr>>& argv, std::vector<std::string>* args, size_t start, size_t len); // Evaluate the expressions in argv, and put the results of Value* in // args. If any expression evaluate to nullptr, free the rest and return // false. Return true on success. bool ReadValueArgs(State* state, int argc, Expr* argv[], std::vector<std::unique_ptr<Value>>* args); // Evaluate the expressions in argv, and put the results of Value* in args. If any // expression evaluate to nullptr, return false. Return true on success. bool ReadValueArgs(State* state, const std::vector<std::unique_ptr<Expr>>& argv, std::vector<std::unique_ptr<Value>>* args); bool ReadValueArgs(State* state, const std::vector<std::unique_ptr<Expr>>& argv, std::vector<std::unique_ptr<Value>>* args, size_t start, size_t len); // Use printf-style arguments to compose an error message to put into // *state. Returns NULL. Loading @@ -145,6 +154,6 @@ Value* StringValue(const char* str); Value* StringValue(const std::string& str); int parse_string(const char* str, Expr** root, int* error_count); int parse_string(const char* str, std::unique_ptr<Expr>* root, int* error_count); #endif // _EXPRESSION_H
edify/parser.yy +27 −44 Original line number Diff line number Diff line Loading @@ -19,6 +19,10 @@ #include <stdlib.h> #include <string.h> #include <memory> #include <string> #include <vector> #include "expr.h" #include "yydefs.h" #include "parser.h" Loading @@ -26,8 +30,8 @@ extern int gLine; extern int gColumn; void yyerror(Expr** root, int* error_count, const char* s); int yyparse(Expr** root, int* error_count); void yyerror(std::unique_ptr<Expr>* root, int* error_count, const char* s); int yyparse(std::unique_ptr<Expr>* root, int* error_count); struct yy_buffer_state; void yy_switch_to_buffer(struct yy_buffer_state* new_buffer); Loading @@ -38,17 +42,11 @@ struct yy_buffer_state* yy_scan_string(const char* yystr); static Expr* Build(Function fn, YYLTYPE loc, size_t count, ...) { va_list v; va_start(v, count); Expr* e = static_cast<Expr*>(malloc(sizeof(Expr))); e->fn = fn; e->name = "(operator)"; e->argc = count; e->argv = static_cast<Expr**>(malloc(count * sizeof(Expr*))); Expr* e = new Expr(fn, "(operator)", loc.start, loc.end); for (size_t i = 0; i < count; ++i) { e->argv[i] = va_arg(v, Expr*); e->argv.emplace_back(va_arg(v, Expr*)); } va_end(v); e->start = loc.start; e->end = loc.end; return e; } Loading @@ -59,10 +57,7 @@ static Expr* Build(Function fn, YYLTYPE loc, size_t count, ...) { %union { char* str; Expr* expr; struct { int argc; Expr** argv; } args; std::vector<std::unique_ptr<Expr>>* args; } %token AND OR SUBSTR SUPERSTR EQ NE IF THEN ELSE ENDIF Loading @@ -70,7 +65,10 @@ static Expr* Build(Function fn, YYLTYPE loc, size_t count, ...) { %type <expr> expr %type <args> arglist %parse-param {Expr** root} %destructor { delete $$; } expr %destructor { delete $$; } arglist %parse-param {std::unique_ptr<Expr>* root} %parse-param {int* error_count} %error-verbose Loading @@ -85,17 +83,11 @@ static Expr* Build(Function fn, YYLTYPE loc, size_t count, ...) { %% input: expr { *root = $1; } input: expr { root->reset($1); } ; expr: STRING { $$ = static_cast<Expr*>(malloc(sizeof(Expr))); $$->fn = Literal; $$->name = $1; $$->argc = 0; $$->argv = NULL; $$->start = @$.start; $$->end = @$.end; $$ = new Expr(Literal, $1, @$.start, @$.end); } | '(' expr ')' { $$ = $2; $$->start=@$.start; $$->end=@$.end; } | expr ';' { $$ = $1; $$->start=@1.start; $$->end=@1.end; } Loading @@ -110,41 +102,32 @@ expr: STRING { | IF expr THEN expr ENDIF { $$ = Build(IfElseFn, @$, 2, $2, $4); } | IF expr THEN expr ELSE expr ENDIF { $$ = Build(IfElseFn, @$, 3, $2, $4, $6); } | STRING '(' arglist ')' { $$ = static_cast<Expr*>(malloc(sizeof(Expr))); $$->fn = FindFunction($1); if ($$->fn == nullptr) { char buffer[256]; snprintf(buffer, sizeof(buffer), "unknown function \"%s\"", $1); yyerror(root, error_count, buffer); Function fn = FindFunction($1); if (fn == nullptr) { std::string msg = "unknown function \"" + std::string($1) + "\""; yyerror(root, error_count, msg.c_str()); YYERROR; } $$->name = $1; $$->argc = $3.argc; $$->argv = $3.argv; $$->start = @$.start; $$->end = @$.end; $$ = new Expr(fn, $1, @$.start, @$.end); $$->argv = std::move(*$3); } ; arglist: /* empty */ { $$.argc = 0; $$.argv = NULL; $$ = new std::vector<std::unique_ptr<Expr>>; } | expr { $$.argc = 1; $$.argv = static_cast<Expr**>(malloc(sizeof(Expr*))); $$.argv[0] = $1; $$ = new std::vector<std::unique_ptr<Expr>>; $$->emplace_back($1); } | arglist ',' expr { $$.argc = $1.argc + 1; $$.argv = static_cast<Expr**>(realloc($$.argv, $$.argc * sizeof(Expr*))); $$.argv[$$.argc-1] = $3; $$->push_back(std::unique_ptr<Expr>($3)); } ; %% void yyerror(Expr** root, int* error_count, const char* s) { void yyerror(std::unique_ptr<Expr>* root, int* error_count, const char* s) { if (strlen(s) == 0) { s = "syntax error"; } Loading @@ -152,7 +135,7 @@ void yyerror(Expr** root, int* error_count, const char* s) { ++*error_count; } int parse_string(const char* str, Expr** root, int* error_count) { int parse_string(const char* str, std::unique_ptr<Expr>* root, int* error_count) { yy_switch_to_buffer(yy_scan_string(str)); return yyparse(root, error_count); }
tests/component/edify_test.cpp +3 −2 Original line number Diff line number Diff line Loading @@ -14,6 +14,7 @@ * limitations under the License. */ #include <memory> #include <string> #include <gtest/gtest.h> Loading @@ -21,7 +22,7 @@ #include "edify/expr.h" static void expect(const char* expr_str, const char* expected) { Expr* e; std::unique_ptr<Expr> e; int error_count = 0; EXPECT_EQ(0, parse_string(expr_str, &e, &error_count)); EXPECT_EQ(0, error_count); Loading Loading @@ -152,7 +153,7 @@ TEST_F(EdifyTest, big_string) { TEST_F(EdifyTest, unknown_function) { // unknown function const char* script1 = "unknown_function()"; Expr* expr; std::unique_ptr<Expr> expr; int error_count = 0; EXPECT_EQ(1, parse_string(script1, &expr, &error_count)); EXPECT_EQ(1, error_count); Loading