Parsing Lexer和解析器之间的边界

Parsing Lexer和解析器之间的边界,parsing,lexer,compiler-construction,Parsing,Lexer,Compiler Construction,我正在做一个pet项目,我必须实现一个lexer/解析器。我正在阅读关于这个主题的文章,并在阅读过程中创建了一个简单的数学解析器 有一点我仍然不太明白,那就是词法分析器和语法分析器之间的界限。考虑下面的句法错误表达: +1.234.2 + pi 我目前正在将其分解为以下内容: UnaryPlusOperatorToken: Lexeme "+" Pos: 1 NumberToken: Lexeme "1.234.2" Pos: 2 TriviaToken: Lexeme " " Pos: 9

我正在做一个pet项目,我必须实现一个lexer/解析器。我正在阅读关于这个主题的文章,并在阅读过程中创建了一个简单的数学解析器

有一点我仍然不太明白,那就是词法分析器和语法分析器之间的界限。考虑下面的句法错误表达:

+1.234.2 + pi
我目前正在将其分解为以下内容:

UnaryPlusOperatorToken: Lexeme "+" Pos: 1
NumberToken: Lexeme "1.234.2" Pos: 2
TriviaToken: Lexeme " " Pos: 9
BinaryAddToken: Lexeme "+" Pos: 10
TriviaToken: Lexeme " " Pos: 11
ConstantToken. Lexeme "pi" Pos: 12
好的,这里有几件事:

  • 词法分析器真的应该关心
    NumberToken
    中错误的额外小数点,并在我正在处理整个解析上下文的“错误包”中添加一个错误,还是应该是解析器稍后捕捉到这个错误
  • lexer应该区分“+”在一个上下文中是一元运算符还是在另一个上下文中是二元运算符?或者它应该简单地生成一个
    PlusToken
    ,然后让解析器知道它是什么
  • 我发现很难理解两者之间的界限在哪里

    以下是我的看法:

    词法分析器真的应该关心NumberToken中错误的额外小数点,并将错误添加到我正在遍历整个解析上下文的“错误包”中,还是应该是解析器稍后捕捉到这个错误

    让我们看看你的选择是什么,并比较利弊:

    • 如果在第二个小数点处停止扫描,解析器将获得以下两个令牌:
      1.234
      .2
      ,并且必须发出类似“意外令牌”的错误

    • 如果lexer将
      1.234.2
      作为单个令牌进行扫描,您将很容易发出类似“无效数字”的错误

    第二种选择将发出更好的错误消息,并且与第一种选择一样易于实现,因此我认为这是更好的解决方案。您这里有一个无效的令牌,请将其视为无效令牌

    lexer应该区分“+”在一个上下文中是一元运算符还是在另一个上下文中是二元运算符?或者它应该简单地生成一个PlusToken,然后让解析器知道它是什么

    没有。lexer应该只输出一个
    +
    令牌。解析器的角色是在解析器规则的上下文中进一步解释该标记的含义



    词法分析器和语法分析器之间的界限有时是相当模糊的。虽然有些顾虑很容易在任何一方都不会产生任何问题,但如果你打错了电话,其他顾虑稍后会咬到你,因此在进行设计选择时,值得格外小心。

    IMHO 1。NumberToken应为“1.234”,后跟“InvalidToken:
    ”2。解释是解析器的工作。谢谢!那么,我是否应该理解lexer根本不应该向解析上下文添加错误,而让解析器稍后再做这项工作呢?lexer当然可以发出错误,但这些错误大多属于“格式错误的令牌”类型。像“这个令牌不属于这里”这样的错误最好留给解析器来处理。但这要视情况而定。例如,假设您想要禁止像
    4--2
    这样的表达式(而不是像
    4-(-2)
    那样解析它们),直接从lexer处理令牌序列
    -
    -可能更容易,但这取决于您的实现。