Make syntax error call yyerror() rather than raising a Python exception
[piyacc.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.piyacc import element
29 from ndcode.piyacc import lex_yy
30
31 # this can be redefined in SECTION1
32 class YYLTYPE:
33   def __init__(
34     self,
35     first_line = 1,
36     first_column = 1,
37     last_line = 1,
38     last_column = 1
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   def copy(self):
45     return YYLTYPE(
46        self.first_line,
47        self.first_column,
48        self.last_line,
49        self.last_column
50     )
51
52 def YYLLOC_DEFAULT(current, stack, n):
53   if n:
54     current.first_line = stack[-n][2].first_line
55     current.first_column = stack[-n][2].first_column
56     current.last_line = stack[-1][2].last_line
57     current.last_column = stack[-1][2].last_column
58   else:
59     current.first_line = current.last_line = stack[-1][2].last_line
60     current.first_column = current.last_column = stack[-1][2].last_column
61
62 # GENERATE SECTION1
63
64 # GENERATE TOKENS
65
66 yystack = None
67 yychar = None
68 YYEMPTY = -1
69
70 yyval = None
71 yyloc = YYLTYPE()
72
73 yylval = None
74 yylloc = YYLTYPE()
75
76 yy_element_stack = None
77
78 # GENERATE SECTION2
79
80 def yyparse(factory, *args, **kwargs):
81   global yystack, yychar, yyval, yyloc, yylval, yylloc, yy_element_stack
82
83   # GENERATE INITIALACTION
84
85   state = 0
86   yystack = [(-1, yylval, yylloc.copy())] # kludge for bison compatibility
87   yychar = -1
88   yy_element_stack = []
89   while True:
90     #print('state', state, 'yystack', yystack)
91     reduce = yy_lr1dfa_states[state][4]
92     if reduce == -1:
93       if yychar == -1:
94         yychar = lex_yy.yylex()
95         #print('yychar', yychar, 'yylval', yylval, 'yylloc', yylloc, 'lex_yy.yytext', lex_yy.yytext)
96         #print('lex_yy.yy_element_space')
97         #xml.etree.ElementTree.dump(lex_yy.yy_element_space)
98         #print('lex_yy.yy_element_token')
99         #xml.etree.ElementTree.dump(lex_yy.yy_element_token)
100       action = yy_lr1dfa_states[state][1][
101         bisect.bisect_right(yy_lr1dfa_states[state][0], yychar)
102       ]
103       if action == -1:
104         yyerror(yylloc, 'syntax error')
105         assert False # error recovery is not implemented yet
106       if (action & 1) == 0:
107         yystack.append((state, yylval, yylloc.copy()))
108
109         # push space then AST element contiguously onto yy_element_stack
110         # even numbered elements are spaces, odd numbered elements are AST
111         yy_element_stack.extend(
112           [lex_yy.yy_element_space, lex_yy.yy_element_token]
113         )
114
115         state = action >> 1
116         #print('shift', state)
117         yychar = -1
118         continue
119       reduce = action >> 1
120     #print('reduce', reduce)
121     len_symbols, ref_data = yy_lr1dfa_productions[reduce]
122     # GENERATE YYLLOC_DEFAULT BEGIN
123     YYLLOC_DEFAULT(yyloc, yystack, len_symbols)
124     # GENERATE END
125     base = len(yystack) - len_symbols
126     yystack.append((state, None, None)) # only has effect if len_symbols == 0
127     state, yyval, _ = yystack[base]
128     ref_data()
129     del yystack[base:]
130     if reduce == 0:
131       assert base == 1
132       break
133     yystack.append((state, yyval, yyloc.copy()))
134
135     # action creates empty space in yy_element_stack[base * 2] if needed
136     assert len(yy_element_stack) >= base * 2 - 1
137
138     # concatenate yy_element_stack[base * 2 - 1:] to a single AST element
139     yy_element_stack[base * 2 - 1:] = [
140       element.concatenate(
141         yy_element_stack[base * 2 - 1:],
142         element.Element
143       )
144     ]
145
146     state = yy_lr1dfa_states[state][3][
147       bisect.bisect_right(yy_lr1dfa_states[state][2], reduce)
148     ]
149     assert state != -1
150
151   # return space then AST then space in the user's choice of element type
152   yy_element_stack.append(lex_yy.yy_element_space)
153   return element.concatenate(yy_element_stack, factory, *args, **kwargs)
154
155 # GENERATE SECTION3