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