Implemented syntax error location tracking and fixed compiler warnings.

parent eb1d1da4
......@@ -278,9 +278,11 @@ 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,22 +303,22 @@ 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:
# print >>sys.stderr, msg
#else:
if not self.interactive:
raise
......@@ -322,3 +326,9 @@ class BisonParser(object):
traceback.print_exc()
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