• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3  *
4  * HDF is dual licensed: you can use it either under the terms of
5  * the GPL, or the BSD license, at your option.
6  * See the LICENSE file in the root of this repository for complete details.
7  */
8 
9 #include "parser/parser.h"
10 
11 #include <regex>
12 
13 #include "ast/ast_array_type.h"
14 #include "ast/ast_enum_type.h"
15 #include "ast/ast_map_type.h"
16 #include "ast/ast_parameter.h"
17 #include "ast/ast_sequenceable_type.h"
18 #include "ast/ast_smq_type.h"
19 #include "ast/ast_struct_type.h"
20 #include "ast/ast_union_type.h"
21 #include "util/logger.h"
22 #include "util/string_builder.h"
23 
24 #define RE_DIGIT      "[0-9]+"
25 #define RE_IDENTIFIER "[a-zA-Z_][a-zA-Z0-9_]*"
26 
27 #define RE_PACKAGE_NUM             3
28 #define RE_PACKAGE_INDEX           0
29 #define RE_PACKAGE_MAJOR_VER_INDEX 1
30 #define RE_PACKAGE_MINOR_VER_INDEX 2
31 
32 namespace OHOS {
33 namespace HDI {
34 static const std::regex RE_PACKAGE(RE_IDENTIFIER "(?:\\." RE_IDENTIFIER ")*\\.[V|v]"
35                                                 "(" RE_DIGIT ")_(" RE_DIGIT ")");
36 static const std::regex RE_IMPORT(
37     RE_IDENTIFIER "(?:\\." RE_IDENTIFIER ")*\\.[V|v]" RE_DIGIT "_" RE_DIGIT "." RE_IDENTIFIER);
38 
Parse(const std::vector<std::string> & sourceFiles)39 bool Parser::Parse(const std::vector<std::string> &sourceFiles)
40 {
41     for (const auto &file : sourceFiles) {
42         if (!ParseOne(file)) {
43             return false;
44         }
45     }
46 
47     return true;
48 }
49 
ParseOne(const std::string & sourceFile)50 bool Parser::ParseOne(const std::string &sourceFile)
51 {
52     if (!Reset(sourceFile)) {
53         return false;
54     }
55 
56     bool ret = ParseFile();
57     ret = CheckIntegrity() && ret;
58     ret = AddAst(ast_) && ret;
59     if (!ret || !errors_.empty()) {
60         ShowError();
61         return false;
62     }
63 
64     return true;
65 }
66 
Reset(const std::string & sourceFile)67 bool Parser::Reset(const std::string &sourceFile)
68 {
69     bool ret = lexer_.Reset(sourceFile);
70     if (!ret) {
71         Logger::E(TAG, "Fail to open file '%s'.", sourceFile.c_str());
72         return false;
73     }
74 
75     errors_.clear();
76     ast_ = nullptr;
77     return true;
78 }
79 
ParseFile()80 bool Parser::ParseFile()
81 {
82     ast_ = new AST();
83     ast_->SetIdlFile(lexer_.GetFilePath());
84     ast_->SetLicense(ParseLicense());
85 
86     if (!ParsePackage()) {
87         return false;
88     }
89 
90     if (!ParseImports()) {
91         return false;
92     }
93 
94     if (!ParseTypeDecls()) {
95         return false;
96     }
97 
98     SetAstFileType();
99     return true;
100 }
101 
ParseLicense()102 std::string Parser::ParseLicense()
103 {
104     Token token = lexer_.PeekToken(false);
105     if (token.kind_ == TokenType::COMMENT_BLOCK) {
106         lexer_.GetToken(false);
107         return token.value_;
108     }
109 
110     return std::string("");
111 }
112 
ParsePackage()113 bool Parser::ParsePackage()
114 {
115     Token token = lexer_.PeekToken();
116     if (token.kind_ != TokenType::PACKAGE) {
117         LogError(token, StringHelper::Format("expected 'package' before '%s' token", token.value_.c_str()));
118         return false;
119     }
120     lexer_.GetToken();
121 
122     token = lexer_.PeekToken();
123     if (token.kind_ != TokenType::ID) {
124         LogError(token, StringHelper::Format("expected name of package before '%s' token", token.value_.c_str()));
125         lexer_.SkipToken(TokenType::SEMICOLON);
126         return false;
127     }
128     std::string packageName = token.value_;
129     lexer_.GetToken();
130 
131     token = lexer_.PeekToken();
132     if (token.kind_ != TokenType::SEMICOLON) {
133         LogError(token, StringHelper::Format("expected ';' before '%s' token", token.value_.c_str()));
134         return false;
135     }
136     lexer_.GetToken();
137 
138     if (packageName.empty()) {
139         LogError(std::string("package name is not expected."));
140         return false;
141     } else if (!CheckPackageName(lexer_.GetFilePath(), packageName)) {
142         LogError(StringHelper::Format(
143             "package name '%s' does not match file apth '%s'.", packageName.c_str(), lexer_.GetFilePath().c_str()));
144         return false;
145     }
146 
147     if (!ParserPackageInfo(packageName)) {
148         LogError(StringHelper::Format("parse package '%s' infomation failed.", packageName.c_str()));
149         return false;
150     }
151 
152     return true;
153 }
154 
ParserPackageInfo(const std::string & packageName)155 bool Parser::ParserPackageInfo(const std::string &packageName)
156 {
157     std::cmatch result;
158     if (!std::regex_match(packageName.c_str(), result, RE_PACKAGE)) {
159         return false;
160     }
161 
162     if (result.size() < RE_PACKAGE_NUM) {
163         return false;
164     }
165 
166     ast_->SetPackageName(result.str(RE_PACKAGE_INDEX).c_str());
167     size_t majorVersion = std::stoul(result.str(RE_PACKAGE_MAJOR_VER_INDEX));
168     size_t minorVersion = std::stoul(result.str(RE_PACKAGE_MINOR_VER_INDEX));
169     ast_->SetVersion(majorVersion, minorVersion);
170     return true;
171 }
172 
ParseImports()173 bool Parser::ParseImports()
174 {
175     Token token = lexer_.PeekToken();
176     while (token.kind_ == TokenType::IMPORT || token.kind_ == TokenType::SEQ) {
177         TokenType kind = token.kind_;
178         lexer_.GetToken();
179 
180         token = lexer_.PeekToken();
181         if (token.kind_ != TokenType::ID) {
182             LogError(token, StringHelper::Format("expected identifier before '%s' token", token.value_.c_str()));
183             lexer_.SkipToken(TokenType::SEMICOLON);
184             token = lexer_.PeekToken();
185             continue;
186         }
187 
188         if (kind == TokenType::IMPORT) {
189             ParseImportInfo();
190         } else {
191             ParseSequenceableInfo();
192         }
193         lexer_.GetToken();
194 
195         token = lexer_.PeekToken();
196         if (token.kind_ != TokenType::SEMICOLON) {
197             LogError(token, StringHelper::Format("expected ';' before '%s'.", token.value_.c_str()));
198             return false;
199         }
200         lexer_.GetToken();
201 
202         token = lexer_.PeekToken();
203     }
204 
205     return true;
206 }
207 
ParseImportInfo()208 void Parser::ParseImportInfo()
209 {
210     Token token = lexer_.PeekToken();
211     std::string importName = token.value_;
212     if (importName.empty()) {
213         LogError(token, StringHelper::Format("import name is empty"));
214         return;
215     }
216 
217     if (!CheckImport(importName)) {
218         LogError(token, StringHelper::Format("import name is illegal"));
219         return;
220     }
221 
222     auto iter = allAsts_.find(importName);
223     AutoPtr<AST> importAst = (iter != allAsts_.end()) ? iter->second : nullptr;
224     if (importAst == nullptr) {
225         LogError(token, StringHelper::Format("can not find idl file from import name '%s'", importName.c_str()));
226         return;
227     }
228 
229     AutoPtr<ASTInterfaceType> interfaceType = importAst->GetInterfaceDef();
230     if (interfaceType != nullptr) {
231         interfaceType->SetSerializable(true);
232     }
233 
234     if (!ast_->AddImport(importAst)) {
235         LogError(token, StringHelper::Format("multiple import of '%s'", importName.c_str()));
236         return;
237     }
238 }
239 
ParseSequenceableInfo()240 void Parser::ParseSequenceableInfo()
241 {
242     Token token = lexer_.PeekToken();
243     std::string seqName = token.value_;
244     if (seqName.empty()) {
245         LogError(token, StringHelper::Format("sequenceable name is empty"));
246         return;
247     }
248 
249     AutoPtr<ASTSequenceableType> seqType = new ASTSequenceableType();
250     size_t index = seqName.rfind('.');
251     if (index != std::string::npos) {
252         seqType->SetName(seqName.substr(index + 1));
253         seqType->SetNamespace(ast_->ParseNamespace(seqName.substr(0, index)));
254     } else {
255         seqType->SetName(seqName);
256     }
257 
258     AutoPtr<AST> seqAst = new AST();
259     seqAst->SetFullName(seqName);
260     seqAst->AddSequenceableDef(seqType);
261     seqAst->SetAStFileType(ASTFileType::AST_SEQUENCEABLE);
262     ast_->AddImport(seqAst);
263     AddAst(seqAst);
264 }
265 
ParseTypeDecls()266 bool Parser::ParseTypeDecls()
267 {
268     Token token = lexer_.PeekToken();
269     while (token.kind_ != TokenType::END_OF_FILE) {
270         switch (token.kind_) {
271             case TokenType::BRACKETS_LEFT:
272                 ParseAttribute();
273                 break;
274             case TokenType::INTERFACE:
275                 ParseInterface();
276                 break;
277             case TokenType::ENUM:
278                 ParseEnumDeclaration();
279                 break;
280             case TokenType::STRUCT:
281                 ParseStructDeclaration();
282                 break;
283             case TokenType::UNION:
284                 ParseUnionDeclaration();
285                 break;
286             default:
287                 LogError(token, StringHelper::Format("'%s' is not expected", token.value_.c_str()));
288                 lexer_.SkipToken(TokenType::SEMICOLON);
289                 break;
290         }
291         token = lexer_.PeekToken();
292     }
293     return true;
294 }
295 
ParseAttribute()296 void Parser::ParseAttribute()
297 {
298     AttrSet attrs = ParseAttributeInfo();
299     Token token = lexer_.PeekToken();
300     switch (token.kind_) {
301         case TokenType::INTERFACE:
302             ParseInterface(attrs);
303             break;
304         case TokenType::ENUM:
305             ParseEnumDeclaration(attrs);
306             break;
307         case TokenType::STRUCT:
308             ParseStructDeclaration(attrs);
309             break;
310         case TokenType::UNION:
311             ParseUnionDeclaration(attrs);
312             break;
313         default:
314             LogError(token, StringHelper::Format("'%s' is not expected", token.value_.c_str()));
315             lexer_.SkipToken(token.kind_);
316             break;
317     }
318 }
319 
ParseAttributeInfo()320 AttrSet Parser::ParseAttributeInfo()
321 {
322     AttrSet attrs;
323     Token token = lexer_.PeekToken();
324     if (token.kind_ != TokenType::BRACKETS_LEFT) {
325         LogError(token, StringHelper::Format("expected '[' before '%s' token", token.value_.c_str()));
326         lexer_.SkipToken(token.kind_);
327         return attrs;
328     }
329     lexer_.GetToken();
330 
331     token = lexer_.PeekToken();
332     while (token.kind_ != TokenType::BRACKETS_RIGHT && token.kind_ != TokenType::END_OF_FILE) {
333         if (!AprseAttrUnit(attrs)) {
334             return attrs;
335         }
336         token = lexer_.PeekToken();
337         if (token.kind_ == TokenType::COMMA) {
338             lexer_.GetToken();
339             token = lexer_.PeekToken();
340             continue;
341         }
342 
343         if (token.kind_ == TokenType::BRACKETS_RIGHT) {
344             lexer_.GetToken();
345             break;
346         } else {
347             LogError(token, StringHelper::Format("expected ',' or ']' before '%s' token", token.value_.c_str()));
348             lexer_.SkipToken(TokenType::BRACKETS_RIGHT);
349             break;
350         }
351     }
352 
353     return attrs;
354 }
355 
AprseAttrUnit(AttrSet & attrs)356 bool Parser::AprseAttrUnit(AttrSet &attrs)
357 {
358     Token token = lexer_.PeekToken();
359     switch (token.kind_) {
360         case TokenType::FULL:
361         case TokenType::LITE:
362         case TokenType::CALLBACK:
363         case TokenType::ONEWAY: {
364             if (attrs.find(token) != attrs.end()) {
365                 LogError(token, StringHelper::Format("Duplicate declared attributes '%s'", token.value_.c_str()));
366             } else {
367                 attrs.insert(token);
368             }
369             lexer_.GetToken();
370             break;
371         }
372         default:
373             LogError(token, StringHelper::Format("'%s' is a illegal attribute", token.value_.c_str()));
374             lexer_.SkipToken(TokenType::BRACKETS_RIGHT);
375             return false;
376     }
377     return true;
378 }
379 
ParseInterface(const AttrSet & attrs)380 void Parser::ParseInterface(const AttrSet &attrs)
381 {
382     AutoPtr<ASTInterfaceType> interfaceType = new ASTInterfaceType;
383     AutoPtr<ASTInfAttr> astAttr = ParseInfAttrInfo(attrs);
384     interfaceType->SetAttribute(astAttr);
385 
386     lexer_.GetToken();
387     Token token = lexer_.PeekToken();
388     if (token.kind_ != TokenType::ID) {
389         LogError(token, StringHelper::Format("expected interface name before '%s' token", token.value_.c_str()));
390     } else {
391         interfaceType->SetName(token.value_);
392         interfaceType->SetNamespace(ast_->ParseNamespace(ast_->GetFullName()));
393         interfaceType->SetLicense(ast_->GetLicense());
394         if (token.value_ != ast_->GetName()) {
395             LogError(
396                 token, StringHelper::Format("interface name '%s' is not equal idl file name", token.value_.c_str()));
397         }
398         lexer_.GetToken();
399     }
400 
401     ParseInterfaceBody(interfaceType);
402     ast_->AddInterfaceDef(interfaceType);
403 }
404 
ParseInfAttrInfo(const AttrSet & attrs)405 AutoPtr<ASTInfAttr> Parser::ParseInfAttrInfo(const AttrSet &attrs)
406 {
407     AutoPtr<ASTInfAttr> infAttr = new ASTInfAttr;
408 
409     for (const auto &attr : attrs) {
410         switch (attr.kind_) {
411             case TokenType::FULL:
412                 infAttr->isFull_ = true;
413                 break;
414             case TokenType::LITE:
415                 infAttr->isLite_ = true;
416                 break;
417             case TokenType::CALLBACK:
418                 infAttr->isCallback_ = true;
419                 break;
420             case TokenType::ONEWAY:
421                 infAttr->isOneWay_ = true;
422                 break;
423             default:
424                 LogError(attr, StringHelper::Format("illegal attribute of interface"));
425                 break;
426         }
427     }
428 
429     return infAttr;
430 }
431 
ParseInterfaceBody(const AutoPtr<ASTInterfaceType> & interface)432 void Parser::ParseInterfaceBody(const AutoPtr<ASTInterfaceType> &interface)
433 {
434     Token token = lexer_.PeekToken();
435     if (token.kind_ != TokenType::BRACES_LEFT) {
436         LogError(token, StringHelper::Format("expected '{' before '%s' token", token.value_.c_str()));
437     } else {
438         lexer_.GetToken();
439     }
440 
441     token = lexer_.PeekToken();
442     while (token.kind_ != TokenType::BRACES_RIGHT && token.kind_ != TokenType::END_OF_FILE) {
443         interface->AddMethod(ParseMethod());
444         token = lexer_.PeekToken();
445     }
446 
447     token = lexer_.PeekToken();
448     if (token.kind_ != TokenType::BRACES_RIGHT) {
449         LogError(token, StringHelper::Format("expected '{' before '%s' token", token.value_.c_str()));
450     } else {
451         lexer_.GetToken();
452     }
453 
454     token = lexer_.PeekToken();
455     if (token.kind_ == TokenType::SEMICOLON) {
456         lexer_.GetToken();
457     }
458 
459     interface->AddVersionMethod(CreateGetVersionMethod());
460 }
461 
ParseMethod()462 AutoPtr<ASTMethod> Parser::ParseMethod()
463 {
464     AutoPtr<ASTMethod> method = new ASTMethod();
465     method->SetAttribute(ParseMethodAttr());
466 
467     Token token = lexer_.PeekToken();
468     if (token.kind_ != TokenType::ID) {
469         LogError(token, StringHelper::Format("expected method name before '%s' token", token.value_.c_str()));
470     } else {
471         method->SetName(token.value_);
472         lexer_.GetToken();
473     }
474 
475     ParseMethodParamList(method);
476 
477     token = lexer_.PeekToken();
478     if (token.kind_ != TokenType::SEMICOLON) {
479         LogError(token, StringHelper::Format("expected ';' before '%s' token", token.value_.c_str()));
480     } else {
481         lexer_.GetToken();
482     }
483 
484     return method;
485 }
486 
ParseMethodAttr()487 AutoPtr<ASTMethodAttr> Parser::ParseMethodAttr()
488 {
489     AutoPtr<ASTMethodAttr> attr = new ASTMethodAttr();
490     Token token = lexer_.PeekToken();
491     if (token.kind_ == TokenType::ID) {
492         return attr;
493     }
494 
495     if (token.kind_ != TokenType::BRACKETS_LEFT) {
496         LogError(token, StringHelper::Format("expected '[' before '%s' token", token.value_.c_str()));
497         lexer_.SkipUntilToken(TokenType::ID);
498         return attr;
499     }
500 
501     lexer_.GetToken();
502     token = lexer_.PeekToken();
503     while (token.kind_ != TokenType::BRACKETS_RIGHT) {
504         switch (token.kind_) {
505             case TokenType::FULL:
506                 attr->isFull_ = true;
507                 break;
508             case TokenType::LITE:
509                 attr->isLite_ = true;
510                 break;
511             case TokenType::ONEWAY:
512                 attr->isOneWay_ = true;
513                 break;
514             default:
515                 LogError(token, StringHelper::Format("expected attribute before '%s' token", token.value_.c_str()));
516                 lexer_.SkipUntilToken(TokenType::BRACKETS_RIGHT);
517                 return attr;
518         }
519 
520         lexer_.GetToken();
521         token = lexer_.PeekToken();
522         if (token.kind_ == TokenType::BRACKETS_RIGHT) {
523             lexer_.GetToken();
524             break;
525         }
526 
527         if (token.kind_ != TokenType::COMMA) {
528             LogError(token, StringHelper::Format("expected ',' before '%s' token", token.value_.c_str()));
529             lexer_.SkipUntilToken(TokenType::BRACKETS_RIGHT);
530             return attr;
531         }
532         lexer_.GetToken();
533         token = lexer_.PeekToken();
534     }
535     return attr;
536 }
537 
CreateGetVersionMethod()538 AutoPtr<ASTMethod> Parser::CreateGetVersionMethod()
539 {
540     AutoPtr<ASTMethod> method = new ASTMethod();
541     method->SetName("GetVersion");
542 
543     AutoPtr<ASTType> type = ast_->FindType("unsigned int");
544     if (type == nullptr) {
545         type = new ASTUintType();
546     }
547     AutoPtr<ASTParameter> majorParam = new ASTParameter("majorVer", ParamAttr::PARAM_OUT, type);
548     AutoPtr<ASTParameter> minorParam = new ASTParameter("minorVer", ParamAttr::PARAM_OUT, type);
549 
550     method->AddParameter(majorParam);
551     method->AddParameter(minorParam);
552     return method;
553 }
554 
ParseMethodParamList(const AutoPtr<ASTMethod> & method)555 void Parser::ParseMethodParamList(const AutoPtr<ASTMethod> &method)
556 {
557     Token token = lexer_.PeekToken();
558     if (token.kind_ != TokenType::PARENTHESES_LEFT) {
559         LogError(token, StringHelper::Format("expected '(' before '%s' token", token.value_.c_str()));
560     } else {
561         lexer_.GetToken();
562     }
563 
564     token = lexer_.PeekToken();
565     if (token.kind_ == TokenType::PARENTHESES_RIGHT) {
566         lexer_.GetToken();
567         return;
568     }
569 
570     while (token.kind_ != TokenType::PARENTHESES_RIGHT && token.kind_ != TokenType::END_OF_FILE) {
571         method->AddParameter(ParseParam());
572         token = lexer_.PeekToken();
573         if (token.kind_ == TokenType::COMMA) {
574             lexer_.GetToken();
575             token = lexer_.PeekToken();
576             if (token.kind_ == TokenType::PARENTHESES_RIGHT) {
577                 LogError(token, StringHelper::Format(""));
578             }
579             continue;
580         }
581 
582         if (token.kind_ == TokenType::PARENTHESES_RIGHT) {
583             lexer_.GetToken();
584             break;
585         } else {
586             LogError(token, StringHelper::Format("expected ',' or ')' before '%s' token", token.value_.c_str()));
587             lexer_.SkipToken(TokenType::PARENTHESES_RIGHT);
588             break;
589         }
590     }
591 }
592 
ParseParam()593 AutoPtr<ASTParameter> Parser::ParseParam()
594 {
595     AutoPtr<ASTParamAttr> paramAttr = ParseParamAttr();
596     AutoPtr<ASTType> paramType = ParseType();
597     std::string paramName = "";
598 
599     Token token = lexer_.PeekToken();
600     if (token.kind_ != TokenType::ID) {
601         LogError(token, StringHelper::Format("expected param name before '%s' token", token.value_.c_str()));
602     } else {
603         paramName = token.value_;
604         lexer_.GetToken();
605     }
606 
607     if (paramType != nullptr && paramType->IsInterfaceType()) {
608         AutoPtr<ASTInterfaceType> ifaceType = dynamic_cast<ASTInterfaceType *>(paramType.Get());
609         if (ifaceType->IsCallback() && paramAttr->value_ != ParamAttr::PARAM_IN) {
610             LogError(token, StringHelper::Format("'%s' parameter of callback interface type must be 'in' attribute",
611                 paramName.c_str()));
612         } else if (!ifaceType->IsCallback() && paramAttr->value_ != ParamAttr::PARAM_OUT) {
613             LogError(token, StringHelper::Format("'%s' parameter of interface type must be 'out' attribute",
614                 paramName.c_str()));
615         }
616     }
617 
618     return new ASTParameter(paramName, paramAttr, paramType);
619 }
620 
ParseParamAttr()621 AutoPtr<ASTParamAttr> Parser::ParseParamAttr()
622 {
623     AutoPtr<ASTParamAttr> attr = new ASTParamAttr(ParamAttr::PARAM_IN);
624     Token token = lexer_.PeekToken();
625     if (token.kind_ != TokenType::BRACKETS_LEFT) {
626         LogError(token, StringHelper::Format("expected '[' before '%s' token", token.value_.c_str()));
627     } else {
628         lexer_.GetToken();
629     }
630 
631     token = lexer_.PeekToken();
632     if (token.kind_ == TokenType::IN) {
633         attr->value_ = ParamAttr::PARAM_IN;
634         lexer_.GetToken();
635     } else if (token.kind_ == TokenType::OUT) {
636         attr->value_ = ParamAttr::PARAM_OUT;
637         lexer_.GetToken();
638     } else {
639         LogError(
640             token, StringHelper::Format("expected 'in' or 'out' attribute before '%s' token", token.value_.c_str()));
641     }
642 
643     token = lexer_.PeekToken();
644     if (token.kind_ != TokenType::BRACKETS_RIGHT) {
645         LogError(token, StringHelper::Format("expected ']' before '%s' token", token.value_.c_str()));
646     } else {
647         lexer_.GetToken();
648     }
649 
650     return attr;
651 }
652 
ParseType()653 AutoPtr<ASTType> Parser::ParseType()
654 {
655     AutoPtr<ASTType> type = nullptr;
656     Token token = lexer_.PeekToken();
657     switch (token.kind_) {
658         case TokenType::BOOLEAN:
659         case TokenType::BYTE:
660         case TokenType::SHORT:
661         case TokenType::INT:
662         case TokenType::LONG:
663         case TokenType::STRING:
664         case TokenType::FLOAT:
665         case TokenType::DOUBLE:
666         case TokenType::FD:
667         case TokenType::ASHMEM:
668         case TokenType::BUFFER_HANDLE:
669         case TokenType::UNSIGNED:
670             type = ParseBasicType();
671             break;
672         case TokenType::LIST:
673             type = ParseListType();
674             break;
675         case TokenType::MAP:
676             type = ParseMapType();
677             break;
678         case TokenType::SMQ:
679             type = ParseSmqType();
680             break;
681         case TokenType::ENUM:
682         case TokenType::STRUCT:
683         case TokenType::UNION:
684         case TokenType::ID:
685         case TokenType::SEQ:
686             type = ParseUserDefType();
687             break;
688         default:
689             LogError(token, StringHelper::Format("'%s' of type is illegal", token.value_.c_str()));
690             return nullptr;
691     }
692     if (type == nullptr) {
693         LogError(token, StringHelper::Format("this type was not declared in this scope"));
694     }
695     if (!CheckType(token, type)) {
696         return nullptr;
697     }
698 
699     while (lexer_.PeekToken().kind_ == TokenType::BRACKETS_LEFT) {
700         type = ParseArrayType(type);
701     }
702     return type;
703 }
704 
ParseBasicType()705 AutoPtr<ASTType> Parser::ParseBasicType()
706 {
707     AutoPtr<ASTType> type = nullptr;
708     Token token = lexer_.PeekToken();
709     if (token.kind_ == TokenType::UNSIGNED) {
710         type = ParseUnsignedType();
711     } else {
712         type = ast_->FindType(token.value_);
713         lexer_.GetToken();
714     }
715 
716     ast_->AddType(type);
717     return type;
718 }
719 
ParseUnsignedType()720 AutoPtr<ASTType> Parser::ParseUnsignedType()
721 {
722     AutoPtr<ASTType> type = nullptr;
723     std::string namePrefix = lexer_.GetToken().value_;
724     Token token = lexer_.PeekToken();
725     switch (token.kind_) {
726         case TokenType::CHAR:
727         case TokenType::SHORT:
728         case TokenType::INT:
729         case TokenType::LONG:
730             type = ast_->FindType(namePrefix + " " + token.value_);
731             lexer_.GetToken();
732             break;
733         default:
734             LogError(
735                 token, StringHelper::Format("'unsigned %s' was not declared in the idl file", token.value_.c_str()));
736             break;
737     }
738 
739     return type;
740 }
741 
ParseArrayType(const AutoPtr<ASTType> & elementType)742 AutoPtr<ASTType> Parser::ParseArrayType(const AutoPtr<ASTType> &elementType)
743 {
744     lexer_.GetToken(); // '['
745 
746     Token token = lexer_.PeekToken();
747     if (token.kind_ != TokenType::BRACKETS_RIGHT) {
748         LogError(token, StringHelper::Format("expected ']' before '%s' token", token.value_.c_str()));
749         return nullptr;
750     }
751     lexer_.GetToken(); // ']'
752 
753     if (elementType == nullptr) {
754         return nullptr;
755     }
756 
757     AutoPtr<ASTArrayType> arrayType = new ASTArrayType();
758     arrayType->SetElementType(elementType);
759     AutoPtr<ASTType> retType = ast_->FindType(arrayType->ToString());
760     if (retType == nullptr) {
761         retType = arrayType.Get();
762     }
763 
764     ast_->AddType(retType);
765     return retType;
766 }
767 
ParseListType()768 AutoPtr<ASTType> Parser::ParseListType()
769 {
770     lexer_.GetToken(); // List
771 
772     Token token = lexer_.PeekToken();
773     if (token.kind_ != TokenType::ANGLE_BRACKETS_LEFT) {
774         LogError(token, StringHelper::Format("expected '<' before '%s' token", token.value_.c_str()));
775     } else {
776         lexer_.GetToken(); // '<'
777     }
778 
779     AutoPtr<ASTType> type = ParseType(); // element type
780     if (type == nullptr) {
781         lexer_.SkipToken(TokenType::ANGLE_BRACKETS_RIGHT);
782         return nullptr;
783     }
784 
785     token = lexer_.PeekToken();
786     if (token.kind_ != TokenType::ANGLE_BRACKETS_RIGHT) {
787         LogError(token, StringHelper::Format("expected '>' before '%s' token", token.value_.c_str()));
788     } else {
789         lexer_.GetToken(); // '>'
790     }
791 
792     AutoPtr<ASTListType> listType = new ASTListType();
793     listType->SetElementType(type);
794     AutoPtr<ASTType> retType = ast_->FindType(listType->ToString());
795     if (retType == nullptr) {
796         retType = listType.Get();
797     }
798 
799     ast_->AddType(retType);
800     return retType;
801 }
802 
ParseMapType()803 AutoPtr<ASTType> Parser::ParseMapType()
804 {
805     lexer_.GetToken(); // 'Map'
806 
807     Token token = lexer_.PeekToken();
808     if (token.kind_ != TokenType::ANGLE_BRACKETS_LEFT) {
809         LogError(token, StringHelper::Format("expected '<' before '%s' token", token.value_.c_str()));
810     } else {
811         lexer_.GetToken(); // '<'
812     }
813 
814     AutoPtr<ASTType> keyType = ParseType(); // key type
815     if (keyType == nullptr) {
816         LogError(token, StringHelper::Format("key type '%s' is illegal", token.value_.c_str()));
817         lexer_.SkipToken(TokenType::ANGLE_BRACKETS_RIGHT);
818         return nullptr;
819     }
820 
821     token = lexer_.PeekToken();
822     if (token.kind_ != TokenType::COMMA) {
823         LogError(token, StringHelper::Format("expected ',' before '%s' token", token.value_.c_str()));
824     } else {
825         lexer_.GetToken(); // ','
826     }
827 
828     AutoPtr<ASTType> valueType = ParseType();
829     if (valueType == nullptr) {
830         LogError(token, StringHelper::Format("key type '%s' is illegal", token.value_.c_str()));
831         lexer_.SkipToken(TokenType::ANGLE_BRACKETS_RIGHT);
832         return nullptr;
833     }
834 
835     token = lexer_.PeekToken();
836     if (token.kind_ != TokenType::ANGLE_BRACKETS_RIGHT) {
837         LogError(token, StringHelper::Format("expected '>' before '%s' token", token.value_.c_str()));
838     } else {
839         lexer_.GetToken();
840     }
841 
842     AutoPtr<ASTMapType> mapType = new ASTMapType();
843     mapType->SetKeyType(keyType);
844     mapType->SetValueType(valueType);
845     AutoPtr<ASTType> retType = ast_->FindType(mapType->ToString());
846     if (retType == nullptr) {
847         retType = mapType.Get();
848     }
849 
850     ast_->AddType(retType);
851     return retType;
852 }
853 
ParseSmqType()854 AutoPtr<ASTType> Parser::ParseSmqType()
855 {
856     lexer_.GetToken(); // 'SharedMemQueue'
857 
858     Token token = lexer_.PeekToken();
859     if (token.kind_ != TokenType::ANGLE_BRACKETS_LEFT) {
860         LogError(token, StringHelper::Format("expected '<' before '%s' token", token.value_.c_str()));
861     } else {
862         lexer_.GetToken(); // '<'
863     }
864 
865     AutoPtr<ASTType> InnerType = ParseType();
866     if (InnerType == nullptr) {
867         lexer_.SkipToken(TokenType::ANGLE_BRACKETS_RIGHT);
868         return nullptr;
869     }
870 
871     token = lexer_.PeekToken();
872     if (token.kind_ != TokenType::ANGLE_BRACKETS_RIGHT) {
873         LogError(token, StringHelper::Format("expected '>' before '%s' token", token.value_.c_str()));
874     } else {
875         lexer_.GetToken(); // '>'
876     }
877 
878     AutoPtr<ASTSmqType> smqType = new ASTSmqType();
879     smqType->SetInnerType(InnerType);
880     AutoPtr<ASTType> retType = ast_->FindType(smqType->ToString());
881     if (retType == nullptr) {
882         retType = smqType.Get();
883     }
884 
885     ast_->AddType(retType);
886     return retType;
887 }
888 
ParseUserDefType()889 AutoPtr<ASTType> Parser::ParseUserDefType()
890 {
891     Token token = lexer_.GetToken();
892     if (token.kind_ == TokenType::ID) {
893         return ast_->FindType(token.value_);
894     }
895 
896     std::string typePrefix = token.value_;
897 
898     token = lexer_.PeekToken();
899     if (token.kind_ != TokenType::ID) {
900         LogError(token, StringHelper::Format("expected identifier before '%s' token", token.value_.c_str()));
901         return nullptr;
902     } else {
903         lexer_.GetToken();
904     }
905 
906     std::string typeName = typePrefix + " " + token.value_;
907     AutoPtr<ASTType> type = ast_->FindType(typeName);
908     ast_->AddType(type);
909     return type;
910 }
911 
ParseEnumDeclaration(const AttrSet & attrs)912 void Parser::ParseEnumDeclaration(const AttrSet &attrs)
913 {
914     AutoPtr<ASTEnumType> enumType = new ASTEnumType;
915     enumType->SetAttribute(ParseUserDefTypeAttr(attrs));
916 
917     lexer_.GetToken();
918     Token token = lexer_.PeekToken();
919     if (token.kind_ != TokenType::ID) {
920         LogError(token, StringHelper::Format("expected enum type name before '%s' token", token.value_.c_str()));
921     } else {
922         lexer_.GetToken();
923         enumType->SetName(token.value_);
924     }
925 
926     token = lexer_.PeekToken();
927     if (token.kind_ == TokenType::COLON || token.kind_ == TokenType::BRACES_LEFT) {
928         enumType->SetBaseType(ParseEnumBaseType());
929     } else {
930         LogError(token, StringHelper::Format("expected ':' or '{' before '%s' token", token.value_.c_str()));
931     }
932 
933     ParserEnumMember(enumType);
934     token = lexer_.PeekToken();
935     if (token.kind_ != TokenType::BRACES_RIGHT) {
936         LogError(token, StringHelper::Format("expected '}' before '%s' token", token.value_.c_str()));
937         return;
938     } else {
939         lexer_.GetToken();
940     }
941 
942     token = lexer_.PeekToken();
943     if (token.kind_ != TokenType::SEMICOLON) {
944         LogError(token, StringHelper::Format("expected ';' before '%s' token", token.value_.c_str()));
945     } else {
946         lexer_.GetToken();
947     }
948 
949     ast_->AddTypeDefinition(enumType.Get());
950 }
951 
ParseEnumBaseType()952 AutoPtr<ASTType> Parser::ParseEnumBaseType()
953 {
954     AutoPtr<ASTType> baseType = nullptr;
955     Token token = lexer_.PeekToken();
956     if (token.kind_ == TokenType::COLON) {
957         lexer_.GetToken();
958 
959         token = lexer_.PeekToken();
960         baseType = ParseType();
961         if (baseType == nullptr) {
962             return nullptr;
963         }
964 
965         switch (baseType->GetTypeKind()) {
966             case TypeKind::TYPE_BYTE:
967             case TypeKind::TYPE_SHORT:
968             case TypeKind::TYPE_INT:
969             case TypeKind::TYPE_LONG:
970             case TypeKind::TYPE_UCHAR:
971             case TypeKind::TYPE_USHORT:
972             case TypeKind::TYPE_UINT:
973             case TypeKind::TYPE_ULONG:
974                 break;
975             default:
976                 LogError(token, StringHelper::Format("illegal base type of enum", baseType->ToString().c_str()));
977                 return nullptr;
978         }
979 
980         token = lexer_.PeekToken();
981         if (token.kind_ != TokenType::BRACES_LEFT) {
982             LogError(token, StringHelper::Format("expected '{' before '%s' token", token.value_.c_str()));
983         }
984         lexer_.GetToken();
985     } else {
986         lexer_.GetToken();
987         baseType = ast_->FindType("int");
988     }
989     return baseType;
990 }
991 
ParserEnumMember(const AutoPtr<ASTEnumType> & enumType)992 void Parser::ParserEnumMember(const AutoPtr<ASTEnumType> &enumType)
993 {
994     while (lexer_.PeekToken().kind_ == TokenType::ID) {
995         Token token = lexer_.GetToken();
996         AutoPtr<ASTEnumValue> enumValue = new ASTEnumValue(token.value_);
997 
998         token = lexer_.PeekToken();
999         if (token.kind_ == TokenType::ASSIGN) {
1000             lexer_.GetToken();
1001             enumValue->SetExprValue(ParseExpr());
1002         }
1003 
1004         enumValue->SetType(enumType->GetBaseType());
1005         enumType->AddMember(enumValue);
1006 
1007         token = lexer_.PeekToken();
1008         if (token.kind_ == TokenType::COMMA) {
1009             lexer_.GetToken();
1010             continue;
1011         }
1012 
1013         if (token.kind_ != TokenType::BRACES_RIGHT) {
1014             LogError(token, StringHelper::Format("expected ',' or '}' before '%s' token", token.value_.c_str()));
1015         }
1016     }
1017 }
1018 
ParseStructDeclaration(const AttrSet & attrs)1019 void Parser::ParseStructDeclaration(const AttrSet &attrs)
1020 {
1021     AutoPtr<ASTStructType> structType = new ASTStructType;
1022     structType->SetAttribute(ParseUserDefTypeAttr(attrs));
1023 
1024     lexer_.GetToken();
1025     Token token = lexer_.PeekToken();
1026     if (token.kind_ != TokenType::ID) {
1027         LogError(token, StringHelper::Format("expected struct name before '%s' token", token.value_.c_str()));
1028     } else {
1029         structType->SetName(token.value_);
1030         lexer_.GetToken();
1031     }
1032 
1033     token = lexer_.PeekToken();
1034     if (token.kind_ != TokenType::BRACES_LEFT) {
1035         LogError(token, StringHelper::Format("expected '{' before '%s' token", token.value_.c_str()));
1036     } else {
1037         lexer_.GetToken();
1038     }
1039 
1040     ParseStructMember(structType);
1041 
1042     token = lexer_.PeekToken();
1043     if (token.kind_ != TokenType::BRACES_RIGHT) {
1044         LogError(token, StringHelper::Format("expected '}' before '%s' token", token.value_.c_str()));
1045     } else {
1046         lexer_.GetToken();
1047     }
1048 
1049     token = lexer_.PeekToken();
1050     if (token.kind_ != TokenType::SEMICOLON) {
1051         LogError(token, StringHelper::Format("expected ';' before '%s' token", token.value_.c_str()));
1052     } else {
1053         lexer_.GetToken();
1054     }
1055 
1056     ast_->AddTypeDefinition(structType.Get());
1057 }
1058 
ParseStructMember(const AutoPtr<ASTStructType> & structType)1059 void Parser::ParseStructMember(const AutoPtr<ASTStructType> &structType)
1060 {
1061     Token token = lexer_.PeekToken();
1062     while (token.kind_ != TokenType::BRACES_RIGHT && token.kind_ != TokenType::END_OF_FILE) {
1063         AutoPtr<ASTType> memberType = ParseType();
1064         if (memberType == nullptr) {
1065             lexer_.SkipToken(TokenType::SEMICOLON);
1066             token = lexer_.PeekToken();
1067             continue;
1068         }
1069 
1070         token = lexer_.PeekToken();
1071         if (token.kind_ != TokenType::ID) {
1072             LogError(token, StringHelper::Format("expected member name before '%s' token", token.value_.c_str()));
1073             lexer_.SkipToken(TokenType::SEMICOLON);
1074             token = lexer_.PeekToken();
1075             continue;
1076         }
1077 
1078         lexer_.GetToken();
1079         std::string memberName = token.value_;
1080         structType->AddMember(memberType, memberName);
1081 
1082         token = lexer_.PeekToken();
1083         if (token.kind_ == TokenType::SEMICOLON) {
1084             lexer_.GetToken();
1085             token = lexer_.PeekToken();
1086             continue;
1087         }
1088 
1089         if (token.kind_ != TokenType::BRACES_RIGHT) {
1090             LogError(token, StringHelper::Format("expected ',' or '}' before '%s' token", token.value_.c_str()));
1091         }
1092     }
1093 }
1094 
ParseUnionDeclaration(const AttrSet & attrs)1095 void Parser::ParseUnionDeclaration(const AttrSet &attrs)
1096 {
1097     AutoPtr<ASTUnionType> unionType = new ASTUnionType;
1098     unionType->SetAttribute(ParseUserDefTypeAttr(attrs));
1099 
1100     lexer_.GetToken();
1101     Token token = lexer_.PeekToken();
1102     if (token.kind_ != TokenType::ID) {
1103         LogError(token, StringHelper::Format("expected struct name before '%s' token", token.value_.c_str()));
1104     } else {
1105         unionType->SetName(token.value_);
1106         lexer_.GetToken();
1107     }
1108 
1109     token = lexer_.PeekToken();
1110     if (token.kind_ != TokenType::BRACES_LEFT) {
1111         LogError(token, StringHelper::Format("expected '{' before '%s' token", token.value_.c_str()));
1112     } else {
1113         lexer_.GetToken();
1114     }
1115 
1116     ParseUnionMember(unionType);
1117 
1118     token = lexer_.PeekToken();
1119     if (token.kind_ != TokenType::BRACES_RIGHT) {
1120         LogError(token, StringHelper::Format("expected '}' before '%s' token", token.value_.c_str()));
1121     } else {
1122         lexer_.GetToken();
1123     }
1124 
1125     token = lexer_.PeekToken();
1126     if (token.kind_ != TokenType::SEMICOLON) {
1127         LogError(token, StringHelper::Format("expected ';' before '%s' token", token.value_.c_str()));
1128     } else {
1129         lexer_.GetToken();
1130     }
1131 
1132     ast_->AddTypeDefinition(unionType.Get());
1133 }
1134 
ParseUnionMember(const AutoPtr<ASTUnionType> & unionType)1135 void Parser::ParseUnionMember(const AutoPtr<ASTUnionType> &unionType)
1136 {
1137     Token token = lexer_.PeekToken();
1138     while (token.kind_ != TokenType::BRACES_RIGHT && token.kind_ != TokenType::END_OF_FILE) {
1139         AutoPtr<ASTType> memberType = ParseType();
1140         if (memberType == nullptr) {
1141             lexer_.SkipToken(TokenType::SEMICOLON);
1142             token = lexer_.PeekToken();
1143             continue;
1144         }
1145 
1146         token = lexer_.PeekToken();
1147         if (token.kind_ != TokenType::ID) {
1148             LogError(token, StringHelper::Format("expected member name before '%s' token", token.value_.c_str()));
1149             lexer_.SkipToken(TokenType::SEMICOLON);
1150             token = lexer_.PeekToken();
1151             continue;
1152         }
1153         lexer_.GetToken();
1154 
1155         std::string memberName = token.value_;
1156         if (!AddUnionMember(unionType, memberType, memberName)) {
1157             LogError(token,
1158                 StringHelper::Format(
1159                     "union not support this type or name of member duplicate '%s'", token.value_.c_str()));
1160         }
1161 
1162         token = lexer_.PeekToken();
1163         if (token.kind_ == TokenType::SEMICOLON) {
1164             lexer_.GetToken();
1165             token = lexer_.PeekToken();
1166             continue;
1167         }
1168 
1169         if (token.kind_ != TokenType::BRACES_RIGHT) {
1170             LogError(token, StringHelper::Format("expected ',' or '}' before '%s' token", token.value_.c_str()));
1171         }
1172     }
1173 }
1174 
AddUnionMember(const AutoPtr<ASTUnionType> & unionType,const AutoPtr<ASTType> & type,const std::string & name)1175 bool Parser::AddUnionMember(
1176     const AutoPtr<ASTUnionType> &unionType, const AutoPtr<ASTType> &type, const std::string &name)
1177 {
1178     for (size_t i = 0; i < unionType->GetMemberNumber(); i++) {
1179         std::string memberName = unionType->GetMemberName(i);
1180         if (name == memberName) {
1181             return false;
1182         }
1183     }
1184 
1185     // Non pod type members are not allowed in the union
1186     if (!type->IsPod()) {
1187         return false;
1188     }
1189 
1190     unionType->AddMember(type, name);
1191     return true;
1192 }
1193 
ParseUserDefTypeAttr(const AttrSet & attrs)1194 AutoPtr<ASTTypeAttr> Parser::ParseUserDefTypeAttr(const AttrSet &attrs)
1195 {
1196     AutoPtr<ASTTypeAttr> attribute = new ASTTypeAttr();
1197     for (const auto &token : attrs) {
1198         switch (token.kind_) {
1199             case TokenType::FULL:
1200                 attribute->isFull_ = true;
1201                 break;
1202             case TokenType::LITE:
1203                 attribute->isLite_ = true;
1204                 break;
1205             default:
1206                 LogError(token, StringHelper::Format("invalid attribute '%s' for type decl", token.value_.c_str()));
1207                 break;
1208         }
1209     }
1210 
1211     return attribute;
1212 }
1213 
ParseExpr()1214 AutoPtr<ASTExpr> Parser::ParseExpr()
1215 {
1216     lexer_.SetParseMode(Lexer::ParseMode::EXPR_MODE);
1217     AutoPtr<ASTExpr> value = ParseAndExpr();
1218     lexer_.SetParseMode(Lexer::ParseMode::DECL_MODE);
1219     return value;
1220 }
1221 
ParseAndExpr()1222 AutoPtr<ASTExpr> Parser::ParseAndExpr()
1223 {
1224     AutoPtr<ASTExpr> left = ParseXorExpr();
1225     Token token = lexer_.PeekToken();
1226     while (token.kind_ == TokenType::AND) {
1227         lexer_.GetToken();
1228         AutoPtr<ASTBinaryExpr> expr = new ASTBinaryExpr;
1229         expr->op_ = BinaryOpKind::AND;
1230         expr->lExpr_ = left;
1231         expr->rExpr_ = ParseXorExpr();
1232 
1233         left = expr.Get();
1234         token = lexer_.PeekToken();
1235     }
1236     return left;
1237 }
1238 
ParseXorExpr()1239 AutoPtr<ASTExpr> Parser::ParseXorExpr()
1240 {
1241     AutoPtr<ASTExpr> left = ParseOrExpr();
1242     Token token = lexer_.PeekToken();
1243     while (token.kind_ == TokenType::XOR) {
1244         lexer_.GetToken();
1245         AutoPtr<ASTBinaryExpr> expr = new ASTBinaryExpr;
1246         expr->op_ = BinaryOpKind::XOR;
1247         expr->lExpr_ = left;
1248         expr->rExpr_ = ParseOrExpr();
1249 
1250         left = expr.Get();
1251         token = lexer_.PeekToken();
1252     }
1253     return left;
1254 }
1255 
ParseOrExpr()1256 AutoPtr<ASTExpr> Parser::ParseOrExpr()
1257 {
1258     AutoPtr<ASTExpr> left = ParseShiftExpr();
1259     Token token = lexer_.PeekToken();
1260     while (token.kind_ == TokenType::OR) {
1261         lexer_.GetToken();
1262         AutoPtr<ASTBinaryExpr> expr = new ASTBinaryExpr;
1263         expr->op_ = BinaryOpKind::OR;
1264         expr->lExpr_ = left;
1265         expr->rExpr_ = ParseShiftExpr();
1266 
1267         left = expr.Get();
1268         token = lexer_.PeekToken();
1269     }
1270     return left;
1271 }
1272 
ParseShiftExpr()1273 AutoPtr<ASTExpr> Parser::ParseShiftExpr()
1274 {
1275     AutoPtr<ASTExpr> left = ParseAddExpr();
1276     Token token = lexer_.PeekToken();
1277     while (token.kind_ == TokenType::LEFT_SHIFT || token.kind_ == TokenType::RIGHT_SHIFT) {
1278         lexer_.GetToken();
1279         BinaryOpKind op = (token.kind_ == TokenType::LEFT_SHIFT) ? BinaryOpKind::LSHIFT : BinaryOpKind::RSHIFT;
1280         AutoPtr<ASTBinaryExpr> expr = new ASTBinaryExpr;
1281         expr->op_ = op;
1282         expr->lExpr_ = left;
1283         expr->rExpr_ = ParseAddExpr();
1284 
1285         left = expr.Get();
1286         token = lexer_.PeekToken();
1287     }
1288     return left;
1289 }
1290 
ParseAddExpr()1291 AutoPtr<ASTExpr> Parser::ParseAddExpr()
1292 {
1293     AutoPtr<ASTExpr> left = ParseMulExpr();
1294     Token token = lexer_.PeekToken();
1295     while (token.kind_ == TokenType::ADD || token.kind_ == TokenType::SUB) {
1296         lexer_.GetToken();
1297         BinaryOpKind op = (token.kind_ == TokenType::ADD) ? BinaryOpKind::ADD : BinaryOpKind::SUB;
1298         AutoPtr<ASTBinaryExpr> expr = new ASTBinaryExpr;
1299         expr->op_ = op;
1300         expr->lExpr_ = left;
1301         expr->rExpr_ = ParseMulExpr();
1302 
1303         left = expr.Get();
1304         token = lexer_.PeekToken();
1305     }
1306     return left;
1307 }
1308 
ParseMulExpr()1309 AutoPtr<ASTExpr> Parser::ParseMulExpr()
1310 {
1311     AutoPtr<ASTExpr> left = ParseUnaryExpr();
1312     Token token = lexer_.PeekToken();
1313     while (
1314         token.kind_ == TokenType::STAR || token.kind_ == TokenType::SLASH || token.kind_ == TokenType::PERCENT_SIGN) {
1315         lexer_.GetToken();
1316         BinaryOpKind op = BinaryOpKind::MUL;
1317         if (token.kind_ == TokenType::SLASH) {
1318             op = BinaryOpKind::DIV;
1319         } else if (token.kind_ == TokenType::PERCENT_SIGN) {
1320             op = BinaryOpKind::MOD;
1321         }
1322         AutoPtr<ASTBinaryExpr> expr = new ASTBinaryExpr;
1323         expr->op_ = op;
1324         expr->lExpr_ = left;
1325         expr->rExpr_ = ParseUnaryExpr();
1326 
1327         left = expr.Get();
1328         token = lexer_.PeekToken();
1329     }
1330     return left;
1331 }
1332 
ParseUnaryExpr()1333 AutoPtr<ASTExpr> Parser::ParseUnaryExpr()
1334 {
1335     Token token = lexer_.PeekToken();
1336     switch (token.kind_) {
1337         case TokenType::ADD:
1338         case TokenType::SUB:
1339         case TokenType::TILDE: {
1340             lexer_.GetToken();
1341             AutoPtr<ASTUnaryExpr> expr = new ASTUnaryExpr;
1342             expr->op_ = UnaryOpKind::PLUS;
1343             if (token.kind_ == TokenType::SUB) {
1344                 expr->op_ = UnaryOpKind::MINUS;
1345             } else if (token.kind_ == TokenType::TILDE) {
1346                 expr->op_ = UnaryOpKind::TILDE;
1347             }
1348 
1349             expr->expr_ = ParseUnaryExpr();
1350             return expr.Get();
1351         }
1352         default:
1353             return ParsePrimaryExpr();
1354     }
1355 }
1356 
ParsePrimaryExpr()1357 AutoPtr<ASTExpr> Parser::ParsePrimaryExpr()
1358 {
1359     Token token = lexer_.PeekToken();
1360     switch (token.kind_) {
1361         case TokenType::PARENTHESES_LEFT: {
1362             lexer_.GetToken();
1363             AutoPtr<ASTExpr> expr = ParseExpr();
1364             token = lexer_.PeekToken();
1365             if (token.kind_ != TokenType::PARENTHESES_RIGHT) {
1366                 LogError(token, StringHelper::Format("expected ')' before %s token", token.value_.c_str()));
1367             } else {
1368                 lexer_.GetToken();
1369                 expr->isParenExpr = true;
1370             }
1371             return expr;
1372         }
1373         case TokenType::NUM:
1374             return ParseNumExpr();
1375         default:
1376             LogError(token, StringHelper::Format("this expression is not supported"));
1377             lexer_.SkipUntilToken(TokenType::COMMA);
1378             return nullptr;
1379     }
1380 }
1381 
ParseNumExpr()1382 AutoPtr<ASTExpr> Parser::ParseNumExpr()
1383 {
1384     Token token = lexer_.GetToken();
1385     AutoPtr<ASTNumExpr> expr = new ASTNumExpr;
1386     expr->value_ = token.value_;
1387     return expr.Get();
1388 }
1389 
CheckType(const Token & token,const AutoPtr<ASTType> & type)1390 bool Parser::CheckType(const Token &token, const AutoPtr<ASTType> &type)
1391 {
1392     if (type == nullptr) {
1393         return false;
1394     }
1395 
1396     if (Options::GetInstance().GetTargetLanguage() == Options::Language::C) {
1397         if (type->IsSequenceableType() || type->IsSmqType() || type->IsAshmemType()) {
1398             LogError(token, StringHelper::Format("The %s type is not supported by c language.",
1399                 type->ToString().c_str()));
1400             return false;
1401         }
1402 
1403         if (Options::GetInstance().DoGenerateKernelCode()) {
1404             switch (type->GetTypeKind()) {
1405                 case TypeKind::TYPE_FLOAT:
1406                 case TypeKind::TYPE_DOUBLE:
1407                 case TypeKind::TYPE_FILEDESCRIPTOR:
1408                 case TypeKind::TYPE_INTERFACE:
1409                     LogError(token,
1410                         StringHelper::Format(
1411                             "The '%s' type is not supported by c language.", type->ToString().c_str()));
1412                     break;
1413                 default:
1414                     break;
1415             }
1416         }
1417     } else if (Options::GetInstance().GetTargetLanguage() == Options::Language::JAVA) {
1418         switch (type->GetTypeKind()) {
1419             case TypeKind::TYPE_UCHAR:
1420             case TypeKind::TYPE_USHORT:
1421             case TypeKind::TYPE_UINT:
1422             case TypeKind::TYPE_ULONG:
1423             case TypeKind::TYPE_ENUM:
1424             case TypeKind::TYPE_STRUCT:
1425             case TypeKind::TYPE_UNION:
1426             case TypeKind::TYPE_SMQ:
1427             case TypeKind::TYPE_UNKNOWN:
1428                 LogError(token,
1429                     StringHelper::Format("The '%s' type is not supported by java language.", type->ToString().c_str()));
1430                 return false;
1431             default:
1432                 break;
1433         }
1434     }
1435 
1436     return true;
1437 }
1438 
SetAstFileType()1439 void Parser::SetAstFileType()
1440 {
1441     if (ast_->GetInterfaceDef() != nullptr) {
1442         if (ast_->GetInterfaceDef()->IsCallback()) {
1443             ast_->SetAStFileType(ASTFileType::AST_ICALLBACK);
1444         } else {
1445             ast_->SetAStFileType(ASTFileType::AST_IFACE);
1446         }
1447     } else {
1448         ast_->SetAStFileType(ASTFileType::AST_TYPES);
1449     }
1450 }
1451 
CheckIntegrity()1452 bool Parser::CheckIntegrity()
1453 {
1454     if (ast_ == nullptr) {
1455         LogError(std::string("ast is nullptr."));
1456         return false;
1457     }
1458 
1459     if (ast_->GetName().empty()) {
1460         LogError(std::string("ast's name is empty."));
1461         return false;
1462     }
1463 
1464     if (ast_->GetPackageName().empty()) {
1465         LogError(std::string("ast's package name is empty."));
1466         return false;
1467     }
1468 
1469     switch (ast_->GetASTFileType()) {
1470         case ASTFileType::AST_IFACE: {
1471             return CheckInterfaceAst();
1472         }
1473         case ASTFileType::AST_ICALLBACK: {
1474             return CheckCallbackAst();
1475         }
1476         case ASTFileType::AST_SEQUENCEABLE: {
1477             LogError(std::string("it's impossible that ast is sequenceable."));
1478             return false;
1479         }
1480         case ASTFileType::AST_TYPES: {
1481             if (ast_->GetInterfaceDef() != nullptr) {
1482                 LogError(std::string("custom ast cannot has interface."));
1483                 return false;
1484             }
1485             break;
1486         }
1487         default:
1488             break;
1489     }
1490 
1491     return true;
1492 }
1493 
CheckInterfaceAst()1494 bool Parser::CheckInterfaceAst()
1495 {
1496     AutoPtr<ASTInterfaceType> interface = ast_->GetInterfaceDef();
1497     if (interface == nullptr) {
1498         LogError(std::string("ast's interface is empty."));
1499         return false;
1500     }
1501 
1502     if (ast_->GetTypeDefinitionNumber() > 0) {
1503         LogError(std::string("interface ast cannot has custom types."));
1504         return false;
1505     }
1506 
1507     if (interface->GetMethodNumber() == 0) {
1508         LogError(std::string("interface ast has no method."));
1509         return false;
1510     }
1511     return true;
1512 }
1513 
CheckCallbackAst()1514 bool Parser::CheckCallbackAst()
1515 {
1516     AutoPtr<ASTInterfaceType> interface = ast_->GetInterfaceDef();
1517     if (interface == nullptr) {
1518         LogError(std::string("ast's interface is empty."));
1519         return false;
1520     }
1521 
1522     if (!interface->IsCallback()) {
1523         LogError(std::string("ast is callback, but ast's interface is not callback."));
1524         return false;
1525     }
1526     return true;
1527 }
1528 
1529 /*
1530  * filePath: ./ohos/interface/foo/v1_0/IFoo.idl
1531  * package OHOS.Hdi.foo.v1_0;
1532  */
CheckPackageName(const std::string & filePath,const std::string & packageName)1533 bool Parser::CheckPackageName(const std::string &filePath, const std::string &packageName)
1534 {
1535     std::string pkgToPath = Options::GetInstance().GetPackagePath(packageName);
1536 
1537     size_t index = filePath.rfind(SEPARATOR);
1538     if (index == std::string::npos) {
1539         return false;
1540     }
1541 
1542     std::string parentDir = filePath.substr(0, index);
1543     return parentDir == pkgToPath;
1544 }
1545 
CheckImport(const std::string & importName)1546 bool Parser::CheckImport(const std::string &importName)
1547 {
1548     if (!std::regex_match(importName.c_str(), RE_IMPORT)) {
1549         LogError(StringHelper::Format("invalid impirt name '%s'", importName.c_str()));
1550         return false;
1551     }
1552 
1553     std::string idlFilePath = Options::GetInstance().GetImportFilePath(importName);
1554     if (!File::CheckValid(idlFilePath)) {
1555         LogError(StringHelper::Format("can not import '%s'", idlFilePath.c_str()));
1556         return false;
1557     }
1558     return true;
1559 }
1560 
AddAst(const AutoPtr<AST> & ast)1561 bool Parser::AddAst(const AutoPtr<AST> &ast)
1562 {
1563     if (ast == nullptr) {
1564         LogError(std::string("ast is nullptr."));
1565         return false;
1566     }
1567 
1568     allAsts_[ast->GetFullName()] = ast;
1569     return true;
1570 }
1571 
LogError(const std::string & message)1572 void Parser::LogError(const std::string &message)
1573 {
1574     errors_.push_back(message);
1575 }
1576 
LogError(const Token & token,const std::string & message)1577 void Parser::LogError(const Token &token, const std::string &message)
1578 {
1579     errors_.push_back(StringHelper::Format("[%s] error:%s", LocInfo(token).c_str(), message.c_str()));
1580 }
1581 
ShowError()1582 void Parser::ShowError()
1583 {
1584     for (const auto &errMsg : errors_) {
1585         Logger::E(TAG, "%s", errMsg.c_str());
1586     }
1587 }
1588 } // namespace HDI
1589 } // namespace OHOS