parsing major operators.
Do not evaluate the expression, but rather only check
for syntatic errors and resolve for precedence.
* only enum_values are parsed.
* annotation parameter values, and array sizes are NOT parsed.
* Unary, binary, and ternary operators supported.
* Assignment operators are NOT considered.
* Cast is NOT supported.
* Pointers are NOT supported.
* Emitted expression doesn't work for Java.
See Ic1f524c604fc72b9d1b7b330b608ff38ce287921 for tests.
Along side with some code for handling float literals
for future use.
Change-Id: I67ff0767a67c66b62e5ddfe75954f94d45ac7793
diff --git a/hidl-gen_y.yy b/hidl-gen_y.yy
index d6f03d0..813bd2e 100644
--- a/hidl-gen_y.yy
+++ b/hidl-gen_y.yy
@@ -5,6 +5,7 @@
#include "ArrayType.h"
#include "CompoundType.h"
#include "Constant.h"
+#include "ConstantExpression.h"
#include "EnumType.h"
#include "Interface.h"
#include "Method.h"
@@ -44,6 +45,7 @@
%token<str> IDENTIFIER
%token<str> IMPORT
%token<str> INTEGER
+%token<str> FLOAT
%token<str> INTERFACE
%token<str> PACKAGE
%token<type> SCALAR
@@ -54,6 +56,30 @@
%token<str> VEC
%token<void> ONEWAY
+/* Operator precedence and associativity, as per
+ * http://en.cppreference.com/w/cpp/language/operator_precedence */
+/* Precedence level 15 ternary operator */
+%right '?' ':'
+/* Precedence level 13 - 14, LTR, logical operators*/
+%left LOGICAL_OR
+%left LOGICAL_AND
+/* Precedence level 10 - 12, LTR, bitwise operators*/
+%left '|'
+%left '^'
+%left '&'
+/* Precedence level 9, LTR */
+%left EQUALITY NEQ
+/* Precedence level 8, LTR */
+%left '<' '>' LEQ GEQ
+/* Precedence level 7, LTR */
+%left LSHIFT RSHIFT
+/* Precedence level 6, LTR */
+%left '+' '-'
+/* Precedence level 5, LTR */
+%left '*' '/' '%'
+/* Precedence level 3, RTL; but we have to use %left here */
+%left UNARY_MINUS UNARY_PLUS '!' '~'
+
%type<str> optIdentifier package
%type<str> const_value
%type<type> fqname
@@ -65,6 +91,7 @@
%type<field> field_declaration
%type<fields> field_declarations struct_or_union_body
+%type<constantExpression> const_expr
%type<enumValue> enum_value
%type<enumValues> enum_values
%type<typedVars> typed_vars
@@ -86,6 +113,7 @@
android::CompoundField *field;
std::vector<android::CompoundField *> *fields;
android::EnumValue *enumValue;
+ android::ConstantExpression *constantExpression;
std::vector<android::EnumValue *> *enumValues;
android::TypedVar *typedVar;
std::vector<android::TypedVar *> *typedVars;
@@ -303,6 +331,38 @@
}
;
+const_expr
+ : INTEGER { $$ = new ConstantExpression($1); }
+ | IDENTIFIER { $$ = new ConstantExpression($1); }
+ | const_expr '?' const_expr ':' const_expr
+ {
+ $$ = new ConstantExpression($1, $3, $5);
+ }
+ | const_expr LOGICAL_OR const_expr { $$ = new ConstantExpression($1, "||", $3); }
+ | const_expr LOGICAL_AND const_expr { $$ = new ConstantExpression($1, "&&", $3); }
+ | const_expr '|' const_expr { $$ = new ConstantExpression($1, "|" , $3); }
+ | const_expr '^' const_expr { $$ = new ConstantExpression($1, "^" , $3); }
+ | const_expr '&' const_expr { $$ = new ConstantExpression($1, "&" , $3); }
+ | const_expr EQUALITY const_expr { $$ = new ConstantExpression($1, "==", $3); }
+ | const_expr NEQ const_expr { $$ = new ConstantExpression($1, "!=", $3); }
+ | const_expr '<' const_expr { $$ = new ConstantExpression($1, "<" , $3); }
+ | const_expr '>' const_expr { $$ = new ConstantExpression($1, ">" , $3); }
+ | const_expr LEQ const_expr { $$ = new ConstantExpression($1, "<=", $3); }
+ | const_expr GEQ const_expr { $$ = new ConstantExpression($1, ">=", $3); }
+ | const_expr LSHIFT const_expr { $$ = new ConstantExpression($1, "<<", $3); }
+ | const_expr RSHIFT const_expr { $$ = new ConstantExpression($1, ">>", $3); }
+ | const_expr '+' const_expr { $$ = new ConstantExpression($1, "+" , $3); }
+ | const_expr '-' const_expr { $$ = new ConstantExpression($1, "-" , $3); }
+ | const_expr '*' const_expr { $$ = new ConstantExpression($1, "*" , $3); }
+ | const_expr '/' const_expr { $$ = new ConstantExpression($1, "/" , $3); }
+ | const_expr '%' const_expr { $$ = new ConstantExpression($1, "%" , $3); }
+ | '+' const_expr %prec UNARY_PLUS { $$ = new ConstantExpression("+", $2); }
+ | '-' const_expr %prec UNARY_MINUS { $$ = new ConstantExpression("-", $2); }
+ | '!' const_expr { $$ = new ConstantExpression("!", $2); }
+ | '~' const_expr { $$ = new ConstantExpression("~", $2); }
+ | '(' const_expr ')' { $$ = $2; }
+ ;
+
const_value
: INTEGER
| STRING_LITERAL ;
@@ -473,14 +533,7 @@
enum_value
: IDENTIFIER { $$ = new EnumValue($1); }
- | IDENTIFIER '=' INTEGER { $$ = new EnumValue($1, $3); }
- | IDENTIFIER '=' IDENTIFIER { $$ = new EnumValue($1, $3); }
- | IDENTIFIER '=' IDENTIFIER '+' INTEGER
- {
- $$ = new EnumValue(
- $1, strdup(
- android::String8::format("%s + %s", $3, $5).string()));
- }
+ | IDENTIFIER '=' const_expr { $$ = new EnumValue($1, $3->value()); }
;
enum_values