2016-11-01 2 views
0

私はIT研究のプロジェクトを持っています。これは、そのプロジェクト(単純化されたJava)のためだけに作られた単純な言語のためのコンパイラを作ることです。文法を解析するために、私は最初のリリース(このプロジェクトではSCRUMメソッドを使わなければならない)のためにjavaccでjjtreeファイルを作ったので、それは完全な文法ではありません。最初はそれがうまくいくように見え、私が何を入力しているのかを正しく読み取るようです。しかし、プロジェクトの他のメンバー(私たちは5人のグループです)と一緒に、jjtreeが生成する訪問者ごとにコンパイルルールを書く必要がありました。それを解決するには、文法にタグを使用する必要があることがわかりました。そこで、問題が発生しました。javaCC "java.lang.ArrayIndexOutOfBoundsException:-1"例外

私はいくつかのルール(特に複数の選択肢を持つもの)でタグを追加しましたが、今度はparsorをテストすると変数の宣言で例外が発生します。例:

class C{ 
    int i=1; 
    main { 
     i++; 
    } 
} 

int i = 1、 ";"と入力すると例外が発生します。 INTに

class C{ 
    int i[1]; 
    main { 
     i++; 
    } 
} 

、第2の後に例外を与える "" 私が入力したときに[1]

をそれは、I = 1 INT後に例外を与える "と、"。

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の初心者です。私は2週間これについています。どこに問題があるのか​​わかりませんし、まだタグの問題があるので、ここから来るかもしれません。

教師が私たちに与えた基本的な文法(フレンチですが、フランス語を知らなくても簡単には分かりません)と、javaCCのために書き直したもの(Release 1では黄色です):

事前に

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 
} 

ありがとう:

http://imgur.com/a/WASPr

は、最後にここにJavaCCの中のコードは、(私はスペースのためにコメントを削除して、彼らはフランス語にいるので、私はそれを再度追加することができます)です助けて、私のために申し訳ありません悪い英語。より多くの情報が必要な場合は、お気軽にお問い合わせください。

答えて

0

次生産には赤緯がない場合を考えてみましょう私

void decls() #DECLS(2): {}{ 
    decl() <PVIRGULE> decls() 
    |{} #VNIL 
} 

に間違って見えます。次に、最初にVNILがスタックにプッシュされ、2つ目のノードがスタックからポップされ、DECLノードがスタックにプッシュされます。したがって、望むように1つのノードをスタックに追加する代わりに、先頭のノードをDECLノードに置き換えます。

それをこのように書く方が良いでしょう:

void decls() #void : {}{ 
    (decl() <PVIRGULE> decls()) #DECLS 
| 
    {} #VNIL 
} 

それとも

void decls() #void : {}{ someDecls() | nothing() } 

void someDecls() #DECLS : {} { decl() <PVIRGULE> decls() } 

void nothing() #VNIL : {} { } 

同様のコメントがあなたの文法中の作品の数に適用されます。

また、この

void decls() #DECLS : {} { decl() (<PVIRGULE> decl())* } 

ボンのチャンスのようなVNILの使用を避けることができます。

+0

ありがとうございます!私は文法を修正するプロジェクトの他の人とそれを見るでしょう:) 残念ながら、それは私の問題を解決しませんでした。しかし、私はタグ内のすべての数字を削除することでそれを解決しました。なぜそれが文法をクラッシュさせたのか考えてみませんか?私はまだタグのための良いドキュメントを見つけることができませんでしたので、私は正確に数字の仕事を知っていない(私は子供のルールの数だったthikingだった) –

+0

右。それは単に「宣言する」生産ではなかった。私は例としてそれを使っていました。 '#DECLS(2)'は、スタックから2つのノードをポップし、その2つを子として新しいノードをプッシュします。 –

+0

もう一度、本当に助けてくれてありがとう!私はあなたの助言に従って、私の文法でいくつかのルールを修正しました。それは今働くようです(すべての指示を読んで、まだいくつかの問題を抱えていますが、少しずつ少しずつ修正しています。すぐに良い文法:))。 ありがとうございます。私はまだ彼らに慣れていませんが、私はそれらを一つずつ追加して結果を見ています –

関連する問題