JCup / JLex download JCup als java_cup_v10k.tar.gz von http://www2.cs.tum.edu/projects/cup/ download JFlex von als jflex-1.4.3.tar.gz von http://jflex.de/ oder download JLex Main.java von http://www.cs.princeton.edu/~appel/modern/java/jlex JCup funktioniert mit JLex als auch mit JFlex, allerdings ist die Handhabung etwas unterschiedlich. 1
JCup auspacken JCUP o.ä cd JCUP Übersetzten javac java_cup/main.java./install oder 2
JLex Im Verzeichnis JCUP, in dem auch java_cup liegt, das Unterverzeichnis JLex einrichten. Main.java dorthin speichern. compilieren javac JLex/Main.java der CLASSPATH muss jetzt nur noch auf das JCUP-Verzeichnis gesetzt werden. 3
Bearbeitung eines Beispiels CLASSPATH setzen export CLASSPATH=.:/.../JCUP java_cup.main example.cup java JLex/Main example.lex beide erzeugen Yylex.class javac example.lex.java erzeugt den Lexer ~/.../JFLEX/jflex/bin/jflex example.lex javac Yylex.java erzeugt den jflex lexer javac parser.java erzeugt den Parser java parser Programmstart 4
JCUP 11(beta) Download von TU München (java-cup-11a.jar und java-cup-11a-runtime.jar) Aufruf: java -cp.:java-cup-11a.jar java_cup.main xyz.cup Lexer bauen mit jflex und Yylex.java compilieren javac -cp.:java-cup-11a-runtime.jar Yylex.java Parser compilieren javac -cp.:java-cup-11a-runtime.jar:java-cup-11a.jar parser.java Ausführung: Unterstrich beachten!! java -cp.:java-cup-11a-runtime.jar parser 5
Package und import user code action code {:...:}; parser code {:...:}; init with {:...:}; scan with {:...:}; Bestandteile cup-file Symbollisten es werden die terminalen und nicht terminalen Symbole beschrieben. Die terminalen Symbole werden in einer Klasse sym.class abgelegt, die die Verbindung zw. Lex und Cup herstellt. Precedence-Declarations Die Reihenfolge von oben nach unten bestimmt die Priorität precedence left linksassoziativte Terminals precedence right rechtsassoziativen Terminals precedence nonasssoc Regeln 6
Regelteil Regeln werden in einer einfacher BNF ähnlichen Notation angegeben Werte, die mit Symbolen verbunden sind, werden über Namen, die dem Symbol durch einen Doppelpunkt folgen, angegeben. expr:e Auf diesen Bezeichner kann man in der nachgestellten Aktion Bezug nehmen. Der Typ ist in den Symboldklarationen festgelegt und muss eine Klasse sein. (Integer, String ) Durch autoboxing und autounboxing ist eien explizite Konvertierung nach beispielsweise int 7
Beispiel 1 expr, term, factor import java_cup.runtime.*; parser code {: public static void main(string args[])throws Exception { new parser(new Yylex(System.in)).parse(); } :} terminal SEMI, PLUS, MINUS, TIMES, DIVIDE, LPAREN, RPAREN; terminal Integer NUMBER; non terminal expr_list, expr_part; non terminal Integer expr, term, fac; 8
Regelteil Wiederholung durch Endlosrekursion expr_part für Ausgabe expr_list ::= expr_list expr_part expr_part; expr_part ::= expr:e {: System.out.println(" = "+e+";"); :} SEMI; expr ::= expr:l PLUS term:r {: RESULT=l.intValue() + r.intvalue(); :} expr:l MINUS term:r {: RESULT=l.intValue() - r.intvalue(); :} term:l {: RESULT=l.intValue(); :}; term ::= term:l TIMES fac:r {: RESULT=l.intValue() * r.intvalue(); :} term:l DIVIDE fac:r {: RESULT=l.intValue() / r.intvalue(); :} fac:l {: RESULT=l.intValue(); :}; fac ::= MINUS NUMBER:n {: RESULT=-n; :} NUMBER:n {: RESULT=n; :} LPAREN expr:e RPAREN {: RESULT=e; :}; 9
Der Lexer dazu import java_cup.runtime.symbol; %% %cup %% ";" { return new Symbol(sym.SEMI); } "+" { return new Symbol(sym.PLUS); } "-" { return new Symbol(sym.MINUS); } "*" { return new Symbol(sym.TIMES); } "/" { return new Symbol(sym.DIVIDE); } Class Integer "(" { return new Symbol(sym.LPAREN); } ")" { return new Symbol(sym.RPAREN); } [0-9]+ { return new Symbol(sym.NUMBER, new Integer(yytext())); } [ \t\r\n\f] { /* ignore white space. */ }. { System.err.println("Illegal character: "+yytext()); } 10
Verbindung JCup / JLex sym.java / sym.class //---------------------------------------------------- // The following code was generated by CUP v0.10k // Mon Jan 24 11:38:40 CET 2011 //---------------------------------------------------- /** CUP generated class containing symbol constants. */ public class sym { /* terminals */ public static final int MINUS = 4; public static final int DIVIDE = 6; public static final int NUMBER = 9; public static final int SEMI = 2; public static final int EOF = 0; public static final int PLUS = 3; public static final int error = 1; public static final int RPAREN = 8; public static final int TIMES = 5; public static final int LPAREN = 7; } 11
import java_cup.runtime.*; Variante 2 parser code {: public static void main(string args[]) throws Exception { System.out.println("Start:"); new parser(new Yylex(System.in)).parse(); } :} /* Terminals (tokens returned by the scanner). */ terminal SEMI, PLUS, MINUS, TIMES, DIVIDE, MOD; terminal UMINUS, LPAREN, RPAREN; terminal Integer NUMBER; /* Non-terminals */ non terminal non terminal Integer expr_list, expr_part; expr; /* Precedences */ precedence left PLUS, MINUS; precedence left TIMES, DIVIDE, MOD; precedence left UMINUS; 12
/* The grammar */ expr_list ::= expr_list expr_part expr_part ; expr_part ::= expr:e {: System.out.println("= " + e); :} SEMI ; expr ::= expr:e1 PLUS expr:e2 {: RESULT = e1.intvalue() + e2.intvalue(); :} expr:e1 MINUS expr:e2 {: RESULT = e1.intvalue() - e2.intvalue(); :} expr:e1 TIMES expr:e2 {: RESULT = e1.intvalue() * e2.intvalue(); :} expr:e1 DIVIDE expr:e2 {: RESULT = e1.intvalue() / e2.intvalue(); :} expr:e1 MOD expr:e2 {: RESULT = e1.intvalue() % e2.intvalue(); :} NUMBER:n {: RESULT = n; :} MINUS expr:e {: RESULT = 0 - e.intvalue(); :} //%prec MINUS LPAREN expr:e RPAREN {: RESULT = e; :} ; 13
j_pl0 import java_cup.runtime.*; parser code {: public static void main(string args[]) throws Exception { new parser(new Yylex(System.in)).parse(); } :} terminal SEMI, PLUS, MINUS, TIMES, DIVIDE, LPAREN, RPAREN,OUTPUT, INPUT, ASSIGN, GT, LT, GE, LE, EQUAL, NE, DOT, COMMA, BEGIN, CALL, CONST, DO, ELSE, END, IF, ODD, PROC, THEN, VAR, WHILE, EOFile, YYEOF; terminal Integer NUM; terminal String Ident; non terminal program, block, blockdecl,constdecl,constlist,vardecl,varlist, procdecllist,procdecl,prochead,statement,statementlist, ass,if1,while1, while2, exprlist, expression, term1, term, factor, cmpop, condition; 14
program ::= block DOT System.exit(1);:}; {: System.out.println("all OK"); block ::= blockdecl statement {: System.out.println("Block accepted");:}; blockdecl::= constdecl vardecl procdecllist {: :}; constdecl::= CONST constlist SEMI {: :} {: :}; constlist::= constlist COMMA Ident EQUAL NUM {: :} Ident EQUAL NUM {: :}; vardecl ::= VAR varlist SEMI {: :} {: :}; varlist ::= varlist COMMA Ident {: :} Ident {: :}; procdecllist::= procdecllist procdecl {: :} {: :}; procdecl ::= prochead block SEMI {: :}; 15
prochead ::= PROC Ident SEMI {: :}; statement::= BEGIN statementlist END {:System.out.println("Begin.. End accepted"); :} ass expression {: :} if1 statement {: :} while1 while2 statement {: :} CALL Ident {: :} INPUT Ident {: :} OUTPUT expression {:System.out.println("Output accepted");:}; statementlist ::= statementlist SEMI statement {:System.out.println("... epted"); :} statement {:System.out.println("StaementList 2 accepted"); :}; ass ::= Ident ASSIGN {: :}; if1 ::= IF condition THEN {: :}; while1 ::= WHILE {: :}; while2 ::= condition DO {: :}; 16
expression::= term1 PLUS exprlist {:System.out.println("Expression accepted");:} term1 MINUS exprlist {: :} term1 {: :}; term1 ::= MINUS term {: :} term {: :}; exprlist::= exprlist PLUS term {:System.out.println("ExprList:ExprList + Term accepted"); :} exprlist MINUS term {:System.out.println("ExprList:ExprList - Term accepted"); :} term {:System.out.println("ExprList:Term accepted"); :}; term ::= term TIMES factor {:System.out.println("Term:Term * Fact accepted"); :} term DIVIDE factor {:System.out.println("Term:Term / Fact accepted"); :} factor {:System.out.println("Term:Fact accepted"); :}; factor::= NUM:x {:System.out.println("Fact Fact "+x+" accepted"); :} Ident :x {:System.out.println("Fact Fact "+x+" accepted"); :} LPAREN expression RPAREN {:System.out.println("Fact Fact (... ) accepted"); :}; cmpop ::= EQUAL {: :} NE {: :} LT {: :} GT {: :} LE {: :} GE {: :}; condition::= ODD expression {: :} expression cmpop expression {: :}; 17
Bauen mit jcup 11(beta) 1. java -cp.:../java-cup-11a.jar java_cup.main pl0.cup 2.../jflex/bin/jflex pl0.lex 3. javac -cp.:../java-cup-11a-runtime.jar:.. Yylex.java 4. javac -cp.:../java-cup-11a-runtime.jar:.. parser.java Test: java -cp.:../java-cup-11a-runtime.jar parser < t.pl0 18