forked from mirrors/gecko-dev
42 lines
1.3 KiB
Python
42 lines
1.3 KiB
Python
#!/usr/bin/env python
|
|
|
|
"""parser.py - A JavaScript parser, currently with many bugs.
|
|
|
|
See README.md for instructions.
|
|
"""
|
|
|
|
from . import parser_tables
|
|
from .lexer import JSLexer
|
|
|
|
|
|
# "type: ignore" because mypy can't see inside js_parser.parser_tables.
|
|
class JSParser(parser_tables.Parser): # type: ignore
|
|
def __init__(self, goal='Script', builder=None):
|
|
super().__init__(goal, builder)
|
|
self._goal = goal
|
|
|
|
def clone(self):
|
|
return JSParser(self._goal, self.methods)
|
|
|
|
def on_recover(self, error_code, lexer, stv):
|
|
"""Check that ASI error recovery is really acceptable."""
|
|
if error_code == 'asi':
|
|
# ASI is allowed in three places:
|
|
# - at the end of the source text
|
|
# - before a close brace `}`
|
|
# - after a LineTerminator
|
|
# Hence the three-part if-condition below.
|
|
#
|
|
# The other quirks of ASI are implemented by massaging the syntax,
|
|
# in parse_esgrammar.py.
|
|
if not self.closed and stv.term != '}' and not lexer.saw_line_terminator():
|
|
lexer.throw("missing semicolon")
|
|
else:
|
|
# ASI is always allowed in this one state.
|
|
assert error_code == 'do_while_asi'
|
|
|
|
|
|
def parse_Script(text):
|
|
lexer = JSLexer(JSParser('Script'))
|
|
lexer.write(text)
|
|
return lexer.close()
|