У меня есть проект в ИТ-исследованиях, который должен сделать компилятор для простого языка, сделанного только для этого проекта (это упрощенный 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):
Наконец вот код в 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
}
Спасибо заранее за помочь, и извините за мой плохой английский. Если вам нужна дополнительная информация, не стесняйтесь спрашивать.
Спасибо! Я увижу, что с другим poeple по проекту, чтобы исправить грамматику :) К сожалению, это не решило мою проблему. Но я сам решил это, удалив все число в тегах. У вас есть идея, почему она рушила грамматику? Я не нашел хорошую документацию для тегов, но я точно не знаю, как работает число (я выбрал это число правил для детей) –
Право. Это было не просто производство 'decls'. Я просто использовал это в качестве примера. Что '#DECLS (2)' делает, поп два узла из стека и толкает новый узел с этими двумя как дети. –
Да, спасибо, ты действительно помог нам! Я следил за вашим советом и исправлял ряд правил в своей грамматике, и, похоже, теперь он работает (он читает все инструкции, у меня все еще есть проблемы с ast, но я почти корректирую их все понемногу, и я думаю, что я должен был бы хорошая грамматика скоро :)). Спасибо за объяснение. Я до сих пор не привык к ним, но я учусь, добавляя их один за другим и вижу результат –