Lexer 是否应该能够区分 "variable" 中包含的语法标记和实际语法标记
Should a Lexer be able to distinguish between Syntax Tokens contained in a "variable" and actual Syntax Tokens
我正在为一种简单的语言 (Gherkin) 编写词法分析器。
虽然完成了一些词法分析器,但我正在为设计决策而苦苦挣扎。
目前,词法分析器有一个示例和一个单步模式。
这意味着它必须跟踪上下文,我宁愿不这样做。
我想让词法分析器尽可能地笨,这样大部分工作都由解析器完成。
我当前方法的问题是我不知道词法分析器在某些情况下是否应该区分语法和文字。
为了更好地理解,这里是该语言的简要概述。
该语言具有如下语法标记:: < > | @
.
语言可以有变量,写成<Name>
.
该语言有一个示例部分,其中语法标记与测试用例的其余部分不同
一个示例 table 如下所示:
Examples:
| Name | Last Name |
| John | Doe |
用 Gherkin 编写的完整(删除不需要的信息)测试如下所示:
@Fancy-Test
Scenario Outline: User logs in
Given user is on login_view
And user enters <Username> in username_field
And user enters <Password> in password_field
And user answers <Qu|estion>
When user clicks on login_button
Then user is logged in
Examples:
|Username|Password|Qu\|estion|
|JohnDoe11|Test<Pass>@@Word|Who am I|
请注意我如何在第一个示例列中转义 |
。
还要注意密码示例中的所有语法字符。
通过转义 |
字符,我可以在测试的示例部分使用它,而不会将其检测为语法标记。
但是对于行 And user answers <Qu|estion>
中的变量,我不需要也不想转义它。
根据语言规范,示例条目可以包含除 |
之外的任何字符,除非进行转义,因为它标志着列的结尾。
这意味着不应将其他语法字符检测为语法标记。
如果没有两种模式,密码示例中的所有语法字符都将被检测为此类标记。
另一部分测试的情况正好相反。
除非在新行的开头(其中 @
和 :
是语法标记),
只有 <>
应被视为语法的一部分
当前的实现通过提到的两种模式来防止这种情况,这不是最佳解决方案。
因此我的问题是:
词法分析器是否应该将其检测为语法标记,然后由解析器获取,解析器发现这些是文字的实际部分?
或者有上下文是更好的方式。
感谢您的回答。
如果你有两种不同的词法环境,那么你就有两种不同的词法环境。它们需要以不同的方式处理。几乎所有现实世界的编程语言都具有这种复杂性,并且大多数词法生成器都有旨在帮助维持适度词法状态的机制。
问题是弄清楚如何在不同的词汇上下文之间进行转换。正如您所注意到的,这可能需要大量工作,这很丑陋。如果它真的很难看,你可能想重新审视你的语言设计,因为不仅仅是你的解析器必须能够预测哪个词法上下文适用于哪里:任何阅读代码的人也需要理解这一点,以及所有算法中内置的微妙之处。如果你不能用几句话清楚地描述算法,你会给代码阅读者带来相当大的负担。
在 Gherkin 的情况下,在我看来这些表很容易识别:它们以第一个标记为 |
的行开始,大概会继续直到您到达第一个标记为的行不是 |
。所以切换词法上下文应该是非常直接的,特别是因为你的词法分析器可能已经需要知道行尾了。
我正在为一种简单的语言 (Gherkin) 编写词法分析器。
虽然完成了一些词法分析器,但我正在为设计决策而苦苦挣扎。
目前,词法分析器有一个示例和一个单步模式。 这意味着它必须跟踪上下文,我宁愿不这样做。 我想让词法分析器尽可能地笨,这样大部分工作都由解析器完成。
我当前方法的问题是我不知道词法分析器在某些情况下是否应该区分语法和文字。
为了更好地理解,这里是该语言的简要概述。
该语言具有如下语法标记:
: < > | @
.语言可以有变量,写成
<Name>
.该语言有一个示例部分,其中语法标记与测试用例的其余部分不同
一个示例 table 如下所示:
Examples:
| Name | Last Name |
| John | Doe |
用 Gherkin 编写的完整(删除不需要的信息)测试如下所示:
@Fancy-Test
Scenario Outline: User logs in
Given user is on login_view
And user enters <Username> in username_field
And user enters <Password> in password_field
And user answers <Qu|estion>
When user clicks on login_button
Then user is logged in
Examples:
|Username|Password|Qu\|estion|
|JohnDoe11|Test<Pass>@@Word|Who am I|
请注意我如何在第一个示例列中转义 |
。
还要注意密码示例中的所有语法字符。
通过转义 |
字符,我可以在测试的示例部分使用它,而不会将其检测为语法标记。
但是对于行 And user answers <Qu|estion>
中的变量,我不需要也不想转义它。
根据语言规范,示例条目可以包含除 |
之外的任何字符,除非进行转义,因为它标志着列的结尾。
这意味着不应将其他语法字符检测为语法标记。 如果没有两种模式,密码示例中的所有语法字符都将被检测为此类标记。
另一部分测试的情况正好相反。
除非在新行的开头(其中 @
和 :
是语法标记),
只有 <>
应被视为语法的一部分
当前的实现通过提到的两种模式来防止这种情况,这不是最佳解决方案。
因此我的问题是: 词法分析器是否应该将其检测为语法标记,然后由解析器获取,解析器发现这些是文字的实际部分? 或者有上下文是更好的方式。
感谢您的回答。
如果你有两种不同的词法环境,那么你就有两种不同的词法环境。它们需要以不同的方式处理。几乎所有现实世界的编程语言都具有这种复杂性,并且大多数词法生成器都有旨在帮助维持适度词法状态的机制。
问题是弄清楚如何在不同的词汇上下文之间进行转换。正如您所注意到的,这可能需要大量工作,这很丑陋。如果它真的很难看,你可能想重新审视你的语言设计,因为不仅仅是你的解析器必须能够预测哪个词法上下文适用于哪里:任何阅读代码的人也需要理解这一点,以及所有算法中内置的微妙之处。如果你不能用几句话清楚地描述算法,你会给代码阅读者带来相当大的负担。
在 Gherkin 的情况下,在我看来这些表很容易识别:它们以第一个标记为 |
的行开始,大概会继续直到您到达第一个标记为的行不是 |
。所以切换词法上下文应该是非常直接的,特别是因为你的词法分析器可能已经需要知道行尾了。