##
# LL(1) parser generated by the Syntax tool.
#
# https://www.npmjs.com/package/syntax-cli
#
#   npm install -g syntax-cli
#
#   syntax-cli --help
#
# To regenerate run:
#
#   syntax-cli \
#     --grammar ~/path-to-grammar-file \
#     --mode LL1 \
#     --output ~/parsermodule.py
##

yytext = ''
yyleng = 0
__ = None

EOF = '$'

def on_parse_begin(string):
    pass

def on_parse_end(parsed):
    pass

{{{MODULE_INCLUDE}}}

{{{PRODUCTION_HANDLERS}}}

ps = {{{PRODUCTIONS}}}
tks = {{{TOKENS}}}
tbl = {{{TABLE}}}

s = None

{{{TOKENIZER}}}

def set_tokenizer(custom_tokenizer):
    global _tokenizer
    _tokenizer = custom_tokenizer

def get_tokenizer():
    return _tokenizer

def parse(string):
    global s
    on_parse_begin(string)

    if _tokenizer is None:
        raise Exception('_tokenizer instance wasn\'t specified.')

    _tokenizer.init_string(string)

    s = [EOF, {{{START}}}]

    t = _tokenizer.get_next_token()
    to = None
    tt = None

    while True:
        to = s.pop()
        tt = tks[t['type']]

        if (to == tt):
            t = _tokenizer.get_next_token()
            continue

        der(to, t, tt)

        if not _tokenizer.has_more_tokens() and len(s) <= 1:
            break

    while len(s) != 1:
        der(s.pop(), t, tt)


    if s[0] != EOF or t['type'] != EOF:
        _parse_error('stack is not empty: ' + str(s) + ', ' + str(t['value']))

    return True

def der(to, t, tt):
    npn = tbl[to][tt]

    if npn is None:
      _unexpected_token(t)

    s.extend(ps[int(npn)][0])

def _unexpected_token(token):
    if token['type'] == EOF:
        _unexpected_end_of_input()

    _tokenizer.throw_unexpected_token(
        token['value'],
        token['start_line'],
        token['start_column']
    )

def _unexpected_end_of_input():
    _parse_error('Unexpected end of input.')

def _parse_error(message):
    raise Exception('SyntaxError: ' + str(message))
