Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5e1a2dc5 authored by Tianjie Xu's avatar Tianjie Xu Committed by android-build-merger
Browse files

Merge "Remove malloc in edify functions" am: 1ea869b0 am: 137d8533

am: eb0623b1

Change-Id: I7c48105d9259b1713e8be5fb2c50ef8d6a92c993
parents b39a90f0 eb0623b1
Loading
Loading
Loading
Loading
+5 −4
Original line number Diff line number Diff line
@@ -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);
    }
}
@@ -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);
+75 −44
Original line number Diff line number Diff line
@@ -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;
    }
@@ -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) {
@@ -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;
@@ -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;
    }
@@ -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()";
@@ -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;
@@ -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;
@@ -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;
@@ -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;
@@ -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;
@@ -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;
@@ -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;
@@ -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;
@@ -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;
@@ -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;
@@ -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;
    }

@@ -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);
}

@@ -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();
@@ -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();
+46 −37
Original line number Diff line number Diff line
@@ -18,7 +18,10 @@
#define _EXPRESSION_H

#include <unistd.h>

#include <memory>
#include <string>
#include <vector>

#include "error_code.h"

@@ -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.
@@ -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.
@@ -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
+27 −44
Original line number Diff line number Diff line
@@ -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"
@@ -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);
@@ -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;
}

@@ -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
@@ -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

@@ -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; }
@@ -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";
  }
@@ -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);
}
+3 −2
Original line number Diff line number Diff line
@@ -14,6 +14,7 @@
 * limitations under the License.
 */

#include <memory>
#include <string>

#include <gtest/gtest.h>
@@ -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);
@@ -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