tiger book読む

tiger bookを読むといいつつ、全然本は読んでません。
ひたすら文法というかJCUPと格闘してます。
コンフリクトは無くなったのが以下のソースです。
まだ、コンパイラは通らないと思います。
JCUPでは名前を使ってバインディングできる素晴らしい機能があるわけですが、
CUP/JLex で書いていますが、後でJFlexとBYACC/Jに書き換えるつもりなので、番号付きで書いてます。
yaccの場合は名前付けなくても動くので単純に文法が長くなってしまい、嬉しさが半減してしまってます。
JCUPは#,%,$等の濃いゴチャゴチャしたイメージのある記号を使っていないからか、
見た目さっぱりすっきりした感じがします。

package Parse;

action code {: static Symbol.Symbol sym(String s) {
	         return Symbol.Symbol.symbol(s);
	        }
	    :};

parser code  {: 
  public Absyn.Exp parseResult;
  Lexer lexer;

  public void syntax_error(java_cup.runtime.Symbol current) {
   report_error("Syntax error (" + current.sym + ")", current);
  }

  ErrorMsg.ErrorMsg errorMsg;

  public void report_error(String message, 
			   java_cup.runtime.Symbol info) {
      errorMsg.error(info.left, message);
  }

  public Grm(Lexer l, ErrorMsg.ErrorMsg err) {
    this();
    errorMsg=err;
    lexer=l;
  }
:};

scan with {: return lexer.nextToken(); :};

terminal String ID, STRING;
terminal Integer INT;
terminal COMMA, COLON, SEMICOLON, LPAREN, RPAREN, 
	LBRACK, RBRACK, LBRACE, RBRACE, DOT, PLUS, MINUS, 
	TIMES, DIVIDE, EQ, NEQ, LT, LE, GT, GE, AND, OR, 
	ASSIGN, ARRAY, IF, THEN, ELSE, WHILE, FOR, TO, DO, 
	LET, IN, END, OF, BREAK, NIL, FUNCTION, VAR, TYPE;

non terminal program, exp, explist, args, rec_fields, decs, dec, ty, id, tyfields,
	tyfield, vardec, fundec, l_value ;


precedence nonassoc THEN ;
precedence left ELSE;
precedence left OR, AND, EQ, LT, LE, GT, GE, NEQ, PLUS, MINUS, TIMES, DIVIDE;

start with program;

program ::=
	  exp:_1					{: RESULT = _1; :}
	;

exp ::=
	  INT:_1					{: RESULT = new IntExp(_1, P()); :}
	| LPAREN RPAREN				{: RESULT = new UnitExp(P()); :}
	| NIL						{: RESULT = new NilExp(P()); :}
	| STRING:_1					{: RESULT = new StringExp(_1, P()); :}
	| BREAK						{: RESULT = new BreakExp(P()); :}
	| l_value:_1				{: RESULT = new VarExp(_1, P()); :}
	| l_value:_1 ASSIGN exp:_3	{: RESULT = new AssignExp(_1, _3, P()); :}
	| LPAREN exp:_2 SEMICOLON explist:_4 RPAREN
								{: RESULT = new SeqExp(addList(_2, _4), P()); :}
	| exp:_1 OR exp:_3			{: RESULT = new IfExp(_1, new IntExp(1, P()), _3, P()); :}
	| exp:_1 AND exp:_3			{: RESULT = new IfExp(_1, _3, new IntExp(0, P()), P()); :}
	| exp:_1 EQ exp:_3			{: RESULT = new OpExp(_1, EqOp, _3, P()); :}
	| exp:_1 LT exp:_3			{: RESULT = new OpExp(_1, LtOp, _3, P()); :}
	| exp:_1 LE exp:_3			{: RESULT = new OpExp(_1, LeOp, _3, P()); :}
	| exp:_1 GT exp:_3			{: RESULT = new OpExp(_1, GtOp, _3, P()); :}
	| exp:_1 GE exp:_3			{: RESULT = new OpExp(_1, GeOp, _3, P()); :}
	| exp:_1 NEQ exp:_3			{: RESULT = new OpExp(_1, NeqOp, _3, P()); :}
	| exp:_1 PLUS exp:_3		{: RESULT = new OpExp(_1, PlusOp, _3, P()); :}
	| exp:_1 MINUS exp:_3		{: RESULT = new OpExp(_1, MinusOp, _3, P()); :}
	| exp:_1 TIMES exp:_3		{: RESULT = new OpExp(_1, TimesOp, _3, P()); :}
	| exp:_1 DIVIDE exp:_3		{: RESULT = new OpExp(_1, DivideOp, _3, P()); :}
	| MINUS exp:_2				{: RESULT = new OpExp(IntExp(0, P()), MinusOp, _2, P()); :}
	| LPAREN exp:_2 RPAREN		{: RESULT = new _2; :}
	| id:_1 LPAREN args:_3 RPAREN
								{: RESULT = new CallExp(_1, _3, P()); :}
	| IF exp:_2 THEN exp:_4		{: RESULT = new IfExp(_2, _4, null, P()); :}
	| IF exp:_2 THEN exp:_4 ELSE exp:_6
								{: RESULT = new IfExp(_2, _4, _6, P()); :}
	| WHILE exp:_2 DO exp:_4	{: RESULT = new WhileExp(_2, _4, P()); :}
	| FOR id:_2 ASSIGN exp:_4 TO exp:_6 DO exp:_8
								{: RESULT = new ForExp(_2, false, _4, _6, _8, P()); :}
	| LET decs:_2 IN END		{: RESULT = new LetExp(_2, UnitExp(P()), P()); :}
	| LET decs:_2 IN exp:_4 END	{: RESULT = new LetExp(_2, _4, P()); :}
	| LET decs:_2 IN exp:_4 SEMICOLON explist:_6 END
								{: RESULT = new LetExp(_2, SeqExp(addList(_4, _6), P()), P()); :}
	| l_value:_1 LBRACK exp:_3 RBRACK OF exp:_6
								{: RESULT = new ArrayExp(_1, _3, _6, P()); :}
	| id:_1 LBRACE rec_fields:_3 RBRACE
								{: RESULT = new RecordExp(_3, _1, P()); :}
	;

