1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53 __version__ = "2.5"
54 __tabversion__ = "2.4"
55
56
57
58
59
60
61
62 yaccdebug = 1
63
64
65 debug_file = 'parser.out'
66 tab_module = 'parsetab'
67 default_lr = 'LALR'
68
69 error_count = 3
70
71 yaccdevel = 0
72
73
74 import re, types, sys, cStringIO, md5, os.path
75
76
78
79
81
82
83
84
85
86
87 try:
88 _INSTANCETYPE = (types.InstanceType, types.ObjectType)
89 except AttributeError:
90 _INSTANCETYPE = types.InstanceType
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
111 - def __str__(self): return self.type
113
114
115
116
117
118
119
120
121
122
125 self.slice = s
126 self.stack = stack
127 self.lexer = None
128 self.parser= None
130 if n >= 0: return self.slice[n].value
131 else: return self.stack[n].value
132
134 self.slice[n].value = v
135
137 return [s.value for s in self.slice[i:j]]
138
140 return len(self.slice)
141
143 return getattr(self.slice[n],"lineno",0)
144
146 startline = getattr(self.slice[n],"lineno",0)
147 endline = getattr(self.slice[n],"endlineno",startline)
148 return startline,endline
149
151 return getattr(self.slice[n],"lexpos",0)
152
154 startpos = getattr(self.slice[n],"lexpos",0)
155 endpos = getattr(self.slice[n],"endlexpos",startpos)
156 return startpos,endpos
157
160
161
162
163
164
165
166
169
170
171
172
173 if magic != "xyzzy":
174 raise YaccError, "Can't directly instantiate Parser. Use yacc() instead."
175
176
177 self.productions = None
178 self.errorfunc = None
179 self.action = { }
180 self.goto = { }
181 self.require = { }
182 self.method = "Unknown LR"
183
186
188 del self.statestack[:]
189 del self.symstack[:]
190 sym = YaccSymbol()
191 sym.type = '$end'
192 self.symstack.append(sym)
193 self.statestack.append(0)
194
195 - def parse(self,input=None,lexer=None,debug=0,tracking=0,tokenfunc=None):
196 if debug or yaccdevel:
197 return self.parsedebug(input,lexer,debug,tracking,tokenfunc)
198 elif tracking:
199 return self.parseopt(input,lexer,debug,tracking,tokenfunc)
200 else:
201 return self.parseopt_notrack(input,lexer,debug,tracking,tokenfunc)
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218 - def parsedebug(self,input=None,lexer=None,debug=0,tracking=0,tokenfunc=None):
219 lookahead = None
220 lookaheadstack = [ ]
221 actions = self.action
222 goto = self.goto
223 prod = self.productions
224 pslice = YaccProduction(None)
225 errorcount = 0
226 endsym = "$end"
227
228 if not lexer:
229 import lex
230 lexer = lex.lexer
231
232
233 pslice.lexer = lexer
234 pslice.parser = self
235
236
237 if input is not None:
238 lexer.input(input)
239
240 if tokenfunc is None:
241
242 get_token = lexer.token
243 else:
244 get_token = tokenfunc
245
246
247
248 statestack = [ ]
249 self.statestack = statestack
250 symstack = [ ]
251 self.symstack = symstack
252
253 pslice.stack = symstack
254 errtoken = None
255
256
257
258 statestack.append(0)
259 sym = YaccSymbol()
260 sym.type = endsym
261 symstack.append(sym)
262 state = 0
263 while 1:
264
265
266
267
268
269 if debug > 1:
270 print 'state', state
271
272
273 if not lookahead:
274 if not lookaheadstack:
275 lookahead = get_token()
276 else:
277 lookahead = lookaheadstack.pop()
278 if not lookahead:
279 lookahead = YaccSymbol()
280 lookahead.type = endsym
281
282
283 if debug:
284 errorlead = ("%s . %s" % (" ".join([xx.type for xx in symstack][1:]), str(lookahead))).lstrip()
285
286
287
288 ltype = lookahead.type
289 t = actions[state].get(ltype)
290
291
292 if debug > 1:
293 print 'action', t
294
295
296 if t is not None:
297 if t > 0:
298
299 if ltype is endsym:
300
301 sys.stderr.write("yacc: Parse error. EOF\n")
302 return
303 statestack.append(t)
304 state = t
305
306
307 if debug > 1:
308 sys.stderr.write("%-60s shift state %s\n" % (errorlead, t))
309
310
311 symstack.append(lookahead)
312 lookahead = None
313
314
315 if errorcount: errorcount -=1
316 continue
317
318 if t < 0:
319
320 p = prod[-t]
321 pname = p.name
322 plen = p.len
323
324
325 sym = YaccSymbol()
326 sym.type = pname
327 sym.value = None
328
329
330 if debug > 1:
331 sys.stderr.write("%-60s reduce %d\n" % (errorlead, -t))
332
333
334 if plen:
335 targ = symstack[-plen-1:]
336 targ[0] = sym
337
338
339 if tracking:
340 t1 = targ[1]
341 sym.lineno = t1.lineno
342 sym.lexpos = t1.lexpos
343 t1 = targ[-1]
344 sym.endlineno = getattr(t1,"endlineno",t1.lineno)
345 sym.endlexpos = getattr(t1,"endlexpos",t1.lexpos)
346
347
348
349
350
351
352
353
354 pslice.slice = targ
355
356 try:
357
358 p.func(pslice)
359 del symstack[-plen:]
360 del statestack[-plen:]
361 symstack.append(sym)
362 state = goto[statestack[-1]][pname]
363 statestack.append(state)
364 except SyntaxError:
365
366 lookaheadstack.append(lookahead)
367 symstack.pop()
368 statestack.pop()
369 state = statestack[-1]
370 sym.type = 'error'
371 lookahead = sym
372 errorcount = error_count
373 self.errorok = 0
374 continue
375
376
377 else:
378
379
380 if tracking:
381 sym.lineno = lexer.lineno
382 sym.lexpos = lexer.lexpos
383
384
385 targ = [ sym ]
386
387
388
389
390
391
392 pslice.slice = targ
393
394 try:
395
396 p.func(pslice)
397 symstack.append(sym)
398 state = goto[statestack[-1]][pname]
399 statestack.append(state)
400 except SyntaxError:
401
402 lookaheadstack.append(lookahead)
403 symstack.pop()
404 statestack.pop()
405 state = statestack[-1]
406 sym.type = 'error'
407 lookahead = sym
408 errorcount = error_count
409 self.errorok = 0
410 continue
411
412
413 if t == 0:
414 n = symstack[-1]
415 return getattr(n,"value",None)
416
417 if t == None:
418
419
420 if debug:
421 sys.stderr.write(errorlead + "\n")
422
423
424
425
426
427
428
429
430
431
432
433
434 if errorcount == 0 or self.errorok:
435 errorcount = error_count
436 self.errorok = 0
437 errtoken = lookahead
438 if errtoken.type is endsym:
439 errtoken = None
440 if self.errorfunc:
441 global errok,token,restart
442 errok = self.errok
443 token = get_token
444 restart = self.restart
445 tok = self.errorfunc(errtoken)
446 del errok, token, restart
447
448 if self.errorok:
449
450
451
452 lookahead = tok
453 errtoken = None
454 continue
455 else:
456 if errtoken:
457 if hasattr(errtoken,"lineno"): lineno = lookahead.lineno
458 else: lineno = 0
459 if lineno:
460 sys.stderr.write("yacc: Syntax error at line %d, token=%s\n" % (lineno, errtoken.type))
461 else:
462 sys.stderr.write("yacc: Syntax error, token=%s" % errtoken.type)
463 else:
464 sys.stderr.write("yacc: Parse error in input. EOF\n")
465 return
466
467 else:
468 errorcount = error_count
469
470
471
472
473
474 if len(statestack) <= 1 and lookahead.type is not endsym:
475 lookahead = None
476 errtoken = None
477 state = 0
478
479 del lookaheadstack[:]
480 continue
481
482
483
484
485
486 if lookahead.type is endsym:
487
488 return
489
490 if lookahead.type != 'error':
491 sym = symstack[-1]
492 if sym.type == 'error':
493
494
495 lookahead = None
496 continue
497 t = YaccSymbol()
498 t.type = 'error'
499 if hasattr(lookahead,"lineno"):
500 t.lineno = lookahead.lineno
501 t.value = lookahead
502 lookaheadstack.append(lookahead)
503 lookahead = t
504 else:
505 symstack.pop()
506 statestack.pop()
507 state = statestack[-1]
508
509 continue
510
511
512 raise RuntimeError, "yacc: internal parser error!!!\n"
513
514
515
516
517
518
519
520
521
522
523 - def parseopt(self,input=None,lexer=None,debug=0,tracking=0,tokenfunc=None):
524 lookahead = None
525 lookaheadstack = [ ]
526 actions = self.action
527 goto = self.goto
528 prod = self.productions
529 pslice = YaccProduction(None)
530 errorcount = 0
531
532
533 if not lexer:
534 import lex
535 lexer = lex.lexer
536
537
538 pslice.lexer = lexer
539 pslice.parser = self
540
541
542 if input is not None:
543 lexer.input(input)
544
545 if tokenfunc is None:
546
547 get_token = lexer.token
548 else:
549 get_token = tokenfunc
550
551
552
553 statestack = [ ]
554 self.statestack = statestack
555 symstack = [ ]
556 self.symstack = symstack
557
558 pslice.stack = symstack
559 errtoken = None
560
561
562
563 statestack.append(0)
564 sym = YaccSymbol()
565 sym.type = '$end'
566 symstack.append(sym)
567 state = 0
568 while 1:
569
570
571
572
573 if not lookahead:
574 if not lookaheadstack:
575 lookahead = get_token()
576 else:
577 lookahead = lookaheadstack.pop()
578 if not lookahead:
579 lookahead = YaccSymbol()
580 lookahead.type = '$end'
581
582
583 ltype = lookahead.type
584 t = actions[state].get(ltype)
585
586 if t is not None:
587 if t > 0:
588
589 if ltype == '$end':
590
591 sys.stderr.write("yacc: Parse error. EOF\n")
592 return
593 statestack.append(t)
594 state = t
595
596 symstack.append(lookahead)
597 lookahead = None
598
599
600 if errorcount: errorcount -=1
601 continue
602
603 if t < 0:
604
605 p = prod[-t]
606 pname = p.name
607 plen = p.len
608
609
610 sym = YaccSymbol()
611 sym.type = pname
612 sym.value = None
613
614 if plen:
615 targ = symstack[-plen-1:]
616 targ[0] = sym
617
618
619 if tracking:
620 t1 = targ[1]
621 sym.lineno = t1.lineno
622 sym.lexpos = t1.lexpos
623 t1 = targ[-1]
624 sym.endlineno = getattr(t1,"endlineno",t1.lineno)
625 sym.endlexpos = getattr(t1,"endlexpos",t1.lexpos)
626
627
628
629
630
631
632
633
634 pslice.slice = targ
635
636 try:
637
638 p.func(pslice)
639 del symstack[-plen:]
640 del statestack[-plen:]
641 symstack.append(sym)
642 state = goto[statestack[-1]][pname]
643 statestack.append(state)
644 except SyntaxError:
645
646 lookaheadstack.append(lookahead)
647 symstack.pop()
648 statestack.pop()
649 state = statestack[-1]
650 sym.type = 'error'
651 lookahead = sym
652 errorcount = error_count
653 self.errorok = 0
654 continue
655
656
657 else:
658
659
660 if tracking:
661 sym.lineno = lexer.lineno
662 sym.lexpos = lexer.lexpos
663
664
665 targ = [ sym ]
666
667
668
669
670
671
672 pslice.slice = targ
673
674 try:
675
676 p.func(pslice)
677 symstack.append(sym)
678 state = goto[statestack[-1]][pname]
679 statestack.append(state)
680 except SyntaxError:
681
682 lookaheadstack.append(lookahead)
683 symstack.pop()
684 statestack.pop()
685 state = statestack[-1]
686 sym.type = 'error'
687 lookahead = sym
688 errorcount = error_count
689 self.errorok = 0
690 continue
691
692
693 if t == 0:
694 n = symstack[-1]
695 return getattr(n,"value",None)
696
697 if t == None:
698
699
700
701
702
703
704
705
706
707
708
709 if errorcount == 0 or self.errorok:
710 errorcount = error_count
711 self.errorok = 0
712 errtoken = lookahead
713 if errtoken.type == '$end':
714 errtoken = None
715 if self.errorfunc:
716 global errok,token,restart
717 errok = self.errok
718 token = get_token
719 restart = self.restart
720 tok = self.errorfunc(errtoken)
721 del errok, token, restart
722
723 if self.errorok:
724
725
726
727 lookahead = tok
728 errtoken = None
729 continue
730 else:
731 if errtoken:
732 if hasattr(errtoken,"lineno"): lineno = lookahead.lineno
733 else: lineno = 0
734 if lineno:
735 sys.stderr.write("yacc: Syntax error at line %d, token=%s\n" % (lineno, errtoken.type))
736 else:
737 sys.stderr.write("yacc: Syntax error, token=%s" % errtoken.type)
738 else:
739 sys.stderr.write("yacc: Parse error in input. EOF\n")
740 return
741
742 else:
743 errorcount = error_count
744
745
746
747
748
749 if len(statestack) <= 1 and lookahead.type != '$end':
750 lookahead = None
751 errtoken = None
752 state = 0
753
754 del lookaheadstack[:]
755 continue
756
757
758
759
760
761 if lookahead.type == '$end':
762
763 return
764
765 if lookahead.type != 'error':
766 sym = symstack[-1]
767 if sym.type == 'error':
768
769
770 lookahead = None
771 continue
772 t = YaccSymbol()
773 t.type = 'error'
774 if hasattr(lookahead,"lineno"):
775 t.lineno = lookahead.lineno
776 t.value = lookahead
777 lookaheadstack.append(lookahead)
778 lookahead = t
779 else:
780 symstack.pop()
781 statestack.pop()
782 state = statestack[-1]
783
784 continue
785
786
787 raise RuntimeError, "yacc: internal parser error!!!\n"
788
789
790
791
792
793
794
795
796
797 - def parseopt_notrack(self,input=None,lexer=None,debug=0,tracking=0,tokenfunc=None):
798 lookahead = None
799 lookaheadstack = [ ]
800 actions = self.action
801 goto = self.goto
802 prod = self.productions
803 pslice = YaccProduction(None)
804 errorcount = 0
805
806
807 if not lexer:
808 import lex
809 lexer = lex.lexer
810
811
812 pslice.lexer = lexer
813 pslice.parser = self
814
815
816 if input is not None:
817 lexer.input(input)
818
819 if tokenfunc is None:
820
821 get_token = lexer.token
822 else:
823 get_token = tokenfunc
824
825
826
827 statestack = [ ]
828 self.statestack = statestack
829 symstack = [ ]
830 self.symstack = symstack
831
832 pslice.stack = symstack
833 errtoken = None
834
835
836
837 statestack.append(0)
838 sym = YaccSymbol()
839 sym.type = '$end'
840 symstack.append(sym)
841 state = 0
842 while 1:
843
844
845
846
847 if not lookahead:
848 if not lookaheadstack:
849 lookahead = get_token()
850 else:
851 lookahead = lookaheadstack.pop()
852 if not lookahead:
853 lookahead = YaccSymbol()
854 lookahead.type = '$end'
855
856
857 ltype = lookahead.type
858 t = actions[state].get(ltype)
859
860 if t is not None:
861 if t > 0:
862
863 if ltype == '$end':
864
865 sys.stderr.write("yacc: Parse error. EOF\n")
866 return
867 statestack.append(t)
868 state = t
869
870 symstack.append(lookahead)
871 lookahead = None
872
873
874 if errorcount: errorcount -=1
875 continue
876
877 if t < 0:
878
879 p = prod[-t]
880 pname = p.name
881 plen = p.len
882
883
884 sym = YaccSymbol()
885 sym.type = pname
886 sym.value = None
887
888 if plen:
889 targ = symstack[-plen-1:]
890 targ[0] = sym
891
892
893
894
895
896
897 pslice.slice = targ
898
899 try:
900
901 p.func(pslice)
902 del symstack[-plen:]
903 del statestack[-plen:]
904 symstack.append(sym)
905 state = goto[statestack[-1]][pname]
906 statestack.append(state)
907 except SyntaxError:
908
909 lookaheadstack.append(lookahead)
910 symstack.pop()
911 statestack.pop()
912 state = statestack[-1]
913 sym.type = 'error'
914 lookahead = sym
915 errorcount = error_count
916 self.errorok = 0
917 continue
918
919
920 else:
921
922 targ = [ sym ]
923
924
925
926
927
928
929 pslice.slice = targ
930
931 try:
932
933 p.func(pslice)
934 symstack.append(sym)
935 state = goto[statestack[-1]][pname]
936 statestack.append(state)
937 except SyntaxError:
938
939 lookaheadstack.append(lookahead)
940 symstack.pop()
941 statestack.pop()
942 state = statestack[-1]
943 sym.type = 'error'
944 lookahead = sym
945 errorcount = error_count
946 self.errorok = 0
947 continue
948
949
950 if t == 0:
951 n = symstack[-1]
952 return getattr(n,"value",None)
953
954 if t == None:
955
956
957
958
959
960
961
962
963
964
965
966 if errorcount == 0 or self.errorok:
967 errorcount = error_count
968 self.errorok = 0
969 errtoken = lookahead
970 if errtoken.type == '$end':
971 errtoken = None
972 if self.errorfunc:
973 global errok,token,restart
974 errok = self.errok
975 token = get_token
976 restart = self.restart
977 tok = self.errorfunc(errtoken)
978 del errok, token, restart
979
980 if self.errorok:
981
982
983
984 lookahead = tok
985 errtoken = None
986 continue
987 else:
988 if errtoken:
989 if hasattr(errtoken,"lineno"): lineno = lookahead.lineno
990 else: lineno = 0
991 if lineno:
992 sys.stderr.write("yacc: Syntax error at line %d, token=%s\n" % (lineno, errtoken.type))
993 else:
994 sys.stderr.write("yacc: Syntax error, token=%s" % errtoken.type)
995 else:
996 sys.stderr.write("yacc: Parse error in input. EOF\n")
997 return
998
999 else:
1000 errorcount = error_count
1001
1002
1003
1004
1005
1006 if len(statestack) <= 1 and lookahead.type != '$end':
1007 lookahead = None
1008 errtoken = None
1009 state = 0
1010
1011 del lookaheadstack[:]
1012 continue
1013
1014
1015
1016
1017
1018 if lookahead.type == '$end':
1019
1020 return
1021
1022 if lookahead.type != 'error':
1023 sym = symstack[-1]
1024 if sym.type == 'error':
1025
1026
1027 lookahead = None
1028 continue
1029 t = YaccSymbol()
1030 t.type = 'error'
1031 if hasattr(lookahead,"lineno"):
1032 t.lineno = lookahead.lineno
1033 t.value = lookahead
1034 lookaheadstack.append(lookahead)
1035 lookahead = t
1036 else:
1037 symstack.pop()
1038 statestack.pop()
1039 state = statestack[-1]
1040
1041 continue
1042
1043
1044 raise RuntimeError, "yacc: internal parser error!!!\n"
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1070 base,ext = os.path.splitext(filename)
1071 if ext != '.py': return 1
1072
1073 try:
1074 f = open(filename)
1075 lines = f.readlines()
1076 f.close()
1077 except IOError:
1078 return 1
1079
1080
1081 fre = re.compile(r'\s*def\s+(p_[a-zA-Z_0-9]*)\(')
1082 counthash = { }
1083 linen = 1
1084 noerror = 1
1085 for l in lines:
1086 m = fre.match(l)
1087 if m:
1088 name = m.group(1)
1089 prev = counthash.get(name)
1090 if not prev:
1091 counthash[name] = linen
1092 else:
1093 sys.stderr.write("%s:%d: Function %s redefined. Previously defined on line %d\n" % (filename,linen,name,prev))
1094 noerror = 0
1095 linen += 1
1096 return noerror
1097
1098
1100 for n,v in d.items():
1101 if n[0:2] == 'p_' and type(v) in (types.FunctionType, types.MethodType): continue
1102 if n[0:2] == 't_': continue
1103
1104 if n[0:2] == 'p_':
1105 sys.stderr.write("yacc: Warning. '%s' not defined as a function\n" % n)
1106 if 1 and isinstance(v,types.FunctionType) and v.func_code.co_argcount == 1:
1107 try:
1108 doc = v.__doc__.split(" ")
1109 if doc[1] == ':':
1110 sys.stderr.write("%s:%d: Warning. Possible grammar rule '%s' defined without p_ prefix.\n" % (v.func_code.co_filename, v.func_code.co_firstlineno,n))
1111 except StandardError:
1112 pass
1113
1114
1115
1116
1117
1118
1119
1120
1121
1123 global Productions, Prodnames, Prodmap, Terminals
1124 global Nonterminals, First, Follow, Precedence, UsedPrecedence, LRitems
1125 global Errorfunc, Signature, Requires
1126
1127 Productions = [None]
1128
1129
1130
1131 Prodnames = { }
1132
1133
1134 Prodmap = { }
1135
1136
1137 Terminals = { }
1138
1139
1140 Nonterminals = { }
1141
1142
1143 First = { }
1144
1145 Follow = { }
1146
1147 Precedence = { }
1148
1149
1150 UsedPrecedence = { }
1151
1152
1153
1154 LRitems = [ ]
1155
1156
1157 Errorfunc = None
1158
1159 Signature = md5.new()
1160
1161
1162
1163 Signature.update(__tabversion__)
1164
1165 Requires = { }
1166
1167
1168 global _vf, _vfc
1169 _vf = cStringIO.StringIO()
1170 _vfc = cStringIO.StringIO()
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1198 for k,v in kw.items():
1199 setattr(self,k,v)
1200 self.lr_index = -1
1201 self.lr0_added = 0
1202 self.lr1_added = 0
1203 self.usyms = [ ]
1204 self.lookaheads = { }
1205 self.lk_added = { }
1206 self.setnumbers = [ ]
1207
1209 if self.prod:
1210 s = "%s -> %s" % (self.name," ".join(self.prod))
1211 else:
1212 s = "%s -> <empty>" % self.name
1213 return s
1214
1217
1218
1220 if n > len(self.prod): return None
1221 p = Production()
1222 p.name = self.name
1223 p.prod = list(self.prod)
1224 p.number = self.number
1225 p.lr_index = n
1226 p.lookaheads = { }
1227 p.setnumbers = self.setnumbers
1228 p.prod.insert(n,".")
1229 p.prod = tuple(p.prod)
1230 p.len = len(p.prod)
1231 p.usyms = self.usyms
1232
1233
1234 try:
1235 p.lrafter = Prodnames[p.prod[n+1]]
1236 except (IndexError,KeyError),e:
1237 p.lrafter = []
1238 try:
1239 p.lrbefore = p.prod[n-1]
1240 except IndexError:
1241 p.lrbefore = None
1242
1243 return p
1244
1247
1248
1249 _is_identifier = re.compile(r'^[a-zA-Z0-9_-]+$')
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1269
1270 if Terminals.has_key(prodname):
1271 sys.stderr.write("%s:%d: Illegal rule name '%s'. Already defined as a token.\n" % (file,line,prodname))
1272 return -1
1273 if prodname == 'error':
1274 sys.stderr.write("%s:%d: Illegal rule name '%s'. error is a reserved word.\n" % (file,line,prodname))
1275 return -1
1276
1277 if not _is_identifier.match(prodname):
1278 sys.stderr.write("%s:%d: Illegal rule name '%s'\n" % (file,line,prodname))
1279 return -1
1280
1281 for x in range(len(syms)):
1282 s = syms[x]
1283 if s[0] in "'\"":
1284 try:
1285 c = eval(s)
1286 if (len(c) > 1):
1287 sys.stderr.write("%s:%d: Literal token %s in rule '%s' may only be a single character\n" % (file,line,s, prodname))
1288 return -1
1289 if not Terminals.has_key(c):
1290 Terminals[c] = []
1291 syms[x] = c
1292 continue
1293 except SyntaxError:
1294 pass
1295 if not _is_identifier.match(s) and s != '%prec':
1296 sys.stderr.write("%s:%d: Illegal name '%s' in rule '%s'\n" % (file,line,s, prodname))
1297 return -1
1298
1299
1300 map = "%s -> %s" % (prodname,syms)
1301 if Prodmap.has_key(map):
1302 m = Prodmap[map]
1303 sys.stderr.write("%s:%d: Duplicate rule %s.\n" % (file,line, m))
1304 sys.stderr.write("%s:%d: Previous definition at %s:%d\n" % (file,line, m.file, m.line))
1305 return -1
1306
1307 p = Production()
1308 p.name = prodname
1309 p.prod = syms
1310 p.file = file
1311 p.line = line
1312 p.func = f
1313 p.number = len(Productions)
1314
1315
1316 Productions.append(p)
1317 Prodmap[map] = p
1318 if not Nonterminals.has_key(prodname):
1319 Nonterminals[prodname] = [ ]
1320
1321
1322 i = 0
1323 while i < len(p.prod):
1324 t = p.prod[i]
1325 if t == '%prec':
1326 try:
1327 precname = p.prod[i+1]
1328 except IndexError:
1329 sys.stderr.write("%s:%d: Syntax error. Nothing follows %%prec.\n" % (p.file,p.line))
1330 return -1
1331
1332 prec = Precedence.get(precname,None)
1333 if not prec:
1334 sys.stderr.write("%s:%d: Nothing known about the precedence of '%s'\n" % (p.file,p.line,precname))
1335 return -1
1336 else:
1337 p.prec = prec
1338 UsedPrecedence[precname] = 1
1339 del p.prod[i]
1340 del p.prod[i]
1341 continue
1342
1343 if Terminals.has_key(t):
1344 Terminals[t].append(p.number)
1345
1346 if not hasattr(p,"prec"):
1347 p.prec = Precedence.get(t,('right',0))
1348 else:
1349 if not Nonterminals.has_key(t):
1350 Nonterminals[t] = [ ]
1351 Nonterminals[t].append(p.number)
1352 i += 1
1353
1354 if not hasattr(p,"prec"):
1355 p.prec = ('right',0)
1356
1357
1358 p.len = len(p.prod)
1359 p.prod = tuple(p.prod)
1360
1361
1362 p.usyms = [ ]
1363 for s in p.prod:
1364 if s not in p.usyms:
1365 p.usyms.append(s)
1366
1367
1368 try:
1369 Prodnames[p.name].append(p)
1370 except KeyError:
1371 Prodnames[p.name] = [ p ]
1372 return 0
1373
1374
1375
1376
1378 line = f.func_code.co_firstlineno
1379 file = f.func_code.co_filename
1380 error = 0
1381
1382 if isinstance(f,types.MethodType):
1383 reqdargs = 2
1384 else:
1385 reqdargs = 1
1386
1387 if f.func_code.co_argcount > reqdargs:
1388 sys.stderr.write("%s:%d: Rule '%s' has too many arguments.\n" % (file,line,f.__name__))
1389 return -1
1390
1391 if f.func_code.co_argcount < reqdargs:
1392 sys.stderr.write("%s:%d: Rule '%s' requires an argument.\n" % (file,line,f.__name__))
1393 return -1
1394
1395 if f.__doc__:
1396
1397 pstrings = f.__doc__.splitlines()
1398 lastp = None
1399 dline = line
1400 for ps in pstrings:
1401 dline += 1
1402 p = ps.split()
1403 if not p: continue
1404 try:
1405 if p[0] == '|':
1406
1407 if not lastp:
1408 sys.stderr.write("%s:%d: Misplaced '|'.\n" % (file,dline))
1409 return -1
1410 prodname = lastp
1411 if len(p) > 1:
1412 syms = p[1:]
1413 else:
1414 syms = [ ]
1415 else:
1416 prodname = p[0]
1417 lastp = prodname
1418 assign = p[1]
1419 if len(p) > 2:
1420 syms = p[2:]
1421 else:
1422 syms = [ ]
1423 if assign != ':' and assign != '::=':
1424 sys.stderr.write("%s:%d: Syntax error. Expected ':'\n" % (file,dline))
1425 return -1
1426
1427
1428 e = add_production(f,file,dline,prodname,syms)
1429 error += e
1430
1431
1432 except StandardError:
1433 sys.stderr.write("%s:%d: Syntax error in rule '%s'\n" % (file,dline,ps))
1434 error -= 1
1435 else:
1436 sys.stderr.write("%s:%d: No documentation string specified in function '%s'\n" % (file,line,f.__name__))
1437 return error
1438
1439
1440
1441
1443 '''
1444 Find each symbol that can be reached from the start symbol.
1445 Print a warning for any nonterminals that can't be reached.
1446 (Unused terminals have already had their warning.)
1447 '''
1448 Reachable = { }
1449 for s in Terminals.keys() + Nonterminals.keys():
1450 Reachable[s] = 0
1451
1452 mark_reachable_from( Productions[0].prod[0], Reachable )
1453
1454 for s in Nonterminals.keys():
1455 if not Reachable[s]:
1456 sys.stderr.write("yacc: Symbol '%s' is unreachable.\n" % s)
1457
1459 '''
1460 Mark all symbols that are reachable from symbol s.
1461 '''
1462 if Reachable[s]:
1463
1464 return
1465 Reachable[s] = 1
1466 for p in Prodnames.get(s,[]):
1467 for r in p.prod:
1468 mark_reachable_from(r, Reachable)
1469
1470
1471
1472
1473
1474
1475
1476
1478 '''
1479 Raise an error for any symbols that don't terminate.
1480 '''
1481 Terminates = {}
1482
1483
1484 for t in Terminals.keys():
1485 Terminates[t] = 1
1486
1487 Terminates['$end'] = 1
1488
1489
1490
1491
1492 for n in Nonterminals.keys():
1493 Terminates[n] = 0
1494
1495
1496 while 1:
1497 some_change = 0
1498 for (n,pl) in Prodnames.items():
1499
1500 for p in pl:
1501
1502 for s in p.prod:
1503 if not Terminates[s]:
1504
1505
1506 p_terminates = 0
1507 break
1508 else:
1509
1510
1511
1512 p_terminates = 1
1513
1514 if p_terminates:
1515
1516 if not Terminates[n]:
1517 Terminates[n] = 1
1518 some_change = 1
1519
1520 break
1521
1522 if not some_change:
1523 break
1524
1525 some_error = 0
1526 for (s,terminates) in Terminates.items():
1527 if not terminates:
1528 if not Prodnames.has_key(s) and not Terminals.has_key(s) and s != 'error':
1529
1530
1531 pass
1532 else:
1533 sys.stderr.write("yacc: Infinite recursion detected for symbol '%s'.\n" % s)
1534 some_error = 1
1535
1536 return some_error
1537
1538
1539
1540
1541
1542
1544 error = 0
1545 for p in Productions:
1546 if not p: continue
1547
1548 for s in p.prod:
1549 if not Prodnames.has_key(s) and not Terminals.has_key(s) and s != 'error':
1550 sys.stderr.write("%s:%d: Symbol '%s' used, but not defined as a token or a rule.\n" % (p.file,p.line,s))
1551 error = 1
1552 continue
1553
1554 unused_tok = 0
1555
1556 if yaccdebug:
1557 _vf.write("Unused terminals:\n\n")
1558 for s,v in Terminals.items():
1559 if s != 'error' and not v:
1560 sys.stderr.write("yacc: Warning. Token '%s' defined, but not used.\n" % s)
1561 if yaccdebug: _vf.write(" %s\n"% s)
1562 unused_tok += 1
1563
1564
1565 if yaccdebug:
1566 _vf.write("\nGrammar\n\n")
1567 for i in range(1,len(Productions)):
1568 _vf.write("Rule %-5d %s\n" % (i, Productions[i]))
1569
1570 unused_prod = 0
1571
1572 for s,v in Nonterminals.items():
1573 if not v:
1574 p = Prodnames[s][0]
1575
1576 unused_prod += 1
1577
1578
1579 if unused_tok == 1:
1580 sys.stderr.write("yacc: Warning. There is 1 unused token.\n")
1581 if unused_tok > 1:
1582 sys.stderr.write("yacc: Warning. There are %d unused tokens.\n" % unused_tok)
1583
1584
1585
1586
1587
1588
1589 if yaccdebug:
1590 _vf.write("\nTerminals, with rules where they appear\n\n")
1591 ks = Terminals.keys()
1592 ks.sort()
1593 for k in ks:
1594 _vf.write("%-20s : %s\n" % (k, " ".join([str(s) for s in Terminals[k]])))
1595 _vf.write("\nNonterminals, with rules where they appear\n\n")
1596 ks = Nonterminals.keys()
1597 ks.sort()
1598 for k in ks:
1599 _vf.write("%-20s : %s\n" % (k, " ".join([str(s) for s in Nonterminals[k]])))
1600
1601 if (cycle_check):
1602 compute_reachable()
1603 error += compute_terminates()
1604
1605 return error
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1623 for p in Productions:
1624 lastlri = p
1625 lri = p.lr_item(0)
1626 i = 0
1627 while 1:
1628 lri = p.lr_item(i)
1629 lastlri.lr_next = lri
1630 if not lri: break
1631 lri.lr_num = len(LRitems)
1632 LRitems.append(lri)
1633 lastlri = lri
1634 i += 1
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1648 plevel = 0
1649 error = 0
1650 for p in plist:
1651 plevel += 1
1652 try:
1653 prec = p[0]
1654 terms = p[1:]
1655 if prec != 'left' and prec != 'right' and prec != 'nonassoc':
1656 sys.stderr.write("yacc: Invalid precedence '%s'\n" % prec)
1657 return -1
1658 for t in terms:
1659 if Precedence.has_key(t):
1660 sys.stderr.write("yacc: Precedence already specified for terminal '%s'\n" % t)
1661 error += 1
1662 continue
1663 Precedence[t] = (prec,plevel)
1664 except:
1665 sys.stderr.write("yacc: Invalid precedence table.\n")
1666 error += 1
1667
1668 return error
1669
1670
1671
1672
1673
1674
1675
1676
1678 error = 0
1679 for precname in Precedence.keys():
1680 if not (Terminals.has_key(precname) or UsedPrecedence.has_key(precname)):
1681 sys.stderr.write("yacc: Precedence rule '%s' defined for unknown symbol '%s'\n" % (Precedence[precname][0],precname))
1682 error += 1
1683 return error
1684
1685
1686
1687
1688
1689
1690
1691
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1709
1710
1711 result = [ ]
1712 for x in beta:
1713 x_produces_empty = 0
1714
1715
1716 for f in First[x]:
1717 if f == '<empty>':
1718 x_produces_empty = 1
1719 else:
1720 if f not in result: result.append(f)
1721
1722 if x_produces_empty:
1723
1724
1725 pass
1726 else:
1727
1728 break
1729 else:
1730
1731
1732
1733 result.append('<empty>')
1734
1735 return result
1736
1737
1738
1739
1740
1741
1743
1744 for k in Nonterminals.keys():
1745 Follow[k] = [ ]
1746
1747 if not start:
1748 start = Productions[1].name
1749
1750 Follow[start] = [ '$end' ]
1751
1752 while 1:
1753 didadd = 0
1754 for p in Productions[1:]:
1755
1756 for i in range(len(p.prod)):
1757 B = p.prod[i]
1758 if Nonterminals.has_key(B):
1759
1760 fst = first(p.prod[i+1:])
1761 hasempty = 0
1762 for f in fst:
1763 if f != '<empty>' and f not in Follow[B]:
1764 Follow[B].append(f)
1765 didadd = 1
1766 if f == '<empty>':
1767 hasempty = 1
1768 if hasempty or i == (len(p.prod)-1):
1769
1770 for f in Follow[p.name]:
1771 if f not in Follow[B]:
1772 Follow[B].append(f)
1773 didadd = 1
1774 if not didadd: break
1775
1776 if 0 and yaccdebug:
1777 _vf.write('\nFollow:\n')
1778 for k in Nonterminals.keys():
1779 _vf.write("%-20s : %s\n" % (k, " ".join([str(s) for s in Follow[k]])))
1780
1781
1782
1783
1784
1785
1787
1788
1789 for t in Terminals.keys():
1790 First[t] = [t]
1791
1792 First['$end'] = ['$end']
1793 First['#'] = ['#']
1794
1795
1796
1797
1798 for n in Nonterminals.keys():
1799 First[n] = []
1800
1801
1802 while 1:
1803 some_change = 0
1804 for n in Nonterminals.keys():
1805 for p in Prodnames[n]:
1806 for f in first(p.prod):
1807 if f not in First[n]:
1808 First[n].append( f )
1809 some_change = 1
1810 if not some_change:
1811 break
1812
1813 if 0 and yaccdebug:
1814 _vf.write('\nFirst:\n')
1815 for k in Nonterminals.keys():
1816 _vf.write("%-20s : %s\n" %
1817 (k, " ".join([str(s) for s in First[k]])))
1818
1819
1820
1821
1822
1823
1824
1825
1826
1828 global _lr_action, _lr_goto, _lr_method
1829 global _lr_goto_cache, _lr0_cidhash
1830
1831 _lr_action = { }
1832 _lr_goto = { }
1833 _lr_method = "Unknown"
1834 _lr_goto_cache = { }
1835 _lr0_cidhash = { }
1836
1837
1838
1839
1840
1841 _add_count = 0
1842
1844 global _add_count
1845
1846 _add_count += 1
1847 prodlist = Productions
1848
1849
1850 J = I[:]
1851 didadd = 1
1852 while didadd:
1853 didadd = 0
1854 for j in J:
1855 for x in j.lrafter:
1856 if x.lr0_added == _add_count: continue
1857
1858 J.append(x.lr_next)
1859 x.lr0_added = _add_count
1860 didadd = 1
1861
1862 return J
1863
1864
1865
1866
1867
1868
1869
1870
1872
1873 g = _lr_goto_cache.get((id(I),x),None)
1874 if g: return g
1875
1876
1877
1878
1879 s = _lr_goto_cache.get(x,None)
1880 if not s:
1881 s = { }
1882 _lr_goto_cache[x] = s
1883
1884 gs = [ ]
1885 for p in I:
1886 n = p.lr_next
1887 if n and n.lrbefore == x:
1888 s1 = s.get(id(n),None)
1889 if not s1:
1890 s1 = { }
1891 s[id(n)] = s1
1892 gs.append(n)
1893 s = s1
1894 g = s.get('$end',None)
1895 if not g:
1896 if gs:
1897 g = lr0_closure(gs)
1898 s['$end'] = g
1899 else:
1900 s['$end'] = gs
1901 _lr_goto_cache[(id(I),x)] = g
1902 return g
1903
1904 _lr0_cidhash = { }
1905
1906
1908
1909 C = [ lr0_closure([Productions[0].lr_next]) ]
1910 i = 0
1911 for I in C:
1912 _lr0_cidhash[id(I)] = i
1913 i += 1
1914
1915
1916 i = 0
1917 while i < len(C):
1918 I = C[i]
1919 i += 1
1920
1921
1922 asyms = { }
1923 for ii in I:
1924 for s in ii.usyms:
1925 asyms[s] = None
1926
1927 for x in asyms.keys():
1928 g = lr0_goto(I,x)
1929 if not g: continue
1930 if _lr0_cidhash.has_key(id(g)): continue
1931 _lr0_cidhash[id(g)] = len(C)
1932 C.append(g)
1933
1934 return C
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1968 nullable = {}
1969 num_nullable = 0
1970 while 1:
1971 for p in Productions[1:]:
1972 if p.len == 0:
1973 nullable[p.name] = 1
1974 continue
1975 for t in p.prod:
1976 if not nullable.has_key(t): break
1977 else:
1978 nullable[p.name] = 1
1979 if len(nullable) == num_nullable: break
1980 num_nullable = len(nullable)
1981 return nullable
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1995 trans = []
1996 for state in range(len(C)):
1997 for p in C[state]:
1998 if p.lr_index < p.len - 1:
1999 t = (state,p.prod[p.lr_index+1])
2000 if Nonterminals.has_key(t[1]):
2001 if t not in trans: trans.append(t)
2002 state = state + 1
2003 return trans
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2015 dr_set = { }
2016 state,N = trans
2017 terms = []
2018
2019 g = lr0_goto(C[state],N)
2020 for p in g:
2021 if p.lr_index < p.len - 1:
2022 a = p.prod[p.lr_index+1]
2023 if Terminals.has_key(a):
2024 if a not in terms: terms.append(a)
2025
2026
2027 if state == 0 and N == Productions[0].prod[0]:
2028 terms.append('$end')
2029
2030 return terms
2031
2032
2033
2034
2035
2036
2037
2039
2040 rel = []
2041 state, N = trans
2042
2043 g = lr0_goto(C[state],N)
2044 j = _lr0_cidhash.get(id(g),-1)
2045 for p in g:
2046 if p.lr_index < p.len - 1:
2047 a = p.prod[p.lr_index + 1]
2048 if empty.has_key(a):
2049 rel.append((j,a))
2050
2051 return rel
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2082
2083 lookdict = {}
2084 includedict = {}
2085
2086
2087 dtrans = {}
2088 for t in trans:
2089 dtrans[t] = 1
2090
2091
2092 for state,N in trans:
2093 lookb = []
2094 includes = []
2095 for p in C[state]:
2096 if p.name != N: continue
2097
2098
2099
2100
2101 lr_index = p.lr_index
2102 j = state
2103 while lr_index < p.len - 1:
2104 lr_index = lr_index + 1
2105 t = p.prod[lr_index]
2106
2107
2108 if dtrans.has_key((j,t)):
2109
2110
2111
2112
2113 li = lr_index + 1
2114 while li < p.len:
2115 if Terminals.has_key(p.prod[li]): break
2116 if not nullable.has_key(p.prod[li]): break
2117 li = li + 1
2118 else:
2119
2120 includes.append((j,t))
2121
2122 g = lr0_goto(C[j],t)
2123 j = _lr0_cidhash.get(id(g),-1)
2124
2125
2126 for r in C[j]:
2127 if r.name != p.name: continue
2128 if r.len != p.len: continue
2129 i = 0
2130
2131 while i < r.lr_index:
2132 if r.prod[i] != p.prod[i+1]: break
2133 i = i + 1
2134 else:
2135 lookb.append((j,r))
2136 for i in includes:
2137 if not includedict.has_key(i): includedict[i] = []
2138 includedict[i].append((state,N))
2139 lookdict[(state,N)] = lookb
2140
2141 return lookdict,includedict
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2161 N = { }
2162 for x in X:
2163 N[x] = 0
2164 stack = []
2165 F = { }
2166 for x in X:
2167 if N[x] == 0: traverse(x,N,stack,F,X,R,FP)
2168 return F
2169
2171 stack.append(x)
2172 d = len(stack)
2173 N[x] = d
2174 F[x] = FP(x)
2175
2176 rel = R(x)
2177 for y in rel:
2178 if N[y] == 0:
2179 traverse(y,N,stack,F,X,R,FP)
2180 N[x] = min(N[x],N[y])
2181 for a in F.get(y,[]):
2182 if a not in F[x]: F[x].append(a)
2183 if N[x] == d:
2184 N[stack[-1]] = sys.maxint
2185 F[stack[-1]] = F[x]
2186 element = stack.pop()
2187 while element != x:
2188 N[stack[-1]] = sys.maxint
2189 F[stack[-1]] = F[x]
2190 element = stack.pop()
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2227 FP = lambda x: readsets[x]
2228 R = lambda x: inclsets.get(x,[])
2229 F = digraph(ntrans,R,FP)
2230 return F
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2245 for trans,lb in lookbacks.items():
2246
2247 for state,p in lb:
2248 if not p.lookaheads.has_key(state):
2249 p.lookaheads[state] = []
2250 f = followset.get(trans,[])
2251 for a in f:
2252 if a not in p.lookaheads[state]: p.lookaheads[state].append(a)
2253
2254
2255
2256
2257
2258
2259
2260
2279
2280
2281
2282
2283
2284
2286 global _lr_method
2287 goto = _lr_goto
2288 action = _lr_action
2289 actionp = { }
2290
2291 _lr_method = method
2292
2293 n_srconflict = 0
2294 n_rrconflict = 0
2295
2296 if yaccdebug:
2297 sys.stderr.write("yacc: Generating %s parsing table...\n" % method)
2298 _vf.write("\n\nParsing method: %s\n\n" % method)
2299
2300
2301
2302
2303 C = lr0_items()
2304
2305 if method == 'LALR':
2306 add_lalr_lookaheads(C)
2307
2308
2309
2310 st = 0
2311 for I in C:
2312
2313 actlist = [ ]
2314 st_action = { }
2315 st_actionp = { }
2316 st_goto = { }
2317 if yaccdebug:
2318 _vf.write("\nstate %d\n\n" % st)
2319 for p in I:
2320 _vf.write(" (%d) %s\n" % (p.number, str(p)))
2321 _vf.write("\n")
2322
2323 for p in I:
2324 try:
2325 if p.len == p.lr_index + 1:
2326 if p.name == "S'":
2327
2328 st_action["$end"] = 0
2329 st_actionp["$end"] = p
2330 else:
2331
2332 if method == 'LALR':
2333 laheads = p.lookaheads[st]
2334 else:
2335 laheads = Follow[p.name]
2336 for a in laheads:
2337 actlist.append((a,p,"reduce using rule %d (%s)" % (p.number,p)))
2338 r = st_action.get(a,None)
2339 if r is not None:
2340
2341 if r > 0:
2342
2343
2344
2345 sprec,slevel = Productions[st_actionp[a].number].prec
2346 rprec,rlevel = Precedence.get(a,('right',0))
2347 if (slevel < rlevel) or ((slevel == rlevel) and (rprec == 'left')):
2348
2349 st_action[a] = -p.number
2350 st_actionp[a] = p
2351 if not slevel and not rlevel:
2352 _vfc.write("shift/reduce conflict in state %d resolved as reduce.\n" % st)
2353 _vf.write(" ! shift/reduce conflict for %s resolved as reduce.\n" % a)
2354 n_srconflict += 1
2355 elif (slevel == rlevel) and (rprec == 'nonassoc'):
2356 st_action[a] = None
2357 else:
2358
2359 if not rlevel:
2360 _vfc.write("shift/reduce conflict in state %d resolved as shift.\n" % st)
2361 _vf.write(" ! shift/reduce conflict for %s resolved as shift.\n" % a)
2362 n_srconflict +=1
2363 elif r < 0:
2364
2365
2366 oldp = Productions[-r]
2367 pp = Productions[p.number]
2368 if oldp.line > pp.line:
2369 st_action[a] = -p.number
2370 st_actionp[a] = p
2371
2372 n_rrconflict += 1
2373 _vfc.write("reduce/reduce conflict in state %d resolved using rule %d (%s).\n" % (st, st_actionp[a].number, st_actionp[a]))
2374 _vf.write(" ! reduce/reduce conflict for %s resolved using rule %d (%s).\n" % (a,st_actionp[a].number, st_actionp[a]))
2375 else:
2376 sys.stderr.write("Unknown conflict in state %d\n" % st)
2377 else:
2378 st_action[a] = -p.number
2379 st_actionp[a] = p
2380 else:
2381 i = p.lr_index
2382 a = p.prod[i+1]
2383 if Terminals.has_key(a):
2384 g = lr0_goto(I,a)
2385 j = _lr0_cidhash.get(id(g),-1)
2386 if j >= 0:
2387
2388 actlist.append((a,p,"shift and go to state %d" % j))
2389 r = st_action.get(a,None)
2390 if r is not None:
2391
2392 if r > 0:
2393 if r != j:
2394 sys.stderr.write("Shift/shift conflict in state %d\n" % st)
2395 elif r < 0:
2396
2397
2398
2399
2400 rprec,rlevel = Productions[st_actionp[a].number].prec
2401 sprec,slevel = Precedence.get(a,('right',0))
2402 if (slevel > rlevel) or ((slevel == rlevel) and (rprec == 'right')):
2403
2404 st_action[a] = j
2405 st_actionp[a] = p
2406 if not rlevel:
2407 n_srconflict += 1
2408 _vfc.write("shift/reduce conflict in state %d resolved as shift.\n" % st)
2409 _vf.write(" ! shift/reduce conflict for %s resolved as shift.\n" % a)
2410 elif (slevel == rlevel) and (rprec == 'nonassoc'):
2411 st_action[a] = None
2412 else:
2413
2414 if not slevel and not rlevel:
2415 n_srconflict +=1
2416 _vfc.write("shift/reduce conflict in state %d resolved as reduce.\n" % st)
2417 _vf.write(" ! shift/reduce conflict for %s resolved as reduce.\n" % a)
2418
2419 else:
2420 sys.stderr.write("Unknown conflict in state %d\n" % st)
2421 else:
2422 st_action[a] = j
2423 st_actionp[a] = p
2424
2425 except StandardError,e:
2426 print sys.exc_info()
2427 raise YaccError, "Hosed in lr_parse_table"
2428
2429
2430 if yaccdebug:
2431 _actprint = { }
2432 for a,p,m in actlist:
2433 if st_action.has_key(a):
2434 if p is st_actionp[a]:
2435 _vf.write(" %-15s %s\n" % (a,m))
2436 _actprint[(a,m)] = 1
2437 _vf.write("\n")
2438 for a,p,m in actlist:
2439 if st_action.has_key(a):
2440 if p is not st_actionp[a]:
2441 if not _actprint.has_key((a,m)):
2442 _vf.write(" ! %-15s [ %s ]\n" % (a,m))
2443 _actprint[(a,m)] = 1
2444
2445
2446 if yaccdebug:
2447 _vf.write("\n")
2448 nkeys = { }
2449 for ii in I:
2450 for s in ii.usyms:
2451 if Nonterminals.has_key(s):
2452 nkeys[s] = None
2453 for n in nkeys.keys():
2454 g = lr0_goto(I,n)
2455 j = _lr0_cidhash.get(id(g),-1)
2456 if j >= 0:
2457 st_goto[n] = j
2458 if yaccdebug:
2459 _vf.write(" %-30s shift and go to state %d\n" % (n,j))
2460
2461 action[st] = st_action
2462 actionp[st] = st_actionp
2463 goto[st] = st_goto
2464
2465 st += 1
2466
2467 if yaccdebug:
2468 if n_srconflict == 1:
2469 sys.stderr.write("yacc: %d shift/reduce conflict\n" % n_srconflict)
2470 if n_srconflict > 1:
2471 sys.stderr.write("yacc: %d shift/reduce conflicts\n" % n_srconflict)
2472 if n_rrconflict == 1:
2473 sys.stderr.write("yacc: %d reduce/reduce conflict\n" % n_rrconflict)
2474 if n_rrconflict > 1:
2475 sys.stderr.write("yacc: %d reduce/reduce conflicts\n" % n_rrconflict)
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2488 if isinstance(modulename, types.ModuleType):
2489 print >>sys.stderr, "Warning module %s is inconsistent with the grammar (ignored)" % modulename
2490 return
2491
2492 basemodulename = modulename.split(".")[-1]
2493 filename = os.path.join(outputdir,basemodulename) + ".py"
2494 try:
2495 f = open(filename,"w")
2496
2497 f.write("""
2498 # %s
2499 # This file is automatically generated. Do not edit.
2500
2501 _lr_method = %s
2502
2503 _lr_signature = %s
2504 """ % (filename, repr(_lr_method), repr(Signature.digest())))
2505
2506
2507 smaller = 1
2508
2509
2510 if smaller:
2511 items = { }
2512
2513 for s,nd in _lr_action.items():
2514 for name,v in nd.items():
2515 i = items.get(name)
2516 if not i:
2517 i = ([],[])
2518 items[name] = i
2519 i[0].append(s)
2520 i[1].append(v)
2521
2522 f.write("\n_lr_action_items = {")
2523 for k,v in items.items():
2524 f.write("%r:([" % k)
2525 for i in v[0]:
2526 f.write("%r," % i)
2527 f.write("],[")
2528 for i in v[1]:
2529 f.write("%r," % i)
2530
2531 f.write("]),")
2532 f.write("}\n")
2533
2534 f.write("""
2535 _lr_action = { }
2536 for _k, _v in _lr_action_items.items():
2537 for _x,_y in zip(_v[0],_v[1]):
2538 if not _lr_action.has_key(_x): _lr_action[_x] = { }
2539 _lr_action[_x][_k] = _y
2540 del _lr_action_items
2541 """)
2542
2543 else:
2544 f.write("\n_lr_action = { ");
2545 for k,v in _lr_action.items():
2546 f.write("(%r,%r):%r," % (k[0],k[1],v))
2547 f.write("}\n");
2548
2549 if smaller:
2550
2551 items = { }
2552
2553 for s,nd in _lr_goto.items():
2554 for name,v in nd.items():
2555 i = items.get(name)
2556 if not i:
2557 i = ([],[])
2558 items[name] = i
2559 i[0].append(s)
2560 i[1].append(v)
2561
2562 f.write("\n_lr_goto_items = {")
2563 for k,v in items.items():
2564 f.write("%r:([" % k)
2565 for i in v[0]:
2566 f.write("%r," % i)
2567 f.write("],[")
2568 for i in v[1]:
2569 f.write("%r," % i)
2570
2571 f.write("]),")
2572 f.write("}\n")
2573
2574 f.write("""
2575 _lr_goto = { }
2576 for _k, _v in _lr_goto_items.items():
2577 for _x,_y in zip(_v[0],_v[1]):
2578 if not _lr_goto.has_key(_x): _lr_goto[_x] = { }
2579 _lr_goto[_x][_k] = _y
2580 del _lr_goto_items
2581 """)
2582 else:
2583 f.write("\n_lr_goto = { ");
2584 for k,v in _lr_goto.items():
2585 f.write("(%r,%r):%r," % (k[0],k[1],v))
2586 f.write("}\n");
2587
2588
2589 f.write("_lr_productions = [\n")
2590 for p in Productions:
2591 if p:
2592 if (p.func):
2593 f.write(" (%r,%d,%r,%r,%d),\n" % (p.name, p.len, p.func.__name__,p.file,p.line))
2594 else:
2595 f.write(" (%r,%d,None,None,None),\n" % (p.name, p.len))
2596 else:
2597 f.write(" None,\n")
2598 f.write("]\n")
2599
2600 f.close()
2601
2602 except IOError,e:
2603 print >>sys.stderr, "Unable to create '%s'" % filename
2604 print >>sys.stderr, e
2605 return
2606
2608 global _lr_action, _lr_goto, _lr_productions, _lr_method
2609 try:
2610 if isinstance(module,types.ModuleType):
2611 parsetab = module
2612 else:
2613 exec "import %s as parsetab" % module
2614
2615 if (optimize) or (Signature.digest() == parsetab._lr_signature):
2616 _lr_action = parsetab._lr_action
2617 _lr_goto = parsetab._lr_goto
2618 _lr_productions = parsetab._lr_productions
2619 _lr_method = parsetab._lr_method
2620 return 1
2621 else:
2622 return 0
2623
2624 except (ImportError,AttributeError):
2625 return 0
2626
2627
2628
2629
2630
2631
2632
2633
2635 global yaccdebug
2636 yaccdebug = debug
2637
2638 initialize_vars()
2639 files = { }
2640 error = 0
2641
2642
2643
2644 Signature.update(method)
2645
2646
2647
2648
2649 if module:
2650
2651 if isinstance(module, types.ModuleType):
2652 ldict = module.__dict__
2653 elif isinstance(module, _INSTANCETYPE):
2654 _items = [(k,getattr(module,k)) for k in dir(module)]
2655 ldict = { }
2656 for i in _items:
2657 ldict[i[0]] = i[1]
2658 else:
2659 raise ValueError,"Expected a module"
2660
2661 else:
2662
2663
2664
2665 try:
2666 raise RuntimeError
2667 except RuntimeError:
2668 e,b,t = sys.exc_info()
2669 f = t.tb_frame
2670 f = f.f_back
2671 if f.f_globals is f.f_locals:
2672 ldict = f.f_globals
2673 else:
2674 ldict = f.f_globals.copy()
2675 ldict.update(f.f_locals)
2676
2677
2678 if not start:
2679 start = ldict.get("start",None)
2680 if start:
2681 Signature.update(start)
2682
2683
2684 ef = ldict.get('p_error',None)
2685 if ef:
2686 if isinstance(ef,types.FunctionType):
2687 ismethod = 0
2688 elif isinstance(ef, types.MethodType):
2689 ismethod = 1
2690 else:
2691 raise YaccError,"'p_error' defined, but is not a function or method."
2692 eline = ef.func_code.co_firstlineno
2693 efile = ef.func_code.co_filename
2694 files[efile] = None
2695
2696 if (ef.func_code.co_argcount != 1+ismethod):
2697 raise YaccError,"%s:%d: p_error() requires 1 argument." % (efile,eline)
2698 global Errorfunc
2699 Errorfunc = ef
2700 else:
2701 print >>sys.stderr, "yacc: Warning. no p_error() function is defined."
2702
2703
2704
2705 if (optimize and lr_read_tables(tabmodule,1)):
2706
2707 del Productions[:]
2708 for p in _lr_productions:
2709 if not p:
2710 Productions.append(None)
2711 else:
2712 m = MiniProduction()
2713 m.name = p[0]
2714 m.len = p[1]
2715 m.file = p[3]
2716 m.line = p[4]
2717 if p[2]:
2718 m.func = ldict[p[2]]
2719 Productions.append(m)
2720
2721 else:
2722
2723 if (module and isinstance(module,_INSTANCETYPE)):
2724 tokens = getattr(module,"tokens",None)
2725 else:
2726 tokens = ldict.get("tokens",None)
2727
2728 if not tokens:
2729 raise YaccError,"module does not define a list 'tokens'"
2730 if not (isinstance(tokens,types.ListType) or isinstance(tokens,types.TupleType)):
2731 raise YaccError,"tokens must be a list or tuple."
2732
2733
2734 requires = ldict.get("require",None)
2735 if requires:
2736 if not (isinstance(requires,types.DictType)):
2737 raise YaccError,"require must be a dictionary."
2738
2739 for r,v in requires.items():
2740 try:
2741 if not (isinstance(v,types.ListType)):
2742 raise TypeError
2743 v1 = [x.split(".") for x in v]
2744 Requires[r] = v1
2745 except StandardError:
2746 print >>sys.stderr, "Invalid specification for rule '%s' in require. Expected a list of strings" % r
2747
2748
2749
2750
2751
2752
2753 if 'error' in tokens:
2754 print >>sys.stderr, "yacc: Illegal token 'error'. Is a reserved word."
2755 raise YaccError,"Illegal token name"
2756
2757 for n in tokens:
2758 if Terminals.has_key(n):
2759 print >>sys.stderr, "yacc: Warning. Token '%s' multiply defined." % n
2760 Terminals[n] = [ ]
2761
2762 Terminals['error'] = [ ]
2763
2764
2765 prec = ldict.get("precedence",None)
2766 if prec:
2767 if not (isinstance(prec,types.ListType) or isinstance(prec,types.TupleType)):
2768 raise YaccError,"precedence must be a list or tuple."
2769 add_precedence(prec)
2770 Signature.update(repr(prec))
2771
2772 for n in tokens:
2773 if not Precedence.has_key(n):
2774 Precedence[n] = ('right',0)
2775
2776
2777 symbols = [ldict[f] for f in ldict.keys()
2778 if (type(ldict[f]) in (types.FunctionType, types.MethodType) and ldict[f].__name__[:2] == 'p_'
2779 and ldict[f].__name__ != 'p_error')]
2780
2781
2782 if len(symbols) == 0:
2783 raise YaccError,"no rules of the form p_rulename are defined."
2784
2785
2786 symbols.sort(lambda x,y: cmp(x.func_code.co_firstlineno,y.func_code.co_firstlineno))
2787
2788
2789 for f in symbols:
2790 if (add_function(f)) < 0:
2791 error += 1
2792 else:
2793 files[f.func_code.co_filename] = None
2794
2795
2796 for f in symbols:
2797 if f.__doc__:
2798 Signature.update(f.__doc__)
2799
2800 lr_init_vars()
2801
2802 if error:
2803 raise YaccError,"Unable to construct parser."
2804
2805 if not lr_read_tables(tabmodule):
2806
2807
2808 for filename in files.keys():
2809 if not validate_file(filename):
2810 error = 1
2811
2812
2813 validate_dict(ldict)
2814
2815 if start and not Prodnames.has_key(start):
2816 raise YaccError,"Bad starting symbol '%s'" % start
2817
2818 augment_grammar(start)
2819 error = verify_productions(cycle_check=check_recursion)
2820 otherfunc = [ldict[f] for f in ldict.keys()
2821 if (type(f) in (types.FunctionType,types.MethodType) and ldict[f].__name__[:2] != 'p_')]
2822
2823
2824 if check_precedence():
2825 error = 1
2826
2827 if error:
2828 raise YaccError,"Unable to construct parser."
2829
2830 build_lritems()
2831 compute_first1()
2832 compute_follow(start)
2833
2834 if method in ['SLR','LALR']:
2835 lr_parse_table(method)
2836 else:
2837 raise YaccError, "Unknown parsing method '%s'" % method
2838
2839 if write_tables:
2840 lr_write_tables(tabmodule,outputdir)
2841
2842 if yaccdebug:
2843 try:
2844 f = open(os.path.join(outputdir,debugfile),"w")
2845 f.write(_vfc.getvalue())
2846 f.write("\n\n")
2847 f.write(_vf.getvalue())
2848 f.close()
2849 except IOError,e:
2850 print >>sys.stderr, "yacc: can't create '%s'" % debugfile,e
2851
2852
2853
2854
2855 p = Parser("xyzzy")
2856 p.productions = Productions
2857 p.errorfunc = Errorfunc
2858 p.action = _lr_action
2859 p.goto = _lr_goto
2860 p.method = _lr_method
2861 p.require = Requires
2862
2863 global parse
2864 parse = p.parse
2865
2866 global parser
2867 parser = p
2868
2869
2870 if (not optimize):
2871 yacc_cleanup()
2872 return p
2873
2874
2875
2876
2878 global _lr_action, _lr_goto, _lr_method, _lr_goto_cache
2879 del _lr_action, _lr_goto, _lr_method, _lr_goto_cache
2880
2881 global Productions, Prodnames, Prodmap, Terminals
2882 global Nonterminals, First, Follow, Precedence, UsedPrecedence, LRitems
2883 global Errorfunc, Signature, Requires
2884
2885 del Productions, Prodnames, Prodmap, Terminals
2886 del Nonterminals, First, Follow, Precedence, UsedPrecedence, LRitems
2887 del Errorfunc, Signature, Requires
2888
2889 global _vf, _vfc
2890 del _vf, _vfc
2891
2892
2893
2894 -def parse(*args,**kwargs):
2895 raise YaccError, "yacc: No parser built with yacc()"
2896