我有一个IT研究项目,就是为一个仅为该项目制作的简单语言编写一个编译器(它是一个简化的java)。为了解析语法,我在javacc中为第一个版本创建了一个jjtree文件(我们必须在这个项目中使用SCRUM方法),所以它还没有完整的语法。起初它似乎运作良好,并正确阅读我进入的内容。但是,当与项目中的另一个(我们是一组五个)时,我们不得不为jjtree生成的每个访问者编写编译规则,我们发现了一些有多项选择的规则问题。我们看到要解决这个问题,我们必须在语法上使用标签,以及我们开始遇到问题的地方。
我在某个规则上添加了标记(特别是有多个选择的规则),现在,当我们测试游标时,它会在变量声明中给出一个异常。例如:
class C{
int i=1;
main {
i++;
}
}
在int i = 1之后,当我输入&#34 ;;"时,它会给出异常。
class C{
int i[1];
main {
i++;
}
}
它在第二个"]"之后给出例外。在int i [1]
在int i = 1之后,当我输入&#34 ;;"时,它会给出异常。
class C{
int i;
int x;
main {
i++;
}
}
输入主要内容时会出现异常。
这是例外:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: -1
at java.util.ArrayList.elementData(ArrayList.java:418)
at java.util.ArrayList.remove(ArrayList.java:495)
at JJTGrammaireJavaCCASA2State.closeNodeScope(JJTGrammaireJavaCCASA2State.java:86)
at GrammaireJavaCCASA2.classe(GrammaireJavaCCASA2.java:50)
at GrammaireJavaCCASA2.main(GrammaireJavaCCASA2.java:9)
有人可以帮帮我吗?我是javaCC的新手,我坚持了两个星期。我无法找到问题的位置,而且我仍然遇到标签问题,所以它可能来自这里。
这里是老师给我们的基本语法(它是法语的,但我认为即使不懂法语也很容易理解)和我们为javaCC重写的那个(我们使用的)版本1)的黄色是什么:
最后这里是javaCC中的代码(我删除了空格的注释,因为它们是法语的,但我可以重新添加它):
options {
VISITOR = true;
MULTI=true;
}
PARSER_BEGIN(GrammaireJavaCCASA2)
import java.io.*;
public class GrammaireJavaCCASA2 {
public static void main(String args[]) throws ParseException {
GrammaireJavaCCASA2 parser = new GrammaireJavaCCASA2(System.in);
SimpleNode root = parser.classe();
root.dump("");
}
}
PARSER_END(GrammaireJavaCCASA2)
SKIP : {
" "
| "\t"
| "\n"
| "\r"
}
TOKEN :{
<VIRGULE : ",">
| <PVIRGULE : ";">
| <PAROUV : "(">
| <PARFER : ")">
| <ACCOLOUV: "{">
| <ACCOLFER: "}">
| <CROOUV: "[">
| <CROFER : "]">
| <PLUS : "+">
| <MOINS : "-">
| <MULT : "*">
| <DIV : "/">
| <AFFECTATION : "=">
| <PLUSEGAL : "+=">
| <INCREMENT : "++">
| <EGALE : "==">
| <SUPERIEUR : ">">
| <DIFFERENT : "!">
| <ET : "&&">
| <OU : "||" >
| <CLASSE : "class">
| <FINAL : "final">
| <MAIN : "main">
| <VOID : "void">
| <RETURN : "return">
| <IF : "if">
| <ELSE : "else">
| <WHILE : "while">
| <TRUE : "true">
| <FALSE : "false">
| <NOMBRE : (["0"-"9"])+>
| <INT : "int">
| <BOOLEAN : "boolean">
| <IDENT : ["a"-"z","A"-"Z"] ( ["a"-"z","A"-"Z","0"-"9"] )*>
}
SimpleNode classe() #CLASSE(3): {}{
<CLASSE> ident() <ACCOLOUV> decls() methmain() <ACCOLFER>{return jjtThis;}
}
void ident() #IDENT: {Token t;}{
t=<IDENT> {jjtThis.value = t.image;}
}
void decls() #DECLS(2): {}{
decl() <PVIRGULE> decls()
|{} #VNIL
}
void decl() #DECL(1) : {}{
vars()
}
void vars() #VARS(2): {}{
var() <PVIRGULE> vars()
|{} #VNIL
}
void var() #void : {}{
typemeth() ident() (<CROOUV> exp() <CROFER> #TABLEAU(3)|vexp() #VAR(3))
}
/*void Var2() : {}{
Vexp()
}*/
void vexp() #AFFECTATIONINIT(1) : {}{
<AFFECTATION> exp()
|{} #OMEGA
}
void methmain() #MAIN(2): {}{
<MAIN> <ACCOLOUV> vars() instrs() <ACCOLFER>
}
void instrs() #INSTRS(2): {}{
instr() <PVIRGULE> instrs()
|{} #INIL
}
void instr() #void : {}{
ident1() (<AFFECTATION> exp() #AFFECTATION(2)
|<PLUSEGAL> exp() #SOMME(2)
|<INCREMENT> #INCREMENT(1))
}
/*void Instr2() : {}{
<AFFECTATION> Exp()
|<PLUSEGAL> Exp()
|<INCREMENT>
}*/
void exp() #EXP1GO(1) : {}{
exp1()
}
void exp1() #EXP1(1): {}{
exp2()
}
void exp2() #void : {}{
<MOINS> terme() [exp2prime()] #NEGATIF(2)
|terme() [exp2prime()] #TERMEEXP(2)
}
void exp2prime() #void : {}{
<PLUS> terme() [exp2prime()] #PLUS(2)
|<MOINS> terme() [exp2prime()] #MOINS(2)
}
void terme() #TERME(2): {}{
fact() [termeprime()]
}
void termeprime() #void : {}{
<MULT> fact() [termeprime()] #PRODUIT(2)
|<DIV> fact() [termeprime()] #DIVISION(2)
}
void fact() #void : {}{
ident1() #IDENT1GO(1)
|<TRUE> #VRAI
|<FALSE> #FAUX
|<NOMBRE> #NOMBRE
}
void ident1() #IDENT1(1) : {}{
ident()
}
void typemeth() #TYPE(1): {}{
type()
}
void type() #void : {}{
<INT> #ENTIER
|<BOOLEAN> #BOOLEEN
}
提前感谢您的帮助,对不起我的英语不好。如果您需要更多信息,请不要犹豫。
答案 0 :(得分:0)
以下制作对我来说是错误的
void decls() #DECLS(2): {}{
decl() <PVIRGULE> decls()
|{} #VNIL
}
考虑没有decl的情况。然后,首先,VNIL
将被推入堆栈,其次,两个节点将从堆栈中弹出,DECL
节点将被推入堆栈。因此,不是像你一样在堆栈中添加一个节点,而是用DECL
节点替换顶层节点。
用这种方式写它会更好:
void decls() #void : {}{
(decl() <PVIRGULE> decls()) #DECLS
|
{} #VNIL
}
或者
void decls() #void : {}{ someDecls() | nothing() }
void someDecls() #DECLS : {} { decl() <PVIRGULE> decls() }
void nothing() #VNIL : {} { }
类似的评论适用于语法中的许多作品。
你也可以避免像这样使用VNIL
void decls() #DECLS : {} { decl() ( <PVIRGULE> decl() )* }
机会。