目前,我使用ECMAScript 5.1实现了一个JavaScript/ JavaCC解析器,并且在ArrayLiteral生产中遇到了问题。
ArrayLiteral :
[ Elision_opt ]
[ ElementList ]
[ ElementList , Elision_opt ]
ElementList :
Elision_opt AssignmentExpression
ElementList , Elision_opt AssignmentExpression
Elision :
,
Elision ,我有三个问题,我会一个一个地问他们。
这是第二个。
我已将此制作简化为以下形式:
ArrayLiteral:
"[" ("," | AssignmentExpression ",") * AssignmentExpression ? "]"请参阅第一个问题,即它是否正确:
现在,我尝试在JavaCC中实现它,如下所示:
void ArrayLiteral() :
{
}
{
"["
(
","
| AssignmentExpression()
","
) *
(
AssignmentExpression()
) ?
"]"
}JavaCC抱怨,或AssignmentExpression (其内容)不明确。显然,需要LOOKAHEAD规范。我花了很多时间试图找出LOOKAHEAD,尝试了不同的东西,比如
LOOKAHEAD (AssignmentExpression() ",") in (...)*LOOKAHEAD (AssignmentExpression() "]") in (...)?还有一些其他的变化,但我无法摆脱JavaCC的警告。
我不明白为什么这样做行不通:
void ArrayLiteral() :
{
}
{
"["
(
LOOKAHEAD ("," | AssignmentExpression() ",")
","
| AssignmentExpression()
","
) *
(
LOOKAHEAD (AssignmentExpression() "]")
AssignmentExpression()
) ?
"]"
}好的,AssignmentExpression()本身是模棱两可的,但是LOOKAHEAD中的尾随","或"]"应该清楚地表明应该选择哪一个--还是我弄错了?
对于这个产品,正确的LOOKAHEAD 规范是什么样子的?
更新
不幸的是,这一做法没有奏效:
void ArrayLiteral() :
{
}
{
"["
(
","
|
LOOKAHEAD (AssignmentExpression() ",")
AssignmentExpression()
","
) *
(
AssignmentExpression()
) ?
"]"
}警告:
Warning: Choice conflict in (...)* construct at line 6, column 5.
Expansion nested within construct and expansion following construct
have common prefixes, one of which is: "function"
Consider using a lookahead of 2 or more for nested expansion.第6行是第一个(之前的LOOKAHEAD。公共前缀"function"只是AssignmentExpression的一个可能的开始。
发布于 2014-11-14 05:28:36
这是另一种方法。它的优点是识别哪些逗号表示未定义的元素,而不使用任何语义操作。
void ArrayLiteral() : {} { "[" MoreArrayLiteral() }
void MoreArrayLiteral() : {} {
"]"
| "," /* undefined item */ MoreArrayLiteral()
| AssignmentExpression() ( "]" | "," MoreArrayLiteral() )
}发布于 2014-11-13 15:43:35
JavaCC生成自顶向下的解析器。首先,我不喜欢自上而下的解析器生成器,所以我不是JavaCC专家,也没有方便的测试工具。
(编辑:,我认为其他东西会起作用,但后来我意识到,我不明白JavaCC是如何对实际的选择进行展望的;就( A | B )* C而言,实际上有三种可能的选择: A、B和C。我以为它会考虑所有这三种选择,但有可能一次做到两种。因此,以下是另一种猜测。
话虽如此,我认为下面的方法是可行的,但它涉及到几乎每一个AssignmentExpression()解析两次。
{
"["
(
","
|
AssignmentExpression()
","
) *
(
LOOKAHEAD (AssignmentExpression() "]")
AssignmentExpression()
) ?
"]"
}正如我在关联问题中指出的,更好的解决方案是以不同的方式重写产品:
"[" AssignmentExpression ? ("," AssignmentExpression ?) * "]"这将导致一种单向查找语法,因此您将不需要LOOKAHEAD声明来处理它。
发布于 2014-11-13 20:18:10
我就是这样解决这个问题的(多亏了@rici的回答):
JSArrayLiteral ArrayLiteral() :
{
boolean lastElementWasAssignmentExpression = false;
}
{
"["
(
(
AssignmentExpression()
{
// Do something with expression
lastElementWasAssignmentExpression = true;
}
) ?
(
","
{
if (!lastElementWasAssignmentExpression)
{
// Do something with elision
}
}
(
AssignmentExpression()
{
// Do something with expression
lastElementWasAssignmentExpression = true;
}
) ?
) *
)
"]"
{
// Do something with results
}
}https://stackoverflow.com/questions/26908705
复制相似问题