如何将令牌类及其相关信息从词法分析器传递到预处理器,然后传递给解析器

时间:2017-02-04 14:35:14

标签: c++ parsing lexer

我尝试实现一个简单的C / C ++解析器,它尝试部分解析C ++语言。所以我需要创建一个Lexer,一个预处理器和一个Parser类。

我正在考虑从这三层传递信息所需的数据类型是什么。通常,这里需要一个Token类,现在,我的Token类如下所示:

struct Token 
{
    TokenKind id; 
    std::string lexeme; 
    int fileIndex;
    int line; 
    int column;
}

我认为最重要的部分是TokenKind(它可以是IDENTIFIERCLASS_KEYWORD或任何其他标点符号,如LPAREN),有时候,词汇也很重要,因为它通常包含类型名称或变量名称信息。

我查看了一些关于如何将令牌传递给Parsers的实现。

1,我看到Clang在其预处理器类中有一些函数,如Preprocessor.cpp:739

void Preprocessor::Lex(Token &Result) 

你看,引用是作为函数参数传递的,函数用结果填充对象,请参阅这里的Clang教程的另一个参考:Clang-tutorial/CItutorial3.cpp at master · loarabia/Clang-tutorial,这里是实例tok在循环中重复使用。

Token tok;
do {
    ci.getPreprocessor().Lex(tok);
    if( ci.getDiagnostics().hasErrorOccurred())
        break;
    ci.getPreprocessor().DumpToken(tok);
    std::cerr << std::endl;
} while ( tok.isNot(clang::tok::eof));

2,对于某些词法分析器生成器,我看到函数yylex()只返回一个int类型,实际上是一个TokenKind,以及其他信息,如实际的lexeme string存储在全局变量中,如yylval

3,对于GCC A tiny GCC front end – Part 3 | Think In Geek的小语言,我看到Lexer返回std::shared_ptr<Token>,即:

  static TokenPtr
  make_identifier (location_t locus, const std::string& str)
  {
    return TokenPtr(new Token (IDENTIFIER, locus, str));
  }

Lexer将令牌对象的智能指针TokenPtr返回给Parser,因此整个令牌将返回到Parser。

4, GCC的cpp库有一些cpp_get_token()函数的接口,如下所示:

const cpp_token *token = cpp_get_token (pfile);

然后token->type就像TokenKind字段一样。

所以,我的问题是:这些实现的优点和缺点是什么。上面提到的一些方法甚至没有预处理层,对我来说,我需要三层(词法分析器,预处理器和解析器)。

请注意,我的解析器不会像clangGCC的解析器那么大。我的主要想法是我的解析器只能解析非常有限的C ++语言部分,我想把它们全部用手写。

编辑类似的问题在这里What should be the datatype of the tokens a lexer returns to its parser?,我也在几天前在那里发表了一些评论,但这个问题不涉及三层。

0 个答案:

没有答案