Fix an error recovery routine that seems to not run often
[pilex.git] / skel_y_tab.py
1 # Copyright (C) 2019 Nick Downing <nick@ndcode.org>
2 # SPDX-License-Identifier: GPL-2.0-with-bison-exception
3 #
4 # This program is free software; you can redistribute it and/or modify it under
5 # the terms of the GNU General Public License as published by the Free Software
6 # Foundation; version 2.
7 #
8 # This program is distributed in the hope that it will be useful, but WITHOUT
9 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
10 # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
11 # details.
12 #
13 # You should have received a copy of the GNU General Public License along with
14 # this program; if not, write to the Free Software Foundation, Inc., 51
15 # Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
16 #
17 # As a special exception, you may create a larger work that contains part or
18 # all of the piyacc parser skeleton and distribute that work under terms of
19 # your choice, so long as that work isn't itself a parser generator using the
20 # skeleton or a modified version thereof as a parser skeleton. Alternatively,
21 # if you modify or redistribute the parser skeleton itself, you may (at your
22 # option) remove this special exception, which will cause the skeleton and the
23 # resulting piyacc output files to be licensed under the GNU General Public
24 # License without this special exception.
25
26 import bisect
27 #import xml.etree.ElementTree
28 from ndcode.pilex import element
29 from ndcode.pilex import lex_yy
30
31 # this can be redefined in SECTION1
32 class YYLTYPE:
33   def __init__(
34     self,
35     first_line = 0,
36     first_column = 0,
37     last_line = 0,
38     last_column = 0
39   ):
40     self.first_line = first_line
41     self.first_column = first_column
42     self.last_line = last_line
43     self.last_column = last_column
44  
45 # GENERATE SECTION1
46
47 # GENERATE TOKENS
48
49 yystack = None
50 yychar = None
51 YYEMPTY = -1
52
53 yyval = None
54 yyloc = None
55
56 yylval = None
57 yylloc = YYLTYPE()
58
59 yy_element_stack = None
60
61 # GENERATE SECTION2
62
63 def yyparse(factory, *args, **kwargs):
64   global yystack, yychar, yyval, yyloc, yylval, yylloc, yy_element_stack
65
66   # GENERATE INITIALACTION
67
68   state = 0
69   yystack = []
70   yylval = None
71   yychar = -1
72   yy_element_stack = []
73   while True:
74     #print('state', state, 'yystack', yystack)
75     assert len(yy_element_stack) == len(yystack) * 2
76     reduce = yy_lr1dfa_states[state][4]
77     if reduce == -1:
78       if yychar == -1:
79         yylval = None
80         yylloc = YYLTYPE() # temporary until lex_yy updated, should be None
81         yychar = lex_yy.yylex()
82         #print('yychar', yychar, 'yylval', yylval, 'yylloc', yylloc, 'lex_yy.yytext', lex_yy.yytext)
83         #print('lex_yy.yy_element_space')
84         #xml.etree.ElementTree.dump(lex_yy.yy_element_space)
85         #print('lex_yy.yy_element_token')
86         #xml.etree.ElementTree.dump(lex_yy.yy_element_token)
87       action = yy_lr1dfa_states[state][1][
88         bisect.bisect_right(yy_lr1dfa_states[state][0], yychar)
89       ]
90       if action == -1:
91         raise Exception('syntax error')
92       if (action & 1) == 0:
93         yystack.append((state, yylval, yylloc))
94
95         # push space then AST element contiguously onto yy_element_stack
96         # even numbered elements are spaces, odd numbered elements are AST
97         yy_element_stack.extend(
98           [lex_yy.yy_element_space, lex_yy.yy_element_token]
99         )
100
101         state = action >> 1
102         #print('shift', state)
103         yychar = -1
104         continue
105       reduce = action >> 1
106     #print('reduce', reduce)
107     len_symbols, ref_data = yy_lr1dfa_productions[reduce]
108     base = len(yystack) - len_symbols
109     yystack.append((state, None, None))
110     state, yyval, yyloc = yystack[base]
111     ref_data()
112     del yystack[base:]
113     if reduce == 0:
114       assert base == 0
115       break
116     yystack.append((state, yyval, yyloc))
117
118     # action creates empty space in yy_element_stack[base * 2] if needed
119     assert len(yy_element_stack) > base * 2
120
121     # concatenate yy_element_stack[base * 2 + 1:] to a single AST element
122     yy_element_stack[base * 2 + 1:] = [
123       element.concatenate(
124         yy_element_stack[base * 2 + 1:],
125         element.Element
126       )
127     ]
128
129     state = yy_lr1dfa_states[state][3][
130       bisect.bisect_right(yy_lr1dfa_states[state][2], reduce)
131     ]
132     assert state != -1
133
134   # return space then AST then space in the user's choice of element type
135   yy_element_stack.append(lex_yy.yy_element_space)
136   return element.concatenate(yy_element_stack, factory, *args, **kwargs)
137
138 # GENERATE SECTION3