%{
import t_def
import y_tab
+
+ def YY_USER_ACTION():
+ line = y_tab.yylloc.last_line
+ column = y_tab.yylloc.last_column
+ y_tab.yylloc.first_line = line
+ y_tab.yylloc.first_column = column
+ p0 = 0
+ p = 0
+ while p < len(yytext):
+ if yytext[p] == '\n':
+ line += 1
+ column = 1
+ p0 = p + 1
+ elif yytext[p] == '\t':
+ column += p - p0
+ column += 8 - ((column - 1) & 7)
+ p0 = p + 1
+ p += 1
+ column += p - p0
+ y_tab.yylloc.last_line = line
+ y_tab.yylloc.last_column = column
%}
%%
"?" return ord('?')
[ \t\v\n\f]+ # whitespace separates tokens
-<INITIAL,COMMENT>. # discard bad characters
+<COMMENT>.|\n # discard bad characters
+<INITIAL>.|\n {
+ y_tab.yyerror(y_tab.yylloc, 'invalid character')
+}
<<EOF>> return 0
%%
if len(sys.argv) < 2:
print(f'usage: {sys.argv[0]:s} program.i')
sys.exit(EXIT_FAILURE)
-program_i = sys.argv[1]
+in_file = sys.argv[1]
-with open(program_i) as fin:
+with open(in_file) as fin:
lex_yy.yyin = fin
+ y_tab.in_file = in_file
y_tab.last_token = -1
y_tab.doing_typedef = False
y_tab.typedef_stack = [set()]
%{
import base_type
+ import sys
import t_def
+ # set this before calling yyparse(), for error messages
+ in_file = None
+
# used to suppress TYPEDEF_NAME after '.', PTR_OP, STRUCT, UNION, ENUM token
last_token = -1
%%
+def yyerror(loc, msg):
+ print(f'{in_file:s}({loc.first_line:d},{loc.first_column:d}..{loc.last_line:d},{loc.last_column:d}): {msg:s}')
+ sys.exit(1)
+
# helper factory to construct Expression object and analyze type and value
def build(factory, *args, **kwargs):
expression = factory(*args, **kwargs)