词法分析的数据结构看起来如何?

Posted

技术标签:

【中文标题】词法分析的数据结构看起来如何?【英文标题】:How does the data structure for a lexical analysis look? 【发布时间】:2017-03-28 09:24:03 【问题描述】:

我知道词法分析器将输入标记化并将其存储在流中,或者至少这是我所理解的。不幸的是,我读过的几乎所有文章都只谈论对简单表达式进行词法分析。我感兴趣的是如何标记如下内容:

if (fooBar > 5) 
  for (var i = 0; i < alot.length; i++) 
    fooBar += 2 + i;
  

请注意这是伪代码。

问题:我想知道词法分析器创建的标记的数据结构是什么样的?我真的不知道我上面给出的代码嵌套的例子。举个例子就好了。

【问题讨论】:

根据您的需要和目标,您可能根本不需要任何特殊的数据结构。词法分析器需要的所有解析器基本上都是整数序列,其中每个整数对应于特定的标记类型。所以你有一个关键字if 的值,一个左括号的值,等等。互联网上有成千上万的词法分析器示例,其中不少比单个令牌类型的值包含更多信息。试着找到他们,看看他们做了什么。 @Someprogrammerdude 所以我不需要订购令牌?例如:带有表达式的数组等 好吧,如果解析器没有以正确的顺序获取标记,它如何​​解析它?它如何检查错误?也许您可以详细说明“数据结构”的含义?因为至少只需要一个整数值(正如我之前解释的那样)。 @Someprogrammerdude 你是对的 @Someprogrammerdude 所以可能是这样的:var tokensArray = [["identifier", "fooBar"], ["operator", "+="]]; 【参考方案1】:

首先,令牌不一定要存储。一些编译器确实将标记存储在表或其他数据结构中,但对于一个简单的编译器(如果有这样的东西),在大多数情况下,词法分析器可以返回下一个要解析的标记的类型,然后在某些情况下就足够了在这种情况下,解析器可能会向词法分析器询问组成标记的实际文本。

如果我们使用您的示例代码,

if (fooBar > 5) 
  for (var i = 0; i < alot.length; i++) 
    fooBar += 2 + i;
  

此示例中第一个标记的类型可能定义为与“if”关键字对应的 TOK_IF。下一个令牌可能是 TOK_LPAREN,然后是 TOK_IDENT,然后是 TOK_GREATER,然后是 TOK_INT_LITERAL,等等。作为词法分析器(或标记器)代码的作者,您应该定义什么类型。 (请注意,有大约一百万种不同的工具可以帮助您避免手动提出这些细节的繁琐任务。)

除了 TOK_IDENT 和 TOK_INT_LITERAL 之外,我们目前看到的标记完全由它们的类型定义。对于这两个,我们需要能够向词法分析器询问基础文本,以便我们可以评估令牌的值。

因此,处理伪代码中 IF 语句的解析器的一小段摘录可能类似于:

...
  switch(lexer.GetNextTokenType())
  case TOK_IF:
    
      // "if" statement  
      if (lexer.GetNextTokenType() != TOK_LPAREN)
        throw SyntaxError('( expected');
      ParseRelationalExpression(lexer);
      if (lexer.GetNextTokenType() != TOK_RPAREN)
        throw SyntaxError(') expected');
      ...

等等。

如果编译器确实选择实际存储标记以供以后参考,并且某些编译器会这样做,例如为了更有效地回溯,一种方法是使用类似于以下的结构

struct 
  int TokenType;
  char* TokenStart;
  int TokenLength;

这些容器可能是链表或 std::vector(假设 C++)。

【讨论】:

很棒的答案!非常适合像我这样的初学者。你应该得到超过 1 分。我更愿意等待并给你一个赏金。

以上是关于词法分析的数据结构看起来如何?的主要内容,如果未能解决你的问题,请参考以下文章

C词法分析器的Python简单实现

三词法分析

pygments 如何猜测词法分析器?

Postgres数据库词法分析和语法分析源码解析

Postgres数据库词法分析和语法分析源码解析

Postgres数据库词法分析和语法分析源码解析