Files
yue 07527c9d69 add hdi-gen tool
Signed-off-by: yue <yueyan4@huawei.com>
2021-09-06 10:58:39 +08:00

337 lines
9.5 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/lexer.h"
#include <utility>
#include "util/string_builder.h"
namespace OHOS {
namespace HDI {
Lexer::Lexer()
{
InitializeKeywords();
}
Lexer::~Lexer()
{
if (currentFile_ != nullptr) {
currentFile_->Close();
}
}
void Lexer::InitializeKeywords()
{
keywords_ = {
{ "boolean", Token::BOOLEAN }, { "byte", Token::BYTE }, { "callback", Token::CALLBACK },
{ "char", Token::CHAR}, { "double", Token::DOUBLE }, { "enum", Token::ENUM },
{ "extends", Token::EXTENDS }, { "float", Token::FLOAT }, { "full", Token::FULL },
{ "import", Token::IMPORT }, { "in", Token::IN }, { "int", Token::INTEGER }, { "interface", Token::INTERFACE },
{ "List", Token::LIST }, { "lite", Token::LITE }, { "long", Token::LONG },
{ "Map", Token::MAP }, { "oneway", Token::ONEWAY }, { "out", Token::OUT },
{ "package", Token::PACKAGE}, { "sequenceable", Token::SEQUENCEABLE }, { "short", Token::SHORT },
{ "String", Token::STRING }, { "struct", Token::STRUCT }, { "union", Token::UNION },
{ "unsigned", Token::UNSIGNED }, { "FileDescriptor", Token::FILEDESCRIPTOR }
};
delimiters_ = {
{'<', Token::ANGLE_BRACKETS_LEFT}, {'>', Token::ANGLE_BRACKETS_RIGHT},
{'{', Token::BRACES_LEFT}, {'}', Token::BRACES_RIGHT},
{'[', Token::BRACKETS_LEFT}, {']', Token::BRACKETS_RIGHT},
{',', Token::COMMA}, {'(', Token::PARENTHESES_LEFT},
{')', Token::PARENTHESES_RIGHT}, {'.', Token::DOT},
{':', Token::COLON}, {';', Token::SEMICOLON},
{'=', Token::ASSIGN}
};
tokenDumps_ = {
{ Token::ANGLE_BRACKETS_LEFT, "<" }, { Token::ANGLE_BRACKETS_RIGHT, ">"}, { Token::BOOLEAN, "boolean"},
{ Token::BRACES_LEFT, "{"}, { Token::BRACES_RIGHT, "}"}, { Token::BRACKETS_LEFT, "["},
{ Token::BRACKETS_RIGHT, "]"}, { Token::BYTE, "byte"}, { Token::CALLBACK, "callback"},
{ Token::CHAR, "char"}, { Token::COLON, ":"}, { Token::COMMA, ","},
{ Token::DOT, "."}, { Token::DOUBLE, "double"}, { Token::END_OF_FILE, "eof"},
{ Token::ENUM, "enum"}, { Token::EXTENDS, "extends"}, { Token::FLOAT, "float"},
{ Token::FULL, "full"}, { Token::IMPORT, "import"}, { Token::IN, "in"},
{ Token::INTEGER, "int"}, { Token::INTERFACE, "interface"}, { Token::LITE, "lite"},
{ Token::LIST, "List"}, { Token::LONG, "long"}, { Token::MAP, "Map"},
{ Token::ONEWAY, "oneway"}, { Token::OUT, "out"}, { Token::PACKAGE, "package"},
{ Token::SEQUENCEABLE, "sequenceable"}, { Token::STRUCT, "struct"}, { Token::PARENTHESES_LEFT, "("},
{ Token::PARENTHESES_RIGHT, ")"}, { Token::SEMICOLON, ";"}, { Token::SHORT, "short"},
{ Token::STRING, "String"}, { Token::UNION, "union"}, { Token::UNSIGNED, "unsigned"},
{ Token::FILEDESCRIPTOR, "FileDescriptor"}
};
}
bool Lexer::OpenSourceFile(const String& filePath)
{
currentFile_ = std::make_unique<File>(filePath, int(File::READ));
if (!currentFile_->IsValid()) {
return false;
}
return true;
}
Token Lexer::GetToken(bool skipComment)
{
if (!havePeek_) {
currentToken_ = ReadToken(skipComment);
}
havePeek_ = false;
return currentToken_;
}
Token Lexer::PeekToken(bool skipComment)
{
if (!havePeek_) {
currentToken_ = ReadToken(skipComment);
havePeek_ = true;
}
return currentToken_;
}
Token Lexer::ReadToken(bool skipComment)
{
while (!currentFile_->IsEof()) {
char c = currentFile_->GetChar();
tokenLineNo_ = currentFile_->GetCharLineNumber();
tokenColumnNo_ = currentFile_->GetCharColumnNumber();
if (IsSpace(c)) {
continue;
} else if (IsAlphabet(c) || c == '_') {
Token t = ReadIdentifier(c);
return t;
} else if (IsDecimalDigital(c)) {
Token t = ReadDecimalDigital(c);
return t;
}
auto iter = delimiters_.find(c);
if (iter != delimiters_.end()) {
return iter->second;
}
if (c == '/') {
if (currentFile_->PeekChar() == '/') {
ReadLineComment(c);
if (!skipComment) {
return currentToken_;
}
continue;
} else if (currentFile_->PeekChar() == '*') {
ReadBlockComment(c);
if (!skipComment) {
return currentToken_;
}
continue;
}
currentToken_ = Token::UNKNOWN;
return currentToken_;
}
currentToken_ = Token::UNKNOWN;
return currentToken_;
}
currentToken_ = Token::END_OF_FILE;
return currentToken_;
}
Token Lexer::ReadIdentifier(char c)
{
StringBuilder sb;
sb.Append(c);
while (!currentFile_->IsEof()) {
c = currentFile_->PeekChar();
if (IsAlphabet(c) || c == '_' || IsDecimalDigital(c) || c == '.') {
c = currentFile_->GetChar();
sb.Append(c);
continue;
}
if (IsSpace(c)) {
currentFile_->GetChar();
}
break;
}
String key = sb.ToString();
auto it = keywords_.find(key);
if (it == keywords_.end()) {
identifier_ = key;
currentToken_ = Token::IDENTIFIER;
} else {
currentToken_ = it->second;
}
return currentToken_;
}
Token Lexer::ReadDecimalDigital(char c)
{
StringBuilder sb;
sb.Append(c);
while (!currentFile_->IsEof()) {
c = currentFile_->PeekChar();
if (IsDecimalDigital(c)) {
c = currentFile_->GetChar();
sb.Append(c);
continue;
} else {
break;
}
}
digit_ = sb.ToString();
currentToken_ = Token::DIGIT;
return currentToken_;
}
Token Lexer::ReadLineComment(char c)
{
StringBuilder sb;
sb.Append(c);
while (!currentFile_->IsEof()) {
c = currentFile_->GetChar();
if (c == '\n') {
break;
}
sb.Append(c);
}
comment_ = sb.ToString();
currentToken_ = Token::COMMENT_LINE;
return currentToken_;
}
Token Lexer::ReadBlockComment(char c)
{
StringBuilder sb;
sb.Append(c);
while (!currentFile_->IsEof()) {
c = currentFile_->GetChar();
sb.Append(c);
if (c == '*' && currentFile_->PeekChar() == '/') {
c = currentFile_->GetChar();
sb.Append(c);
break;
}
}
comment_ = sb.ToString();
currentToken_ = Token::COMMENT_BLOCK;
return currentToken_;
}
void Lexer::SkipCurrentLine()
{
while (!currentFile_->IsEof()) {
char c = currentFile_->GetChar();
if (c == '\n') {
currentFile_->GetChar();
return;
}
}
}
bool Lexer::SkipCurrentLine(char untilChar)
{
while (!currentFile_->IsEof()) {
int c = currentFile_->GetChar();
if (c == untilChar) {
return true;
}
if (c == '\n') {
currentFile_->GetChar();
return false;
}
}
return true;
}
void Lexer::Skip(char untilChar)
{
while (!currentFile_->IsEof()) {
int c = currentFile_->GetChar();
if (c == untilChar) {
return;
}
}
}
void Lexer::SkipEof()
{
while (!currentFile_->IsEof()) {}
}
int Lexer::TokenToChar(Token token)
{
switch (token) {
case Token::ANGLE_BRACKETS_LEFT:
return '<';
case Token::ANGLE_BRACKETS_RIGHT:
return '>';
case Token::BRACES_LEFT:
return '{';
case Token::BRACES_RIGHT:
return '}';
case Token::BRACKETS_LEFT:
return '[';
case Token::BRACKETS_RIGHT:
return ']';
case Token::COMMA:
return ',';
case Token::DOT:
return '.';
case Token::PARENTHESES_LEFT:
return '(';
case Token::PARENTHESES_RIGHT:
return ')';
case Token::COLON:
return ':';
case Token::SEMICOLON:
return ';';
case Token::BOOLEAN:
case Token::BYTE:
case Token::CHAR:
case Token::COMMENT_BLOCK:
case Token::COMMENT_LINE:
case Token::DOUBLE:
case Token::END_OF_FILE:
case Token::FLOAT:
case Token::IDENTIFIER:
case Token::IN:
case Token::INTEGER:
case Token::LIST:
case Token::LONG:
case Token::MAP:
case Token::ONEWAY:
case Token::OUT:
case Token::SEQUENCEABLE:
case Token::SHORT:
case Token::STRING:
default:
return -1;
}
}
String Lexer::DumpToken() const
{
auto iter = tokenDumps_.find(currentToken_);
if (iter != tokenDumps_.end()) {
return iter->second;
}
if (currentToken_ == Token::COMMENT_BLOCK || currentToken_ == Token::COMMENT_LINE) {
return comment_;
}
if (currentToken_ == Token::IDENTIFIER) {
return identifier_;
}
return "unknown token";
}
} // namespace HDI
} // namespace OHOS