javaCC" java.lang.ArrayIndexOutOfBoundsException:-1"例外

时间:2016-11-01 16:03:39

标签: java exception grammar javacc

我有一个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)的黄色是什么:

http://imgur.com/a/WASPr

最后这里是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
}

提前感谢您的帮助,对不起我的英语不好。如果您需要更多信息,请不要犹豫。

1 个答案:

答案 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() )* }

机会。