2016-11-01 3 views
0

У меня есть проект в ИТ-исследованиях, который должен сделать компилятор для простого языка, сделанного только для этого проекта (это упрощенный Java). Чтобы разобрать грамматику, я создал файл jjtree в javacc для первого выпуска (мы должны использовать метод SCRUM в этом проекте), поэтому он еще не с полной грамматикой. Сначала это работает хорошо, и правильно читать то, что я вхожу. Но тогда, когда с другим проектом (мы - группа из пяти человек), мы должны были написать правило компиляции для каждого посетителя, которое генерирует jjtree, мы обнаружили некоторую проблему для правила с множественным выбором. Мы увидели, что для решения этого вопроса мы должны использовать теги в грамматике, и именно там у нас возникла проблема.javaCC "java.lang.ArrayIndexOutOfBoundsException: -1" exception

Я добавил тег на какое-то правило (особенно с множественным выбором), и теперь, когда мы тестируем парсер, он дает нам исключение в объявлениях переменной. Например:

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

Он дает исключение после int i = 1, когда я вхожу в «;».

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

Это дает исключение после второго "]" в межд я [1]

Это дает исключение после того, как INT I = 1, когда я войти в ";".

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 
} 

Спасибо заранее за помочь, и извините за мой плохой английский. Если вам нужна дополнительная информация, не стесняйтесь спрашивать.

ответ

0

Следующая продукция выглядит не так мне

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

Рассмотрим случай, когда нет никакого Децл. Затем, во-первых, 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())* } 

Бон шанс.

+0

Спасибо! Я увижу, что с другим poeple по проекту, чтобы исправить грамматику :) К сожалению, это не решило мою проблему. Но я сам решил это, удалив все число в тегах. У вас есть идея, почему она рушила грамматику? Я не нашел хорошую документацию для тегов, но я точно не знаю, как работает число (я выбрал это число правил для детей) –

+0

Право. Это было не просто производство 'decls'. Я просто использовал это в качестве примера. Что '#DECLS (2)' делает, поп два узла из стека и толкает новый узел с этими двумя как дети. –

+0

Да, спасибо, ты действительно помог нам! Я следил за вашим советом и исправлял ряд правил в своей грамматике, и, похоже, теперь он работает (он читает все инструкции, у меня все еще есть проблемы с ast, но я почти корректирую их все понемногу, и я думаю, что я должен был бы хорошая грамматика скоро :)). Спасибо за объяснение. Я до сих пор не привык к ним, но я учусь, добавляя их один за другим и вижу результат –