解析成员表达式的语法
Parse grammar for a member expression
标准成员表达式的正确语法是什么?
例如代码中的 ast:
test.test.function()
会是
MemberExpression("test", MemberExpression("test", MethodCall("function")))
同样对于变量:
test.test.test.variable
MemberExpression("test", MemberExpression("test", MemberExpression("test", Variable("variable"))))
当然取决于语言 :-) 但在大多数语法中它是非常直接的(见下文)。
尽管如此,请发表评论。正如下面的语法所示,成员访问(如函数调用,通常还有下标)就像一个后缀运算符;点(或箭头,在类 C 语言中)之后的符号是表示成员名称的符号。这不是一个表达;成员查找中的唯一表达式位于运算符的左侧。所以 a.b.c
应该对应于一个类似这样的 AST 节点:
MemberLookup(MemberLookup(Variable("a"), "b"), "c")
和a.b.func(2, c)
应该变成:
MethodCall(MemberLookup(Variable("a"), "b"),
"func",
List(Number(2), Variable("c")))
或者,也许,
Apply(MemberLookup(MemberLookup(Variable("a"), "b"), "func"),
List(Number(2), Variable("c"))
(区别与隐含的 self
/this
参数有关;有多种策略可以处理这个问题。对比 Java、Python 和 Lua 三种完全不同的策略。)
无论如何,这里有几个简单的语法片段:
C
这里是 C 语法的摘录(在 C 标准的附录 A 中找到:
<pre>
<i>postfix-expression</i>:
<i>primary-expression</i>
<i>postfix-expression</i> <b>'['</b> <i>expression</i> ']'
<i>postfix-expression</i> <b>'('</b> <i>argument-expression-list<sub>opt</sub></i> '<b>)</b>'
<i>postfix-expression</i> <b>'.'</b> <i>identifier</i>
<i>postfix-expression</i> <b>'->'</b> <i>identifier</i>
<i>postfix-expression</i> <b>'++'</b>
<i>postfix-expression</i> <b>'--'</b>
</pre>
我包含的不仅仅是成员访问函数,因为它表明 .identifier
和 ->identifier
的处理方式与任何其他后缀运算符一样,这是一个有用的见解。同样的产生式还包括两个后缀括号运算符,下标 ([...]
) 和函数调用 ((...)
),它们在这里似乎是相关的。但我遗漏了复合文字(我会把它放入 primary-expression
)。
Python
Python 3.9 文档的可比较摘录:
<pre>
<i>primary</i>:
<i>primary</i> '<b>.</b>' <i>NAME</i>
<i>primary</i> '<b>(</b>' [<i>arguments</i>] '<b>)</b>'
<i>primary</i> '<b>[</b>' <i>slices</i> '<b>]</b>'
<i>primary</i> <i>genexp</i>
<i>atom</i>
</pre>
标准成员表达式的正确语法是什么?
例如代码中的 ast:
test.test.function()
会是
MemberExpression("test", MemberExpression("test", MethodCall("function")))
同样对于变量:
test.test.test.variable
MemberExpression("test", MemberExpression("test", MemberExpression("test", Variable("variable"))))
当然取决于语言 :-) 但在大多数语法中它是非常直接的(见下文)。
尽管如此,请发表评论。正如下面的语法所示,成员访问(如函数调用,通常还有下标)就像一个后缀运算符;点(或箭头,在类 C 语言中)之后的符号是表示成员名称的符号。这不是一个表达;成员查找中的唯一表达式位于运算符的左侧。所以 a.b.c
应该对应于一个类似这样的 AST 节点:
MemberLookup(MemberLookup(Variable("a"), "b"), "c")
和a.b.func(2, c)
应该变成:
MethodCall(MemberLookup(Variable("a"), "b"),
"func",
List(Number(2), Variable("c")))
或者,也许,
Apply(MemberLookup(MemberLookup(Variable("a"), "b"), "func"),
List(Number(2), Variable("c"))
(区别与隐含的 self
/this
参数有关;有多种策略可以处理这个问题。对比 Java、Python 和 Lua 三种完全不同的策略。)
无论如何,这里有几个简单的语法片段:
C
这里是 C 语法的摘录(在 C 标准的附录 A 中找到:
<pre>
<i>postfix-expression</i>:
<i>primary-expression</i>
<i>postfix-expression</i> <b>'['</b> <i>expression</i> ']'
<i>postfix-expression</i> <b>'('</b> <i>argument-expression-list<sub>opt</sub></i> '<b>)</b>'
<i>postfix-expression</i> <b>'.'</b> <i>identifier</i>
<i>postfix-expression</i> <b>'->'</b> <i>identifier</i>
<i>postfix-expression</i> <b>'++'</b>
<i>postfix-expression</i> <b>'--'</b>
</pre>
我包含的不仅仅是成员访问函数,因为它表明 .identifier
和 ->identifier
的处理方式与任何其他后缀运算符一样,这是一个有用的见解。同样的产生式还包括两个后缀括号运算符,下标 ([...]
) 和函数调用 ((...)
),它们在这里似乎是相关的。但我遗漏了复合文字(我会把它放入 primary-expression
)。
Python
Python 3.9 文档的可比较摘录:
<pre>
<i>primary</i>:
<i>primary</i> '<b>.</b>' <i>NAME</i>
<i>primary</i> '<b>(</b>' [<i>arguments</i>] '<b>)</b>'
<i>primary</i> '<b>[</b>' <i>slices</i> '<b>]</b>'
<i>primary</i> <i>genexp</i>
<i>atom</i>
</pre>