2016-11-01 2 views
0

저는 IT 연구 프로젝트가 있습니다.이 프로젝트는 해당 프로젝트 (단순화 된 Java) 용으로 만 만들어진 간단한 언어를위한 컴파일러입니다. 문법을 구문 분석하기 위해 나는 첫 번째 릴리스 (이 프로젝트에서 SCRUM 메소드를 사용해야한다.)를 위해 javacc에서 jjtree 파일을 만들었으므로 완전한 문법이 아니다. 처음 엔 좋은 일을하고, 내가 무엇을 입력하고 있는지 정확하게 읽는 것 같습니다. 그런 다음 프로젝트에서 다른 그룹 (우리는 다섯 그룹)과 함께 jjtree가 생성하는 각 방문자에 대해 편집 규칙을 작성해야 할 때 다중 선택 규칙을 사용하는 데 문제가 있음을 발견했습니다. 우리는 문법에 따라 태그를 사용해야한다는 것을 알았습니다. 그곳에서 우리는 어떤 문제가 생기기 시작했습니다.javaCC "java.lang.ArrayIndexOutOfBoundsException : -1"예외

일부 규칙 (특히 객관식이있는 태그)에 태그를 추가 했으므로 이제 parsor를 테스트 할 때 변수 선언에 예외가 생깁니다. 예 :

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

int i = 1 뒤에 ";"을 입력하면 예외가 발생합니다.

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

I 입력 때, "]", 두 번째는 INT에서 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에 익숙하지 않고 2 주 동안이 문제에 매달렸다. 문제가있는 곳을 찾을 수 없으며 태그에 몇 가지 문제가 있습니다. 여기에서 올 수 있습니다.

교사가 주신 기본 문법은 다음과 같습니다 (프랑스어로되어 있지만 프랑스어를 모르더라도 쉽게 알 수 없음). javaCC에 대해 다시 작성한 문구 (릴리스 1에서는 노란색을 사용함) :

마지막으로 여기 JavaCC에서의 코드가의

http://imgur.com/a/WASPr

는 (I 공간에 대한 해설을 삭제하고 프랑스에 있기하지만 난 그것을 다시 추가 할 수 있습니다) :

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 : {} { } 

비슷한 댓글이 문법에 작품의 숫자에 적용됩니다.

또한이

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

봉 기회처럼 VNIL의 사용을 피할 수 있습니다.

+0

고마워요! 문법을 수정하는 프로젝트의 다른 쪽과 함께 그것을 볼 것입니다 :) 불행히도, 그것은 내 문제를 해결하지 못했습니다. 하지만 태그의 모든 숫자를 제거하여 직접 해결했습니다. 왜 그것이 문법을 깨뜨리는 지 생각해 보셨습니까? 나는 태그에 대한 좋은 문서를 아직 찾지 못해서 번호 작업이 정확히 어떻게되는지 모르겠다. (나는 자식 규칙의 수를 틱했다.) –

+0

맞다. ''decls ''생산 만이 아니었다. 나는 그걸 예제로 사용하고있었습니다. '#DECLS (2)'가하는 일은 스택에서 두 개의 노드를 팝하고 그 둘을 자식으로하여 새로운 노드를 푸시하는 것입니다. –

+0

다시 한번 감사드립니다. 나는 당신의 충고를 따라 내 문법의 규칙을 정정하고 지금은 효과가있는 것으로 보인다. (그것은 모든 수업을 읽었을 뿐이다. 나는 여전히 천재와 약간의 문제가 있지만 거의 모든 것을 조금씩 교정한다. 곧 좋은 문법 :)). 설명해 주셔서 감사합니다. 나는 아직도 그들에게 익숙해지지 않고있다. 그러나 나는 그들을 하나씩 추가하고 그 결과를 보아서 배우고있다. –