explist ::=
	  exp:_1 SEMICOLON explist:_3
								{: RESULT = addList(_1, _3); :}
	| exp:_1					{: RESULT = list(_1); :}
	;

args ::=						{: RESULT = list(); :}
	| exp:_1 COMMA args:_3		{: RESULT = addList(_1, _3); :}
	| exp:_1					{: RESULT = list(_1); :}
	;

rec_fields ::=					{: RESULT = list(); :}
	| id:_1 EQ exp:_3 COMMA rec_fields:_5
	  							{: RESULT = addList(tuple(_1, _3), _5); :}
	| id:_1 EQ exp:_3			{: RESULT = list(tuple(_1, _3)); :}
	;

/* Declaraciones */

decs ::= 						{: RESULT = list(); :}
	| dec:_1 decs:_2			{: RESULT = fundeLFunTipos(_1, _2); :}
	;


/* Declaracion de Types */

dec ::=
	  TYPE id:_2 EQ ty:_4		{: RESULT = TypeDec(_2, _4, P()); :}
	| vardec:_1					{: RESULT = _1; :}
	| fundec:_1					{: RESULT = _1; :}
	;

ty	::=
	  id:_1						{: RESULT = NameTy(_1); :}
	| LBRACE tyfields:_2 RBRACE	{: RESULT = RecordTy(_2); :}
	| ARRAY OF id:_3			{: RESULT = ArrayTy(_3); :}
	;

id	::=
	  ID:_1						{: RESULT = _1; :}
	;

tyfields ::=					{: RESULT = list(); :}
	| tyfield:_1 COMMA tyfields:_3
								{: RESULT = addList(_1, _3); :}
	| tyfield:_1				{: RESULT = list(_1); :}
	;

tyfield ::=
	  id:_1 COLON id:_3			{: RESULT = TyField(false, _1, new NameTy(_3)); :}
	;


/* Declaracion of variables */

vardec ::=
	  VAR id:_2 ASSIGN exp:_4	{: RESULT = new VarDec(_2, false, null, _4, P()); :}
	| VAR id:_2 COLON id:_4 ASSIGN exp:_6
								{: RESULT = new VarDec(_2, false, _4, _6, P()); :}
	;

/* Declaracion of funcion */

fundec ::=
	  FUNCTION id:_2 LPAREN tyfields:_4 RPAREN EQ exp:_7
								{: RESULT = new FunctionDec(_2, _4, null, _7, P()); :}
	| FUNCTION id:_2 LPAREN tyfields:_4 RPAREN COLON id:_7 EQ exp:_9
								{: RESULT = new FunctionDec(_2, _4, _7, _9, P())]; :}
	;

l_value ::=
	  id:_1						{: RESULT = new SimpleVar(_1); :}
	| l_value:_1 DOT id:_3		{: RESULT = new FieldVar(_1, _3); :}
	| l_value:_1 LBRACK exp:_3 RBRACK
								{: RESULT = new SubscriptVar(_1, _3) :}
	;