Skip to content
Snippets Groups Projects
Commit 930b44e0 authored by Sander Mathijs van Veen's avatar Sander Mathijs van Veen
Browse files

Implemented syntax error location tracking and fixed compiler warnings.

parent eb1d1da4
No related branches found
No related tags found
No related merge requests found
......@@ -278,8 +278,10 @@ cdef class ParserEngine:
s += ' {\n'
s += ' PyObject* obj = PyErr_Occurred();\n'
s += ' if (obj)\n'
s += ' if (obj) {\n'
s += ' //yyerror("exception raised");\n'
s += ' YYERROR;\n'
s += ' }\n'
s += ' }\n'
return s
......@@ -333,27 +335,46 @@ cdef class ParserEngine:
#writelines = f.writelines
# grammar file prologue
write("\n".join([
"%{",
write('\n'.join([
'%code top {',
'',
'#include "Python.h"',
"extern FILE *yyin;",
"extern int yylineno;"
"extern char *yytext;",
"#define YYSTYPE void*",
'extern FILE *yyin;',
#'extern int yylineno;'
'extern char *yytext;',
'#define YYSTYPE void*',
#'extern void *py_callback(void *, char *, int, void*, ...);',
'void *(*py_callback)(void *, char *, int, int, ...);',
'void (*py_input)(void *, char *, int *, int);',
'void *py_parser;',
'char *rules_hash = "%s";' % self.parserHash,
'#define YYERROR_VERBOSE 1',
'',
"%}",
'}',
'',
'%code requires {',
'',
'#define YYLTYPE YYLTYPE',
'typedef struct YYLTYPE',
'{',
' int first_line;',
' int first_column;',
' int last_line;',
' int last_column;',
' char *filename;',
'} YYLTYPE;',
#'',
#'YYLTYPE yylloc; /* location data */'
'',
'}',
'',
'%locations',
'',
]))
# write out tokens and start target dec
write("%%token %s\n\n" % " ".join(gTokens))
write("%%start %s\n\n" % gStart)
write('%%token %s\n\n' % ' '.join(gTokens))
write('%%start %s\n\n' % gStart)
# write out precedences
for p in gPrecedences:
......@@ -448,44 +469,52 @@ cdef class ParserEngine:
except:
traceback.print_exc()
write("\n\n%%\n\n")
write('\n\n%%\n\n')
# now generate C code
epilogue = "\n".join([
epilogue = '\n'.join([
'void do_parse(void *parser1,',
' void *(*cb)(void *, char *, int, int, void *, ...),',
' void *(*cb)(void *, char *, int, int, ...),',
' void (*in)(void *, char*, int *, int),',
' int debug',
' )',
'{',
' //printf("Not calling yyparse\\n");',
' //return;',
' py_callback = cb;',
' py_input = in;',
" py_parser = parser1;",
" yydebug = debug;",
" //yyin = stdin;",
' //printf("calling yyparse(), in=0x%lx\\n", py_input);',
" yyparse();",
' //printf("Back from parser\\n");',
"}",
"int yyerror(char *mesg)",
"{",
' //printf("yytext=0x%lx\\n", yytext);',
' PyObject *args = PyTuple_New(3);',
' int ret;',
' py_parser = parser1;',
' yydebug = debug;',
' yyparse();',
'}',
'',
'int yyerror(char *msg)',
'{',
' PyObject *fn = PyObject_GetAttrString((PyObject *)py_parser,',
' "report_syntax_error");',
' if (!fn)',
' return 1;',
'',
' PyObject *args;',
' args = Py_BuildValue("(s,s,i,i,i,i)", msg, yytext,',
' yylloc.first_line, yylloc.first_column,',
' yylloc.last_line, yylloc.last_column);',
'',
' if (!args)',
' return 1;',
#'',
#' fprintf(stderr, "%d.%d-%d.%d: error: \'%s\' before \'%s\'.",',
#' yylloc.first_line, yylloc.first_column,',
#' yylloc.last_line, yylloc.last_column, msg, yytext);',
'',
' PyTuple_SetItem(args, 0, PyInt_FromLong(yylineno+1));',
' PyTuple_SetItem(args, 1, PyString_FromString(mesg));',
' PyTuple_SetItem(args, 2, PyString_FromString(yytext));',
' PyObject *res = PyObject_CallObject(fn, args);',
' Py_DECREF(args);',
'',
' ret = PyObject_SetAttrString((PyObject *)py_parser, "last_error", args);',
' //printf("PyObject_SetAttrString: %d\\n", ret);',
' if (!res)',
' return 1;',
'',
' //printf("line %d: %s before %s\\n", yylineno+1, mesg, yytext);',
" //exit(0);",
"}",
]) + "\n"
' Py_DECREF(res);',
' return 0;',
'}',
]) + '\n'
write(epilogue)
# done with grammar file
......
......@@ -24,8 +24,11 @@ from bison_ import ParserEngine
from .node import BisonNode
class BisonSyntaxError(Exception):
pass
def __init__(self, msg, args):
super(BisonSyntaxError, self).__init__(msg)
self.first_line, self.first_col, self.last_line, self.last_col, \
self.message, self.token_value = args
class TimeoutError(Exception):
pass
......@@ -184,8 +187,9 @@ class BisonParser(object):
if self.verbose:
print 'no handler for %s, using default' % targetname
self.last = self.default_node_class(targetname, option=option,
names=names, values=values)
cls = self.default_node_class
self.last = cls(target=targetname, option=option, names=names,
values=values)
# assumedly the last thing parsed is at the top of the tree
return self.last
......@@ -299,26 +303,32 @@ class BisonParser(object):
"""
if filename != None:
msg = '%s:%d: "%s" near "%s"' \
% ((filename,) + error)
#if filename != None:
# msg = '%s:%d: "%s" near "%s"' \
# % ((filename,) + error)
if not self.interactive:
raise BisonSyntaxError(msg)
# if not self.interactive:
# raise BisonSyntaxError(msg)
print >>sys.stderr, msg
elif hasattr(error, '__getitem__') and isinstance(error[0], int):
msg = 'Line %d: "%s" near "%s"' % error
# print >>sys.stderr, msg
#elif hasattr(error, '__getitem__') and isinstance(error[0], int):
# msg = 'Line %d: "%s" near "%s"' % error
if not self.interactive:
raise BisonSyntaxError(msg)
# if not self.interactive:
# raise BisonSyntaxError(msg)
print >>sys.stderr, msg
else:
if not self.interactive:
raise
# print >>sys.stderr, msg
#else:
if not self.interactive:
raise
if self.verbose:
traceback.print_exc()
if self.verbose:
traceback.print_exc()
print 'ERROR:', error
print 'ERROR:', error
def report_syntax_error(self, msg, yytext, first_line, first_col,
last_line, last_col):
yytext = yytext.replace('\n', '\\n')
args = (first_line, first_col, last_line, last_col, msg, yytext)
raise BisonSyntaxError('%d.%d-%d.%d: "%s" near "%s".' % args, args)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment