Просмотр исходного кода

Finished exception handling (successfully pass through of exceptions).

Sander Mathijs van Veen 14 лет назад
Родитель
Сommit
d83b7274f5
3 измененных файлов с 35 добавлено и 72 удалено
  1. 5 5
      src/c/bisondynlib-linux.c
  2. 4 36
      src/pyrex/bison_.pyx
  3. 26 31
      src/python/bison.py

+ 5 - 5
src/c/bisondynlib-linux.c

@@ -39,11 +39,9 @@ char *bisondynlib_lookup_hash(void *handle)
 PyObject *bisondynlib_run(void *handle, PyObject *parser, void *cb, void *in, int debug)
 {
     PyObject *(*pparser)(PyObject *, void *, void *, int);
-    //PyObject *result;
 
-    //printf("bisondynlib_run: looking up parser\n");
     pparser = bisondynlib_lookup_parser(handle);
-    //printf("bisondynlib_run: calling parser, py_input=0x%lx\n", in);
+
     if (!pparser) {
         PyErr_SetString(PyExc_RuntimeError,
                         "bisondynlib_lookup_parser() returned NULL");
@@ -52,8 +50,10 @@ PyObject *bisondynlib_run(void *handle, PyObject *parser, void *cb, void *in, in
 
     (*pparser)(parser, cb, in, debug);
 
-    //printf("bisondynlib_run: back from parser\n");
-    //return result;
+    // Do not ignore a raised exception, but pass the exception through.
+    if (PyErr_Occurred())
+        return NULL;
+
     Py_INCREF(Py_None);
     return Py_None;
 

+ 4 - 36
src/pyrex/bison_.pyx

@@ -88,6 +88,7 @@ cdef public object py_callback(object parser, char *target, int option, \
     Py_INCREF(names)
     Py_INCREF(values)
 
+    # Construct handler's names and values list.
     for i in range(nargs):
         termname = <char*>va_arg(ap, str_type)
         PyList_SetItem(names, i, termname)
@@ -103,24 +104,16 @@ cdef public object py_callback(object parser, char *target, int option, \
         PyList_SetItem(values, i, valobj)
         Py_INCREF(valobj)
 
-    #if parser.verbose:
-    #    print 'py_callback: calling handler:', \
-    #          (target, option, names, values)
-
+    va_end(ap)
 
     # Set the signal handler and a timeout alarm
     #signal.signal(signal.SIGALRM, parser.handle_timeout)
     #signal.alarm(parser.timeout)
 
-    va_end(ap)
-
     res = parser._handle(target, option, names, values)
 
     #signal.alarm(0)
 
-    #if parser.verbose:
-    #    print 'py_callback: handler returned:', res
-
     return res
 
 # callback routine for reading input
@@ -280,36 +273,11 @@ cdef class ParserEngine:
     def generate_exception_handler(self):
         s = ''
 
-        #s = s + '          if ($$ && $$ != Py_None && PyObject_HasAttrString($$, "_pyBisonError"))\n'
-        #s = s + '          {\n'
-        #s = s + ' yyerror(PyString_AsString(PyObject_GetAttrString(py_parser, "last_error")));\n'
-        #s = s + '             Py_INCREF(Py_None);\n'
-        #s = s + '             YYERROR;\n'
-        #s = s + '          }\n'
-
-        s += '          if ($$ && $$ != Py_None)\n'
         s += '          {\n'
-        s += '            if (PyObject_HasAttrString($$, "_pyBisonError"))\n'
-        s += '            {\n'
-        s += '              //PyObject* last_error = PyObject_GetAttrString(py_parser, "last_error");\n'
-        s += '              //if (last_error && PyString_Check(last_error))\n'
-        s += '              //  yyerror(PyString_AsString(last_error));\n'
-        s += '              //else\n'
-        s += '              //  yyerror("No \\"last_error\\" attribute set in BisonError or not a string");\n'
-        s += '              Py_INCREF(Py_None);\n'
+        s += '            PyObject* obj = PyErr_Occurred();\n'
+        s += '            if (obj)\n'
         s += '              YYERROR;\n'
-        s += '            }\n'
         s += '          }\n'
-        #s += '          else\n'
-        #s += '          {\n'
-        #s += '            PyObject* obj = PyErr_Occurred();\n'
-        #s += '            if (obj)\n'
-        #s += '            {\n'
-        #s += '              fprintf(stderr, "exception caught in bison_:\\n");\n'
-        #s += '              PyErr_Print();\n'
-        #s += '              YYERROR;\n'
-        #s += '            }\n'
-        #s += '          }\n'
 
         return s
 

+ 26 - 31
src/python/bison.py

@@ -324,15 +324,8 @@ class BisonParser(object):
                 print 'BisonParser._handle: call handler at line %s with: %s' \
                       % (hdlrline, str((targetname, option, names, values)))
 
-            #self.last = handler(target=targetname, option=option, names=names,
-            #                    values=values)
-            try:
-                self.last = handler(target=targetname, option=option,
-                                    names=names, values=values)
-            except Exception as e:
-                #traceback.print_exception(*sys.exc_info())
-                return self.error(e, sys.exc_info())
-            #    raise
+            self.last = handler(target=targetname, option=option, names=names,
+                                values=values)
 
             #if self.verbose:
             #    print 'handler for %s returned %s' \
@@ -396,11 +389,11 @@ class BisonParser(object):
         while not self.file.closed:
             # do the parsing job, spew if error
             self.last = None
-            self.last_error = None
-            self.engine.runEngine(debug)
 
-            if self.last_error:
-                self.report_last_error(filename, self.last_error)
+            try:
+                self.engine.runEngine(debug)
+            except Exception as e:
+                self.report_last_error(filename, e)
 
             if self.verbose:
                 print 'Parser.run: back from engine'
@@ -442,24 +435,24 @@ class BisonParser(object):
 
         return bytes
 
-    def _error(self, linenum, msg, tok):
-        # TODO: should this function be removed?
-        print 'Parser: line %s: syntax error "%s" before "%s"' \
-              % (linenum, msg, tok)
+    #def _error(self, linenum, msg, tok):
+    #    # TODO: should this function be removed?
+    #    print 'Parser: line %s: syntax error "%s" before "%s"' \
+    #          % (linenum, msg, tok)
 
-    def error(self, exception, traceback_info):
-        """
-        Return the result of this method from a handler to notify a syntax error
-        """
-        # TODO: should this function be removed?
-        self.last_error = BisonError(exception, traceback_info)
+    #def error(self, exception, traceback_info):
+    #    """
+    #    Return the result of this method from a handler to notify a syntax error
+    #    """
+    #    # TODO: should this function be removed?
+    #    self.last_error = BisonError(exception, traceback_info)
 
-        return self.last_error
+    #    return self.last_error
 
-    def exception(self, exception):
-        # TODO: should this function be removed?
-        self.lastexception = exception
-        return BisonException(exception)
+    #def exception(self, exception):
+    #    # TODO: should this function be removed?
+    #    self.lastexception = exception
+    #    return BisonException(exception)
 
     def report_last_error(self, filename, error):
         if filename != None:
@@ -478,11 +471,13 @@ class BisonParser(object):
 
             print >>sys.stderr, msg
         else:
-            print error
             if not self.interactive:
-                raise error.value
+                raise
+
+            if self.verbose:
+                traceback.print_exc()
 
-            traceback.print_exception(*error.traceback_info)
+            print 'ERROR:', error
 
     def toxml(self):
         """