1 /*
2  * Copyright (c) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "parser/parser.h"
17 #include <cstdio>
18 #include "ast/ast_array_type.h"
19 #include "ast/ast_list_type.h"
20 #include "ast/ast_map_type.h"
21 #include "ast/ast_parameter.h"
22 #include "ast/ast_sequenceable_type.h"
23 #include "util/logger.h"
24 #include "util/string_builder.h"
25 
26 namespace OHOS {
27 namespace Idl {
28 const char* Parser::tag = "Parser";
29 
Parser(const Options & options)30 Parser::Parser(const Options& options)
31     : options_(options)
32 {}
33 
Parse(const String & sourceFile)34 bool Parser::Parse(const String& sourceFile)
35 {
36     bool ret = lexer_.OpenSourceFile(sourceFile);
37     if (!ret) {
38         Logger::E(tag, "Fail to open file \"%s\".", sourceFile.string());
39         return false;
40     }
41     ret = ParseFile();
42     ret = CheckIntegrity() && ret;
43     if (!ret) {
44         ShowError();
45         return false;
46     }
47     if (options_.DoDumpAST()) {
48         String astStr = module_->Dump("");
49         printf("%s\n", astStr.string());
50     }
51     return ret;
52 }
53 
ParseFile()54 bool Parser::ParseFile()
55 {
56     bool ret = true;
57 
58     module_ = new ASTModule();
59     module_->SetIdlFile(lexer_.GetSourceFile()->GetPath());
60 
61     ParseLicense();
62 
63     Token token;
64     while ((token = lexer_.PeekToken()) != Token::END_OF_FILE) {
65         switch (token) {
66             case Token::BRACKETS_LEFT:
67             case Token::INTERFACE:
68                 ret = ParseInterface() && ret;
69                 continue;
70             case Token::SEQUENCEABLE:
71                 ret = ParseSequenceable() && ret;
72                 continue;
73             case Token::COMMENT_LINE:
74                 lexer_.GetToken();
75                 continue;
76             default:
77                 LogError(token, String::Format("%s is not expected.", lexer_.DumpToken().string()));
78                 lexer_.GetToken();
79                 ret = false;
80                 continue;
81         }
82     }
83     lexer_.GetToken();
84 
85     return ret;
86 }
87 
ParseLicense()88 bool Parser::ParseLicense()
89 {
90     Token token = lexer_.PeekToken(false);
91     if (token != Token::COMMENT_BLOCK) {
92         return false;
93     }
94 
95     lexer_.GetToken(false);
96 
97     module_->SetLicense(lexer_.GetComment());
98 
99     return true;
100 }
101 
ParseInterface()102 bool Parser::ParseInterface()
103 {
104     bool ret = true;
105     bool hasProperties = false;
106     bool oneway = false;
107     Token token = lexer_.GetToken();
108     if (token == Token::BRACKETS_LEFT) {
109         token = lexer_.PeekToken();
110         if (token != Token::ONEWAY) {
111             LogError(Token::IDENTIFIER,
112                 String::Format("\"%s\" is an illegal interface property.", lexer_.DumpToken().string()));
113             if (token != Token::BRACKETS_RIGHT) {
114                 lexer_.SkipCurrentLine(Lexer::TokenToChar(Token::BRACKETS_RIGHT));
115             }
116             ret = false;
117         }
118         lexer_.GetToken();
119         oneway = true;
120         hasProperties = true;
121         token = lexer_.PeekToken();
122         if (token != Token::BRACKETS_RIGHT) {
123             LogError(Token::IDENTIFIER, String("\"]\" is expected."));
124             while (token != Token::BRACKETS_RIGHT && token != Token::INTERFACE && token != Token::END_OF_FILE) {
125                 lexer_.GetToken();
126                 token = lexer_.PeekToken();
127             }
128             ret = false;
129         } else {
130             lexer_.GetToken();
131         }
132 
133         token = lexer_.PeekToken();
134         if (token != Token::INTERFACE) {
135             LogError(Token::IDENTIFIER, String("\"interface\" is expected."));
136             ret = false;
137         } else {
138             lexer_.GetToken();
139         }
140     }
141     String interfaceFullName;
142     bool middleRes = ParseInterfaceMiddle(token, interfaceFullName);
143     if (!middleRes) {
144         return middleRes;
145     }
146     return ParseInterfaceEnd(token, interfaceFullName, hasProperties, oneway, ret);
147 }
148 
ParseInterfaceMiddle(Token & token,String & interfaceFullName)149 bool Parser::ParseInterfaceMiddle(Token& token, String& interfaceFullName)
150 {
151     token = lexer_.PeekToken();
152     if (token != Token::IDENTIFIER) {
153         LogError(token, String::Format("%s is not expected.", lexer_.DumpToken().string()));
154         lexer_.SkipCurrentLine();
155         return false;
156     } else {
157         lexer_.GetToken();
158         interfaceFullName = lexer_.GetIdentifier();
159         token = lexer_.PeekToken();
160     }
161     if (token != Token::SEMICOLON && token != Token::BRACES_LEFT) {
162         LogError(token, String::Format("%s is not expected.", lexer_.DumpToken().string()));
163         lexer_.SkipCurrentLine();
164         return false;
165     }
166 
167     if (interfaceFullName.IsEmpty()) {
168         LogError(Token::IDENTIFIER, String("Interface name is expected."));
169         return false;
170     } else if (!IsValidTypeName(interfaceFullName)) {
171         LogError(Token::IDENTIFIER, String::Format("Interface name \"%s\" is illegal.", interfaceFullName.string()));
172         return false;
173     } else if (interfaceFullName.IndexOf(".") == -1) {
174         if (!(options_.GetTargetLanguage().Equals("ts")) && !(options_.GetTargetLanguage().Equals("rust"))) {
175             LogError(Token::IDENTIFIER, String::Format("Interface name \"%s\" does not have namespace.",
176             interfaceFullName.string()));
177             return false;
178         }
179     }
180     return true;
181 }
182 
ParseInterfaceEnd(Token & token,String & interfaceFullName,bool hasProperties,bool oneway,bool ret)183 bool Parser::ParseInterfaceEnd(Token& token, String& interfaceFullName, bool hasProperties, bool oneway, bool ret)
184 {
185     AutoPtr<ASTInterfaceType> interface = new ASTInterfaceType();
186     parsingInterface_ = interface;
187     int index = interfaceFullName.LastIndexOf('.');
188     if (index != -1) {
189         interface->SetName(interfaceFullName.Substring(index + 1));
190         interface->SetNamespace(module_->ParseNamespace(interfaceFullName.Substring(0, index + 1)));
191     } else {
192         interface->SetName(interfaceFullName);
193         interface->SetNamespace(NameSpaceEmpty());
194     }
195     // read ';'
196     lexer_.GetToken();
197     if (token == Token::SEMICOLON) {
198         if (hasProperties) {
199             LogError(Token::IDENTIFIER, String("Interface forward declaration should not have properties."));
200             return false;
201         }
202         interface->SetExternal(true);
203         module_->AddInterface(interface);
204         return true;
205     } else {
206         if (!interface->GetName().Equals(module_->GetName())) {
207             LogError(Token::IDENTIFIER, String::Format("Module name \"%s\" is not equal to interface name  \"%s\".",
208                 module_->GetName().string(), interface->GetName().string()));
209             return false;
210         }
211 
212         interface->SetLicense(module_->GetLicense());
213         interface->SetOneway(oneway);
214 
215         while (token != Token::BRACES_RIGHT && token != Token::END_OF_FILE) {
216             ret = ParseMethod(interface) && ret;
217             token = lexer_.PeekToken();
218         }
219 
220         if (token != Token::BRACES_RIGHT) {
221             ret = false;
222         } else {
223             lexer_.GetToken();
224             module_->AddInterface(interface);
225         }
226         return ret;
227     }
228     return true;
229 }
230 
ParseMethodProperties(bool & oneway,bool & cacheable,int & cacheTime)231 bool Parser::ParseMethodProperties(bool& oneway, bool& cacheable, int& cacheTime)
232 {
233     Token token;
234     bool isParseOneway = false;
235 
236     oneway = false;
237     cacheable = false;
238     lexer_.GetToken();
239     token = lexer_.PeekToken();
240     while (token != Token::BRACKETS_RIGHT && token != Token::END_OF_FILE) {
241         lexer_.GetToken();
242         if (token != Token::ONEWAY && token != Token::CACHEABLE) {
243             LogError(Token::IDENTIFIER, String::Format("\"%s\" is an illegal method property.",
244                 lexer_.DumpToken().string()));
245             break;
246         }
247 
248         if (token == Token::ONEWAY && isParseOneway == false) {
249             oneway = true;
250             isParseOneway = true;
251         } else if (token == Token::CACHEABLE && cacheable == false) {
252             if (!lexer_.ParseCacheable(cacheTime)) {
253                 LogError(Token::CACHEABLE, "cacheable time format is incorrect.");
254                 return false;
255             }
256             cacheable = true;
257         } else {
258             return false;
259         }
260 
261         token = lexer_.PeekToken();
262         if (token == Token::COMMA) {
263             lexer_.GetToken();
264             token = lexer_.PeekToken();
265         }
266     }
267 
268     if (token != Token::BRACKETS_RIGHT) {
269         LogError(Token::IDENTIFIER, String("\"]\" is expected."));
270         return false;
271     } else {
272         lexer_.GetToken();
273     }
274     return true;
275 }
276 
SetMethodAttr(ASTMethod * method,ASTType * returnType,bool oneway,bool cacheable,int cacheTime)277 void Parser::SetMethodAttr(ASTMethod* method, ASTType *returnType, bool oneway, bool cacheable, int cacheTime)
278 {
279     method->SetName(lexer_.GetIdentifier());
280     method->SetOneway(oneway);
281     method->SetReturnType(returnType);
282     if (cacheable == true) {
283         method->SetCacheable(cacheTime);
284         module_->SetHasCacheableProxyMethods(true);
285     }
286 
287     return;
288 }
289 
ParseMethodName(Token & token,ASTType * type,ASTInterfaceType * interface)290 bool Parser::ParseMethodName(Token& token, ASTType* type, ASTInterfaceType* interface)
291 {
292     if (type == nullptr) {
293         token = lexer_.PeekToken();
294         if (token == Token::BRACES_RIGHT) {
295             return false;
296         }
297         // jump over colon
298         lexer_.GetToken();
299         while (token != Token::SEMICOLON && token != Token::END_OF_FILE) {
300             token = lexer_.PeekToken();
301             if (token == Token::BRACES_RIGHT) {
302                 break;
303             }
304             lexer_.GetToken();
305         }
306         return false;
307     }
308     if (interface->IsOneway()) {
309         if (!type->IsVoidType()) {
310             LogError(token, String("void return type expected in oneway interface."));
311             return false;
312         }
313     }
314     token = lexer_.PeekToken();
315     if (token != Token::IDENTIFIER) {
316         LogError(token, String("Method name is expected."));
317         if (token == Token::BRACES_RIGHT) {
318             return false;
319         }
320         // jump over colon
321         lexer_.GetToken();
322         while (token != Token::SEMICOLON && token != Token::END_OF_FILE) {
323             token = lexer_.PeekToken();
324             if (token == Token::BRACES_RIGHT) {
325                 break;
326             }
327             lexer_.GetToken();
328         }
329         return false;
330     }
331     return true;
332 }
333 
ParseMethodBrackets(Token & token,ASTMethod * method,bool & ret)334 bool Parser::ParseMethodBrackets(Token& token, ASTMethod* method, bool& ret)
335 {
336     if (method->IsOneway()) {
337         if (!method->GetReturnType()->IsVoidType()) {
338             LogError(token, String("void return type expected in oneway method."));
339             return false;
340         }
341     }
342     token = lexer_.PeekToken();
343     if (token != Token::PARENTHESES_LEFT) {
344         LogError(token, String("\"(\" is expected."));
345         if (token == Token::BRACES_RIGHT) {
346             return false;
347         }
348         // jump over colon
349         lexer_.GetToken();
350         while (token != Token::SEMICOLON && token != Token::END_OF_FILE) {
351             token = lexer_.PeekToken();
352             if (token == Token::BRACES_RIGHT) {
353                 break;
354             }
355             lexer_.GetToken();
356         }
357         return false;
358     }
359     token = lexer_.GetToken();
360 
361     token = lexer_.PeekToken();
362     while (token != Token::PARENTHESES_RIGHT && token != Token::END_OF_FILE) {
363         ret = ParseParameter(method) && ret;
364         token = lexer_.PeekToken();
365         if (token == Token::COMMA) {
366             lexer_.GetToken();
367             token = lexer_.PeekToken();
368         }
369     }
370     return true;
371 }
372 
ParseMethod(ASTInterfaceType * interface)373 bool Parser::ParseMethod(ASTInterfaceType* interface)
374 {
375     bool ret = true;
376     bool oneway = false;
377     bool cacheable = false;
378     int cacheTime;
379     Token token = lexer_.PeekToken();
380     if ((token == Token::BRACKETS_LEFT) && (ParseMethodProperties(oneway, cacheable, cacheTime) == false)) {
381         return false;
382     }
383 
384     AutoPtr<ASTType> type = ParseType();
385     if (!ParseMethodName(token, type, interface)) {
386         return false;
387     }
388 
389     token = lexer_.GetToken();
390     AutoPtr<ASTMethod> method = new ASTMethod();
391     if (method == nullptr) {
392         LogError(token, String("method is nullptr."));
393         return false;
394     }
395     SetMethodAttr(method, type, oneway, cacheable, cacheTime);
396     if (!ParseMethodBrackets(token, method, ret)) {
397         return false;
398     }
399 
400     if (interface->IsOneway() || method->IsOneway()) {
401         for (size_t i = 0; i< method->GetParameterNumber(); i++) {
402             auto parameter = method->GetParameter(i);
403             if (parameter->IsOutParameter()) {
404                 LogError(token, String("out parameter type not expected in oneway method."));
405                 return false;
406             }
407         }
408     }
409     lexer_.GetToken();
410     if (!ret) {
411         lexer_.SkipCurrentLine();
412         return false;
413     }
414 
415     token = lexer_.PeekToken();
416     if (token != Token::SEMICOLON) {
417         LogError(token, String("\";\" is expected."));
418         if (token != Token::BRACES_RIGHT) {
419             lexer_.SkipCurrentLine(Lexer::TokenToChar(Token::BRACES_RIGHT));
420         }
421         return false;
422     }
423     lexer_.GetToken();
424 
425     interface->AddMethod(method);
426 
427     return ret;
428 }
429 
ParseParameterPeek(Token & token)430 bool Parser::ParseParameterPeek(Token& token)
431 {
432     if (token != Token::BRACKETS_LEFT) {
433         LogError(token, String("\"[\" is expected."));
434         // jump to ',' or ')'
435         while (token != Token::COMMA && token != Token::PARENTHESES_RIGHT && token != Token::END_OF_FILE) {
436             lexer_.GetToken();
437             token = lexer_.PeekToken();
438         }
439         return false;
440     }
441     return true;
442 }
443 
ParseParameterInOut(Token & token,ASTParameter * parameter)444 bool Parser::ParseParameterInOut(Token& token, ASTParameter* parameter)
445 {
446     token = lexer_.PeekToken();
447     while (token != Token::BRACKETS_RIGHT && token != Token::END_OF_FILE) {
448         switch (token) {
449             case Token::IN:
450                 lexer_.GetToken();
451                 parameter->SetInParameter(true);
452                 break;
453             case Token::OUT:
454                 lexer_.GetToken();
455                 parameter->SetOutParameter(true);
456                 break;
457             case Token::INOUT:
458                 lexer_.GetToken();
459                 parameter->SetInParameter(true);
460                 parameter->SetOutParameter(true);
461                 break;
462             default:
463                 LogError(token, String("\"in\" or \"out\" or \"inout\" is expected."));
464                 break;
465         }
466         token = lexer_.PeekToken();
467         if (token == Token::COMMA) {
468             lexer_.GetToken();
469             token = lexer_.PeekToken();
470             continue;
471         }
472         if (token != Token::BRACKETS_RIGHT) {
473             LogError(token, String("\",\" or \"]\" is expected."));
474             // jump to ',' or ')'
475             while (token != Token::COMMA && token != Token::PARENTHESES_RIGHT && token != Token::END_OF_FILE) {
476                 lexer_.GetToken();
477                 token = lexer_.PeekToken();
478             }
479             return false;
480         }
481     }
482     return true;
483 }
484 
ParseParameter(ASTMethod * method)485 bool Parser::ParseParameter(ASTMethod* method)
486 {
487     Token token = lexer_.PeekToken();
488     if (!ParseParameterPeek(token)) {
489         return false;
490     }
491     lexer_.GetToken();
492 
493     AutoPtr<ASTParameter> parameter = new ASTParameter();
494     if (parameter == nullptr) {
495         return false;
496     }
497 
498     if (!ParseParameterInOut(token, parameter)) {
499         return false;
500     }
501 
502     // read ']'
503     lexer_.GetToken();
504 
505     AutoPtr<ASTType> type = ParseType();
506     if (type == nullptr) {
507         // jump to ',' or ')'
508         while (token != Token::COMMA && token != Token::PARENTHESES_RIGHT && token != Token::END_OF_FILE) {
509             lexer_.GetToken();
510             token = lexer_.PeekToken();
511         }
512         return false;
513     }
514 
515     token = lexer_.PeekToken();
516     if (token != Token::IDENTIFIER) {
517         LogError(token, String("Parameter name is expected."));
518         // jump to ',' or ')'
519         while (token != Token::COMMA && token != Token::PARENTHESES_RIGHT && token != Token::END_OF_FILE) {
520             lexer_.GetToken();
521             token = lexer_.PeekToken();
522         }
523         return false;
524     }
525     lexer_.GetToken();
526 
527     parameter->SetName(lexer_.GetIdentifier());
528     parameter->SetType(type);
529     method->AddParameter(parameter);
530 
531     return true;
532 }
533 
ParseType()534 AutoPtr<ASTType> Parser::ParseType()
535 {
536     AutoPtr<ASTType> type;
537 
538     Token token = lexer_.PeekToken();
539     if (IsPrimitiveType(token)) {
540         lexer_.GetToken();
541         type = module_->FindType(lexer_.DumpToken());
542     } else if (token == Token::LIST) {
543         type = ParseList();
544     } else if (token == Token::MAP) {
545         type = ParseMap();
546     } else if (token == Token::IDENTIFIER) {
547         lexer_.GetToken();
548         if (parsingInterface_ != nullptr &&
549             parsingInterface_->GetName().Equals(lexer_.GetIdentifier())) {
550             type = parsingInterface_.Get();
551         } else {
552             type = module_->FindType(lexer_.GetIdentifier());
553         }
554     } else {
555         LogError(token, String("Type name is expected."));
556         return nullptr;
557     }
558 
559     if (type == nullptr || type.Get() == nullptr) {
560         LogError(token, String::Format("Type \"%s\" was not declared in the module.", lexer_.DumpToken().string()));
561         return nullptr;
562     }
563 
564     token = lexer_.PeekToken();
565     if (token == Token::BRACKETS_LEFT) {
566         lexer_.GetToken();
567         token = lexer_.PeekToken();
568         if (token != Token::BRACKETS_RIGHT) {
569             LogError(token, String("\"]\" is expected."));
570             return nullptr;
571         }
572         lexer_.GetToken();
573 
574         AutoPtr<ASTArrayType> arrayType = new ASTArrayType();
575         if (arrayType == nullptr) {
576             LogError(token, String("arrayType is nullptr."));
577             return nullptr;
578         }
579         arrayType->SetElementType(type);
580 
581         type = module_->FindType(arrayType->ToString());
582         if (type == nullptr) {
583             module_->AddType(arrayType);
584             type = static_cast<ASTType*>(arrayType.Get());
585         }
586     }
587 
588     return type;
589 }
590 
ParseList()591 AutoPtr<ASTType> Parser::ParseList()
592 {
593     lexer_.GetToken();
594 
595     Token token = lexer_.PeekToken();
596     if (token != Token::ANGLE_BRACKETS_LEFT) {
597         LogError(token, String("\"<\" is expected."));
598         return nullptr;
599     }
600     lexer_.GetToken();
601 
602     AutoPtr<ASTType> type = ParseType();
603     if (type == nullptr) {
604         lexer_.SkipCurrentLine('>');
605         return nullptr;
606     }
607 
608     token = lexer_.PeekToken();
609     if (token != Token::ANGLE_BRACKETS_RIGHT) {
610         LogError(token, String("\">\" is expected."));
611         return nullptr;
612     }
613     lexer_.GetToken();
614 
615     AutoPtr<ASTListType> list = new ASTListType();
616     list->SetElementType(type);
617 
618     AutoPtr<ASTType> ret = module_->FindType(list->ToString());
619     if (ret == nullptr) {
620         module_->AddType(list);
621         ret = list.Get();
622     }
623 
624     return ret;
625 }
626 
ParseMap()627 AutoPtr<ASTType> Parser::ParseMap()
628 {
629     lexer_.GetToken();
630 
631     Token token = lexer_.PeekToken();
632     if (token != Token::ANGLE_BRACKETS_LEFT) {
633         LogError(token, String("\"<\" is expected."));
634         return nullptr;
635     }
636     lexer_.GetToken();
637 
638     AutoPtr<ASTType> keyType = ParseType();
639     if (keyType == nullptr) {
640         lexer_.SkipCurrentLine('>');
641         return nullptr;
642     }
643 
644     token = lexer_.PeekToken();
645     if (token != Token::COMMA) {
646         LogError(token, String("\",\" is expected."));
647         return nullptr;
648     }
649     lexer_.GetToken();
650 
651     AutoPtr<ASTType> valueType = ParseType();
652     if (valueType == nullptr) {
653         lexer_.SkipCurrentLine('>');
654         return nullptr;
655     }
656 
657     token = lexer_.PeekToken();
658     if (token != Token::ANGLE_BRACKETS_RIGHT) {
659         LogError(token, String("\">\" is expected."));
660         return nullptr;
661     }
662     lexer_.GetToken();
663 
664     AutoPtr<ASTMapType> map = new ASTMapType();
665     map->SetKeyType(keyType);
666     map->SetValueType(valueType);
667 
668     AutoPtr<ASTType> ret = module_->FindType(map->ToString());
669     if (ret == nullptr) {
670         module_->AddType(map);
671         ret = map.Get();
672     }
673 
674     return ret;
675 }
676 
ParseSequenceable()677 bool Parser::ParseSequenceable()
678 {
679     lexer_.GetToken();
680 
681     String classFullName;
682 
683     Token token = lexer_.PeekToken();
684     if (token != Token::IDENTIFIER) {
685         LogError(token, String::Format("%s is not expected.", lexer_.DumpToken().string()));
686         lexer_.SkipCurrentLine();
687         return false;
688     } else {
689         lexer_.GetToken();
690         classFullName = lexer_.GetIdentifier();
691         token = lexer_.PeekToken();
692     }
693 
694     if (token != Token::SEMICOLON) {
695         LogError(token, String::Format("%s is not expected.", lexer_.DumpToken().string()));
696         lexer_.SkipCurrentLine();
697         return false;
698     }
699 
700     // read ';'
701     lexer_.GetToken();
702 
703     if (classFullName.IsEmpty()) {
704         LogError(Token::IDENTIFIER, String("Class name is expected."));
705         return false;
706     } else if (!IsValidTypeName(classFullName)) {
707         LogError(Token::IDENTIFIER, String::Format("Class name \"%s\" is illegal.", classFullName.string()));
708         return false;
709     }
710 
711     AutoPtr<ASTSequenceableType> sequenceable = new ASTSequenceableType();
712     int index = classFullName.LastIndexOf('.');
713     if (index != -1) {
714         sequenceable->SetName(classFullName.Substring(index + 1));
715         sequenceable->SetNamespace(module_->ParseNamespace(classFullName.Substring(0, index + 1)));
716     } else {
717         sequenceable->SetName(classFullName);
718         sequenceable->SetNamespace(NameSpaceEmpty());
719     }
720     module_->AddSequenceable(sequenceable);
721 
722     return true;
723 }
724 
CheckIntegrity()725 bool Parser::CheckIntegrity()
726 {
727     bool definedInterface = false;
728     size_t interfaceNumber = module_->GetInterfaceNumber();
729     for (size_t i = 0; i < interfaceNumber; i++) {
730         if (!module_->GetInterface(i)->IsExternal()) {
731             definedInterface = true;
732             break;
733         }
734     }
735     if (!definedInterface) {
736         LogError(Token::UNKNOWN, String("An interface is not defined."));
737         return false;
738     }
739 
740     return true;
741 }
742 
IsValidTypeName(const String & typeName)743 bool Parser::IsValidTypeName(const String& typeName)
744 {
745     if (typeName[0] == '.') {
746         return false;
747     }
748 
749     if (typeName[typeName.GetLength() - 1] == '.') {
750         return false;
751     }
752 
753     return true;
754 }
755 
LogError(Token token,const String & message)756 void Parser::LogError(Token token, const String& message)
757 {
758     AutoPtr<ErrorInfo> error = new ErrorInfo();
759 
760     String sourceFile = lexer_.GetSourceFile()->GetPath();
761 #ifdef __MINGW32__
762     error->file_ = sourceFile.Substring(sourceFile.LastIndexOf('\\') + 1);
763 #else
764     error->file_ = sourceFile.Substring(sourceFile.LastIndexOf('/') + 1);
765 #endif
766     error->lineNo_ = lexer_.GetTokenLineNumber();
767     error->columnNo_ = lexer_.GetTokenColumnNumber();
768     error->message_ = message;
769 
770     if (errors_ == nullptr) {
771         errors_ = error;
772     } else {
773         ErrorInfo* pos = errors_;
774         while (pos->next_ != nullptr) {
775             pos = pos->next_;
776         }
777         pos->next_ = error;
778     }
779 }
780 
ShowError()781 void Parser::ShowError()
782 {
783     ErrorInfo* error = errors_;
784     while (error != nullptr) {
785         Logger::E(tag, "%s[line %d, column %d] %s", error->file_.string(),
786             error->lineNo_, error->columnNo_, error->message_.string());
787         error = error->next_;
788     }
789 }
790 
NameSpaceEmpty()791 AutoPtr<ASTNamespace> Parser::NameSpaceEmpty()
792 {
793     AutoPtr<ASTNamespace> currNspace = nullptr;
794     currNspace = module_->FindNamespace("");
795     if (currNspace == nullptr) {
796         currNspace = new ASTNamespace("");
797         module_->AddNamespace(currNspace);
798     }
799     return currNspace;
800 }
801 } // namespace Idl
802 } // namespace OHOS
803