Ejemplo de integración de un analizador léxico (lexer) y un analizador sintáctico (parser) implementados en JLex y CUP. Fuente: http://www.cis.uab.edu/courses/cs602/
1. Universidad Tecnológica Centroamericana
Ingeniería en Sistemas Computacionales
Compiladores I
Prof. Egdares Futch H.
CUP - Ejemplo complejo de uso, incluyendo JFlex y AST
Operator.java Pam.jlex
%%
// Operator is an auxiliary class %{
to define lexical token values for private void echo () { System . out . print (yytext ()); }
// operators.
private java_cup . runtime . Symbol token (int token_class,
class Operator { Object token_value) {
return new java_cup . runtime . Symbol (token_class, yychar,
// adding operators yychar + yylength (), token_value);
public final static Integer PLUS }
= new Integer ('+'); private java_cup . runtime . Symbol token (int token_class) {
public final static Integer MINUS return new java_cup . runtime . Symbol (token_class, yychar,
= new Integer ('-'); yychar + yylength (), null);
}
// multiplying operators %}
public final static Integer TIMES
= new Integer ('*'); %function nextToken
public final static Integer SLASH %type java_cup . runtime . Symbol
= new Integer ('/'); %char
%eofval{
// relational operators { return token (Symbol . EOF); }
public final static int LT = 0; %eofval}
public final static int LE = 1;
public final static int GT = 2; d = [0-9]
public final static int GE = 3; l = [A-Za-z]
public final static int EQ = 4;
public final static int NE = 5; %%
[ tn] { echo (); }
// I/O operators ";" { echo (); return token (Symbol . SEMICOLON); }
public final static Integer READ "," { echo (); return token (Symbol . COMMA); }
= new Integer (10); "." { echo (); return token (Symbol . DOT); }
public final static Integer WRITE "<" { echo (); return token (Symbol . RELOP, new Integer
= new Integer (11); (Operator . LT)); }
} "<=" { echo (); return token (Symbol . RELOP, new Integer
(Operator . LE)); }
">" { echo (); return token (Symbol . RELOP, new Integer
(Operator . GT)); }
">=" { echo (); return token (Symbol . RELOP, new Integer
(Operator . GE)); }
"=" { echo (); return token (Symbol . RELOP, new Integer
(Operator . EQ)); }
"<>" { echo (); return token (Symbol . RELOP, new Integer
(Operator . NE)); }
"(" { echo (); return token (Symbol . LEFTPAREN); }
")" { echo (); return token (Symbol . RIGHTPAREN); }
"+" { echo (); return token (Symbol . ADDOP, Operator .
PLUS); }
"-" { echo (); return token (Symbol . ADDOP, Operator .
MINUS); }
"*" { echo (); return token (Symbol . MULTOP, Operator .
TIMES); }
"/" { echo (); return token (Symbol . MULTOP, Operator .
SLASH); }
":=" { echo (); return token (Symbol . ASSIGN); }
do { echo (); return token (Symbol . DO); }
else { echo (); return token (Symbol . ELSE); }
end { echo (); return token (Symbol . END); }
fi { echo (); return token (Symbol . FI); }
if { echo (); return token (Symbol . IF); }
read { echo (); return token (Symbol . IO, Operator . READ); }
then { echo (); return token (Symbol . THEN); }
to { echo (); return token (Symbol . TO); }
while { echo (); return token (Symbol . WHILE); }
write { echo (); return token (Symbol . IO, Operator . WRITE); }
{d}+ { echo (); return token (Symbol . INTEGER, new Integer
(yytext ())); }
{l}({l}|{d})* { echo (); return token (Symbol . ID, yytext ()); }
2. // SyntaxTree.java parser code {:
Yylex lexer;
// SyntaxTree is a class to
represent a node of a ternary // Error handling function.
syntax tree.
public void report_fatal_error (String message, Object info) {
class SyntaxTree { done_parsing ();
System . out . println (message);
private String node; System . exit (1);
private SyntaxTree left; }
private SyntaxTree middle;
private SyntaxTree right; // This constructor assumes that the parser is named PamParser.
// constructor functions public PamParser (Yylex l) {
this ();
public SyntaxTree (String lexer = l;
node_value, SyntaxTree left_tree, }
SyntaxTree middle_tree,
SyntaxTree right_tree) { :};
node = new String
(node_value); action code {:
left = left_tree;
middle = middle_tree; java.util.Dictionary dict = new java.util.Hashtable();
right = right_tree;
} Integer get(String id) {
return((Integer)dict.get(id.intern()));
public SyntaxTree () { }
this ("", null, null, null); void put(String id, int v) {
node = null; dict.put(id.intern(), new Integer(v));
} }
public SyntaxTree (String :};
node_value) {
this (node_value, null, null, scan with {: return lexer . nextToken (); :};
null);
} terminal Integer INTEGER, RELOP, ADDOP, MULTOP, IO;
terminal String ID;
// selector functions terminal SEMICOLON, LEFTPAREN, RIGHTPAREN, COMMA, DOT, ASSIGN,
DO, ELSE, END, FI, IF, THEN, TO, WHILE;
public String root () {
return node; } non terminal SyntaxTree program, series, statement, else_option, id,
public SyntaxTree left () { id_list,
return left; } comparison, expression, term, factor;
public SyntaxTree middle () {
return middle; } start with program;
public SyntaxTree right () {
return right; } program ::= series:ser DOT {: RESULT = ser; :};
// print prints the tree in series ::= statement:st {: RESULT = st; :}
Cambridge Polish prefix notation. | series:ser SEMICOLON statement:st {: RESULT = new SyntaxTree (";",
ser, st); :};
public void print () {
System . out . println (""); statement ::= IO:io id_list:il
System . out . println ("Syntax {: if (io == Operator . READ)
Tree"); RESULT = new SyntaxTree ("read", il);
System . out . println ("------ else
-----"); RESULT = new SyntaxTree ("write", il); :}
System . out . println (""); | id:var ASSIGN expression:exp {: RESULT = new SyntaxTree (":=", var,
printTree (); exp); :}
System . out . println (""); | IF comparison:comp THEN series:then_ser else_option:else_ser FI
} {: RESULT = new SyntaxTree ("if", comp, then_ser, else_ser); :}
| TO expression:exp DO series:ser END
{: RESULT = new SyntaxTree ("to", exp, ser); :}
| WHILE comparison:comp DO series:ser END
{: RESULT = new SyntaxTree ("while", comp, ser); :}
;
id ::= ID:id {: RESULT = new SyntaxTree ("id", new SyntaxTree (id)); :};
id_list ::= id:i {: RESULT = i; :}
| id_list:il COMMA id:i {: RESULT = new SyntaxTree (",", il, i); :};
else_option ::= ELSE series:ser {: RESULT = ser; :}
| {: RESULT = null; :};
comparison ::= expression:exp1 RELOP:relop expression:exp2
{: switch (relop . intValue ()) {
3. class Pam { case Operator . LT : RESULT = new SyntaxTree ("<", exp1,
exp2); break;
public static void main (String case Operator . LE : RESULT = new SyntaxTree ("<=", exp1,
args []) { exp2); break;
PamParser parser; case Operator . GT : RESULT = new SyntaxTree (">", exp1,
SyntaxTree syntax_tree; exp2); break;
case Operator . GE : RESULT = new SyntaxTree (">=", exp1,
System . out . println ("Source exp2); break;
Program"); case Operator . EQ : RESULT = new SyntaxTree ("=", exp1,
System . out . println ("------ exp2); break;
--------"); case Operator . NE : RESULT = new SyntaxTree ("<>", exp1,
System . out . println (""); exp2); break; } :};
parser = new PamParser (new expression ::= expression:exp ADDOP:addop term:t
Yylex (System . in)); {: if (addop == Operator . PLUS)
try { RESULT = new SyntaxTree ("+", exp, t);
syntax_tree = (SyntaxTree) else
parser . parse () . value; RESULT = new SyntaxTree ("-", exp, t); :}
syntax_tree . print (); | term:t {: RESULT = t; :};
System . out . println ("");
System . out . println term ::= term:t MULTOP:multop factor:f
("Parse successful"); {: if (multop == Operator . TIMES)
} RESULT = new SyntaxTree ("*", t, f);
catch (Throwable e) { else
e . printStackTrace (); RESULT = new SyntaxTree ("/", t, f); :}
System . out . println (e); | factor:f {: RESULT = f; :};
}
} factor ::= LEFTPAREN expression:exp RIGHTPAREN {: RESULT = exp; :}
| INTEGER:n
} {: RESULT = new SyntaxTree ("integer", new SyntaxTree (n . toString
())); :}
| id:i {: put(id, e.intValue()); RESULT = i; :};