什么是词法分析器的工作?

3
最初的回答:
我正在编写一个Markdown解析器。在这个过程中,我意识到我并没有完全理解它的核心职责。
最常见的词法分析器定义是将输入流中的字符转换为输出流中的令牌。
Input         →  Output 
(characters)     (tokens)

一开始听起来很简单,但在此产生的问题是词法分析器在将其令牌输出交给解析器之前应该进行多少语义解释


拿Markdown语法举例:

### Headline
*This* is an emphasized word.

这可能会被词法分析器翻译成以下一系列标记:

词法分析器1的输出

.headline("Headline")
.emphasis("This")
.text"(" is an emphasized word.")

但是根据语法(或词素集)的不同,它也可以更细致地进行翻译:

Lexer 2 输出

.controlSymbol("#")
.controlSymbol("#")
.controlSymbol("#")
.text(" Headline")
.controlSymbol("*")
.text("This")
.controlSymbol("*")
.text"(" is an emphasized word.")

似乎让词法分析器生成类似于 Lexer 1 的输出更加实用,因为解析器将更容易处理。但这也意味着词法分析器需要在语义上理解代码的含义。它不仅仅是将一系列字符映射到标记上。它需要向前查看并识别模式。(例如,它需要能够区分** Hey * you *** Hey ** you。它不能简单地将双星号**翻译成.openingEmphasis,因为那取决于后面的上下文。)
根据此Stackoverflow帖子CommonMark定义,似乎先将Markdown输入拆分为多个块(表示一个或多个行),然后在第二步中分析每个块的内容是有意义的。对于上面的示例,这意味着以下内容:
.headlineBlock("Headline")
.paragraphBlock("*This* is an emphasized word.")

最初的回答:
这不能算作有效的标记序列,因为其中一些词元("*")尚未被解析,将此paragraphBlock传递给解析器是错误的。
所以我的问题是:
你会在哪里划线呢?
词法分析器应该做多少语义工作?在词法分析器的定义中是否有一些硬性的限制我不知道?
为词法分析器定义文法的最佳方法是什么?

词法分析器应该进行多少语义解释:没有。零。无。Nulla. Rien. - user207421
所以你的意思是,即使词法分析器在编程语言的源代码中读取到一个开括号 (,它也应该始终返回 .openingParenthesis,而不管它是否是字符串/注释的一部分?因为这已经是一种语义解释,用于区分在代码中具有含义和没有含义的括号。它已经在说:“这个括号与那个括号的含义不同。” 即使词法分析器不知道 什么 是含义,它也知道有两个不同的含义,并且需要区分它们。 - Mischa
是的,这正是我所说的。解析器负责解析,而不是词法分析器。扫描仪处理正则语言,解析器处理上下文无关语言。注意:这是语法,而不是语义。注意2:由扫描仪删除注释,而不以任何方式将它们返回给oarssrparser。你的语言定义到目前为止可能存在歧义。 - user207421
@user207421 注释和字符串字面量被识别为单个标记,因此由于标记不能在其他标记内部,括号 ( 不会成为注释或字符串字面量的一部分。我所见过的任何词法分析器都不会将注释和字符串字面量的处理委托给解析器。 - sepp2k
2
如果你选择了第一种方式,那么### Head *line*的结果应该是什么呢?.headline(.text("Head"), .emphasis("line"))?那么你的词法分析器将会生成一棵树,因此实际上它就是一个解析器(当然,你也可以决定像Markdown这样简单的东西不需要词法分析器,而直接编写无词法分析器的解析器)。通常,任何可以嵌套的内容都不能成为单个标记。因此,词法分析器的结果更像是你的第二个版本(尽管我个人会将###视为单个标记)。 - sepp2k
1个回答

0

BNF 用于描述许多语言/创建词法分析器和语法分析器。

大多数情况下使用 Look right 1 来定义一个明确的格式。

最近我在研究 SQL BNF,链接如下: https://github.com/ronsavage/SQL/blob/master/sql-92.bnf

我决定我的词法分析器只返回终端令牌字符串,类似于您的选项 1。

  • '('
  • ')'
  • '关键字'
  • '-- 注释 eol'
  • '12.34'
  • ...

任何定义语法树的规则都留给语法分析器处理。

  • <Document> := <lines>
  • <Lines> := <line> [<Lines>]
  • <line> := ...

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接