mirror of
https://github.com/openharmony/drivers_framework.git
synced 2026-07-21 03:35:25 -04:00
fcc8f03111
Signed-off-by: yueyan <yueyan4@huawei.com>
1558 lines
45 KiB
C++
Executable File
1558 lines
45 KiB
C++
Executable File
/*
|
|
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
|
*
|
|
* HDF is dual licensed: you can use it either under the terms of
|
|
* the GPL, or the BSD license, at your option.
|
|
* See the LICENSE file in the root of this repository for complete details.
|
|
*/
|
|
|
|
#include "parser/parser.h"
|
|
#include <regex>
|
|
#include "ast/ast_array_type.h"
|
|
#include "ast/ast_enum_type.h"
|
|
#include "ast/ast_list_type.h"
|
|
#include "ast/ast_map_type.h"
|
|
#include "ast/ast_smq_type.h"
|
|
#include "ast/ast_parameter.h"
|
|
#include "ast/ast_sequenceable_type.h"
|
|
#include "ast/ast_struct_type.h"
|
|
#include "ast/ast_union_type.h"
|
|
#include "util/logger.h"
|
|
#include "util/string_builder.h"
|
|
|
|
#define RE_DIGIT "[0-9]+"
|
|
#define RE_IDENTIFIER "[a-zA-Z_][a-zA-Z0-9_]*"
|
|
|
|
static const std::regex rePackage(RE_IDENTIFIER "(?:\\." RE_IDENTIFIER ")*\\.[V|v]" "(" RE_DIGIT ")_(" RE_DIGIT ")");
|
|
static const std::regex reImport(RE_IDENTIFIER "(?:\\." RE_IDENTIFIER ")*\\.[V|v]" RE_DIGIT "_" RE_DIGIT "." RE_IDENTIFIER);
|
|
|
|
namespace OHOS {
|
|
namespace HDI {
|
|
const char* Parser::TAG = "Parser";
|
|
|
|
Parser::Parser(const Options& options, const AutoPtr<ASTModule>& module)
|
|
:options_(options), lexer_(nullptr), errors_(nullptr), ast_(nullptr), astModule_(module)
|
|
{}
|
|
|
|
bool Parser::Parse(const String& sourceFile)
|
|
{
|
|
lexer_ = std::make_shared<Lexer>();
|
|
bool ret = lexer_->OpenSourceFile(sourceFile);
|
|
if (!ret) {
|
|
Logger::E(TAG, "Fail to open file '%s'.", sourceFile.string());
|
|
return false;
|
|
}
|
|
|
|
ret = ParseFile();
|
|
ret = CheckIntegrity() && ret;
|
|
ret = AddAst() && ret;
|
|
if (!ret || errors_ != nullptr) {
|
|
ShowError();
|
|
return false;
|
|
}
|
|
|
|
if (options_.DoDumpAST()) {
|
|
String astStr = ast_->Dump("");
|
|
printf("%s\n", astStr.string());
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
bool Parser::Parse(const String& sourceFile, std::shared_ptr<FileDetail>& fileDetailPtr)
|
|
{
|
|
lexer_ = std::make_shared<Lexer>();
|
|
bool ret = lexer_->OpenSourceFile(sourceFile);
|
|
if (!ret) {
|
|
Logger::E(TAG, "Fail to open file '%s'.", sourceFile.string());
|
|
return false;
|
|
}
|
|
|
|
ret = ParseIdlDetail(fileDetailPtr);
|
|
if (!ret) {
|
|
ShowError();
|
|
return false;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
bool Parser::ParseIdlDetail(std::shared_ptr<FileDetail>& fileDetailPtr)
|
|
{
|
|
bool ret = true;
|
|
fileDetailPtr = std::make_shared<FileDetail>();
|
|
fileDetailPtr->SetFilePath(lexer_->GetFilePath());
|
|
|
|
Token token;
|
|
while ((token = lexer_->PeekToken()) != Token::END_OF_FILE) {
|
|
switch (token) {
|
|
case Token::PACKAGE:
|
|
ret = ParseIdlPackage(fileDetailPtr) && ret;
|
|
break;
|
|
case Token::IMPORT:
|
|
ret = ParseIdlImport(fileDetailPtr) && ret;
|
|
break;
|
|
default:
|
|
lexer_->GetToken();
|
|
break;
|
|
}
|
|
}
|
|
lexer_->GetToken();
|
|
return ret;
|
|
}
|
|
|
|
bool Parser::ParseIdlPackage(std::shared_ptr<FileDetail>& fileDetailPtr)
|
|
{
|
|
lexer_->GetToken();
|
|
String packageName;
|
|
|
|
Token token = lexer_->PeekToken();
|
|
if (token != Token::IDENTIFIER) {
|
|
if (token == Token::SEMICOLON) {
|
|
LogError(String::Format("expected identifier before ';'."));
|
|
lexer_->GetToken();
|
|
} else {
|
|
LogError(String::Format("'%s' is an invalid package name.", lexer_->DumpToken().string()));
|
|
}
|
|
lexer_->SkipCurrentLine();
|
|
return false;
|
|
} else {
|
|
lexer_->GetToken();
|
|
packageName = lexer_->GetIdentifier();
|
|
token = lexer_->PeekToken();
|
|
}
|
|
|
|
if (token != Token::SEMICOLON) {
|
|
LogError(String::Format("expected ';' before '%s'", lexer_->DumpToken().string()));
|
|
return false;
|
|
}
|
|
|
|
// read ';'
|
|
lexer_->GetToken();
|
|
|
|
if (packageName.IsEmpty()) {
|
|
LogError(String("Package name is not expected."));
|
|
return false;
|
|
} else if (!IsValidTypeName(packageName)) {
|
|
LogError(String::Format("Package name '%s' is illegal.", packageName.string()));
|
|
return false;
|
|
} else if (!CheckPackageName(lexer_->GetFilePath(), packageName)) {
|
|
LogError(String::Format("Package name '%s' does not match file apth '%s'.",
|
|
packageName.string(), lexer_->GetFilePath().string()));
|
|
return false;
|
|
}
|
|
|
|
fileDetailPtr->SetPackageName(packageName);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool Parser::ParseIdlImport(std::shared_ptr<FileDetail>& fileDetailPtr)
|
|
{
|
|
lexer_->GetToken();
|
|
|
|
String importPkgName;
|
|
Token token = lexer_->PeekToken();
|
|
if (token != Token::IDENTIFIER) {
|
|
if (token == Token::SEMICOLON) {
|
|
LogError(String::Format("expected identifier before ';'."));
|
|
lexer_->GetToken();
|
|
} else {
|
|
LogError(String::Format("'%s' is an invalid import package name.", lexer_->DumpToken().string()));
|
|
}
|
|
lexer_->SkipCurrentLine();
|
|
return false;
|
|
}
|
|
lexer_->GetToken();
|
|
importPkgName = lexer_->GetIdentifier();
|
|
|
|
token = lexer_->PeekToken();
|
|
if (token != Token::SEMICOLON) {
|
|
LogError(String::Format("expected ';' before '%s'.", lexer_->DumpToken().string()));
|
|
return false;
|
|
}
|
|
|
|
// read ';'
|
|
lexer_->GetToken();
|
|
if (importPkgName.IsEmpty()) {
|
|
LogError(String("import package name is not expected."));
|
|
return false;
|
|
} else if (!IsValidTypeName(importPkgName)) {
|
|
LogError(String::Format("import package name '%s' is illegal.", importPkgName.string()));
|
|
return false;
|
|
}
|
|
|
|
if (!fileDetailPtr->AddImport(importPkgName)) {
|
|
LogError(String::Format("the package of '%s' has been imported.", importPkgName.string()));
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool Parser::ParseFile()
|
|
{
|
|
bool ret = true;
|
|
ast_ = new AST();
|
|
ast_->SetIdlFile(lexer_->GetFilePath());
|
|
ParseLicense();
|
|
|
|
Token token;
|
|
while ((token = lexer_->PeekToken()) != Token::END_OF_FILE) {
|
|
switch (token) {
|
|
case Token::PACKAGE:
|
|
ret = ParsePackageName() && ret;
|
|
continue;
|
|
case Token::IMPORT:
|
|
ret = ParseImport() && ret;
|
|
continue;
|
|
case Token::SEQUENCEABLE:
|
|
ret = ParseSequenceable() && ret;
|
|
continue;
|
|
case Token::BRACKETS_LEFT:
|
|
ret = ParseAttribute() && ret;
|
|
continue;
|
|
case Token::INTERFACE:
|
|
ret = ParseInterface() && ret;
|
|
continue;
|
|
case Token::COMMENT_LINE:
|
|
lexer_->GetToken();
|
|
continue;
|
|
case Token::ENUM:
|
|
ret = ParseEnumDefine() && ret;
|
|
continue;
|
|
case Token::STRUCT:
|
|
ret = ParseStructDefine() && ret;
|
|
continue;
|
|
case Token::UNION:
|
|
ret = ParseUnionDefine() && ret;
|
|
continue;
|
|
default:
|
|
LogError(String::Format("'%s' is not expected.", lexer_->DumpToken().string()));
|
|
lexer_->GetToken();
|
|
ret = false;
|
|
continue;
|
|
}
|
|
}
|
|
lexer_->GetToken();
|
|
SetAstFileType();
|
|
|
|
return ret;
|
|
}
|
|
|
|
bool Parser::ParseLicense()
|
|
{
|
|
Token token = lexer_->PeekToken(false);
|
|
if (token != Token::COMMENT_BLOCK) {
|
|
return false;
|
|
}
|
|
|
|
lexer_->GetToken(false);
|
|
|
|
ast_->SetLicense(lexer_->GetComment());
|
|
|
|
return true;
|
|
}
|
|
|
|
bool Parser::ParsePackageName()
|
|
{
|
|
lexer_->GetToken();
|
|
String packageFullName;
|
|
Token token = lexer_->PeekToken();
|
|
if (token != Token::IDENTIFIER) {
|
|
if (token == Token::SEMICOLON) {
|
|
LogError(String::Format("expected identifier before ';'."));
|
|
} else {
|
|
LogError(String::Format("'%s' is an invalid package name.", lexer_->DumpToken().string()));
|
|
}
|
|
lexer_->SkipCurrentLine();
|
|
lexer_->GetToken();
|
|
return false;
|
|
} else {
|
|
lexer_->GetToken();
|
|
packageFullName = lexer_->GetIdentifier();
|
|
token = lexer_->PeekToken();
|
|
}
|
|
|
|
if (token != Token::SEMICOLON) {
|
|
LogError(String::Format("expected ';' before '%s'", lexer_->DumpToken().string()));
|
|
return false;
|
|
}
|
|
|
|
// read ';'
|
|
lexer_->GetToken();
|
|
if (packageFullName.IsEmpty()) {
|
|
LogError(String("Package name is not expected."));
|
|
return false;
|
|
} else if (!IsValidTypeName(packageFullName)) {
|
|
LogError(String::Format("Package name '%s' is illegal.", packageFullName.string()));
|
|
return false;
|
|
} else if (!CheckPackageName(lexer_->GetFilePath(), packageFullName)) {
|
|
LogError(String::Format("Package name '%s' does not match file apth '%s'.",
|
|
packageFullName.string(), lexer_->GetFilePath().string()));
|
|
return false;
|
|
}
|
|
|
|
if (!ParserPackageInfo(packageFullName)) {
|
|
LogError(String::Format("Parse package '%s' infomation failed.", packageFullName.string()));
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool Parser::ParserPackageInfo(const String& packageName)
|
|
{
|
|
std::cmatch result;
|
|
if (!std::regex_match(packageName.string(), result, rePackage)) {
|
|
return false;
|
|
}
|
|
|
|
if (result.size() < 3) {
|
|
return false;
|
|
}
|
|
|
|
ast_->SetPackageName(result.str(0).c_str());
|
|
size_t majorVersion = std::atoi(result.str(1).c_str());
|
|
size_t minorVersion = std::atoi(result.str(2).c_str());
|
|
ast_->SetVersion(majorVersion, minorVersion);
|
|
return true;
|
|
}
|
|
|
|
bool Parser::ParseImport()
|
|
{
|
|
lexer_->GetToken();
|
|
|
|
String packageFullName;
|
|
|
|
Token token = lexer_->PeekToken();
|
|
if (token != Token::IDENTIFIER) {
|
|
if (token == Token::SEMICOLON) {
|
|
LogError(String::Format("expected identifier before ';'."));
|
|
} else {
|
|
LogError(String::Format("%s is an invalid import package name.", lexer_->DumpToken().string()));
|
|
}
|
|
lexer_->SkipCurrentLine();
|
|
lexer_->GetToken();
|
|
return false;
|
|
}
|
|
lexer_->GetToken();
|
|
packageFullName = lexer_->GetIdentifier();
|
|
|
|
token = lexer_->PeekToken();
|
|
if (token != Token::SEMICOLON) {
|
|
LogError(String::Format("expected ';' before '%s'.", lexer_->DumpToken().string()));
|
|
return false;
|
|
}
|
|
|
|
// read ';'
|
|
lexer_->GetToken();
|
|
if (packageFullName.IsEmpty()) {
|
|
LogError(String("import package name is not expected."));
|
|
return false;
|
|
} else if (!IsValidTypeName(packageFullName)) {
|
|
LogError(String::Format("import package name '%s' is illegal.", packageFullName.string()));
|
|
return false;
|
|
}
|
|
|
|
AutoPtr<AST> importAst = astModule_->GetAst(packageFullName);
|
|
if (importAst == nullptr) {
|
|
LogError(String("not find import ast."));
|
|
return false;
|
|
}
|
|
|
|
if (!ast_->AddImport(importAst)) {
|
|
LogError(String::Format("the package '%s' has been import", packageFullName.string()));
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool Parser::ParseSequenceable()
|
|
{
|
|
lexer_->GetToken();
|
|
String classFullName;
|
|
|
|
Token token = lexer_->PeekToken();
|
|
if (token != Token::IDENTIFIER) {
|
|
if (token == Token::SEMICOLON) {
|
|
LogError(String::Format("expected identifier before ';'."));
|
|
} else {
|
|
LogError(String::Format("'%s' is not expected.", lexer_->DumpToken().string()));
|
|
}
|
|
lexer_->SkipCurrentLine();
|
|
lexer_->GetToken();
|
|
return false;
|
|
}
|
|
lexer_->GetToken();
|
|
classFullName = lexer_->GetIdentifier();
|
|
|
|
token = lexer_->PeekToken();
|
|
if (token != Token::SEMICOLON) {
|
|
LogError(String::Format("expected ';' before '%s'.", lexer_->DumpToken().string()));
|
|
return false;
|
|
}
|
|
// read ';'
|
|
lexer_->GetToken();
|
|
|
|
if (classFullName.IsEmpty()) {
|
|
LogError(String("class name is not expected."));
|
|
return false;
|
|
} else if (!IsValidTypeName(classFullName)) {
|
|
LogError(String::Format("class name '%s' is illegal.", classFullName.string()));
|
|
return false;
|
|
}
|
|
|
|
AutoPtr<ASTSequenceableType> sequenceable = new ASTSequenceableType();
|
|
int index = classFullName.LastIndexOf('.');
|
|
if (index != -1) {
|
|
sequenceable->SetName(classFullName.Substring(index + 1));
|
|
sequenceable->SetNamespace(ast_->ParseNamespace(classFullName.Substring(0, index + 1)));
|
|
} else {
|
|
sequenceable->SetName(classFullName);
|
|
}
|
|
|
|
AutoPtr<AST> sequenceableAst = new AST();
|
|
sequenceableAst->SetFullName(classFullName);
|
|
sequenceableAst->AddSequenceableDef(sequenceable);
|
|
sequenceableAst->SetAStFileType(ASTFileType::AST_SEQUENCEABLE);
|
|
ast_->AddImport(sequenceableAst);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool Parser::ParseAttribute()
|
|
{
|
|
bool ret = true;
|
|
AutoPtr<Attribute> attributes = nullptr;
|
|
|
|
if (!ParseAttributeBody(attributes)) {
|
|
return false;
|
|
}
|
|
|
|
Token token = lexer_->PeekToken();
|
|
switch (token) {
|
|
case Token::ENUM:
|
|
ret = ParseEnumDefine(attributes) && ret;
|
|
break;
|
|
case Token::STRUCT:
|
|
ret = ParseStructDefine(attributes) && ret;
|
|
break;
|
|
case Token::UNION:
|
|
ret = ParseUnionDefine(attributes) && ret;
|
|
break;
|
|
case Token::INTERFACE:
|
|
ret = ParseInterface(attributes) && ret;
|
|
break;
|
|
default: {
|
|
LogError(String::Format("'%s' is not expected.", lexer_->DumpToken().string()));
|
|
return false;
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
bool Parser::ParseInterface(const AutoPtr<Attribute>& attributes)
|
|
{
|
|
lexer_->GetToken();
|
|
String interfaceName;
|
|
|
|
Token token = lexer_->PeekToken();
|
|
if (token != Token::IDENTIFIER) {
|
|
LogError(String::Format("'%s' is not expected.", lexer_->DumpToken().string()));
|
|
lexer_->Skip('}');
|
|
lexer_->GetToken();
|
|
return false;
|
|
}
|
|
lexer_->GetToken();
|
|
interfaceName = lexer_->GetIdentifier();
|
|
|
|
token = lexer_->PeekToken();
|
|
if (token != Token::BRACES_LEFT) {
|
|
LogError(String::Format("expected '{' after the '%s'.", lexer_->DumpToken().string()));
|
|
lexer_->Skip('}');
|
|
lexer_->GetToken();
|
|
return false;
|
|
}
|
|
lexer_->GetToken();
|
|
|
|
if (interfaceName.IsEmpty()) {
|
|
LogError(String("interface name is expected."));
|
|
return false;
|
|
}
|
|
|
|
AutoPtr<ASTInterfaceType> interface = new ASTInterfaceType();
|
|
interface->SetName(interfaceName);
|
|
interface->SetNamespace(ast_->ParseNamespace(ast_->GetFullName()));
|
|
|
|
if (!interface->GetName().Equals(ast_->GetName())) {
|
|
LogError(String::Format("Module name '%s' is not equal to interface name '%s'.",
|
|
ast_->GetName().string(), interface->GetName().string()));
|
|
}
|
|
|
|
interface->SetLicense(ast_->GetLicense());
|
|
if (attributes != nullptr) {
|
|
interface->SetOneWay(attributes->isOneWay);
|
|
interface->SetCallback(attributes->isCallback);
|
|
interface->SetFull(attributes->isFull);
|
|
interface->SetLite(attributes->isLite);
|
|
}
|
|
return ParseInterfaceBody(interface);
|
|
}
|
|
|
|
bool Parser::ParseInterfaceBody(const AutoPtr<ASTInterfaceType>& interface)
|
|
{
|
|
bool ret = true;
|
|
Token token = lexer_->PeekToken();
|
|
while (token != Token::BRACES_RIGHT && token != Token::END_OF_FILE) {
|
|
ret = ParseMethod(interface) && ret;
|
|
token = lexer_->PeekToken();
|
|
}
|
|
|
|
if (token != Token::BRACES_RIGHT) {
|
|
LogError(String::Format("'%s' is not expected.", lexer_->DumpToken().string()));
|
|
lexer_->SkipEof();
|
|
return false;
|
|
}
|
|
lexer_->GetToken();
|
|
|
|
if (ast_->GetInterfaceDef() != nullptr) {
|
|
LogError(String::Format("an interface class already exists int idl file."));
|
|
lexer_->SkipEof();
|
|
return false;
|
|
}
|
|
|
|
SetVersionInterfaceMethod(interface);
|
|
|
|
ast_->AddInterfaceDef(interface);
|
|
return ret;
|
|
}
|
|
|
|
bool Parser::ParseMethod(const AutoPtr<ASTInterfaceType>& interface)
|
|
{
|
|
AutoPtr<Attribute> attributes = nullptr;
|
|
if (!ParseAttributeBody(attributes)) {
|
|
return false;
|
|
}
|
|
|
|
Token token = lexer_->PeekToken();
|
|
if (token != Token::IDENTIFIER) {
|
|
LogError(String("Method name is expected."));
|
|
if (token == Token::BRACES_RIGHT) {
|
|
return false;
|
|
}
|
|
// jump over colon
|
|
lexer_->GetToken();
|
|
while (token != Token::SEMICOLON && token != Token::END_OF_FILE) {
|
|
token = lexer_->PeekToken();
|
|
if (token == Token::BRACES_RIGHT) {
|
|
break;
|
|
}
|
|
lexer_->GetToken();
|
|
}
|
|
return false;
|
|
}
|
|
lexer_->GetToken();
|
|
|
|
AutoPtr<ASTMethod> method = new ASTMethod();
|
|
method->SetName(lexer_->GetIdentifier());
|
|
|
|
if (attributes != nullptr) {
|
|
method->SetOneWay(attributes->isOneWay || interface->IsOneWay());
|
|
method->SetFull(attributes->isFull);
|
|
method->SetLite(attributes->isLite);
|
|
}
|
|
|
|
if (!ParseParameterList(method)) {
|
|
return false;
|
|
}
|
|
|
|
interface->AddMethod(method);
|
|
return true;
|
|
}
|
|
|
|
void Parser::SetVersionInterfaceMethod(const AutoPtr<ASTInterfaceType>& interface)
|
|
{
|
|
AutoPtr<ASTMethod> method = new ASTMethod();
|
|
method->SetName("GetVersion");
|
|
|
|
AutoPtr<ASTType> type = ast_->FindType("unsigned int");
|
|
if (type == nullptr) {
|
|
type = new ASTUintType();
|
|
}
|
|
AutoPtr<ASTParameter> majorParam = new ASTParameter("majorVer", ParamAttr::PARAM_OUT, type);
|
|
AutoPtr<ASTParameter> minorParam = new ASTParameter("minorVer", ParamAttr::PARAM_OUT, type);
|
|
|
|
method->AddParameter(majorParam);
|
|
method->AddParameter(minorParam);
|
|
interface->AddVersionMethod(method);
|
|
}
|
|
|
|
bool Parser::ParseAttributeBody(AutoPtr<Attribute>& attributes)
|
|
{
|
|
Token token = lexer_->PeekToken();
|
|
if (token != Token::BRACKETS_LEFT) {
|
|
return true;
|
|
}
|
|
lexer_->GetToken();
|
|
attributes = new Attribute();
|
|
token = lexer_->PeekToken();
|
|
while (token != Token::BRACKETS_RIGHT) {
|
|
if (!ParseAttributeParam(attributes)) {
|
|
return false;
|
|
}
|
|
|
|
token = lexer_->PeekToken();
|
|
if (token == Token::COMMA) {
|
|
lexer_->GetToken();
|
|
token = lexer_->PeekToken();
|
|
} else if (token == Token::BRACKETS_RIGHT) {
|
|
break;
|
|
} else {
|
|
LogError(String::Format("'%s' is not expected.", lexer_->DumpToken().string()));
|
|
lexer_->Skip(Lexer::TokenToChar(Token::BRACKETS_RIGHT));
|
|
lexer_->GetToken();
|
|
return false;
|
|
}
|
|
}
|
|
lexer_->GetToken();
|
|
return true;
|
|
}
|
|
|
|
bool Parser::ParseAttributeParam(AutoPtr<Attribute>& attributes)
|
|
{
|
|
Token token = lexer_->GetToken();
|
|
switch (token) {
|
|
case Token::ONEWAY:
|
|
if (options_.DoGenerateKernelCode()) {
|
|
LogError(String::Format("'%s' is not supported in kernel code.", lexer_->DumpToken().string()));
|
|
lexer_->Skip(Lexer::TokenToChar(Token::BRACKETS_RIGHT));
|
|
lexer_->GetToken();
|
|
return false;
|
|
}
|
|
attributes->isOneWay = true;
|
|
break;
|
|
case Token::CALLBACK:
|
|
attributes->isCallback = true;
|
|
break;
|
|
case Token::FULL:
|
|
attributes->isFull = true;
|
|
break;
|
|
case Token::LITE:
|
|
attributes->isLite = true;
|
|
break;
|
|
default: {
|
|
LogError(String::Format("'%s' is not expected.", lexer_->DumpToken().string()));
|
|
lexer_->Skip(Lexer::TokenToChar(Token::BRACKETS_RIGHT));
|
|
lexer_->GetToken();
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool Parser::ParseParameterList(AutoPtr<ASTMethod>& method)
|
|
{
|
|
bool ret = true;
|
|
Token token = lexer_->PeekToken();
|
|
if (token != Token::PARENTHESES_LEFT) {
|
|
LogError(String("'(' is expected."));
|
|
lexer_->Skip(';');
|
|
return false;
|
|
}
|
|
lexer_->GetToken();
|
|
|
|
token = lexer_->PeekToken();
|
|
while (token != Token::PARENTHESES_RIGHT && token != Token::END_OF_FILE) {
|
|
ret = ParseParameter(method) && ret;
|
|
token = lexer_->PeekToken();
|
|
if (token == Token::COMMA) {
|
|
lexer_->GetToken();
|
|
token = lexer_->PeekToken();
|
|
} else if (token != Token::PARENTHESES_RIGHT) {
|
|
LogError(String::Format("'%s' is not expected.", lexer_->DumpToken().string()));
|
|
lexer_->SkipCurrentLine(';');
|
|
lexer_->GetToken();
|
|
return false;
|
|
}
|
|
}
|
|
|
|
lexer_->GetToken();
|
|
if (!ret) {
|
|
lexer_->SkipCurrentLine();
|
|
return false;
|
|
}
|
|
|
|
token = lexer_->PeekToken();
|
|
if (token != Token::SEMICOLON) {
|
|
LogError(String("';' is expected."));
|
|
return false;
|
|
}
|
|
lexer_->GetToken();
|
|
return true;
|
|
}
|
|
|
|
bool Parser::ParseParameter(const AutoPtr<ASTMethod>& method)
|
|
{
|
|
AutoPtr<ASTParameter> parameter = new ASTParameter();
|
|
if (!ParseParamAttr(parameter)) {
|
|
return false;
|
|
}
|
|
|
|
AutoPtr<ASTType> type = ParseType();
|
|
|
|
Token token = lexer_->PeekToken();
|
|
if (type == nullptr) {
|
|
while (token != Token::COMMA && token != Token::PARENTHESES_RIGHT && token != Token::END_OF_FILE) {
|
|
lexer_->GetToken();
|
|
token = lexer_->PeekToken();
|
|
}
|
|
return false;
|
|
}
|
|
|
|
if (token != Token::IDENTIFIER) {
|
|
LogError(String("Parameter name is expected."));
|
|
while (token != Token::COMMA && token != Token::PARENTHESES_RIGHT && token != Token::END_OF_FILE) {
|
|
lexer_->GetToken();
|
|
token = lexer_->PeekToken();
|
|
}
|
|
return false;
|
|
}
|
|
lexer_->GetToken();
|
|
|
|
parameter->SetName(lexer_->GetIdentifier());
|
|
parameter->SetType(type);
|
|
|
|
if (method->IsOneWay() && parameter->GetAttribute() == ParamAttr::PARAM_OUT) {
|
|
LogError(String::Format("The attribute of parameter '%s' cannot be 'out'.", parameter->GetName().string()));
|
|
return false;
|
|
}
|
|
|
|
method->AddParameter(parameter);
|
|
return true;
|
|
}
|
|
|
|
bool Parser::ParseParamAttr(const AutoPtr<ASTParameter>& parameter)
|
|
{
|
|
Token token = lexer_->PeekToken();
|
|
if (token != Token::BRACKETS_LEFT) {
|
|
LogError(String("'[' is expected."));
|
|
while (token != Token::COMMA && token != Token::PARENTHESES_RIGHT && token != Token::END_OF_FILE) {
|
|
lexer_->GetToken();
|
|
token = lexer_->PeekToken();
|
|
}
|
|
return false;
|
|
}
|
|
lexer_->GetToken();
|
|
|
|
if (parameter == nullptr) {
|
|
return false;
|
|
}
|
|
|
|
token = lexer_->PeekToken();
|
|
if (token == Token::IN) {
|
|
lexer_->GetToken();
|
|
parameter->SetAttribute(ParamAttr::PARAM_IN);
|
|
} else if (token == Token::OUT) {
|
|
lexer_->GetToken();
|
|
parameter->SetAttribute(ParamAttr::PARAM_OUT);
|
|
} else {
|
|
LogError(String::Format("'%s' is not a parameter property, it must be 'in' or 'out'.",
|
|
lexer_->DumpToken().string()));
|
|
while (token != Token::SEMICOLON && token != Token::END_OF_FILE) {
|
|
lexer_->GetToken();
|
|
token = lexer_->PeekToken();
|
|
}
|
|
return false;
|
|
}
|
|
|
|
token = lexer_->PeekToken();
|
|
if (token != Token::BRACKETS_RIGHT) {
|
|
LogError(String::Format("']' is expected."));
|
|
while (token != Token::SEMICOLON && token != Token::END_OF_FILE) {
|
|
lexer_->GetToken();
|
|
token = lexer_->PeekToken();
|
|
}
|
|
return false;
|
|
}
|
|
lexer_->GetToken();
|
|
|
|
return true;
|
|
}
|
|
|
|
AutoPtr<ASTType> Parser::ParseType()
|
|
{
|
|
int typeLineNo = lexer_->GetTokenLineNumber();
|
|
int typeColumnNo = lexer_->GetTokenColumnNumber();
|
|
AutoPtr<ASTType> type;
|
|
|
|
Token token = lexer_->PeekToken();
|
|
if (IsPrimitiveType(token)) {
|
|
lexer_->GetToken();
|
|
type = ast_->FindType(lexer_->DumpToken());
|
|
} else if (token == Token::LIST) {
|
|
type = ParseList();
|
|
} else if (token == Token::MAP) {
|
|
type = ParseMap();
|
|
} else if (token == Token::SMEMQUEUE) {
|
|
type = ParseSharedMemQueueMetaType();
|
|
} else if (token == Token::ENUM || token == Token::STRUCT || token == Token::UNION) {
|
|
type = ParseCustomType();
|
|
} else if (token == Token::IDENTIFIER) {
|
|
lexer_->GetToken();
|
|
type = ast_->FindType(lexer_->GetIdentifier());
|
|
} else if (token == Token::UNSIGNED) {
|
|
lexer_->GetToken();
|
|
type = ParseUnsignedType(typeLineNo, typeColumnNo);
|
|
} else {
|
|
LogError(typeLineNo, typeColumnNo, String("Invalid type name."));
|
|
return nullptr;
|
|
}
|
|
|
|
if (type == nullptr) {
|
|
LogError(typeLineNo, typeColumnNo, String::Format("Type '%s' was not declared in any idl file.",
|
|
lexer_->DumpToken().string()));
|
|
}
|
|
|
|
token = lexer_->PeekToken();
|
|
if (token == Token::BRACKETS_LEFT) {
|
|
lexer_->GetToken();
|
|
type = ParseArrayType(type);
|
|
}
|
|
|
|
if (!CheckType(typeLineNo, typeColumnNo, type)) {
|
|
return nullptr;
|
|
}
|
|
|
|
return type;
|
|
}
|
|
|
|
AutoPtr<ASTType> Parser::ParseUnsignedType(int typeLineNo, int typeColumnNo)
|
|
{
|
|
AutoPtr<ASTType> type = nullptr;
|
|
String unsignedStr = lexer_->DumpToken();
|
|
Token token = lexer_->PeekToken();
|
|
switch (token) {
|
|
case Token::CHAR:
|
|
case Token::SHORT:
|
|
case Token::INTEGER:
|
|
case Token::LONG: {
|
|
type = ast_->FindType(unsignedStr + " " + lexer_->DumpToken());
|
|
lexer_->GetToken();
|
|
break;
|
|
}
|
|
default: {
|
|
LogError(typeLineNo, typeColumnNo,
|
|
String::Format("'unsigned %s' type was not declared in the idl file.",
|
|
lexer_->DumpToken().string()));
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
return type;
|
|
}
|
|
|
|
AutoPtr<ASTType> Parser::ParseList()
|
|
{
|
|
lexer_->GetToken();
|
|
|
|
Token token = lexer_->PeekToken();
|
|
if (token != Token::ANGLE_BRACKETS_LEFT) {
|
|
LogError(String("'<' is expected."));
|
|
return nullptr;
|
|
}
|
|
lexer_->GetToken();
|
|
|
|
AutoPtr<ASTType> type = ParseType();
|
|
if (type == nullptr) {
|
|
lexer_->SkipCurrentLine('>');
|
|
lexer_->GetToken();
|
|
return nullptr;
|
|
}
|
|
|
|
token = lexer_->PeekToken();
|
|
if (token != Token::ANGLE_BRACKETS_RIGHT) {
|
|
LogError(String("'>' is expected."));
|
|
return nullptr;
|
|
}
|
|
lexer_->GetToken();
|
|
|
|
AutoPtr<ASTListType> list = new ASTListType();
|
|
list->SetElementType(type);
|
|
|
|
AutoPtr<ASTType> ret = ast_->FindType(list->ToString());
|
|
if (ret == nullptr) {
|
|
ast_->AddType(list.Get());
|
|
ret = list.Get();
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
AutoPtr<ASTType> Parser::ParseMap()
|
|
{
|
|
lexer_->GetToken();
|
|
|
|
Token token = lexer_->PeekToken();
|
|
if (token != Token::ANGLE_BRACKETS_LEFT) {
|
|
LogError(String("'<' is expected."));
|
|
return nullptr;
|
|
}
|
|
lexer_->GetToken();
|
|
|
|
AutoPtr<ASTType> keyType = ParseType();
|
|
if (keyType == nullptr) {
|
|
lexer_->SkipCurrentLine('>');
|
|
return nullptr;
|
|
}
|
|
|
|
token = lexer_->PeekToken();
|
|
if (token != Token::COMMA) {
|
|
LogError(String("',' is expected."));
|
|
return nullptr;
|
|
}
|
|
lexer_->GetToken();
|
|
|
|
AutoPtr<ASTType> valueType = ParseType();
|
|
if (valueType == nullptr) {
|
|
lexer_->SkipCurrentLine('>');
|
|
return nullptr;
|
|
}
|
|
|
|
token = lexer_->PeekToken();
|
|
if (token != Token::ANGLE_BRACKETS_RIGHT) {
|
|
LogError(String("'>' is expected."));
|
|
return nullptr;
|
|
}
|
|
lexer_->GetToken();
|
|
|
|
AutoPtr<ASTMapType> map = new ASTMapType();
|
|
map->SetKeyType(keyType);
|
|
map->SetValueType(valueType);
|
|
|
|
AutoPtr<ASTType> ret = ast_->FindType(map->ToString());
|
|
if (ret == nullptr) {
|
|
ast_->AddType(map.Get());
|
|
ret = map.Get();
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
AutoPtr<ASTType> Parser::ParseSharedMemQueueMetaType()
|
|
{
|
|
lexer_->GetToken();
|
|
|
|
Token token = lexer_->PeekToken();
|
|
if (token != Token::ANGLE_BRACKETS_LEFT) {
|
|
LogError(String("'<' is expected."));
|
|
return nullptr;
|
|
}
|
|
lexer_->GetToken();
|
|
|
|
AutoPtr<ASTType> InnerType = ParseType();
|
|
if (InnerType == nullptr) {
|
|
lexer_->SkipCurrentLine('>');
|
|
return nullptr;
|
|
}
|
|
|
|
token = lexer_->PeekToken();
|
|
if (token != Token::ANGLE_BRACKETS_RIGHT) {
|
|
LogError(String("'>' is expected."));
|
|
return nullptr;
|
|
}
|
|
lexer_->GetToken();
|
|
|
|
AutoPtr<ASTSharedMemQueueType> type = new ASTSharedMemQueueType();
|
|
type->SetInnerType(InnerType);
|
|
AutoPtr<ASTType> ret = ast_->FindType(type->ToString());
|
|
if (ret == nullptr) {
|
|
ast_->AddType(type.Get());
|
|
ret = type.Get();
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
AutoPtr<ASTType> Parser::ParseArrayType(const AutoPtr<ASTType>& elementType)
|
|
{
|
|
Token token = lexer_->PeekToken();
|
|
if (token != Token::BRACKETS_RIGHT) {
|
|
LogError(String("']' is expected."));
|
|
return nullptr;
|
|
}
|
|
lexer_->GetToken();
|
|
|
|
if (elementType == nullptr) {
|
|
return nullptr;
|
|
}
|
|
|
|
AutoPtr<ASTArrayType> arrayType = new ASTArrayType();
|
|
arrayType->SetElementType(elementType);
|
|
AutoPtr<ASTType> type = ast_->FindType(arrayType->ToString());
|
|
|
|
if (type == nullptr) {
|
|
ast_->AddType(arrayType.Get());
|
|
type = static_cast<ASTType*>(arrayType.Get());
|
|
}
|
|
|
|
return type;
|
|
}
|
|
|
|
AutoPtr<ASTType> Parser::ParseCustomType()
|
|
{
|
|
Token token = lexer_->GetToken();
|
|
String typePrefix;
|
|
if (token == Token::ENUM) {
|
|
typePrefix = "enum";
|
|
} else if (token == Token::STRUCT) {
|
|
typePrefix = "struct";
|
|
} else if (token == Token::UNION) {
|
|
typePrefix = "union";
|
|
}
|
|
|
|
token = lexer_->PeekToken();
|
|
if (token != Token::IDENTIFIER) {
|
|
LogError(String("custom type name is expected."));
|
|
return nullptr;
|
|
}
|
|
|
|
String typeName = typePrefix + " " + lexer_->GetIdentifier();
|
|
lexer_->GetToken();
|
|
AutoPtr<ASTType> type = ast_->FindType(typeName);
|
|
if (type != nullptr) {
|
|
ast_->AddType(type);
|
|
}
|
|
|
|
return type;
|
|
}
|
|
|
|
bool Parser::ParseEnumDefine(const AutoPtr<Attribute>& attributes)
|
|
{
|
|
lexer_->GetToken();
|
|
AutoPtr<ASTEnumType> type = new ASTEnumType();
|
|
|
|
Token token = lexer_->PeekToken();
|
|
if (token != Token::IDENTIFIER) {
|
|
LogError(String("custom enum type name is expected."));
|
|
return false;
|
|
}
|
|
type->SetName(lexer_->GetIdentifier());
|
|
lexer_->GetToken();
|
|
|
|
if (!ParseEnumBaseType(type)) {
|
|
return false;
|
|
}
|
|
|
|
token = lexer_->PeekToken();
|
|
if (token != Token::BRACES_LEFT) {
|
|
lexer_->SkipCurrentLine(';');
|
|
return false;
|
|
}
|
|
lexer_->GetToken();
|
|
|
|
if (!ParseEnumMember(type)) {
|
|
return false;
|
|
}
|
|
|
|
token = lexer_->PeekToken();
|
|
if (token != Token::SEMICOLON) {
|
|
LogError(String::Format("'%s' is not expected.", lexer_->DumpToken().string()));
|
|
lexer_->SkipCurrentLine();
|
|
return false;
|
|
}
|
|
lexer_->GetToken();
|
|
|
|
if (attributes != nullptr) {
|
|
type->SetFull(attributes->isFull);
|
|
type->SetLite(attributes->isLite);
|
|
}
|
|
|
|
ast_->AddTypeDefinition(type.Get());
|
|
return true;
|
|
}
|
|
|
|
bool Parser::ParseEnumBaseType(const AutoPtr<ASTEnumType>& type)
|
|
{
|
|
Token token = lexer_->PeekToken();
|
|
if (token == Token::COLON) {
|
|
lexer_->GetToken();
|
|
AutoPtr<ASTType> baseType = ParseType();
|
|
if (baseType == nullptr) {
|
|
LogError("no base type of enum type");
|
|
lexer_->SkipCurrentLine(';');
|
|
return false;
|
|
}
|
|
if (baseType->IsByteType() ||
|
|
baseType->IsShortType() ||
|
|
baseType->IsIntegerType() ||
|
|
baseType->IsLongType() ||
|
|
baseType->IsUcharType() ||
|
|
baseType->IsUshortType() ||
|
|
baseType->IsUintType() ||
|
|
baseType->IsUlongType()) {
|
|
ast_->AddType(baseType);
|
|
type->SetBaseType(baseType);
|
|
type->SetDisplayBase(true);
|
|
} else {
|
|
LogError("invaild base type of enum type");
|
|
lexer_->SkipCurrentLine(';');
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if (type->GetBaseType() == nullptr) {
|
|
AutoPtr<ASTType> baseType = ast_->FindType("int");
|
|
if (baseType == nullptr) {
|
|
ast_->AddType(new ASTIntegerType());
|
|
baseType = ast_->FindType("int");
|
|
}
|
|
type->SetBaseType(baseType);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool Parser::ParseEnumMember(const AutoPtr<ASTEnumType>& type)
|
|
{
|
|
Token token = lexer_->PeekToken();
|
|
while (token != Token::BRACES_RIGHT) {
|
|
if (token != Token::IDENTIFIER) {
|
|
lexer_->SkipCurrentLine(';');
|
|
return false;
|
|
}
|
|
AutoPtr<ASTEnumValue> enumValue = new ASTEnumValue(lexer_->GetIdentifier());
|
|
lexer_->GetToken();
|
|
|
|
token = lexer_->PeekToken();
|
|
if (token == Token::ASSIGN) {
|
|
lexer_->GetToken();
|
|
token = lexer_->PeekToken();
|
|
if (token == Token::DIGIT) {
|
|
enumValue->SetValue(lexer_->GetDigit());
|
|
lexer_->GetToken();
|
|
token = lexer_->PeekToken();
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if (token == Token::COMMA) {
|
|
lexer_->GetToken();
|
|
token = lexer_->PeekToken();
|
|
} else if (token == Token::BRACES_RIGHT) {
|
|
} else {
|
|
lexer_->SkipCurrentLine(';');
|
|
return false;
|
|
}
|
|
enumValue->SetType(type->GetBaseType());
|
|
type->AddMember(enumValue);
|
|
}
|
|
lexer_->GetToken();
|
|
return true;
|
|
}
|
|
|
|
bool Parser::ParseStructDefine(const AutoPtr<Attribute>& attributes)
|
|
{
|
|
lexer_->GetToken();
|
|
|
|
AutoPtr<ASTStructType> type = new ASTStructType();
|
|
if (type == nullptr) {
|
|
lexer_->SkipCurrentLine(';');
|
|
return false;
|
|
}
|
|
|
|
Token token = lexer_->PeekToken();
|
|
if (token != Token::IDENTIFIER) {
|
|
LogError(String("custom struct type name is expected."));
|
|
return false;
|
|
}
|
|
type->SetName(lexer_->GetIdentifier());
|
|
lexer_->GetToken();
|
|
|
|
if (!ParseStructMember(type)) {
|
|
return false;
|
|
}
|
|
|
|
if (attributes != nullptr) {
|
|
type->SetFull(attributes->isFull);
|
|
type->SetLite(attributes->isLite);
|
|
}
|
|
|
|
ast_->AddTypeDefinition(type.Get());
|
|
return true;
|
|
}
|
|
|
|
bool Parser::ParseStructMember(const AutoPtr<ASTStructType>& type)
|
|
{
|
|
Token token = lexer_->PeekToken();
|
|
if (token != Token::BRACES_LEFT) {
|
|
lexer_->SkipCurrentLine(';');
|
|
return false;
|
|
}
|
|
lexer_->GetToken();
|
|
|
|
token = lexer_->PeekToken();
|
|
while (token != Token::BRACES_RIGHT) {
|
|
AutoPtr<ASTType> member = ParseType();
|
|
if (member == nullptr) {
|
|
lexer_->SkipCurrentLine(';');
|
|
return false;
|
|
}
|
|
String typeName = member->ToString();
|
|
|
|
token = lexer_->PeekToken();
|
|
if (token != Token::IDENTIFIER) {
|
|
LogError(String("member name is expected."));
|
|
return false;
|
|
}
|
|
String memberName = lexer_->GetIdentifier();
|
|
lexer_->GetToken();
|
|
type->AddMember(member, memberName);
|
|
|
|
token = lexer_->PeekToken();
|
|
if (token == Token::SEMICOLON) {
|
|
lexer_->GetToken();
|
|
token = lexer_->PeekToken();
|
|
} else if (token == Token::BRACES_RIGHT) {
|
|
break;
|
|
} else {
|
|
lexer_->SkipCurrentLine(';');
|
|
return false;
|
|
}
|
|
}
|
|
lexer_->GetToken();
|
|
|
|
token = lexer_->PeekToken();
|
|
if (token != Token::SEMICOLON) {
|
|
LogError(String::Format("'%s' is not expected.", lexer_->DumpToken().string()));
|
|
lexer_->SkipCurrentLine();
|
|
return false;
|
|
}
|
|
lexer_->GetToken();
|
|
return true;
|
|
}
|
|
|
|
bool Parser::ParseUnionDefine(const AutoPtr<Attribute>& attributes)
|
|
{
|
|
lexer_->GetToken();
|
|
|
|
AutoPtr<ASTUnionType> type = new ASTUnionType();
|
|
if (type == nullptr) {
|
|
lexer_->SkipCurrentLine(';');
|
|
return false;
|
|
}
|
|
|
|
Token token = lexer_->PeekToken();
|
|
if (token != Token::IDENTIFIER) {
|
|
LogError(String("custom union type name is expected."));
|
|
return false;
|
|
}
|
|
type->SetName(lexer_->GetIdentifier());
|
|
lexer_->GetToken();
|
|
|
|
if (!ParseUnionMember(type)) {
|
|
return false;
|
|
}
|
|
|
|
if (attributes != nullptr) {
|
|
type->SetFull(attributes->isFull);
|
|
type->SetLite(attributes->isLite);
|
|
}
|
|
|
|
ast_->AddTypeDefinition(type.Get());
|
|
return true;
|
|
}
|
|
|
|
bool Parser::ParseUnionMember(const AutoPtr<ASTUnionType>& type)
|
|
{
|
|
Token token = lexer_->PeekToken();
|
|
if (token != Token::BRACES_LEFT) {
|
|
lexer_->SkipCurrentLine(';');
|
|
return false;
|
|
}
|
|
lexer_->GetToken();
|
|
|
|
token = lexer_->PeekToken();
|
|
while (token != Token::BRACES_RIGHT) {
|
|
AutoPtr<ASTType> member = ParseType();
|
|
if (member == nullptr) {
|
|
lexer_->SkipCurrentLine(';');
|
|
return false;
|
|
}
|
|
String typeName = member->ToString();
|
|
|
|
token = lexer_->PeekToken();
|
|
if (token != Token::IDENTIFIER) {
|
|
LogError(String("member name is expected."));
|
|
return false;
|
|
}
|
|
String memberName = lexer_->GetIdentifier();
|
|
lexer_->GetToken();
|
|
type->AddMember(member, memberName);
|
|
|
|
token = lexer_->PeekToken();
|
|
if (token == Token::SEMICOLON) {
|
|
lexer_->GetToken();
|
|
token = lexer_->PeekToken();
|
|
} else if (token == Token::BRACES_RIGHT) {
|
|
break;
|
|
} else {
|
|
lexer_->SkipCurrentLine(';');
|
|
return false;
|
|
}
|
|
}
|
|
lexer_->GetToken();
|
|
|
|
token = lexer_->PeekToken();
|
|
if (token != Token::SEMICOLON) {
|
|
LogError(String::Format("'%s' is not expected.", lexer_->DumpToken().string()));
|
|
lexer_->SkipCurrentLine();
|
|
return false;
|
|
}
|
|
lexer_->GetToken();
|
|
return true;
|
|
}
|
|
|
|
bool Parser::CheckType(int lineNo, int columnNo, const AutoPtr<ASTType>& type)
|
|
{
|
|
if (type == nullptr) {
|
|
return false;
|
|
}
|
|
|
|
if (options_.GetTargetLanguage().Equals("c")) {
|
|
if (type->IsSequenceableType()) {
|
|
LogError(lineNo, columnNo, String::Format("The sequenceable type is not supported by c language."));
|
|
return false;
|
|
}
|
|
|
|
if (options_.DoGenerateKernelCode()) {
|
|
switch (type->GetTypeKind()) {
|
|
case TypeKind::TYPE_FLOAT:
|
|
case TypeKind::TYPE_DOUBLE:
|
|
case TypeKind::TYPE_FILEDESCRIPTOR:
|
|
case TypeKind::TYPE_INTERFACE:
|
|
LogError(lineNo, columnNo, String::Format("The '%s' type is not supported by c language.",
|
|
lexer_->DumpToken().string()));
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
} else if (options_.GetTargetLanguage().Equals("java")) {
|
|
switch (type->GetTypeKind()) {
|
|
case TypeKind::TYPE_UCHAR:
|
|
case TypeKind::TYPE_USHORT:
|
|
case TypeKind::TYPE_UINT:
|
|
case TypeKind::TYPE_ULONG:
|
|
case TypeKind::TYPE_ENUM:
|
|
case TypeKind::TYPE_STRUCT:
|
|
case TypeKind::TYPE_UNION:
|
|
case TypeKind::TYPE_UNKNOWN:
|
|
LogError(lineNo, columnNo, String::Format("The '%s' type is not supported by java language.",
|
|
lexer_->DumpToken().string()));
|
|
return false;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void Parser::SetAstFileType()
|
|
{
|
|
if (ast_->GetInterfaceDef() != nullptr) {
|
|
if (ast_->GetInterfaceDef()->IsCallback()) {
|
|
ast_->SetAStFileType(ASTFileType::AST_ICALLBACK);
|
|
} else {
|
|
ast_->SetAStFileType(ASTFileType::AST_IFACE);
|
|
}
|
|
} else {
|
|
ast_->SetAStFileType(ASTFileType::AST_TYPES);
|
|
}
|
|
}
|
|
|
|
bool Parser::CheckIntegrity()
|
|
{
|
|
if (ast_ == nullptr) {
|
|
LogError(String("ast is nullptr."));
|
|
return false;
|
|
}
|
|
|
|
if (ast_->GetName().IsEmpty()) {
|
|
LogError(String("ast's name is empty."));
|
|
return false;
|
|
}
|
|
|
|
if (ast_->GetPackageName().IsEmpty()) {
|
|
LogError(String("ast's package name is empty."));
|
|
return false;
|
|
}
|
|
|
|
switch (ast_->GetASTFileType()) {
|
|
case ASTFileType::AST_IFACE: {
|
|
return CheckInterfaceAst();
|
|
}
|
|
case ASTFileType::AST_ICALLBACK: {
|
|
return CheckCallbackAst();
|
|
}
|
|
case ASTFileType::AST_SEQUENCEABLE: {
|
|
LogError(String("it's impossible that ast is sequenceable."));
|
|
return false;
|
|
}
|
|
case ASTFileType::AST_TYPES: {
|
|
if (ast_->GetInterfaceDef() != nullptr) {
|
|
LogError(String("custom ast cannot has interface."));
|
|
return false;
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool Parser::CheckInterfaceAst()
|
|
{
|
|
AutoPtr<ASTInterfaceType> interface = ast_->GetInterfaceDef();
|
|
if (interface == nullptr) {
|
|
LogError(String("ast's interface is empty."));
|
|
return false;
|
|
}
|
|
|
|
if (ast_->GetTypeDefinitionNumber() > 0) {
|
|
LogError(String("interface ast cannot has custom types."));
|
|
return false;
|
|
}
|
|
|
|
if (interface->GetMethodNumber() == 0) {
|
|
LogError(String("interface ast has no method."));
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool Parser::CheckCallbackAst()
|
|
{
|
|
AutoPtr<ASTInterfaceType> interface = ast_->GetInterfaceDef();
|
|
if (interface == nullptr) {
|
|
LogError(String("ast's interface is empty."));
|
|
return false;
|
|
}
|
|
|
|
if (!interface->IsCallback()) {
|
|
LogError(String("ast is callback, but ast's interface is not callback."));
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool Parser::IsValidTypeName(const String& typeName)
|
|
{
|
|
if (typeName[0] == '.') {
|
|
return false;
|
|
}
|
|
|
|
if (typeName[typeName.GetLength() - 1] == '.') {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
* For example
|
|
* filePath: ./ohos/interface/foo/v1_0/IFoo.idl
|
|
* package OHOS.Hdi.foo.v1_0;
|
|
*/
|
|
bool Parser::CheckPackageName(const String& filePath, const String& packageName)
|
|
{
|
|
String pkgToPath = Options::GetInstance().GetPackagePath(packageName);
|
|
|
|
int index = filePath.LastIndexOf(File::pathSeparator);
|
|
if (index == -1) {
|
|
return false;
|
|
}
|
|
|
|
String parentDir = filePath.Substring(0, index);
|
|
if (parentDir.IndexOf(pkgToPath) == -1) {
|
|
return false;
|
|
}
|
|
|
|
return parentDir.EndsWith(pkgToPath);
|
|
}
|
|
|
|
bool Parser::AddAst()
|
|
{
|
|
if (ast_ == nullptr) {
|
|
LogError(String("ast is nullptr."));
|
|
return false;
|
|
}
|
|
astModule_->AddAST(ast_->GetFullName(), ast_);
|
|
return true;
|
|
}
|
|
|
|
void Parser::LogError(const String& message)
|
|
{
|
|
AutoPtr<ErrorInfo> error = new ErrorInfo();
|
|
|
|
String sourceFile = lexer_->GetFilePath();
|
|
#ifdef __MINGW32__
|
|
error->file_ = sourceFile.Substring(sourceFile.LastIndexOf('\\') + 1);
|
|
#else
|
|
error->file_ = sourceFile.Substring(sourceFile.LastIndexOf('/') + 1);
|
|
#endif
|
|
error->lineNo_ = lexer_->GetTokenLineNumber();
|
|
error->columnNo_ = lexer_->GetTokenColumnNumber();
|
|
error->message_ = message;
|
|
|
|
if (errors_ == nullptr) {
|
|
errors_ = error;
|
|
} else {
|
|
AutoPtr<ErrorInfo> pos = errors_;
|
|
while (pos->next_ != nullptr) {
|
|
pos = pos->next_;
|
|
}
|
|
pos->next_ = error;
|
|
}
|
|
}
|
|
|
|
void Parser::LogError(int lineNo, int columnNo, const String& message)
|
|
{
|
|
AutoPtr<ErrorInfo> error = new ErrorInfo();
|
|
|
|
String sourceFile = lexer_->GetFilePath();
|
|
#ifdef __MINGW32__
|
|
error->file_ = sourceFile.Substring(sourceFile.LastIndexOf('\\') + 1);
|
|
#else
|
|
error->file_ = sourceFile.Substring(sourceFile.LastIndexOf('/') + 1);
|
|
#endif
|
|
error->lineNo_ = lineNo;
|
|
error->columnNo_ = columnNo;
|
|
error->message_ = message;
|
|
|
|
if (errors_ == nullptr) {
|
|
errors_ = error;
|
|
} else {
|
|
AutoPtr<ErrorInfo> pos = errors_;
|
|
while (pos->next_ != nullptr) {
|
|
pos = pos->next_;
|
|
}
|
|
pos->next_ = error;
|
|
}
|
|
}
|
|
|
|
void Parser::ShowError()
|
|
{
|
|
AutoPtr<ErrorInfo> error = errors_;
|
|
while (error != nullptr) {
|
|
Logger::E(TAG, "%s[line %d, column %d] %s", error->file_.string(),
|
|
error->lineNo_, error->columnNo_, error->message_.string());
|
|
error = error->next_;
|
|
}
|
|
}
|
|
} // namespace HDI
|
|
} // namespace OHOS
|