OK, the parser now looks more decent.
[repair.git] / Repair / RepairCompiler / MCC / MDL.cup
1 package MCC;
2 import MCC.IR.ParseNode;
3 import MCC.IR.ParseNodeVector;
4 import java.util.*;
5
6 action code {:
7
8         public static boolean errors;
9         public static boolean debug;
10
11         // debugMessage: writes debug production message only if debug = true
12
13         void debugMessage (String production) {
14                 if (debug) {
15                         System.out.println("Applying production: " + production);
16                 }
17         }
18
19         String unescape (String str) {
20             StringBuffer sb = new StringBuffer();
21             int i;
22             // Note that we skip the first and last characters (they're "'s)
23             for (i = 1; i < str.length() - 1; i++) {
24                 if (str.charAt(i) == '\\') {
25                     i++;
26                     switch (str.charAt(i)) {
27                     case '\"':
28                         sb.append('\"');
29                         break;
30                     case '\'':
31                         sb.append('\'');
32                         break;
33                     case '\\':
34                         sb.append('\\');
35                         break;
36                     case 't':
37                         sb.append('\t');
38                         break;
39                     case 'n':
40                         sb.append('\n');
41                         break;
42                     default:
43                         System.err.print("Error in string literal: ");
44                         System.err.println(str.charAt(i));
45                         System.err.println("Aborting...");
46                         break;
47                     }
48                 } else {
49                     sb.append(str.charAt(i));
50                 }
51             }
52             return sb.toString();
53         }
54 :}
55
56 init with {: :}
57
58 parser code {:
59
60         public String filename;
61        
62         public void syntax_error (java_cup.runtime.Symbol current) {
63
64                 CUP$MDLParser$actions.errors = true;
65                 Symbol symbol = (Symbol) current;
66
67                 //System.out.println("current.value = "+current.value + " " + current.value.equals("true"));
68                 //System.out.println("current = " + current);
69
70                 boolean isInteger = true;
71                 try{ 
72                    Integer.parseInt(current.value.toString());
73                 } catch(NumberFormatException e) { isInteger = false;}
74
75                 report_error(filename+":"+(symbol.line+1)+": Syntax error at column " 
76                 + (LineCount.getColumn(symbol.left)+1) +": " + current.value, current);
77
78                 if (current.value.equals("true") || isInteger)
79                    System.out.println("Did you mean literal("+current.value+")?");
80                
81                 if (LineCount.getColumn(symbol.left) == 0)      
82                    System.out.println("Did you forget a semicolon on the previous line?");    
83                 
84
85                 System.out.println();
86                 System.exit(0);
87         }
88
89         public void report_fatal_error (String message, Object info) {
90                 
91                  done_parsing();
92                  report_error(message, info);
93                  CUP$MDLParser$actions.errors = true;
94         }
95
96         public int curPos () {
97                 return cur_token.left;
98         }
99
100         public int curLine (int back) {
101                 Stack st = new Stack();
102                 int i;
103
104                 for (i = 0; i < back; i++) {
105                         st.push(stack.pop());
106                 }
107
108                 java_cup.runtime.Symbol s;
109                 s = (java_cup.runtime.Symbol) st.peek();
110
111                 for (i = 0; i < back; i++) {
112                         stack.push(st.pop());
113                 }
114
115                 return LineCount.getLine(s.left);
116         }
117         
118 :}
119
120 // TERMINALS /////////////////////////////////////////////////////////////
121
122     terminal BAD;
123
124     terminal String ID;
125     terminal String DECIMAL;
126     terminal String CHAR;
127     terminal String STRING;
128
129     terminal OPENBRACE;
130     terminal CLOSEBRACE;
131     terminal OPENPAREN;
132     terminal CLOSEPAREN; 
133     terminal OPENBRACKET;
134     terminal CLOSEBRACKET;
135
136     terminal ADD; 
137     terminal SUB; 
138     terminal MULT; 
139     terminal DIV;
140
141     terminal NOT;
142     terminal LT;
143     terminal GT;
144     terminal LE;
145     terminal GE;
146     terminal EQ;
147     terminal NE;
148
149     terminal FORALL;
150     terminal IN;
151     terminal INTEST;
152
153     terminal COMMA;
154     terminal SIZEOF;
155
156     terminal DOT;
157     terminal DOTINV;
158
159     terminal AND;
160     terminal OR;
161
162     terminal LITERAL;
163
164     terminal IMPLIES;
165     terminal TRUE;
166     terminal FALSE;
167     terminal ISVALID;
168     terminal FOR;
169     terminal TO;
170     terminal CAST;
171
172     terminal PARAM;
173     terminal STRUCTURE;
174     terminal RESERVED;
175     terminal BIT;
176     terminal BYTE;
177     terminal SHORT;
178       
179     terminal LABEL;
180     terminal INT;
181     terminal SUBTYPE;
182     terminal OF;
183
184     terminal SEMICOLON;
185     terminal COLON;
186
187     terminal SET;
188     terminal ARROW;
189     terminal MANY;
190     terminal BAR;
191
192     terminal PARTITION;
193     terminal ELEMENT;
194     terminal DELAY;
195     terminal STATIC;
196
197     terminal NULL;
198     terminal CRASH;
199
200 // NON-TERMINALS /////////////////////////////////////////////////////////
201
202 /*
203                 TYPE                    NAME
204 ------------------------------------------------------------------------*/
205
206 nonterminal     ParseNode               rules;
207 nonterminal     ParseNode               rule;
208 nonterminal     ParseNode               ruletype;
209 nonterminal     ParseNode               optquantifiers;
210 nonterminal     ParseNode               quantifiers;
211 nonterminal     ParseNode               quantifier;
212 nonterminal     ParseNode               inclusion;
213 nonterminal     ParseNode               expr;
214 nonterminal     ParseNode               literal;
215                 
216 nonterminal     ParseNode               simple_expr;
217 nonterminal     ParseNode               location;
218
219 nonterminal     ParseNode               set;
220 nonterminal     ParseNode               listofliterals;
221
222 precedence nonassoc OR;
223 precedence nonassoc AND;
224
225 precedence nonassoc EQ, NE; 
226 precedence nonassoc LT, LE, GE, GT;
227
228 precedence left INTEST;
229
230 precedence left ADD, SUB;
231 precedence left MULT, DIV;
232 precedence left NOT;
233 precedence left DOT;
234
235 // PRODUCTION RULES  /////////////////////////////////////////////////////
236
237 start with rules;
238
239 rules ::= 
240
241         rules:rules rule:rule
242         {:
243         debugMessage(PRODSTRING);
244         rules.addChild(rule);
245         RESULT = rules;
246         :} 
247
248         | rule:rule 
249         {:
250         debugMessage(PRODSTRING);
251         ParseNode rules = new ParseNode("rules", parser.curLine(1));
252         rules.addChild(rule);
253         RESULT = rules; 
254         :}
255         ;
256
257 rule ::= 
258    
259         ruletype:ruletype OPENBRACKET optquantifiers:quantifiers CLOSEBRACKET 
260                 COMMA expr:guard IMPLIES inclusion:inclusion SEMICOLON
261         {:
262         debugMessage(PRODSTRING);
263         ParseNode rule = new ParseNode("rule", parser.curLine(9));
264         if (ruletype != null) {
265                 rule.addChild(ruletype);
266         }
267         if (quantifiers != null) {
268                 rule.addChild(quantifiers);
269         }
270         rule.addChild(guard);
271         rule.addChild(inclusion);
272         RESULT = rule;
273         :}
274         ;
275
276 ruletype ::= 
277    
278         STATIC 
279         {:
280         debugMessage(PRODSTRING);
281         RESULT = new ParseNode("static", parser.curLine(1));
282         :} 
283
284         | DELAY 
285         {:
286         debugMessage(PRODSTRING);
287         RESULT = new ParseNode("delay", parser.curLine(1));
288         :} 
289    
290         | /* nothing */
291         {:
292         debugMessage(PRODSTRING);
293         RESULT = null;
294         :}        
295         ;
296
297 optquantifiers ::=
298
299         quantifiers:quantifiers        
300         {:
301         debugMessage(PRODSTRING);
302         RESULT = quantifiers;
303         :}
304
305         | /* nothing */
306         {:
307         debugMessage(PRODSTRING);
308         RESULT = null;
309         :}
310         ;
311
312 quantifiers ::=
313
314         quantifiers:quantifiers COMMA quantifier:quantifier
315         {:
316         debugMessage(PRODSTRING);
317         quantifiers.addChild(quantifier);
318         RESULT = quantifiers;
319         :}
320             
321         | quantifier:quantifier
322         {:
323         debugMessage(PRODSTRING);
324         ParseNode quantifiers = new ParseNode("quantifiers", parser.curLine(1));
325         quantifiers.addChild(quantifier);
326         RESULT = quantifiers;
327         :}
328         ;       
329
330 quantifier ::= 
331            
332         FORALL ID:var IN set:set
333         {:
334         debugMessage(PRODSTRING);
335         ParseNode q = new ParseNode("quantifier", parser.curLine(4));
336         q.addChild("forall", parser.curLine(4));
337         q.addChild("var", parser.curLine(3)).addChild(var);
338         q.addChild(set);
339         RESULT = q;
340         :}
341            
342         | FORALL LT ID:r1 COMMA ID:r2 GT IN ID:relation
343         {:
344         debugMessage(PRODSTRING);
345         ParseNode q = new ParseNode("quantifier", parser.curLine(7));
346         q.addChild("relation", parser.curLine(1)).addChild(relation);
347         q.addChild("left", parser.curLine(5)).addChild(r1);
348         q.addChild("right", parser.curLine(3)).addChild(r2);
349         RESULT = q;
350         :}
351
352         | FOR ID:var EQ expr:lower TO expr:upper
353         {:
354         debugMessage(PRODSTRING);
355         ParseNode q = new ParseNode("quantifier", parser.curLine(5));
356         q.addChild("for");
357         q.addChild("var", parser.curLine(4)).addChild(var);
358         q.addChild("lower", parser.curLine(3)).addChild(lower);
359         q.addChild("upper", parser.curLine(1)).addChild(upper);
360         RESULT = q;
361         :}
362         ;
363            
364 inclusion ::= 
365           
366         expr:expr IN ID:setname
367         {:
368         debugMessage(PRODSTRING);
369         ParseNode set = (new ParseNode("inclusion", parser.curLine(3))).addChild("set");
370         set.addChild(expr);
371         set.addChild("name", parser.curLine(1)).addChild(setname);
372         RESULT = set.getRoot(); 
373         :}
374
375         | LT expr:r1 COMMA expr:r2 GT IN ID:relationname
376         {:
377         debugMessage(PRODSTRING);
378         ParseNode relation = (new ParseNode("inclusion", parser.curLine(7))).addChild("relation");
379         relation.addChild("left").addChild(r1);
380         relation.addChild("right").addChild(r2);
381         relation.addChild("name", parser.curLine(1)).addChild(relationname);
382         RESULT = relation.getRoot();
383         :}
384         ;
385
386 simple_expr ::= 
387         
388         location:location
389         {:
390         debugMessage(PRODSTRING);
391         ParseNode se = new ParseNode("simple_expr", parser.curLine(1));
392         se.addChild(location);
393         RESULT = se;
394         :}
395         ;
396
397 location ::=
398
399         ID:var
400         {:
401         debugMessage(PRODSTRING);
402         ParseNode loc = new ParseNode("location", parser.curLine(1));   
403         loc.addChild("var").addChild(var);
404         RESULT = loc;
405         :}
406
407         | simple_expr:dotexpr DOT ID:field
408         {:
409         debugMessage(PRODSTRING);
410         ParseNode dot = (new ParseNode("location", parser.curLine(3))).addChild("dot");
411         dot.addChild(dotexpr);
412         dot.addChild("field", parser.curLine(1)).addChild(field);
413         RESULT = dot.getRoot();
414         :}
415
416         | simple_expr:dotexpr DOT ID:field OPENBRACKET expr:index CLOSEBRACKET
417         {:
418         debugMessage(PRODSTRING);
419         ParseNode dot = (new ParseNode("location", parser.curLine(6))).addChild("dot");
420         dot.addChild(dotexpr);
421         dot.addChild("field", parser.curLine(4)).addChild(field);
422         dot.addChild("index", parser.curLine(2)).addChild(index);
423         RESULT = dot.getRoot();
424         :}
425
426         | CAST OPENPAREN ID:type COMMA simple_expr:expr CLOSEPAREN
427         {:
428         debugMessage(PRODSTRING);
429         ParseNode cast = (new ParseNode("location", parser.curLine(6))).addChild("cast");
430         cast.addChild("type").addChild(type);
431         cast.addChild(expr);
432         RESULT = cast.getRoot();
433         :}
434         ;
435
436 expr ::= 
437
438         simple_expr:se 
439         {:
440         debugMessage(PRODSTRING);
441         ParseNode expr = new ParseNode("expr", parser.curLine(1));
442         expr.addChild(se);
443         RESULT = expr;
444         :}
445
446         | expr:expr INTEST ID:setname
447         {:
448         debugMessage(PRODSTRING);
449         ParseNode elementof = (new ParseNode("expr", parser.curLine(3))).addChild("elementof");
450         elementof.addChild(expr);
451         elementof.addChild("name").addChild(setname);
452         RESULT = elementof.getRoot();
453         :}
454
455         | LT expr:r1 COMMA expr:r2 GT INTEST ID:relationname
456         {:
457         debugMessage(PRODSTRING);
458         ParseNode tupleof = (new ParseNode("expr", parser.curLine(7))).addChild("tupleof"); 
459         tupleof.addChild("left").addChild(r1);
460         tupleof.addChild("right").addChild(r2);
461         tupleof.addChild("name").addChild(relationname);
462         RESULT = tupleof.getRoot();
463         :}
464
465         | OPENPAREN expr:expr CLOSEPAREN 
466         {:
467         debugMessage(PRODSTRING);
468         RESULT = expr;
469         :}     
470     
471         | LITERAL OPENPAREN literal:literal CLOSEPAREN       
472         {:
473         debugMessage(PRODSTRING);
474         ParseNode expr = new ParseNode("expr", parser.curLine(4));
475         expr.addChild(literal);
476         RESULT = expr;
477         :}
478                 
479         | expr:leftexpr LT expr:rightexpr 
480         {:
481         debugMessage(PRODSTRING);
482         ParseNode bool = (new ParseNode("expr", parser.curLine(3))).addChild("operator");
483         bool.addChild("op").addChild("lt");
484         bool.addChild("left", parser.curLine(3)).addChild(leftexpr);
485         bool.addChild("right", parser.curLine(1)).addChild(rightexpr);
486         RESULT = bool.getRoot();
487         :}
488
489         | expr:leftexpr LE expr:rightexpr 
490         {:
491         debugMessage(PRODSTRING);
492         ParseNode bool = (new ParseNode("expr", parser.curLine(3))).addChild("operator");
493         bool.addChild("op").addChild("le");
494         bool.addChild("left", parser.curLine(3)).addChild(leftexpr);
495         bool.addChild("right", parser.curLine(1)).addChild(rightexpr);
496         RESULT = bool.getRoot();
497         :}
498
499         | expr:leftexpr GT expr:rightexpr 
500         {:
501         debugMessage(PRODSTRING);
502         ParseNode bool = (new ParseNode("expr", parser.curLine(3))).addChild("operator");
503         bool.addChild("op").addChild("gt");
504         bool.addChild("left", parser.curLine(3)).addChild(leftexpr);
505         bool.addChild("right", parser.curLine(1)).addChild(rightexpr);
506         RESULT = bool.getRoot();
507         :}
508
509         | expr:leftexpr GE expr:rightexpr 
510         {:
511         debugMessage(PRODSTRING);
512         ParseNode bool = (new ParseNode("expr", parser.curLine(3))).addChild("operator");
513         bool.addChild("op").addChild("ge");
514         bool.addChild("left", parser.curLine(3)).addChild(leftexpr);
515         bool.addChild("right", parser.curLine(1)).addChild(rightexpr);
516         RESULT = bool.getRoot();
517         :}
518
519         | expr:leftexpr EQ expr:rightexpr 
520         {:
521         debugMessage(PRODSTRING);
522         ParseNode bool = (new ParseNode("expr", parser.curLine(3))).addChild("operator");
523         bool.addChild("op").addChild("eq");
524         bool.addChild("left", parser.curLine(3)).addChild(leftexpr);
525         bool.addChild("right", parser.curLine(1)).addChild(rightexpr);
526         RESULT = bool.getRoot();
527         :}
528    
529         | expr:leftexpr NE expr:rightexpr 
530         {:
531         debugMessage(PRODSTRING);
532         ParseNode bool = (new ParseNode("expr", parser.curLine(3))).addChild("operator");
533         bool.addChild("op").addChild("ne");
534         bool.addChild("left", parser.curLine(3)).addChild(leftexpr);
535         bool.addChild("right", parser.curLine(1)).addChild(rightexpr);
536         RESULT = bool.getRoot();
537         :}
538
539         | expr:leftexpr ADD expr:rightexpr 
540         {:
541         debugMessage(PRODSTRING);
542         ParseNode bool = (new ParseNode("expr", parser.curLine(3))).addChild("operator");
543         bool.addChild("op").addChild("add");
544         bool.addChild("left", parser.curLine(3)).addChild(leftexpr);
545         bool.addChild("right", parser.curLine(1)).addChild(rightexpr);
546         RESULT = bool.getRoot();
547         :}
548
549         | expr:leftexpr SUB expr:rightexpr 
550         {:
551         debugMessage(PRODSTRING);
552         ParseNode bool = (new ParseNode("expr", parser.curLine(3))).addChild("operator");
553         bool.addChild("op").addChild("sub");
554         bool.addChild("left", parser.curLine(3)).addChild(leftexpr);
555         bool.addChild("right", parser.curLine(1)).addChild(rightexpr);
556         RESULT = bool.getRoot();
557         :}
558
559         | expr:leftexpr DIV expr:rightexpr 
560         {:
561         debugMessage(PRODSTRING);
562         ParseNode bool = (new ParseNode("expr", parser.curLine(3))).addChild("operator");
563         bool.addChild("op").addChild("div");
564         bool.addChild("left", parser.curLine(3)).addChild(leftexpr);
565         bool.addChild("right", parser.curLine(1)).addChild(rightexpr);
566         RESULT = bool.getRoot();
567         :}
568
569         | expr:leftexpr MULT expr:rightexpr 
570         {:
571         debugMessage(PRODSTRING);
572         ParseNode bool = (new ParseNode("expr", parser.curLine(3))).addChild("operator");
573         bool.addChild("op").addChild("mult");
574         bool.addChild("left", parser.curLine(3)).addChild(leftexpr);
575         bool.addChild("right", parser.curLine(1)).addChild(rightexpr);
576         RESULT = bool.getRoot();
577         :}
578
579         | expr:leftexpr AND expr:rightexpr 
580         {:
581         debugMessage(PRODSTRING);
582         ParseNode bool = (new ParseNode("expr", parser.curLine(3))).addChild("operator");
583         bool.addChild("op").addChild("and");
584         bool.addChild("left", parser.curLine(3)).addChild(leftexpr);
585         bool.addChild("right", parser.curLine(1)).addChild(rightexpr);
586         RESULT = bool.getRoot();
587         :}
588    
589         | expr:leftexpr OR expr:rightexpr 
590         {:
591         debugMessage(PRODSTRING);
592         ParseNode bool = (new ParseNode("expr", parser.curLine(3))).addChild("operator");
593         bool.addChild("op").addChild("and");
594         bool.addChild("left", parser.curLine(3)).addChild(leftexpr);
595         bool.addChild("right", parser.curLine(1)).addChild(rightexpr);
596         RESULT = bool.getRoot();
597         :}
598
599         | NOT expr:expr 
600         {:
601         debugMessage(PRODSTRING);
602         ParseNode bool = (new ParseNode("expr", parser.curLine(3))).addChild("operator");
603         bool.addChild("op").addChild("not");
604         bool.addChild("left").addChild(expr);
605         RESULT = bool.getRoot();
606         :}
607    
608         | ISVALID OPENPAREN expr:innerexpr CLOSEPAREN
609         {:
610         debugMessage(PRODSTRING);
611         ParseNode expr  = new ParseNode("expr", parser.curLine(4)); 
612         expr.addChild("isvalid").addChild(innerexpr);
613         RESULT = expr;
614         :}
615
616         | ISVALID OPENPAREN expr:innerexpr COMMA ID:type CLOSEPAREN
617         {:
618         debugMessage(PRODSTRING);
619         ParseNode isvalid = (new ParseNode("expr", parser.curLine(6))).addChild("isvalid");
620         isvalid.addChild(innerexpr);
621         isvalid.addChild("type", parser.curLine(2)).addChild(type);
622         RESULT = isvalid.getRoot();
623         :}
624         ;             
625
626 /** standard *********************************/
627
628 literal ::=
629
630         TRUE
631         {:
632         debugMessage(PRODSTRING);
633         RESULT = (new ParseNode("literal", parser.curLine(1))).addChild("boolean").addChild("true").getRoot();
634         :}
635         
636         | FALSE
637         {:
638         debugMessage(PRODSTRING);
639         RESULT = (new ParseNode("literal", parser.curLine(1))).addChild("boolean").addChild("false").getRoot();
640         :}
641         
642         | DECIMAL:dec
643         {:
644         debugMessage(PRODSTRING);
645         RESULT = (new ParseNode("literal", parser.curLine(1))).addChild("decimal").addChild(dec).getRoot();
646         :}
647          
648         | STRING:str
649         {:
650         debugMessage(PRODSTRING);
651         RESULT = (new ParseNode("literal", parser.curLine(1))).addChild("string").addChild(str).getRoot();
652         :}
653          
654         | CHAR:chr
655         {:
656         debugMessage(PRODSTRING);
657         RESULT = (new ParseNode("literal", parser.curLine(1))).addChild("char").addChild(chr).getRoot();
658         :}
659          
660         | ID:literal
661         {:
662         debugMessage(PRODSTRING);
663         RESULT = (new ParseNode("literal", parser.curLine(1))).addChild("token").addChild(literal).getRoot();
664         :}
665         ;
666
667 set ::=
668     
669         ID:setname
670         {:
671         debugMessage(PRODSTRING);
672         ParseNode set = new ParseNode("set", parser.curLine(1));
673         set.addChild("name").addChild(setname);
674         RESULT = set;
675         :}
676     
677         | OPENBRACE listofliterals:list CLOSEBRACE
678         {:
679         debugMessage(PRODSTRING);
680         ParseNode set = new ParseNode("set", parser.curLine(3));
681         set.addChild(list);
682         RESULT = set;
683         :}
684         ;
685     
686
687 listofliterals ::=
688                
689         listofliterals:list COMMA literal:literal
690         {:
691         debugMessage(PRODSTRING);
692         list.addChild(literal);
693         RESULT = list;
694         :}
695
696         | literal:literal
697         {: 
698         debugMessage(PRODSTRING);
699         ParseNode list = new ParseNode("listofliterals", parser.curLine(1));
700         list.addChild(literal);
701         RESULT = list;
702         :}
703         ;
704
705
706
707