Implemented syntax error location tracking and fixed compiler warnings.

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