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
26namespace OHOS {
27namespace Idl {
28const char* Parser::tag = "Parser";
29
30Parser::Parser(const Options& options)
31    : options_(options)
32{}
33
34bool 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
54bool 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
88bool 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
102bool 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
149bool 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
183bool 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
231bool 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
277void 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
290bool 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
334bool 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
373bool 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
430bool 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
444bool 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
485bool 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
534AutoPtr<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
591AutoPtr<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
627AutoPtr<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
677bool 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
725bool 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
743bool 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
756void 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
781void 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
791AutoPtr<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