我的语法如下:
PARSER_BEGIN(Parser)
package parser;
public class Parser {}
PARSER_END(Parser)
SKIP: {
" "
| "\t"
| "\n"
| "\r"
| "\f"
}
TOKEN : {
<MIX: "mix">
| <WITH: "with">
| <FUNCTION: "function">
| <MANIFEST: "manifest">
| <REPEAT: "repeat">
| <NAT: "nat">
| <REAL: "real">
| <MAT: "mat">
| <FOR: "for">
| <INSTRUCTIONS: "instructions">
}
TOKEN : {
<LPAREN: "(">
| <RPAREN: ")">
| <LBRACE: "{">
| <RBRACE: "}">
| <COLON: ":">
| <ASSIGN: "=">
}
// Include the necessary <INTEGER_LITERAL> included in most examples
TOKEN : {
<IDENTIFIER: <LETTER> (<LETTER>|<DIGIT>)*>
// Letter and Digit are the unicode values.
}
void Program() :
{}
{
( Manifest() )*
<INSTRUCTIONS>
Statement()
<EOF>
}
void Manifest() :
{}
{
<MANIFEST> (Type())? PrimaryExpression()
}
void Statement() :
{}
{
Instruction()
| Function()
}
void Instruction() :
{}
{
(TypingList())* Identifier() <ASSIGN> Expression()
}
void TypingList() :
{}
{
Type() ( TypingRest() )*
}
void TypingRest() :
{}
{
<COMMA> Type()
}
void Type() :
{}
{
<MAT>
| <NAT>
| <REAL>
}
void Function() :
{}
{
<FUNCTION> Identifier() <LPAREN> (FormalParameterList())* <RPAREN> (<COLON> TypingList())? <LBRACE>
Statement()
<RBRACE>
}
void FormalParemeterList() :
{}
{
FormalParameter() (FormalParameterRest() )*
}
void FormalParameter() :
{}
{
(TypingList())* Identifier()
}
void FormalParameterRest() :
{}
{
<COMMA> FormalParameter()
}
void Instruction() :
{}
{
(TypingList())* Identifier() <ASSIGN> Expression()
}
void Identifier() :
{}
{
<IDENTIFIER>
}
void Expression() :
{}
{
<MIX> Identifier() <WITH> Identifier() <FOR> <INTEGER_LITERAL>
}
这应该使我能够解析一个简单的程序,例如:
manifest itemOne
manifest itemTwo
instructions
function doThis(argument) : nat {
temp = mix one with two for 3
}
two = mix item3 with item4
然而,当JavaCC在函数temp = mix...
中看到doThis
语句时,它声明它找到了一个标识符,但是期待其他任何东西:
Exception in thread "main" parser.ParseException: Encountered " <IDENTIFIER> "temp "" at line x, column y.
Was expecting one of:
"for" ...
"}" ...
但是,正如您所看到的,我的语法表明您可以使用标识符为其分配mix
的值。但错误是说这是无效或不正确的。我尝试了几种变体,但似乎没有任何效果。
答案 0 :(得分:2)
问题在于您告诉JavaCC只有一个Instruction()
| BranchStatement()|WhileStatement()|Function()
。因此,一旦解析器访问其中一个状态,就不能再在那里重新访问。
为了解决这个问题,请将Kleene Closure +放在Statement()
转换周围,例如:
void Statement() :
{}
{
(
Instruction()
| BranchStatement()
| WhileStatement()
| Function()
)+
}
+
运算符告诉自动机必须至少访问此状态一次,但可以重复。