词法分析器是否应该区分不同类型的字符串标记?

时间:2018-12-05 17:02:07

标签: html parsing token lexer transpiler

我正在写一种类似玉的语言,可以转换为html。标签定义如下:

section #mainWrapper .container

此代码将转换为:

<section id="mainWrapper" class="container">

词法分析器应该区分类和id还是只吐出带有名称的特殊字符?

换句话说,令牌数组应如下所示:

[
    {type: 'tag', value: 'section'},
    {type: 'id', value: 'mainWrapper'},
    {type: 'class', value: 'container'}
]

然后解析器将它们组装成树

还是词法分析器应该是非常原始的并且仅返回匹配的字符串,然后解析器负责区分它们?:

[
    {type: 'name', value: 'section'},
    {type: 'name', value: '#mainWrapper'},
    {type: 'name', value: '.container'}
]

1 个答案:

答案 0 :(得分:1)

根据经验,令牌解析器不应解析,而解析器不应令牌化。

在这种具体情况下,在我看来,像section这样的类似名称的标记的任何未经修饰的使用都不一定一定是tagsection更有可能是一个标记,因为它的语法上下文。如果令牌发布者尝试将其标记为tag,则令牌发布者正在跟踪语法上下文,这意味着它正在解析。

信号.#不太清晰。您可以将它们视为单字符标记(语法将坚持使用名称),或者可以将它们视为特殊字符串类型的第一个字符。有些事情可能会以一种或另一种方式影响您:

  • 可以使用空格将符号与以下名称分隔吗? (# mainWrapper)。如果是这样,则该印记可能是令牌。

  • 类或id的词法形式与名称不同吗?例如,考虑使用特殊字符。如果您不知道对象之前没有任何标记,就无法准确识别该对象,那么最好将其视为单个标记。

  • 还有其他表示class名称的方法。例如,您如何表示多个类?我脑海中浮现出一些可能性:

    #classA #classB
    #(classA classB)
    #"classA classB"
    class = "classA classB"
    

    如果第一个选项以外的任何其他选项均有效,则可能应该将#设为令牌。但是正确处理带引号的字符串可能会带来其他挑战。特别是,它可能需要重新标记字符串文字的内容,这违反了解析器不应标记化的启发式方法。幸运的是,这些不是绝对的规则。有时需要重新标记。但是请尽量减少。

将词汇和句法分析分开不应成为束手无策。这是一种代码组织技术,旨在使各个部分更易于编写,理解,调试和记录。经常(但并非总是)这种分隔使您的语言用户更容易理解语法,这也很重要。但这并不适合每个解析任务,并且精确的边界是灵活的(但不是多孔的:您可以将边界放在最方便的位置,但是一旦放置,就不要试图通过裂缝推动事物了。)

如果您发现这样的关注点分离对您的项目来说太困难了,您应该重新考虑您的语言设计或尝试进行无扫描仪的解析。