【问题标题】:Parsing array-in-struct references解析结构中的数组引用
【发布时间】:2014-11-05 02:05:35
【问题描述】:

我正在使用第三方解析器来开发具有数组和结构的编程语言。假设 Str 是一个结构体类型变量,其中包含一个名为 A 的数组,而 I 是一个整数变量,对于如下表达式:

Str.A[I]

解析器生成以下表达式树(伪代码):

StructMember
(
    Left = "Str"
    Right = ArraySubscript
    (
        Left = "A"
        Right = "I"
    )
)

我期待别的东西:

ArraySubscript
(
    Left = StructMember
    (
        Left = "Str"
        Right = "A"
    )
    Right = "I"
)

因为在执行或生成代码时,首先解析结构成员,然后执行下标。

从理论的角度来看,首先评估的操作不应该在语法树中比接下来评估的操作更深吗?换句话说,这种行为是否应该被视为解析器中的错误?

编辑 rici:如果 StrA 是一个结构数组,这是我得到的树:

StructMember
(
    Left = ArraySubscript
    (
        Left = "StrA"
        Right = "I"
    )
    Right = ArraySubscript
    (
        Left = "A"
        Right = "I"
    )
)

那是表达式StrA[I].A[I]。

EDIT2:对于表达式 S.A[I].T,这是我得到的:

StructMember
(
    Left = "S"
    Right = StructMember
    (
        Left = ArraySubscript
        (
            Left = "A"
            Right = "I"
        )
        Right = "T"
     )
 )

从执行顺序的角度来看,这也没有多大意义。

【问题讨论】:

  • 您的语言是否允许您将Foo.(X+Y) 之类的东西写成Foo.X + Foo.Y 的快捷方式?
  • 我也觉得有点奇怪,但是没有真正的 AST 理论。有时,解析要求(特别是在使用 LL 语法时)会迫使您进入一个与您不完全一样的语法,然后需要在后续通道中调整 AST。只是出于好奇,如果 A 是一个结构数组,那么 S.A[I].T 会得到什么?
  • @sepp2k:据我所知不是。
  • 对我来说,您的“我期待”的假设是错误的。 AST 应该按照输入语言的语法来捕获语言输入,抽象掉标点符号、空格等。代码生成、表达式评估等通常发生在后期阶段,使用它们自己的数据结构(由 AST 构建)。因此,我认为这不是解析器错误,因为您对 AST 目的的假设是不正确的。顺便说一句:如果不指定语言,您的问题就不清楚,不能像@rici 指出的那样回答“没有真正的 AST 理论”
  • 关于你的编辑:你得到那棵树的表达是什么?我不认为你输入了 rici 询问的相同表达方式。如果你输入的表达式真的包含两个.s,那么你得到的树是完全错误的。

标签: parsing compiler-construction abstract-syntax-tree


【解决方案1】:

考虑一下我们可能需要哪些简单的信息可能会有所帮助,例如:

X[i]

在这里,我希望解析树看起来像:

ArraySubscript ( Left = "X" Right = "i" )

因此,对于数组,您完全需要属性 Left 和 Right。 而对于对结构成员的引用,我希望左侧引用结构,而分析树的右侧引用结构属性。例如,如果 struct 属性是一个简单类型(例如整数),那么 StructMember 可能看起来像这样:

StructMember ( Left = "Str" Right = "simple" )

引用类似的东西:

Str.simple

您看到的结果与如何考虑每个属性的简单分解是一致的。

【讨论】:

  • 我不相信。您的原始示例无可挑剔,但对于我的具体情况,有两个看似可行的选项 - 顶部的下标与顶部的 structmember。问题是——理论认为哪一个是正确的。任一元素中的 Left 和 Right 都可以是表达式。
  • 看,A[I] 不是结构成员。 A 是。
  • 啊。我理解你的问题。您的问题的答案最终将通过操作顺序和您的绑定规则来解决。如果您将更高的操作优先级放在解析结构属性成员资格上,您将得到您的结果。或者,如果你从右到左解决,你会得到你的结果。如果您从左到右解析或在数组引用上放置更高的操作优先级,您将得到您看到的结果。这真的是语法如何定义的问题。
  • 除了从左到右之外,没有其他方法可以解析这样的表达式。 A 只存在于结构范围内;没办法先解析A[I],再看Str。执行顺序是明确的。
  • @SevaAlekseyev 这不是这里“操作顺序”的意思。该术语通常用于指代优先级。例如在a + b * c 中,操作顺序告诉我们它等价于a + (b * c) 而不是(a + b) * c - 它没有告诉我们评估abc 的顺序。如果. 运算符将表达式作为其右操作数(这将是非常不寻常的),那么理论上操作顺序可以表明Str.A[i]Str.(A[i]) 相同,并且其语义仍然可能是.. .
【解决方案2】:

在大多数语言中,成员访问运算符的右操作数是标识符,而不是表达式。其语法如下所示:

expression ::=
    ...
    | expression '.' identifier

在这种情况下,您得到的 AST 不符合语法。事实上,StructMember 节点的 right 成员甚至不应该有 expression 类型,而是类型 string(或任何你用来表示标识符的)。

你得到的树将等同于Str.(A[I]),根据该语法,这甚至不是有效的语法。

理论上你的语言语法可能是这样的:

expression ::=
    ...
    | expression '.' expression

如果是这种情况,Str.(A[I]) 将是有效的语法,如果. 的优先级低于数组下标的优先级,Str.A[I] 确实会被解析为Str.(A[I]),从而使您得到的树是正确的。这将是非常不寻常的,您在评论中说,据您所知,情况并非如此。

所以我们必须假设你的语言的语法看起来像我展示的第一个语法,你的解析器要么有问题,要么不打算给出与语法完全匹配的树。

【讨论】:

  • 树是否匹配形式语法是解析器错误的真正衡量标准。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-05-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-11-05
  • 2016-05-25
  • 1970-01-01
相关资源
最近更新 更多