/* * Copyright (C) 2009 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include "expr.h" #include "parser.h" int expect(const char* expr_str, const char* expected, int* errors) { Expr* e; int error; char* result; printf("."); yy_scan_string(expr_str); error = yyparse(&e); if (error > 0) { fprintf(stderr, "error parsing \"%s\"\n", expr_str); ++*errors; return 0; } result = Evaluate(NULL, e); if (result == NULL && expected != NULL) { fprintf(stderr, "error evaluating \"%s\"\n", expr_str); ++*errors; return 0; } if (result == NULL && expected == NULL) { return 1; } if (strcmp(result, expected) != 0) { fprintf(stderr, "evaluating \"%s\": expected \"%s\", got \"%s\"\n", expr_str, expected, result); ++*errors; free(result); return 0; } free(result); return 1; } int test() { int errors = 0; expect("a", "a", &errors); expect("\"a\"", "a", &errors); expect("\"\\x61\"", "a", &errors); expect("# this is a comment\n" " a\n" " \n", "a", &errors); // sequence operator expect("a; b; c", "c", &errors); // string concat operator expect("a + b", "ab", &errors); expect("a + \n \"b\"", "ab", &errors); expect("a + b +\nc\n", "abc", &errors); // string concat function expect("concat(a, b)", "ab", &errors); expect("concat(a,\n \"b\")", "ab", &errors); expect("concat(a + b,\nc,\"d\")", "abcd", &errors); expect("\"concat\"(a + b,\nc,\"d\")", "abcd", &errors); // logical and expect("a && b", "b", &errors); expect("a && \"\"", "", &errors); expect("\"\" && b", "", &errors); expect("\"\" && \"\"", "", &errors); expect("\"\" && abort()", "", &errors); // test short-circuiting expect("t && abort()", NULL, &errors); // logical or expect("a || b", "a", &errors); expect("a || \"\"", "a", &errors); expect("\"\" || b", "b", &errors); expect("\"\" || \"\"", "", &errors); expect("a || abort()", "a", &errors); // test short-circuiting expect("\"\" || abort()", NULL, &errors); // logical not expect("!a", "", &errors); expect("! \"\"", "t", &errors); expect("!!a", "t", &errors); // precedence expect("\"\" == \"\" && b", "b", &errors); expect("a + b == ab", "t", &errors); expect("ab == a + b", "t", &errors); expect("a + (b == ab)", "a", &errors); expect("(ab == a) + b", "b", &errors); // substring function expect("is_substring(cad, abracadabra)", "t", &errors); expect("is_substring(abrac, abracadabra)", "t", &errors); expect("is_substring(dabra, abracadabra)", "t", &errors); expect("is_substring(cad, abracxadabra)", "", &errors); expect("is_substring(abrac, axbracadabra)", "", &errors); expect("is_substring(dabra, abracadabrxa)", "", &errors); // ifelse function expect("ifelse(t, yes, no)", "yes", &errors); expect("ifelse(!t, yes, no)", "no", &errors); expect("ifelse(t, yes, abort())", "yes", &errors); expect("ifelse(!t, abort(), no)", "no", &errors); // if "statements" expect("if t then yes else no endif", "yes", &errors); expect("if \"\" then yes else no endif", "no", &errors); expect("if \"\" then yes endif", "", &errors); expect("if \"\"; t then yes endif", "yes", &errors); printf("\n"); return errors; } int main(int argc, char** argv) { RegisterBuiltins(); FinishRegistration(); if (argc == 1) { return test() != 0; } FILE* f = fopen(argv[1], "r"); char buffer[8192]; int size = fread(buffer, 1, 8191, f); fclose(f); buffer[size] = '\0'; Expr* root; yy_scan_bytes(buffer, size); int error = yyparse(&root); printf("parse returned %d\n", error); if (error == 0) { char* result = Evaluate(NULL, root); printf("result is [%s]\n", result == NULL ? "(NULL)" : result); } return 0; }