词法分析器应该区分不同类型的字符串标记吗?
Should lexer distinguish different types of string tokens?
我正在编写一种可以转换为 html 的类似玉石的语言。标签定义如下所示:
section #mainWrapper .container
这转换为:
<section id="mainWrapper" class="container">
词法分析器应该区分 class 和 id 还是应该只吐出带有名称的特殊字符?
换句话说,令牌数组应该是这样的:
[
{type: 'tag', value: 'section'},
{type: 'id', value: 'mainWrapper'},
{type: 'class', value: 'container'}
]
然后解析器将它们组装成一棵树
或者词法分析器应该非常原始,只匹配 return 个字符串,然后解析器负责区分它们?:
[
{type: 'name', value: 'section'},
{type: 'name', value: '#mainWrapper'},
{type: 'name', value: '.container'}
]
根据经验,分词器不应该解析,解析器也不应该分词。
在这个具体案例中,在我看来,每次未经修饰地使用类似名称的标记(例如 section
)都不一定是 tag
。由于其句法上下文,section
更有可能是一个标记。如果标记器尝试将其标记为 tag
,则标记器正在跟踪句法上下文,这意味着它正在解析。
印记 .
和 #
不太明确。您可以将它们视为单字符标记(语法将坚持在其后跟一个名称),或者您可以将它们视为特殊类型字符串的第一个字符。有些事情可能会以某种方式影响您:
印记可以用空格与后面的名字分开吗? (# mainWrapper
)。如果是这样,印记可能是一个标记。
class 或 id 的词法形式与名称不同吗?例如,考虑使用特殊字符。如果您不知道物体前面有什么印记(如果有的话)就无法准确识别该物体,那么最好将其视为单个标记。
还有其他表示 class
名称的方法吗?例如,你如何表示多个classes?我脑海中浮现出一些可能性:
#classA #classB
#(classA classB)
#"classA classB"
class = "classA classB"
如果除第一个选项之外的任何选项都有效,您可能应该将 #
设为一个标记。但是正确处理带引号的字符串可能会产生其他挑战。特别是,它可能需要重新标记字符串文字的内容,这将违反解析器不应标记化的启发式。幸运的是,这些并不是绝对的规则。有时需要重新标记化。但是尽量少。
词法分析和句法分析的分离不应该是一件紧身衣。这是一种代码组织技术,旨在使各个部分更易于编写、理解、调试和记录。通常(但并非总是)这样的情况是,分离使您的语言的用户更容易理解语法,这也很重要。但它并不适用于所有的解析任务,精确的边界是灵活的(但不是多孔的:你可以把边界放在最方便的地方,但一旦放好了,就不要试图从裂缝中塞东西。)
如果您发现这种关注点分离对您的项目来说太困难,您应该重新考虑您的语言设计或尝试无扫描程序解析。
我正在编写一种可以转换为 html 的类似玉石的语言。标签定义如下所示:
section #mainWrapper .container
这转换为:
<section id="mainWrapper" class="container">
词法分析器应该区分 class 和 id 还是应该只吐出带有名称的特殊字符?
换句话说,令牌数组应该是这样的:
[
{type: 'tag', value: 'section'},
{type: 'id', value: 'mainWrapper'},
{type: 'class', value: 'container'}
]
然后解析器将它们组装成一棵树
或者词法分析器应该非常原始,只匹配 return 个字符串,然后解析器负责区分它们?:
[
{type: 'name', value: 'section'},
{type: 'name', value: '#mainWrapper'},
{type: 'name', value: '.container'}
]
根据经验,分词器不应该解析,解析器也不应该分词。
在这个具体案例中,在我看来,每次未经修饰地使用类似名称的标记(例如 section
)都不一定是 tag
。由于其句法上下文,section
更有可能是一个标记。如果标记器尝试将其标记为 tag
,则标记器正在跟踪句法上下文,这意味着它正在解析。
印记 .
和 #
不太明确。您可以将它们视为单字符标记(语法将坚持在其后跟一个名称),或者您可以将它们视为特殊类型字符串的第一个字符。有些事情可能会以某种方式影响您:
印记可以用空格与后面的名字分开吗? (
# mainWrapper
)。如果是这样,印记可能是一个标记。class 或 id 的词法形式与名称不同吗?例如,考虑使用特殊字符。如果您不知道物体前面有什么印记(如果有的话)就无法准确识别该物体,那么最好将其视为单个标记。
还有其他表示
class
名称的方法吗?例如,你如何表示多个classes?我脑海中浮现出一些可能性:#classA #classB #(classA classB) #"classA classB" class = "classA classB"
如果除第一个选项之外的任何选项都有效,您可能应该将
#
设为一个标记。但是正确处理带引号的字符串可能会产生其他挑战。特别是,它可能需要重新标记字符串文字的内容,这将违反解析器不应标记化的启发式。幸运的是,这些并不是绝对的规则。有时需要重新标记化。但是尽量少。
词法分析和句法分析的分离不应该是一件紧身衣。这是一种代码组织技术,旨在使各个部分更易于编写、理解、调试和记录。通常(但并非总是)这样的情况是,分离使您的语言的用户更容易理解语法,这也很重要。但它并不适用于所有的解析任务,精确的边界是灵活的(但不是多孔的:你可以把边界放在最方便的地方,但一旦放好了,就不要试图从裂缝中塞东西。)
如果您发现这种关注点分离对您的项目来说太困难,您应该重新考虑您的语言设计或尝试无扫描程序解析。