Bug 1318110 - Correctly handle parse errors in inner IPDL parsers. r=billm

The IPDL parser handles include statements by using a stack of
parsers. If an inner parser encounters a parsing error, it will print
out an error message, which is maybe okay, but then it makes two
mistakes:

1. It does not pop the current parser off of the parser stack. This
means that the file that included the syntactically invalid file will
be parsed as though it were the invalid file. In bkelly's case, an
.ipdl file included an invalid .ipdlh file, so he got a bizarre error
message about how you can't define a protocol in a header, because the
parser was treating the protocol in the .ipdl file as though it were
in the .ipdlh file. I fixed this by using a "finally" clause to pop
the parser stack, ensuring that it is correct even in case of error.

2. A parse error in the include should cause the entire parse to fail,
but instead it will keep going. inc.tu will get set to None, which
eventually causes an error later in type checking, when it attempts to
examine inc.tu. I fixed this by only catching the parse error where we
invoke the outermost parser. This has the drawback that later errors
in other files will not be reported. An alternate fix would set a
global flag to indicate that a parse error had occured, and somehow
report that to the caller.

I think this bug was introduced in 2009 by commit
cb8189926a69872c73508fba50830f0d07af341f.

MozReview-Commit-ID: DhbDUO7MXGB

--HG--
extra : rebase_source : cee371cd54ebf575f78aa8b2441afbde8b3c2b8f
This commit is contained in:
Andrew McCreight 2016-11-17 14:18:06 -08:00
Родитель 29a838b47b
Коммит 72a1e0edd5
2 изменённых файлов: 8 добавлений и 6 удалений

Просмотреть файл

@ -9,7 +9,7 @@ from cStringIO import StringIO
from ipdl.cgen import IPDLCodeGen
from ipdl.lower import LowerToCxx, msgenums
from ipdl.parser import Parser
from ipdl.parser import Parser, ParseError
from ipdl.type import TypeCheck
from ipdl.cxx.cgen import CxxCodeGen
@ -26,8 +26,12 @@ def parse(specstring, filename='/stdin', includedirs=[ ], errout=sys.stderr):
type = 'header'
else:
type = 'protocol'
return Parser(type, name).parse(specstring, os.path.abspath(filename), includedirs, errout)
try:
return Parser(type, name).parse(specstring, os.path.abspath(filename), includedirs, errout)
except ParseError as p:
print >>errout, p
return None
def typecheck(ast, errout=sys.stderr):
'''Return True iff |ast| is well typed. Print errors to |errout| if

Просмотреть файл

@ -78,11 +78,9 @@ class Parser:
try:
ast = self.parser.parse(input=input, lexer=self.lexer,
debug=self.debug)
except ParseError, p:
print >>errout, p
return None
finally:
Parser.current = Parser.parseStack.pop()
Parser.current = Parser.parseStack.pop()
return ast
def resolveIncludePath(self, filepath):