1/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17D                   [0-9]
18L                   [a-zA-Z_]
19H                   [a-fA-F0-9]
20E                   [Ee][+-]?{D}+
21FS                  (f|F|l|L)
22IS                  (u|U|l|L)*
23
24COMPONENT           {L}({L}|{D})*
25DOT                 [.]
26AT                  [@]
27VERSION             {AT}{D}+{DOT}{D}+
28FQNAME              ({COMPONENT}|{VERSION})(({DOT}|":"+){COMPONENT}|{VERSION})*
29
30%{
31
32#include "Annotation.h"
33#include "AST.h"
34#include "ArrayType.h"
35#include "CompoundType.h"
36#include "ConstantExpression.h"
37#include "DeathRecipientType.h"
38#include "DocComment.h"
39#include "EnumType.h"
40#include "HandleType.h"
41#include "MemoryType.h"
42#include "Method.h"
43#include "PointerType.h"
44#include "ScalarType.h"
45#include "Scope.h"
46#include "StringType.h"
47#include "VectorType.h"
48#include "FmqType.h"
49
50#include "hidl-gen_y-helpers.h"
51
52#include <assert.h>
53#include <algorithm>
54#include <hidl-util/StringHelper.h>
55
56using namespace android;
57using token = yy::parser::token;
58
59#define SCALAR_TYPE(kind)                                        \
60    {                                                            \
61        yylval->type = new ScalarType(ScalarType::kind, *scope); \
62        return token::TYPE;                                      \
63    }
64
65#define YY_DECL int yylex(YYSTYPE* yylval_param, YYLTYPE* yylloc_param,  \
66    yyscan_t yyscanner, android::AST* const ast, android::Scope** const scope)
67
68#ifndef YYSTYPE
69#define YYSTYPE yy::parser::semantic_type
70#endif
71
72#ifndef YYLTYPE
73#define YYLTYPE yy::parser::location_type
74#endif
75
76#define YY_USER_ACTION yylloc->step(); yylloc->columns(yyleng);
77
78%}
79
80%option yylineno
81%option noyywrap
82%option nounput
83%option noinput
84%option reentrant
85%option bison-bridge
86%option bison-locations
87
88%%
89
90\/\*([^*]|\*+[^*\/])*\*+\/  {
91                                std::string str(yytext);
92
93                                // Add the lines to location (to keep it updated)
94                                yylloc->lines(std::count(str.begin(), str.end(), '\n'));
95
96                                str = StringHelper::LTrim(str, "/");
97                                bool isDoc = StringHelper::StartsWith(str, "**");
98                                str = StringHelper::LTrimAll(str, "*");
99                                str = StringHelper::RTrim(str, "/");
100                                str = StringHelper::RTrimAll(str, "*");
101
102                                yylval->str = strdup(str.c_str());
103                                return isDoc ? token::DOC_COMMENT : token::MULTILINE_COMMENT;
104                            }
105
106"//"[^\r\n]*        {
107                        ast->addUnhandledComment(
108                                new DocComment(yytext,
109                                               convertYYLoc(*yylloc, ast),
110                                               CommentType::SINGLELINE));
111                    }
112
113"enum"              { return token::ENUM; }
114"extends"           { return token::EXTENDS; }
115"generates"         { return token::GENERATES; }
116"import"            { return token::IMPORT; }
117"interface"         { return token::INTERFACE; }
118"package"           { return token::PACKAGE; }
119"safe_union"        { return token::SAFE_UNION; }
120"struct"            { return token::STRUCT; }
121"typedef"           { return token::TYPEDEF; }
122"union"             { return token::UNION; }
123"bitfield"          { yylval->templatedType = new BitFieldType(*scope); return token::TEMPLATED; }
124"vec"               { yylval->templatedType = new VectorType(*scope); return token::TEMPLATED; }
125"oneway"            { return token::ONEWAY; }
126
127"bool"              { SCALAR_TYPE(KIND_BOOL); }
128"int8_t"            { SCALAR_TYPE(KIND_INT8); }
129"uint8_t"           { SCALAR_TYPE(KIND_UINT8); }
130"int16_t"           { SCALAR_TYPE(KIND_INT16); }
131"uint16_t"          { SCALAR_TYPE(KIND_UINT16); }
132"int32_t"           { SCALAR_TYPE(KIND_INT32); }
133"uint32_t"          { SCALAR_TYPE(KIND_UINT32); }
134"int64_t"           { SCALAR_TYPE(KIND_INT64); }
135"uint64_t"          { SCALAR_TYPE(KIND_UINT64); }
136"float"             { SCALAR_TYPE(KIND_FLOAT); }
137"double"            { SCALAR_TYPE(KIND_DOUBLE); }
138
139"death_recipient"   { yylval->type = new DeathRecipientType(*scope); return token::TYPE; }
140"handle"            { yylval->type = new HandleType(*scope); return token::TYPE; }
141"memory"            { yylval->type = new MemoryType(*scope); return token::TYPE; }
142"pointer"           { yylval->type = new PointerType(*scope); return token::TYPE; }
143"string"            { yylval->type = new StringType(*scope); return token::TYPE; }
144
145"fmq_sync"          { yylval->type = new FmqType("::android::hardware", "MQDescriptorSync", *scope, "fmq_sync"); return token::TEMPLATED; }
146"fmq_unsync"        { yylval->type = new FmqType("::android::hardware", "MQDescriptorUnsync", *scope, "fmq_unsync"); return token::TEMPLATED; }
147
148"("                 { return('('); }
149")"                 { return(')'); }
150"<"                 { return('<'); }
151">"                 { return('>'); }
152"{"                 { return('{'); }
153"}"                 { return('}'); }
154"["                 { return('['); }
155"]"                 { return(']'); }
156":"                 { return(':'); }
157";"                 { return(';'); }
158","                 { return(','); }
159"."                 { return('.'); }
160"="                 { return('='); }
161"+"                 { return('+'); }
162"-"                 { return('-'); }
163"*"                 { return('*'); }
164"/"                 { return('/'); }
165"%"                 { return('%'); }
166"&"                 { return('&'); }
167"|"                 { return('|'); }
168"^"                 { return('^'); }
169"<<"                { return(token::LSHIFT); }
170">>"                { return(token::RSHIFT); }
171"&&"                { return(token::LOGICAL_AND); }
172"||"                { return(token::LOGICAL_OR);  }
173"!"                 { return('!'); }
174"~"                 { return('~'); }
175"<="                { return(token::LEQ); }
176">="                { return(token::GEQ); }
177"=="                { return(token::EQUALITY); }
178"!="                { return(token::NEQ); }
179"?"                 { return('?'); }
180"@"                 { return('@'); }
181"#"                 { return('#'); }
182
183{COMPONENT}         { yylval->str = strdup(yytext); return token::IDENTIFIER; }
184{FQNAME}            { yylval->str = strdup(yytext); return token::FQNAME; }
185
1860[xX]{H}+{IS}?      { yylval->str = strdup(yytext); return token::INTEGER; }
1870{D}+{IS}?          { yylval->str = strdup(yytext); return token::INTEGER; }
188{D}+{IS}?           { yylval->str = strdup(yytext); return token::INTEGER; }
189L?\"(\\.|[^\\"])*\" { yylval->str = strdup(yytext); return token::STRING_LITERAL; }
190
191{D}+{E}{FS}?        { yylval->str = strdup(yytext); return token::FLOAT; }
192{D}+\.{E}?{FS}?     { yylval->str = strdup(yytext); return token::FLOAT; }
193{D}*\.{D}+{E}?{FS}? { yylval->str = strdup(yytext); return token::FLOAT; }
194
195\n|\r\n             { yylloc->lines(); }
196[ \t\f\v]           { /* ignore all other whitespace */ }
197
198.                   { yylval->str = strdup(yytext); return token::UNKNOWN; }
199
200%%
201
202namespace android {
203
204status_t parseFile(AST* ast, std::unique_ptr<FILE, std::function<void(FILE *)>> file) {
205    yyscan_t scanner;
206    yylex_init(&scanner);
207
208    yyset_in(file.get(), scanner);
209
210    Scope* scopeStack = ast->getMutableRootScope();
211    int res = yy::parser(scanner, ast, &scopeStack).parse();
212
213    yylex_destroy(scanner);
214
215    if (res != 0 || ast->syntaxErrors() != 0) {
216        return UNKNOWN_ERROR;
217    }
218
219    return OK;
220}
221
222}  // namespace android
223