################################################################################
# Copyright (c) 2015, Broad Institute, Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
#
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# * Neither the name Broad Institute, Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
################################################################################
#
# This file was generated by Hermes Parser Generator on Sun Aug 13 18:58:49 2017
# 
# Hermes command: hermes generate grammar.hgr --name=wdl --header
# Run from: . (relative to this file)
# Hermes version: hermes-parser 2.0rc6
# 
# !!! DO NOT CHANGE THIS FILE DIRECTLY !!!
# 
# If you wish to change something in this file, either change the grammar and
# re-generate this file, or change the templates in Hermes and regenerate.
# See the Hermes repository: http://github.com/scottfrazer/hermes
#
################################################################################
import sys
import os
import re
import base64
import argparse
from builtins import chr
from collections import OrderedDict
# Common Code #
def parse_tree_string(parsetree, indent=None, b64_source=True, indent_level=0, debug=False):
    indent_str = (' ' * indent * indent_level) if indent else ''
    if isinstance(parsetree, ParseTree):
        children = [parse_tree_string(child, indent, b64_source, indent_level+1, debug) for child in parsetree.children]
        debug_str = parsetree.debug_str() if debug else ''
        if indent is None or len(children) == 0:
            return '{0}({1}: {2}{3})'.format(indent_str, parsetree.nonterminal, debug_str, ', '.join(children))
        else:
            return '{0}({1}:{2}\n{3}\n{4})'.format(
                indent_str,
                parsetree.nonterminal,
                debug_str,
                ',\n'.join(children),
                indent_str
            )
    elif isinstance(parsetree, Terminal):
        return indent_str + parsetree.dumps(b64_source=b64_source)
def ast_string(ast, indent=None, b64_source=True, indent_level=0):
    indent_str = (' ' * indent * indent_level) if indent else ''
    next_indent_str = (' ' * indent * (indent_level+1)) if indent else ''
    if isinstance(ast, Ast):
        children = OrderedDict([(k, ast_string(v, indent, b64_source, indent_level+1)) for k, v in ast.attributes.items()])
        if indent is None:
            return '({0}: {1})'.format(
                ast.name,
                ', '.join('{0}={1}'.format(k, v) for k, v in children.items())
            )
        else:
            return '({0}:\n{1}\n{2})'.format(
                ast.name,
                ',\n'.join(['{0}{1}={2}'.format(next_indent_str, k, v) for k, v in children.items()]),
                indent_str
            )
    elif isinstance(ast, list):
        children = [ast_string(element, indent, b64_source, indent_level+1) for element in ast]
        if indent is None or len(children) == 0:
            return '[{0}]'.format(', '.join(children))
        else:
            return '[\n{1}\n{0}]'.format(
                indent_str,
                ',\n'.join(['{0}{1}'.format(next_indent_str, child) for child in children]),
            )
    elif isinstance(ast, Terminal):
        return ast.dumps(b64_source=b64_source)
class Terminal:
  def __init__(self, id, str, source_string, resource, line, col):
      self.__dict__.update(locals())
  def getId(self):
      return self.id
  def ast(self):
      return self
  def dumps(self, b64_source=True, **kwargs):
      source_string = base64.b64encode(self.source_string.encode('utf-8')).decode('utf-8') if b64_source else self.source_string
      return '<{resource}:{line}:{col} {terminal} "{source}">'.format(
          resource=self.resource,
          line=self.line,
          col=self.col,
          terminal=self.str,
          source=source_string
      )
  def __str__(self):
      return self.dumps()
class NonTerminal():
  def __init__(self, id, str):
    self.__dict__.update(locals())
    self.list = False
  def __str__(self):
    return self.str
class AstTransform:
  pass
class AstTransformSubstitution(AstTransform):
  def __init__(self, idx):
    self.__dict__.update(locals())
  def __repr__(self):
    return '$' + str(self.idx)
  def __str__(self):
    return self.__repr__()
class AstTransformNodeCreator(AstTransform):
  def __init__( self, name, parameters ):
    self.__dict__.update(locals())
  def __repr__( self ):
    return self.name + '( ' + ', '.join(['%s=$%s' % (k,str(v)) for k,v in self.parameters.items()]) + ' )'
  def __str__(self):
    return self.__repr__()
class AstList(list):
  def ast(self):
      retval = []
      for ast in self:
          retval.append(ast.ast())
      return retval
  def dumps(self, indent=None, b64_source=True):
      args = locals()
      del args['self']
      return ast_string(self, **args)
class ParseTree():
  def __init__(self, nonterminal):
      self.__dict__.update(locals())
      self.children = []
      self.astTransform = None
      self.isExpr = False
      self.isNud = False
      self.isPrefix = False
      self.isInfix = False
      self.nudMorphemeCount = 0
      self.isExprNud = False # true for rules like _expr := {_expr} + {...}
      self.list_separator_id = None
      self.list = False
  def debug_str(self):
      from copy import deepcopy
      def h(v):
          if v == False or v is None:
              return str(v)
          from xtermcolor import colorize
          return colorize(str(v), ansi=190)
      d = deepcopy(self.__dict__)
      for key in ['self', 'nonterminal', 'children']:
          del d[key]
      f = {k: v for k, v in d.items() if v != False and v is not None}
      return ' [{}]'.format(', '.join(['{}={}'.format(k,h(v)) for k,v in f.items()]))
  def add(self, tree):
      self.children.append( tree )
  def is_compound_nud(self):
      return isinstance(self.children[0], ParseTree) and \
             self.children[0].isNud and \
             not self.children[0].isPrefix and \
             not self.isExprNud and \
             not self.isInfix
  def ast(self):
      if self.list == True:
          r = AstList()
          if len(self.children) == 0:
              return r
          for child in self.children:
              if isinstance(child, Terminal) and self.list_separator_id is not None and child.id == self.list_separator_id:
                  continue
              r.append(child.ast())
          return r
      elif self.isExpr:
          if isinstance(self.astTransform, AstTransformSubstitution):
              return self.children[self.astTransform.idx].ast()
          elif isinstance(self.astTransform, AstTransformNodeCreator):
              parameters = OrderedDict()
              for name, idx in self.astTransform.parameters.items():
                  if idx == '$':
                      child = self.children[0]
                  elif self.is_compound_nud():
                      if idx < self.children[0].nudMorphemeCount:
                          child = self.children[0].children[idx]
                      else:
                          index = idx - self.children[0].nudMorphemeCount + 1
                          child = self.children[index]
                  elif len(self.children) == 1 and not isinstance(self.children[0], ParseTree) and not isinstance(self.children[0], list):
                      return self.children[0]
                  else:
                      child = self.children[idx]
                  parameters[name] = child.ast()
              return Ast(self.astTransform.name, parameters)
      else:
          if isinstance(self.astTransform, AstTransformSubstitution):
              return self.children[self.astTransform.idx].ast()
          elif isinstance(self.astTransform, AstTransformNodeCreator):
              parameters = OrderedDict()
              for name, idx in self.astTransform.parameters.items():
                  parameters[name] = self.children[idx].ast()
              return Ast(self.astTransform.name, parameters)
          elif len(self.children):
              return self.children[0].ast()
          else:
              return None
  def dumps(self, indent=None, b64_source=True, debug=False):
      args = locals()
      del args['self']
      return parse_tree_string(self, **args)
class Ast():
    def __init__(self, name, attributes):
        self.__dict__.update(locals())
    def attr(self, attr):
        return self.attributes[attr]
    def dumps(self, indent=None, b64_source=True):
        args = locals()
        del args['self']
        return ast_string(self, **args)
class SyntaxError(Exception):
    def __init__(self, message):
        self.__dict__.update(locals())
    def __str__(self):
        return self.message
class TokenStream(list):
    def __init__(self, arg=[]):
        super(TokenStream, self).__init__(arg)
        self.index = 0
    def advance(self):
        self.index += 1
        return self.current()
    def last(self):
        return self[-1]
    def current(self):
        try:
            return self[self.index]
        except IndexError:
            return None
class DefaultSyntaxErrorHandler:
    def __init__(self):
        self.errors = []
    def _error(self, string):
        error = SyntaxError(string)
        self.errors.append(error)
        return error
    def unexpected_eof(self):
        return self._error("Error: unexpected end of file")
    def excess_tokens(self):
        return self._error("Finished parsing without consuming all tokens.")
    def unexpected_symbol(self, nonterminal, actual_terminal, expected_terminals, rule):
        return self._error("Unexpected symbol (line {line}, col {col}) when parsing parse_{nt}.  Expected {expected}, got {actual}.".format(
            line=actual_terminal.line,
            col=actual_terminal.col,
            nt=nonterminal,
            expected=', '.join(expected_terminals),
            actual=actual_terminal
        ))
    def no_more_tokens(self, nonterminal, expected_terminal, last_terminal):
        return self._error("No more tokens.  Expecting " + expected_terminal)
    def invalid_terminal(self, nonterminal, invalid_terminal):
        return self._error("Invalid symbol ID: {} ({})".format(invalid_terminal.id, invalid_terminal.string))
    def unrecognized_token(self, string, line, col):
        lines = string.split('\n')
        bad_line = lines[line-1]
        return self._error('Unrecognized token on line {}, column {}:\n\n{}\n{}'.format(
            line, col, bad_line, ''.join([' ' for x in range(col-1)]) + '^'
        ))
    def missing_list_items(self, method, required, found, last):
        return self._error("List for {} requires {} items but only {} were found.".format(method, required, found))
    def missing_terminator(self, method, terminator, last):
        return self._error("List for "+method+" is missing a terminator")
class ParserContext:
  def __init__(self, tokens, errors):
    self.__dict__.update(locals())
    self.nonterminal_string = None
    self.rule_string = None
# Parser Code #
terminals = {
    0: 'raw_cmd_start',
    1: 'dash',
    2: 'not_equal',
    3: 'boolean',
    4: 'float',
    5: 'cmd_param_start',
    6: 'task',
    7: 'dot',
    8: 'rsquare',
    9: 'in',
    10: 'workflow',
    11: 'plus',
    12: 'not',
    13: 'meta',
    14: 'equal',
    15: 'lteq',
    16: 'lbrace',
    17: 'asterisk',
    18: 'if',
    19: 'raw_command',
    20: 'lparen',
    21: 'else',
    22: 'output',
    23: 'double_pipe',
    24: 'double_equal',
    25: 'while',
    26: 'cmd_part',
    27: 'cmd_attr_hint',
    28: 'call',
    29: 'parameter_meta',
    30: 'raw_cmd_end',
    31: 'then',
    32: 'runtime',
    33: 'qmark',
    34: 'input',
    35: 'e',
    36: 'lt',
    37: 'slash',
    38: 'type_e',
    39: 'integer',
    40: 'cmd_param_end',
    41: 'import',
    42: 'string',
    43: 'comma',
    44: 'rbrace',
    45: 'rparen',
    46: 'lsquare',
    47: 'double_ampersand',
    48: 'type',
    49: 'gt',
    50: 'identifier',
    51: 'scatter',
    52: 'object',
    53: 'as',
    54: 'colon',
    55: 'fqn',
    56: 'gteq',
    57: 'percent',
    'raw_cmd_start': 0,
    'dash': 1,
    'not_equal': 2,
    'boolean': 3,
    'float': 4,
    'cmd_param_start': 5,
    'task': 6,
    'dot': 7,
    'rsquare': 8,
    'in': 9,
    'workflow': 10,
    'plus': 11,
    'not': 12,
    'meta': 13,
    'equal': 14,
    'lteq': 15,
    'lbrace': 16,
    'asterisk': 17,
    'if': 18,
    'raw_command': 19,
    'lparen': 20,
    'else': 21,
    'output': 22,
    'double_pipe': 23,
    'double_equal': 24,
    'while': 25,
    'cmd_part': 26,
    'cmd_attr_hint': 27,
    'call': 28,
    'parameter_meta': 29,
    'raw_cmd_end': 30,
    'then': 31,
    'runtime': 32,
    'qmark': 33,
    'input': 34,
    'e': 35,
    'lt': 36,
    'slash': 37,
    'type_e': 38,
    'integer': 39,
    'cmd_param_end': 40,
    'import': 41,
    'string': 42,
    'comma': 43,
    'rbrace': 44,
    'rparen': 45,
    'lsquare': 46,
    'double_ampersand': 47,
    'type': 48,
    'gt': 49,
    'identifier': 50,
    'scatter': 51,
    'object': 52,
    'as': 53,
    'colon': 54,
    'fqn': 55,
    'gteq': 56,
    'percent': 57,
}
# table[nonterminal][terminal] = rule
table = [
    [-1, -1, -1, -1, -1, -1, 7, -1, -1, -1, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7, -1, -1, 7, -1, -1, -1, -1, -1, -1, 7, -1, -1, -1, -1, 6, -1, -1, -1, -1],
    [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1],
    [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 19, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1],
    [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 57, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1],
    [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1],
    [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 52, -1, -1, 51, -1, 52, -1, -1, -1, 52, -1, -1, 52, -1, -1, 52, 52, -1, -1, -1, -1, -1, -1, -1, -1, 52, -1, -1, -1, -1, -1, 52, -1, -1, -1, 52, -1, -1, 52, -1, -1, -1, -1, -1, -1],
    [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 17, -1, -1, -1, -1, -1, 13, -1, -1, 14, -1, -1, -1, -1, -1, -1, 16, -1, -1, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1],
    [-1, -1, -1, -1, -1, -1, 4, -1, -1, -1, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1],
    [-1, -1, -1, -1, -1, -1, -1, 68, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1],
    [-1, -1, -1, -1, -1, -1, -1, 65, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 66, -1, -1, -1, -1, -1, 66, -1, -1, -1, 66, -1, -1, -1, -1, -1, -1, 66, -1, -1],
    [-1, -1, -1, -1, -1, 23, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1],
    [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 27, -1, -1, -1, -1, -1, -1, -1, -1, -1, 27, -1, -1, -1, -1, -1, -1, -1, -1, -1],
    [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 67, -1, -1],
    [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 24, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1],
    [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1],
    [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 37, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1],
    [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1],
    [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 72, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1],
    [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 59, -1, -1, -1, -1],
    [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 64, -1, -1, -1, -1, -1, -1, -1, -1, -1, 64, -1, -1, -1, -1, -1, -1, -1, -1, -1],
    [-1, -1, -1, -1, -1, 21, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 20, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1],
    [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 28, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1],
    [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1],
    [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 70, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1],
    [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 69, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1],
    [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1],
    [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1],
    [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 53, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1],
    [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 26, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1],
    [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 74, -1, -1, -1, -1, -1, -1, -1],
    [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 55, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1],
    [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1],
    [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 58, -1, -1, -1, -1, -1, -1, -1],
    [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1],
    [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 30, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1],
    [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1],
    [-1, 38, -1, 38, 38, -1, -1, -1, -1, -1, -1, 38, 38, -1, -1, -1, 38, -1, 38, -1, 38, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 38, -1, -1, -1, 38, -1, -1, 38, -1, -1, -1, 38, -1, -1, -1, 38, -1, 38, -1, -1, -1, -1, -1],
    [-1, -1, -1, -1, -1, -1, 12, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1],
    [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1],
    [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1],
    [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 32, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1],
    [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 36, -1, -1, -1, -1, -1, -1, -1, -1, -1, 36, -1, -1, -1, -1, -1, -1, -1, -1, -1],
    [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1],
    [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 61, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1],
    [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1],
    [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1],
    [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 50, -1, -1, 50, -1, 50, -1, -1, -1, 50, -1, -1, 50, -1, -1, 50, 50, -1, -1, -1, -1, -1, -1, -1, -1, 50, -1, -1, -1, -1, -1, 50, -1, -1, -1, 50, -1, -1, 50, -1, 49, -1, -1, -1, -1],
    [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 9, -1, -1, -1, -1],
    [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1],
    [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, -1, -1, -1, 63, -1, -1],
    [-1, -1, -1, -1, -1, -1, 2, -1, -1, -1, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 2, -1, -1, 2, -1, -1, -1, -1, -1, -1, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1],
    [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 71, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1],
    [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1],
    [-1, -1, -1, -1, -1, -1, 35, -1, -1, -1, 35, -1, -1, 35, 34, -1, -1, -1, 35, 35, -1, -1, 35, -1, -1, 35, -1, -1, 35, 35, -1, -1, 35, -1, 35, -1, -1, -1, 35, -1, -1, -1, -1, -1, 35, -1, -1, -1, 35, -1, -1, 35, -1, -1, -1, -1, -1, -1],
    [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 40, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1],
    [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 73, -1, -1, -1, -1, -1, -1],
    [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 33, -1, -1, -1, -1, -1, -1, -1],
    [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 48, -1, -1, -1, -1, 44, -1, -1, -1, 46, -1, -1, 43, -1, -1, 41, 47, -1, -1, -1, -1, -1, -1, -1, -1, 42, -1, -1, -1, -1, -1, -1, -1, -1, -1, 42, -1, -1, 45, -1, -1, -1, -1, -1, -1],
    [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 29, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1],
    [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1],
    [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1],
]
nonterminal_first = {
    58: [53, -1],
    59: [41, -1],
    60: [19],
    61: [34],
    62: [-1, 48, 38, 55],
    63: [16, -1],
    64: [22, 29, 13, 32, 19],
    65: [38, 10, 48, 6],
    66: [7],
    67: [-1, 7],
    68: [5],
    69: [38, 48],
    70: [55],
    71: [27],
    72: [38, 48, -1],
    73: [14],
    74: [-1, 25, 38, 18, 28, 29, 48, 51, 13, 22],
    75: [18],
    76: [53],
    77: [38, 48],
    78: [5, 26],
    79: [32],
    80: [38, 48],
    81: [13],
    82: [29],
    83: [50, -1],
    84: [50, -1],
    85: [28],
    86: [22],
    87: [50],
    88: [16],
    89: [34, -1],
    90: [50],
    91: [29, -1, 32, 19, 13, 22],
    92: [13],
    93: [1, 3, 4, 12, 11, 35, -1, 39, 16, 46, 18, 42, 50, 52, 20],
    94: [35, 1, 3, 16, 39, 4, 46, 18, 42, 50, 12, 11, 52, 20],
    95: [6],
    96: [38, 48, -1],
    97: [41],
    98: [16],
    99: [38, 48],
    100: [50, -1],
    101: [22],
    102: [-1, 27],
    103: [38, 48, -1],
    104: [53, -1],
    105: [53],
    106: [5, -1, 26],
    107: [38, 48, 55],
    108: [-1, 6, 48, 38, 10, 41],
    109: [25],
    110: [-1, 38, 6, 48, 10],
    111: [14, -1],
    112: [10],
    113: [51],
    114: [50],
    115: [25, 38, 18, 28, 29, 48, 51, 13, 22],
    116: [29],
    117: [1, 35, 3, 16, 39, 4, 46, 18, 42, 20, 12, 11, 52, 50],
    118: [1, 3, 4, 20, 12, 11, 35, -1, 39, 16, 46, 18, 42, 52, 50],
}
nonterminal_follow = {
    58: [48, 6, -1, 38, 10, 41],
    59: [38, 10, 48, 6, -1],
    60: [44, 29, 32, 19, 13, 22],
    61: [44, 34],
    62: [44],
    63: [25, 38, 18, 28, 44, 29, 48, 51, 13, 22],
    64: [44, 29, 32, 19, 13, 22],
    65: [-1, 38, 48, 6, 10],
    66: [44, 48, 38, 55],
    67: [44, 48, 38, 55],
    68: [30, 5, 26],
    69: [38, 48, 44],
    70: [44, 48, 38, 55],
    71: [1, 3, 4, 27, 20, 12, 11, 35, 39, 16, 46, 18, 42, 52, 50],
    72: [29, 32, 19, 34, 13, 22],
    73: [25, -1, 28, 29, 6, 32, 10, 34, 13, 38, 18, 44, 48, 19, 51, 22],
    74: [44],
    75: [25, 38, 18, 28, 44, 29, 48, 51, 13, 22],
    76: [25, 38, 16, 18, 28, 44, 29, 48, 51, 13, 22],
    77: [44, 48, 38, 55],
    78: [30, 5, 26],
    79: [44, 29, 32, 19, 13, 22],
    80: [50, 43, 8],
    81: [25, 38, 18, 28, 44, 29, 48, 51, 13, 22],
    82: [25, 38, 18, 28, 44, 29, 48, 51, 13, 22],
    83: [44],
    84: [44, 34],
    85: [25, 38, 18, 28, 44, 29, 48, 51, 13, 22],
    86: [44, 29, 32, 19, 13, 22],
    87: [44, 43],
    88: [25, 38, 18, 28, 44, 29, 48, 51, 13, 22],
    89: [44],
    90: [44, 34, 43],
    91: [44],
    92: [44, 29, 32, 19, 13, 22],
    93: [44],
    94: [44, 43],
    95: [-1, 38, 48, 6, 10],
    96: [8],
    97: [48, 6, -1, 38, 10, 41],
    98: [25, 38, 18, 28, 44, 29, 48, 32, 19, 51, 13, 22],
    99: [25, -1, 28, 29, 6, 32, 10, 34, 13, 38, 18, 44, 48, 19, 51, 22],
    100: [44],
    101: [25, 38, 18, 28, 44, 29, 48, 51, 13, 22],
    102: [1, 35, 3, 16, 39, 4, 46, 18, 42, 20, 12, 11, 52, 50],
    103: [44],
    104: [25, 38, 16, 18, 28, 44, 29, 48, 51, 13, 22],
    105: [48, 6, -1, 38, 10, 41],
    106: [30],
    107: [44, 48, 38, 55],
    108: [-1],
    109: [25, 38, 18, 28, 44, 29, 48, 51, 13, 22],
    110: [-1],
    111: [25, -1, 28, 29, 6, 32, 10, 34, 13, 38, 18, 44, 48, 19, 51, 22],
    112: [-1, 38, 48, 6, 10],
    113: [25, 38, 18, 28, 44, 29, 48, 51, 13, 22],
    114: [44, 50],
    115: [25, 38, 18, 28, 44, 29, 48, 51, 13, 22],
    116: [44, 29, 32, 19, 13, 22],
    117: [1, -1, 2, 3, 4, 6, 11, 8, 12, 10, 13, 15, 16, 17, 18, 19, 21, 20, 22, 23, 24, 25, 27, 28, 29, 31, 32, 34, 36, 37, 35, 38, 39, 40, 46, 45, 43, 42, 44, 47, 48, 49, 50, 51, 52, 54, 55, 56, 57],
    118: [45, 8],
}
rule_first = {
    0: [-1, 41],
    1: [38, -1, 10, 48, 6],
    2: [-1, 38, 41, 48, 6, 10],
    3: [10],
    4: [6],
    5: [38, 48],
    6: [53],
    7: [-1],
    8: [41],
    9: [53],
    10: [38, -1, 48],
    11: [-1, 29, 32, 19, 13, 22],
    12: [6],
    13: [19],
    14: [22],
    15: [32],
    16: [29],
    17: [13],
    18: [5, -1, 26],
    19: [19],
    20: [26],
    21: [5],
    22: [-1, 27],
    23: [5],
    24: [27],
    25: [38, -1, 48],
    26: [22],
    27: [38, 48],
    28: [32],
    29: [29],
    30: [13],
    31: [50, -1],
    32: [16],
    33: [50],
    34: [14],
    35: [-1],
    36: [38, 48],
    37: [14],
    38: [1, 35, 3, 16, 39, 4, 46, 18, 42, 20, 12, 11, 52, 50],
    39: [25, -1, 38, 18, 28, 29, 48, 51, 13, 22],
    40: [10],
    41: [28],
    42: [38, 48],
    43: [25],
    44: [18],
    45: [51],
    46: [22],
    47: [29],
    48: [13],
    49: [53],
    50: [-1],
    51: [16],
    52: [-1],
    53: [28],
    54: [34, -1],
    55: [16],
    56: [50, -1],
    57: [34],
    58: [50],
    59: [53],
    60: [38, -1, 48, 55],
    61: [22],
    62: [38, 48],
    63: [55],
    64: [38, 48],
    65: [7],
    66: [-1],
    67: [55],
    68: [7],
    69: [29],
    70: [13],
    71: [25],
    72: [18],
    73: [51],
    74: [50],
    75: [38, -1, 48],
    76: [48],
    77: [48],
    78: [48],
    79: [48],
    80: [1, 35, 3, 16, 39, 4, 46, 18, 42, 20, 12, 11, 52, 50],
    81: [1, 35, 3, 16, 39, 4, 46, 18, 42, 20, 12, 11, 52, 50],
    82: [1, 35, 3, 16, 39, 4, 46, 18, 42, 20, 12, 11, 52, 50],
    83: [1, 35, 3, 16, 39, 4, 46, 18, 42, 20, 12, 11, 52, 50],
    84: [1, 35, 3, 16, 39, 4, 46, 18, 42, 20, 12, 11, 52, 50],
    85: [1, 35, 3, 16, 39, 4, 46, 18, 42, 20, 12, 11, 52, 50],
    86: [1, 35, 3, 16, 39, 4, 46, 18, 42, 20, 12, 11, 52, 50],
    87: [1, 35, 3, 16, 39, 4, 46, 18, 42, 20, 12, 11, 52, 50],
    88: [1, 35, 3, 16, 39, 4, 46, 18, 42, 20, 12, 11, 52, 50],
    89: [1, 35, 3, 16, 39, 4, 46, 18, 42, 20, 12, 11, 52, 50],
    90: [1, 35, 3, 16, 39, 4, 46, 18, 42, 20, 12, 11, 52, 50],
    91: [1, 35, 3, 16, 39, 4, 46, 18, 42, 20, 12, 11, 52, 50],
    92: [1, 35, 3, 16, 39, 4, 46, 18, 42, 20, 12, 11, 52, 50],
    93: [12],
    94: [11],
    95: [1],
    96: [1, 35, -1, 3, 16, 39, 4, 46, 18, 42, 20, 12, 11, 52, 50],
    97: [50],
    98: [50],
    99: [50],
    100: [50, -1],
    101: [52],
    102: [46],
    103: [35, 1, -1, 3, 16, 39, 4, 46, 18, 42, 50, 12, 11, 52, 20],
    104: [16],
    105: [20],
    106: [18],
    107: [42],
    108: [50],
    109: [3],
    110: [39],
    111: [4],
}
nonterminal_rules = {
    58: [
        "$_gen2 = $import_namespace",
        "$_gen2 = :_empty",
    ],
    59: [
        "$_gen0 = list($import)",
    ],
    60: [
        "$command = :raw_command :raw_cmd_start $_gen5 :raw_cmd_end -> RawCommand( parts=$2 )",
    ],
    61: [
        "$call_input = :input :colon $_gen14 -> Inputs( map=$2 )",
    ],
    62: [
        "$_gen15 = list($wf_output)",
    ],
    63: [
        "$_gen12 = $call_body",
        "$_gen12 = :_empty",
    ],
    64: [
        "$sections = $command",
        "$sections = $outputs",
        "$sections = $runtime",
        "$sections = $parameter_meta",
        "$sections = $meta",
    ],
    65: [
        "$workflow_or_task_or_decl = $workflow",
        "$workflow_or_task_or_decl = $task",
        "$workflow_or_task_or_decl = $declaration",
    ],
    66: [
        "$wf_output_wildcard = :dot :asterisk -> $1",
    ],
    67: [
        "$_gen16 = $wf_output_wildcard",
        "$_gen16 = :_empty",
    ],
    68: [
        "$cmd_param = :cmd_param_start $_gen6 $e :cmd_param_end -> CommandParameter( attributes=$1, expr=$2 )",
    ],
    69: [
        "$output_kv = $type_e :identifier :equal $e -> Output( type=$0, name=$1, expression=$3 )",
    ],
    70: [
        "$wf_output_wildcard_syntax = :fqn $_gen16 -> WorkflowOutputWildcard( fqn=$0, wildcard=$1 )",
    ],
    71: [
        "$cmd_param_kv = :cmd_attr_hint :identifier :equal $e -> CommandParameterAttr( key=$1, value=$3 )",
    ],
    72: [
        "$_gen3 = list($declaration)",
    ],
    73: [
        "$setter = :equal $e -> $1",
    ],
    74: [
        "$_gen10 = list($wf_body_element)",
    ],
    75: [
        "$if_stmt = :if :lparen $e :rparen :lbrace $_gen10 :rbrace -> If( expression=$2, body=$5 )",
    ],
    76: [
        "$alias = :as :identifier -> $1",
    ],
    77: [
        "$wf_output_declaration_syntax = $type_e :identifier :equal $e -> WorkflowOutputDeclaration( type=$0, name=$1, expression=$3 )",
    ],
    78: [
        "$command_part = :cmd_part",
        "$command_part = $cmd_param",
    ],
    79: [
        "$runtime = :runtime $map -> Runtime( map=$1 )",
    ],
    80: [
        "$type_e = :type <=> :lsquare $_gen17 :rsquare -> Type( name=$0, subtype=$2 )",
        "$type_e = :type <=> :qmark -> OptionalType( innerType=$0 )",
        "$type_e = :type <=> :plus -> NonEmptyType( innerType=$0 )",
        "$type_e = :type",
    ],
    81: [
        "$wf_meta = :meta $map -> Meta( map=$1 )",
    ],
    82: [
        "$wf_parameter_meta = :parameter_meta $map -> ParameterMeta( map=$1 )",
    ],
    83: [
        "$_gen8 = list($kv)",
    ],
    84: [
        "$_gen14 = list($mapping, :comma)",
    ],
    85: [
        "$call = :call :fqn $_gen11 $_gen12 -> Call( task=$1, alias=$2, body=$3 )",
    ],
    86: [
        "$outputs = :output :lbrace $_gen7 :rbrace -> Outputs( attributes=$2 )",
    ],
    87: [
        "$object_kv = :identifier :colon $e -> ObjectKV( key=$0, value=$2 )",
    ],
    88: [
        "$call_body = :lbrace $_gen3 $_gen13 :rbrace -> CallBody( declarations=$1, io=$2 )",
    ],
    89: [
        "$_gen13 = list($call_input)",
    ],
    90: [
        "$mapping = :identifier :equal $e -> IOMapping( key=$0, value=$2 )",
    ],
    91: [
        "$_gen4 = list($sections)",
    ],
    92: [
        "$meta = :meta $map -> Meta( map=$1 )",
    ],
    93: [
        "$_gen20 = list($map_kv, :comma)",
    ],
    94: [
        "$map_kv = $e :colon $e -> MapLiteralKv( key=$0, value=$2 )",
    ],
    95: [
        "$task = :task :identifier :lbrace $_gen3 $_gen4 :rbrace -> Task( name=$1, declarations=$3, sections=$4 )",
    ],
    96: [
        "$_gen17 = list($type_e, :comma)",
    ],
    97: [
        "$import = :import :string $_gen2 -> Import( uri=$1, namespace=$2 )",
    ],
    98: [
        "$map = :lbrace $_gen8 :rbrace -> $1",
    ],
    99: [
        "$declaration = $type_e :identifier $_gen9 -> Declaration( type=$0, name=$1, expression=$2 )",
    ],
    100: [
        "$_gen19 = list($object_kv, :comma)",
    ],
    101: [
        "$wf_outputs = :output :lbrace $_gen15 :rbrace -> WorkflowOutputs( outputs=$2 )",
    ],
    102: [
        "$_gen6 = list($cmd_param_kv)",
    ],
    103: [
        "$_gen7 = list($output_kv)",
    ],
    104: [
        "$_gen11 = $alias",
        "$_gen11 = :_empty",
    ],
    105: [
        "$import_namespace = :as :identifier -> $1",
    ],
    106: [
        "$_gen5 = list($command_part)",
    ],
    107: [
        "$wf_output = $wf_output_declaration_syntax",
        "$wf_output = $wf_output_wildcard_syntax",
    ],
    108: [
        "$document = $_gen0 $_gen1 -> Namespace( imports=$0, body=$1 )",
    ],
    109: [
        "$while_loop = :while :lparen $e :rparen :lbrace $_gen10 :rbrace -> WhileLoop( expression=$2, body=$5 )",
    ],
    110: [
        "$_gen1 = list($workflow_or_task_or_decl)",
    ],
    111: [
        "$_gen9 = $setter",
        "$_gen9 = :_empty",
    ],
    112: [
        "$workflow = :workflow :identifier :lbrace $_gen10 :rbrace -> Workflow( name=$1, body=$3 )",
    ],
    113: [
        "$scatter = :scatter :lparen :identifier :in $e :rparen :lbrace $_gen10 :rbrace -> Scatter( item=$2, collection=$4, body=$7 )",
    ],
    114: [
        "$kv = :identifier :colon $e -> RuntimeAttribute( key=$0, value=$2 )",
    ],
    115: [
        "$wf_body_element = $call",
        "$wf_body_element = $declaration",
        "$wf_body_element = $while_loop",
        "$wf_body_element = $if_stmt",
        "$wf_body_element = $scatter",
        "$wf_body_element = $wf_outputs",
        "$wf_body_element = $wf_parameter_meta",
        "$wf_body_element = $wf_meta",
    ],
    116: [
        "$parameter_meta = :parameter_meta $map -> ParameterMeta( map=$1 )",
    ],
    117: [
        "$e = $e :double_pipe $e -> LogicalOr( lhs=$0, rhs=$2 )",
        "$e = $e :double_ampersand $e -> LogicalAnd( lhs=$0, rhs=$2 )",
        "$e = $e :double_equal $e -> Equals( lhs=$0, rhs=$2 )",
        "$e = $e :not_equal $e -> NotEquals( lhs=$0, rhs=$2 )",
        "$e = $e :lt $e -> LessThan( lhs=$0, rhs=$2 )",
        "$e = $e :lteq $e -> LessThanOrEqual( lhs=$0, rhs=$2 )",
        "$e = $e :gt $e -> GreaterThan( lhs=$0, rhs=$2 )",
        "$e = $e :gteq $e -> GreaterThanOrEqual( lhs=$0, rhs=$2 )",
        "$e = $e :plus $e -> Add( lhs=$0, rhs=$2 )",
        "$e = $e :dash $e -> Subtract( lhs=$0, rhs=$2 )",
        "$e = $e :asterisk $e -> Multiply( lhs=$0, rhs=$2 )",
        "$e = $e :slash $e -> Divide( lhs=$0, rhs=$2 )",
        "$e = $e :percent $e -> Remainder( lhs=$0, rhs=$2 )",
        "$e = :not $e -> LogicalNot( expression=$1 )",
        "$e = :plus $e -> UnaryPlus( expression=$1 )",
        "$e = :dash $e -> UnaryNegation( expression=$1 )",
        "$e = :identifier <=> :lparen $_gen18 :rparen -> FunctionCall( name=$0, params=$2 )",
        "$e = :identifier <=> :lsquare $e :rsquare -> ArrayOrMapLookup( lhs=$0, rhs=$2 )",
        "$e = :identifier <=> :dot :identifier -> MemberAccess( lhs=$0, rhs=$2 )",
        "$e = :object :lbrace $_gen19 :rbrace -> ObjectLiteral( map=$2 )",
        "$e = :lsquare $_gen18 :rsquare -> ArrayLiteral( values=$1 )",
        "$e = :lbrace $_gen20 :rbrace -> MapLiteral( map=$1 )",
        "$e = :lparen $_gen18 :rparen -> TupleLiteral( values=$1 )",
        "$e = :if $e :then $e :else $e -> TernaryIf( cond=$1, iftrue=$3, iffalse=$5 )",
        "$e = :string",
        "$e = :identifier",
        "$e = :boolean",
        "$e = :integer",
        "$e = :float",
    ],
    118: [
        "$_gen18 = list($e, :comma)",
    ],
}
rules = {
    0: "$_gen0 = list($import)",
    1: "$_gen1 = list($workflow_or_task_or_decl)",
    2: "$document = $_gen0 $_gen1 -> Namespace( imports=$0, body=$1 )",
    3: "$workflow_or_task_or_decl = $workflow",
    4: "$workflow_or_task_or_decl = $task",
    5: "$workflow_or_task_or_decl = $declaration",
    6: "$_gen2 = $import_namespace",
    7: "$_gen2 = :_empty",
    8: "$import = :import :string $_gen2 -> Import( uri=$1, namespace=$2 )",
    9: "$import_namespace = :as :identifier -> $1",
    10: "$_gen3 = list($declaration)",
    11: "$_gen4 = list($sections)",
    12: "$task = :task :identifier :lbrace $_gen3 $_gen4 :rbrace -> Task( name=$1, declarations=$3, sections=$4 )",
    13: "$sections = $command",
    14: "$sections = $outputs",
    15: "$sections = $runtime",
    16: "$sections = $parameter_meta",
    17: "$sections = $meta",
    18: "$_gen5 = list($command_part)",
    19: "$command = :raw_command :raw_cmd_start $_gen5 :raw_cmd_end -> RawCommand( parts=$2 )",
    20: "$command_part = :cmd_part",
    21: "$command_part = $cmd_param",
    22: "$_gen6 = list($cmd_param_kv)",
    23: "$cmd_param = :cmd_param_start $_gen6 $e :cmd_param_end -> CommandParameter( attributes=$1, expr=$2 )",
    24: "$cmd_param_kv = :cmd_attr_hint :identifier :equal $e -> CommandParameterAttr( key=$1, value=$3 )",
    25: "$_gen7 = list($output_kv)",
    26: "$outputs = :output :lbrace $_gen7 :rbrace -> Outputs( attributes=$2 )",
    27: "$output_kv = $type_e :identifier :equal $e -> Output( type=$0, name=$1, expression=$3 )",
    28: "$runtime = :runtime $map -> Runtime( map=$1 )",
    29: "$parameter_meta = :parameter_meta $map -> ParameterMeta( map=$1 )",
    30: "$meta = :meta $map -> Meta( map=$1 )",
    31: "$_gen8 = list($kv)",
    32: "$map = :lbrace $_gen8 :rbrace -> $1",
    33: "$kv = :identifier :colon $e -> RuntimeAttribute( key=$0, value=$2 )",
    34: "$_gen9 = $setter",
    35: "$_gen9 = :_empty",
    36: "$declaration = $type_e :identifier $_gen9 -> Declaration( type=$0, name=$1, expression=$2 )",
    37: "$setter = :equal $e -> $1",
    38: "$map_kv = $e :colon $e -> MapLiteralKv( key=$0, value=$2 )",
    39: "$_gen10 = list($wf_body_element)",
    40: "$workflow = :workflow :identifier :lbrace $_gen10 :rbrace -> Workflow( name=$1, body=$3 )",
    41: "$wf_body_element = $call",
    42: "$wf_body_element = $declaration",
    43: "$wf_body_element = $while_loop",
    44: "$wf_body_element = $if_stmt",
    45: "$wf_body_element = $scatter",
    46: "$wf_body_element = $wf_outputs",
    47: "$wf_body_element = $wf_parameter_meta",
    48: "$wf_body_element = $wf_meta",
    49: "$_gen11 = $alias",
    50: "$_gen11 = :_empty",
    51: "$_gen12 = $call_body",
    52: "$_gen12 = :_empty",
    53: "$call = :call :fqn $_gen11 $_gen12 -> Call( task=$1, alias=$2, body=$3 )",
    54: "$_gen13 = list($call_input)",
    55: "$call_body = :lbrace $_gen3 $_gen13 :rbrace -> CallBody( declarations=$1, io=$2 )",
    56: "$_gen14 = list($mapping, :comma)",
    57: "$call_input = :input :colon $_gen14 -> Inputs( map=$2 )",
    58: "$mapping = :identifier :equal $e -> IOMapping( key=$0, value=$2 )",
    59: "$alias = :as :identifier -> $1",
    60: "$_gen15 = list($wf_output)",
    61: "$wf_outputs = :output :lbrace $_gen15 :rbrace -> WorkflowOutputs( outputs=$2 )",
    62: "$wf_output = $wf_output_declaration_syntax",
    63: "$wf_output = $wf_output_wildcard_syntax",
    64: "$wf_output_declaration_syntax = $type_e :identifier :equal $e -> WorkflowOutputDeclaration( type=$0, name=$1, expression=$3 )",
    65: "$_gen16 = $wf_output_wildcard",
    66: "$_gen16 = :_empty",
    67: "$wf_output_wildcard_syntax = :fqn $_gen16 -> WorkflowOutputWildcard( fqn=$0, wildcard=$1 )",
    68: "$wf_output_wildcard = :dot :asterisk -> $1",
    69: "$wf_parameter_meta = :parameter_meta $map -> ParameterMeta( map=$1 )",
    70: "$wf_meta = :meta $map -> Meta( map=$1 )",
    71: "$while_loop = :while :lparen $e :rparen :lbrace $_gen10 :rbrace -> WhileLoop( expression=$2, body=$5 )",
    72: "$if_stmt = :if :lparen $e :rparen :lbrace $_gen10 :rbrace -> If( expression=$2, body=$5 )",
    73: "$scatter = :scatter :lparen :identifier :in $e :rparen :lbrace $_gen10 :rbrace -> Scatter( item=$2, collection=$4, body=$7 )",
    74: "$object_kv = :identifier :colon $e -> ObjectKV( key=$0, value=$2 )",
    75: "$_gen17 = list($type_e, :comma)",
    76: "$type_e = :type <=> :lsquare $_gen17 :rsquare -> Type( name=$0, subtype=$2 )",
    77: "$type_e = :type <=> :qmark -> OptionalType( innerType=$0 )",
    78: "$type_e = :type <=> :plus -> NonEmptyType( innerType=$0 )",
    79: "$type_e = :type",
    80: "$e = $e :double_pipe $e -> LogicalOr( lhs=$0, rhs=$2 )",
    81: "$e = $e :double_ampersand $e -> LogicalAnd( lhs=$0, rhs=$2 )",
    82: "$e = $e :double_equal $e -> Equals( lhs=$0, rhs=$2 )",
    83: "$e = $e :not_equal $e -> NotEquals( lhs=$0, rhs=$2 )",
    84: "$e = $e :lt $e -> LessThan( lhs=$0, rhs=$2 )",
    85: "$e = $e :lteq $e -> LessThanOrEqual( lhs=$0, rhs=$2 )",
    86: "$e = $e :gt $e -> GreaterThan( lhs=$0, rhs=$2 )",
    87: "$e = $e :gteq $e -> GreaterThanOrEqual( lhs=$0, rhs=$2 )",
    88: "$e = $e :plus $e -> Add( lhs=$0, rhs=$2 )",
    89: "$e = $e :dash $e -> Subtract( lhs=$0, rhs=$2 )",
    90: "$e = $e :asterisk $e -> Multiply( lhs=$0, rhs=$2 )",
    91: "$e = $e :slash $e -> Divide( lhs=$0, rhs=$2 )",
    92: "$e = $e :percent $e -> Remainder( lhs=$0, rhs=$2 )",
    93: "$e = :not $e -> LogicalNot( expression=$1 )",
    94: "$e = :plus $e -> UnaryPlus( expression=$1 )",
    95: "$e = :dash $e -> UnaryNegation( expression=$1 )",
    96: "$_gen18 = list($e, :comma)",
    97: "$e = :identifier <=> :lparen $_gen18 :rparen -> FunctionCall( name=$0, params=$2 )",
    98: "$e = :identifier <=> :lsquare $e :rsquare -> ArrayOrMapLookup( lhs=$0, rhs=$2 )",
    99: "$e = :identifier <=> :dot :identifier -> MemberAccess( lhs=$0, rhs=$2 )",
    100: "$_gen19 = list($object_kv, :comma)",
    101: "$e = :object :lbrace $_gen19 :rbrace -> ObjectLiteral( map=$2 )",
    102: "$e = :lsquare $_gen18 :rsquare -> ArrayLiteral( values=$1 )",
    103: "$_gen20 = list($map_kv, :comma)",
    104: "$e = :lbrace $_gen20 :rbrace -> MapLiteral( map=$1 )",
    105: "$e = :lparen $_gen18 :rparen -> TupleLiteral( values=$1 )",
    106: "$e = :if $e :then $e :else $e -> TernaryIf( cond=$1, iftrue=$3, iffalse=$5 )",
    107: "$e = :string",
    108: "$e = :identifier",
    109: "$e = :boolean",
    110: "$e = :integer",
    111: "$e = :float",
}
def is_terminal(id): return isinstance(id, int) and 0 <= id <= 57
def parse(tokens, errors=None, start=None):
    if errors is None:
        errors = DefaultSyntaxErrorHandler()
    if isinstance(tokens, str):
        tokens = lex(tokens, 'string', errors)
    ctx = ParserContext(tokens, errors)
    tree = parse_document(ctx)
    if tokens.current() != None:
        raise ctx.errors.excess_tokens()
    return tree
def expect(ctx, terminal_id):
    current = ctx.tokens.current()
    if not current:
        raise ctx.errors.no_more_tokens(ctx.nonterminal, terminals[terminal_id], ctx.tokens.last())
    if current.id != terminal_id:
        raise ctx.errors.unexpected_symbol(ctx.nonterminal, current, [terminals[terminal_id]], ctx.rule)
    next = ctx.tokens.advance()
    if next and not is_terminal(next.id):
        raise ctx.errors.invalid_terminal(ctx.nonterminal, next)
    return current
# START definitions for expression parser: e
infix_binding_power_e = {
    23: 4000, # $e = $e :double_pipe $e -> LogicalOr( lhs=$0, rhs=$2 )
    47: 5000, # $e = $e :double_ampersand $e -> LogicalAnd( lhs=$0, rhs=$2 )
    24: 6000, # $e = $e :double_equal $e -> Equals( lhs=$0, rhs=$2 )
    2: 6000, # $e = $e :not_equal $e -> NotEquals( lhs=$0, rhs=$2 )
    36: 7000, # $e = $e :lt $e -> LessThan( lhs=$0, rhs=$2 )
    15: 7000, # $e = $e :lteq $e -> LessThanOrEqual( lhs=$0, rhs=$2 )
    49: 7000, # $e = $e :gt $e -> GreaterThan( lhs=$0, rhs=$2 )
    56: 7000, # $e = $e :gteq $e -> GreaterThanOrEqual( lhs=$0, rhs=$2 )
    11: 8000, # $e = $e :plus $e -> Add( lhs=$0, rhs=$2 )
    1: 8000, # $e = $e :dash $e -> Subtract( lhs=$0, rhs=$2 )
    17: 9000, # $e = $e :asterisk $e -> Multiply( lhs=$0, rhs=$2 )
    37: 9000, # $e = $e :slash $e -> Divide( lhs=$0, rhs=$2 )
    57: 9000, # $e = $e :percent $e -> Remainder( lhs=$0, rhs=$2 )
    20: 11000, # $e = :identifier <=> :lparen list($e, :comma) :rparen -> FunctionCall( name=$0, params=$2 )
    46: 12000, # $e = :identifier <=> :lsquare $e :rsquare -> ArrayOrMapLookup( lhs=$0, rhs=$2 )
    7: 13000, # $e = :identifier <=> :dot :identifier -> MemberAccess( lhs=$0, rhs=$2 )
}
prefix_binding_power_e = {
    12: 10000, # $e = :not $e -> LogicalNot( expression=$1 )
    11: 10000, # $e = :plus $e -> UnaryPlus( expression=$1 )
    1: 10000, # $e = :dash $e -> UnaryNegation( expression=$1 )
}
def get_infix_binding_power_e(terminal_id):
    try:
        return infix_binding_power_e[terminal_id]
    except:
        return 0
def get_prefix_binding_power_e(terminal_id):
    try:
        return prefix_binding_power_e[terminal_id]
    except:
        return 0
def parse_e(ctx):
    return parse_e_internal(ctx, rbp=0)
def parse_e_internal(ctx, rbp=0):
    left = nud_e(ctx)
    if isinstance(left, ParseTree):
        left.isExpr = True
        left.isNud = True
    while ctx.tokens.current() and rbp < get_infix_binding_power_e(ctx.tokens.current().id):
        left = led_e(left, ctx)
    if left:
        left.isExpr = True
    return left
def nud_e(ctx):
    tree = ParseTree(NonTerminal(117, 'e'))
    current = ctx.tokens.current()
    ctx.nonterminal = "e"
    if not current:
        return tree
    elif current.id in rule_first[93]:
        # rule first == not
        # e first == dash, e, boolean, lbrace, integer, float, lsquare, if, string, lparen, not, plus, object, identifier
        # $e = :not $e -> LogicalNot( expression=$1 )
        ctx.rule = rules[93]
        ast_parameters = OrderedDict([
            ('expression', 1),
        ])
        tree.astTransform = AstTransformNodeCreator('LogicalNot', ast_parameters)
        tree.nudMorphemeCount = 2
        tree.add(expect(ctx, 12))
        tree.add(parse_e_internal(ctx, get_prefix_binding_power_e(12)))
        tree.isPrefix = True
    elif current.id in rule_first[94]:
        # rule first == plus
        # e first == dash, e, boolean, lbrace, integer, float, lsquare, if, string, lparen, not, plus, object, identifier
        # $e = :plus $e -> UnaryPlus( expression=$1 )
        ctx.rule = rules[94]
        ast_parameters = OrderedDict([
            ('expression', 1),
        ])
        tree.astTransform = AstTransformNodeCreator('UnaryPlus', ast_parameters)
        tree.nudMorphemeCount = 2
        tree.add(expect(ctx, 11))
        tree.add(parse_e_internal(ctx, get_prefix_binding_power_e(11)))
        tree.isPrefix = True
    elif current.id in rule_first[95]:
        # rule first == dash
        # e first == dash, e, boolean, lbrace, integer, float, lsquare, if, string, lparen, not, plus, object, identifier
        # $e = :dash $e -> UnaryNegation( expression=$1 )
        ctx.rule = rules[95]
        ast_parameters = OrderedDict([
            ('expression', 1),
        ])
        tree.astTransform = AstTransformNodeCreator('UnaryNegation', ast_parameters)
        tree.nudMorphemeCount = 2
        tree.add(expect(ctx, 1))
        tree.add(parse_e_internal(ctx, get_prefix_binding_power_e(1)))
        tree.isPrefix = True
    elif current.id in rule_first[97]:
        # rule first == identifier
        # e first == dash, e, boolean, lbrace, integer, float, lsquare, if, string, lparen, not, plus, object, identifier
        # $e = :identifier <=> :lparen $_gen18 :rparen -> FunctionCall( name=$0, params=$2 )
        ctx.rule = rules[97]
        tree.astTransform = AstTransformSubstitution(0)
        tree.nudMorphemeCount = 1
        tree.add(expect(ctx, 50))
    elif current.id in rule_first[98]:
        # rule first == identifier
        # e first == dash, e, boolean, lbrace, integer, float, lsquare, if, string, lparen, not, plus, object, identifier
        # $e = :identifier <=> :lsquare $e :rsquare -> ArrayOrMapLookup( lhs=$0, rhs=$2 )
        ctx.rule = rules[98]
        tree.astTransform = AstTransformSubstitution(0)
        tree.nudMorphemeCount = 1
        tree.add(expect(ctx, 50))
    elif current.id in rule_first[99]:
        # rule first == identifier
        # e first == dash, e, boolean, lbrace, integer, float, lsquare, if, string, lparen, not, plus, object, identifier
        # $e = :identifier <=> :dot :identifier -> MemberAccess( lhs=$0, rhs=$2 )
        ctx.rule = rules[99]
        tree.astTransform = AstTransformSubstitution(0)
        tree.nudMorphemeCount = 1
        tree.add(expect(ctx, 50))
    elif current.id in rule_first[101]:
        # rule first == object
        # e first == dash, e, boolean, lbrace, integer, float, lsquare, if, string, lparen, not, plus, object, identifier
        # $e = :object :lbrace $_gen19 :rbrace -> ObjectLiteral( map=$2 )
        ctx.rule = rules[101]
        ast_parameters = OrderedDict([
            ('map', 2),
        ])
        tree.astTransform = AstTransformNodeCreator('ObjectLiteral', ast_parameters)
        tree.nudMorphemeCount = 4
        tree.add(expect(ctx, 52))
        tree.add(expect(ctx, 16))
        tree.add(parse__gen19(ctx))
        tree.add(expect(ctx, 44))
    elif current.id in rule_first[102]:
        # rule first == lsquare
        # e first == dash, e, boolean, lbrace, integer, float, lsquare, if, string, lparen, not, plus, object, identifier
        # $e = :lsquare $_gen18 :rsquare -> ArrayLiteral( values=$1 )
        ctx.rule = rules[102]
        ast_parameters = OrderedDict([
            ('values', 1),
        ])
        tree.astTransform = AstTransformNodeCreator('ArrayLiteral', ast_parameters)
        tree.nudMorphemeCount = 3
        tree.add(expect(ctx, 46))
        tree.add(parse__gen18(ctx))
        tree.add(expect(ctx, 8))
    elif current.id in rule_first[104]:
        # rule first == lbrace
        # e first == dash, e, boolean, lbrace, integer, float, lsquare, if, string, lparen, not, plus, object, identifier
        # $e = :lbrace $_gen20 :rbrace -> MapLiteral( map=$1 )
        ctx.rule = rules[104]
        ast_parameters = OrderedDict([
            ('map', 1),
        ])
        tree.astTransform = AstTransformNodeCreator('MapLiteral', ast_parameters)
        tree.nudMorphemeCount = 3
        tree.add(expect(ctx, 16))
        tree.add(parse__gen20(ctx))
        tree.add(expect(ctx, 44))
    elif current.id in rule_first[105]:
        # rule first == lparen
        # e first == dash, e, boolean, lbrace, integer, float, lsquare, if, string, lparen, not, plus, object, identifier
        # $e = :lparen $_gen18 :rparen -> TupleLiteral( values=$1 )
        ctx.rule = rules[105]
        ast_parameters = OrderedDict([
            ('values', 1),
        ])
        tree.astTransform = AstTransformNodeCreator('TupleLiteral', ast_parameters)
        tree.nudMorphemeCount = 3
        tree.add(expect(ctx, 20))
        tree.add(parse__gen18(ctx))
        tree.add(expect(ctx, 45))
    elif current.id in rule_first[106]:
        # rule first == if
        # e first == dash, e, boolean, lbrace, integer, float, lsquare, if, string, lparen, not, plus, object, identifier
        # $e = :if $e :then $e :else $e -> TernaryIf( cond=$1, iftrue=$3, iffalse=$5 )
        ctx.rule = rules[106]
        ast_parameters = OrderedDict([
            ('cond', 1),
            ('iftrue', 3),
            ('iffalse', 5),
        ])
        tree.astTransform = AstTransformNodeCreator('TernaryIf', ast_parameters)
        tree.nudMorphemeCount = 6
        tree.add(expect(ctx, 18))
        tree.add(parse_e(ctx))
        tree.add(expect(ctx, 31))
        tree.add(parse_e(ctx))
        tree.add(expect(ctx, 21))
        tree.add(parse_e(ctx))
    elif current.id in rule_first[107]:
        # rule first == string
        # e first == dash, e, boolean, lbrace, integer, float, lsquare, if, string, lparen, not, plus, object, identifier
        # $e = :string
        ctx.rule = rules[107]
        tree.astTransform = AstTransformSubstitution(0)
        tree.nudMorphemeCount = 1
        tree.add(expect(ctx, 42))
    elif current.id in rule_first[108]:
        # rule first == identifier
        # e first == dash, e, boolean, lbrace, integer, float, lsquare, if, string, lparen, not, plus, object, identifier
        # $e = :identifier
        ctx.rule = rules[108]
        tree.astTransform = AstTransformSubstitution(0)
        tree.nudMorphemeCount = 1
        tree.add(expect(ctx, 50))
    elif current.id in rule_first[109]:
        # rule first == boolean
        # e first == dash, e, boolean, lbrace, integer, float, lsquare, if, string, lparen, not, plus, object, identifier
        # $e = :boolean
        ctx.rule = rules[109]
        tree.astTransform = AstTransformSubstitution(0)
        tree.nudMorphemeCount = 1
        tree.add(expect(ctx, 3))
    elif current.id in rule_first[110]:
        # rule first == integer
        # e first == dash, e, boolean, lbrace, integer, float, lsquare, if, string, lparen, not, plus, object, identifier
        # $e = :integer
        ctx.rule = rules[110]
        tree.astTransform = AstTransformSubstitution(0)
        tree.nudMorphemeCount = 1
        tree.add(expect(ctx, 39))
    elif current.id in rule_first[111]:
        # rule first == float
        # e first == dash, e, boolean, lbrace, integer, float, lsquare, if, string, lparen, not, plus, object, identifier
        # $e = :float
        ctx.rule = rules[111]
        tree.astTransform = AstTransformSubstitution(0)
        tree.nudMorphemeCount = 1
        tree.add(expect(ctx, 4))
    return tree
def led_e(left, ctx):
    tree = ParseTree(NonTerminal(117, 'e'))
    current = ctx.tokens.current()
    ctx.nonterminal = "e"
    if current.id == 23: # :double_pipe
        # $e = $e :double_pipe $e -> LogicalOr( lhs=$0, rhs=$2 )
        ctx.rule = rules[80]
        ast_parameters = OrderedDict([
            ('lhs', 0),
            ('rhs', 2),
        ])
        tree.astTransform = AstTransformNodeCreator('LogicalOr', ast_parameters)
        tree.isExprNud = True
        tree.add(left)
        tree.add(expect(ctx, 23)) # :double_pipe
        modifier = 0
        tree.isInfix = True
        tree.add(parse_e_internal(ctx, get_infix_binding_power_e(23) - modifier))
    if current.id == 47: # :double_ampersand
        # $e = $e :double_ampersand $e -> LogicalAnd( lhs=$0, rhs=$2 )
        ctx.rule = rules[81]
        ast_parameters = OrderedDict([
            ('lhs', 0),
            ('rhs', 2),
        ])
        tree.astTransform = AstTransformNodeCreator('LogicalAnd', ast_parameters)
        tree.isExprNud = True
        tree.add(left)
        tree.add(expect(ctx, 47)) # :double_ampersand
        modifier = 0
        tree.isInfix = True
        tree.add(parse_e_internal(ctx, get_infix_binding_power_e(47) - modifier))
    if current.id == 24: # :double_equal
        # $e = $e :double_equal $e -> Equals( lhs=$0, rhs=$2 )
        ctx.rule = rules[82]
        ast_parameters = OrderedDict([
            ('lhs', 0),
            ('rhs', 2),
        ])
        tree.astTransform = AstTransformNodeCreator('Equals', ast_parameters)
        tree.isExprNud = True
        tree.add(left)
        tree.add(expect(ctx, 24)) # :double_equal
        modifier = 0
        tree.isInfix = True
        tree.add(parse_e_internal(ctx, get_infix_binding_power_e(24) - modifier))
    if current.id == 2: # :not_equal
        # $e = $e :not_equal $e -> NotEquals( lhs=$0, rhs=$2 )
        ctx.rule = rules[83]
        ast_parameters = OrderedDict([
            ('lhs', 0),
            ('rhs', 2),
        ])
        tree.astTransform = AstTransformNodeCreator('NotEquals', ast_parameters)
        tree.isExprNud = True
        tree.add(left)
        tree.add(expect(ctx, 2)) # :not_equal
        modifier = 0
        tree.isInfix = True
        tree.add(parse_e_internal(ctx, get_infix_binding_power_e(2) - modifier))
    if current.id == 36: # :lt
        # $e = $e :lt $e -> LessThan( lhs=$0, rhs=$2 )
        ctx.rule = rules[84]
        ast_parameters = OrderedDict([
            ('lhs', 0),
            ('rhs', 2),
        ])
        tree.astTransform = AstTransformNodeCreator('LessThan', ast_parameters)
        tree.isExprNud = True
        tree.add(left)
        tree.add(expect(ctx, 36)) # :lt
        modifier = 0
        tree.isInfix = True
        tree.add(parse_e_internal(ctx, get_infix_binding_power_e(36) - modifier))
    if current.id == 15: # :lteq
        # $e = $e :lteq $e -> LessThanOrEqual( lhs=$0, rhs=$2 )
        ctx.rule = rules[85]
        ast_parameters = OrderedDict([
            ('lhs', 0),
            ('rhs', 2),
        ])
        tree.astTransform = AstTransformNodeCreator('LessThanOrEqual', ast_parameters)
        tree.isExprNud = True
        tree.add(left)
        tree.add(expect(ctx, 15)) # :lteq
        modifier = 0
        tree.isInfix = True
        tree.add(parse_e_internal(ctx, get_infix_binding_power_e(15) - modifier))
    if current.id == 49: # :gt
        # $e = $e :gt $e -> GreaterThan( lhs=$0, rhs=$2 )
        ctx.rule = rules[86]
        ast_parameters = OrderedDict([
            ('lhs', 0),
            ('rhs', 2),
        ])
        tree.astTransform = AstTransformNodeCreator('GreaterThan', ast_parameters)
        tree.isExprNud = True
        tree.add(left)
        tree.add(expect(ctx, 49)) # :gt
        modifier = 0
        tree.isInfix = True
        tree.add(parse_e_internal(ctx, get_infix_binding_power_e(49) - modifier))
    if current.id == 56: # :gteq
        # $e = $e :gteq $e -> GreaterThanOrEqual( lhs=$0, rhs=$2 )
        ctx.rule = rules[87]
        ast_parameters = OrderedDict([
            ('lhs', 0),
            ('rhs', 2),
        ])
        tree.astTransform = AstTransformNodeCreator('GreaterThanOrEqual', ast_parameters)
        tree.isExprNud = True
        tree.add(left)
        tree.add(expect(ctx, 56)) # :gteq
        modifier = 0
        tree.isInfix = True
        tree.add(parse_e_internal(ctx, get_infix_binding_power_e(56) - modifier))
    if current.id == 11: # :plus
        # $e = $e :plus $e -> Add( lhs=$0, rhs=$2 )
        ctx.rule = rules[88]
        ast_parameters = OrderedDict([
            ('lhs', 0),
            ('rhs', 2),
        ])
        tree.astTransform = AstTransformNodeCreator('Add', ast_parameters)
        tree.isExprNud = True
        tree.add(left)
        tree.add(expect(ctx, 11)) # :plus
        modifier = 0
        tree.isInfix = True
        tree.add(parse_e_internal(ctx, get_infix_binding_power_e(11) - modifier))
    if current.id == 1: # :dash
        # $e = $e :dash $e -> Subtract( lhs=$0, rhs=$2 )
        ctx.rule = rules[89]
        ast_parameters = OrderedDict([
            ('lhs', 0),
            ('rhs', 2),
        ])
        tree.astTransform = AstTransformNodeCreator('Subtract', ast_parameters)
        tree.isExprNud = True
        tree.add(left)
        tree.add(expect(ctx, 1)) # :dash
        modifier = 0
        tree.isInfix = True
        tree.add(parse_e_internal(ctx, get_infix_binding_power_e(1) - modifier))
    if current.id == 17: # :asterisk
        # $e = $e :asterisk $e -> Multiply( lhs=$0, rhs=$2 )
        ctx.rule = rules[90]
        ast_parameters = OrderedDict([
            ('lhs', 0),
            ('rhs', 2),
        ])
        tree.astTransform = AstTransformNodeCreator('Multiply', ast_parameters)
        tree.isExprNud = True
        tree.add(left)
        tree.add(expect(ctx, 17)) # :asterisk
        modifier = 0
        tree.isInfix = True
        tree.add(parse_e_internal(ctx, get_infix_binding_power_e(17) - modifier))
    if current.id == 37: # :slash
        # $e = $e :slash $e -> Divide( lhs=$0, rhs=$2 )
        ctx.rule = rules[91]
        ast_parameters = OrderedDict([
            ('lhs', 0),
            ('rhs', 2),
        ])
        tree.astTransform = AstTransformNodeCreator('Divide', ast_parameters)
        tree.isExprNud = True
        tree.add(left)
        tree.add(expect(ctx, 37)) # :slash
        modifier = 0
        tree.isInfix = True
        tree.add(parse_e_internal(ctx, get_infix_binding_power_e(37) - modifier))
    if current.id == 57: # :percent
        # $e = $e :percent $e -> Remainder( lhs=$0, rhs=$2 )
        ctx.rule = rules[92]
        ast_parameters = OrderedDict([
            ('lhs', 0),
            ('rhs', 2),
        ])
        tree.astTransform = AstTransformNodeCreator('Remainder', ast_parameters)
        tree.isExprNud = True
        tree.add(left)
        tree.add(expect(ctx, 57)) # :percent
        modifier = 0
        tree.isInfix = True
        tree.add(parse_e_internal(ctx, get_infix_binding_power_e(57) - modifier))
    if current.id == 20: # :lparen
        # $e = :identifier <=> :lparen $_gen18 :rparen -> FunctionCall( name=$0, params=$2 )
        ctx.rule = rules[97]
        ast_parameters = OrderedDict([
            ('name', 0),
            ('params', 2),
        ])
        tree.astTransform = AstTransformNodeCreator('FunctionCall', ast_parameters)
        tree.add(left)
        tree.add(expect(ctx, 20)) # :lparen
        tree.add(parse__gen18(ctx))
        tree.add(expect(ctx, 45)) # :rparen
    if current.id == 46: # :lsquare
        # $e = :identifier <=> :lsquare $e :rsquare -> ArrayOrMapLookup( lhs=$0, rhs=$2 )
        ctx.rule = rules[98]
        ast_parameters = OrderedDict([
            ('lhs', 0),
            ('rhs', 2),
        ])
        tree.astTransform = AstTransformNodeCreator('ArrayOrMapLookup', ast_parameters)
        tree.add(left)
        tree.add(expect(ctx, 46)) # :lsquare
        modifier = 0
        tree.add(parse_e_internal(ctx, get_infix_binding_power_e(46) - modifier))
        tree.add(expect(ctx, 8)) # :rsquare
    if current.id == 7: # :dot
        # $e = :identifier <=> :dot :identifier -> MemberAccess( lhs=$0, rhs=$2 )
        ctx.rule = rules[99]
        ast_parameters = OrderedDict([
            ('lhs', 0),
            ('rhs', 2),
        ])
        tree.astTransform = AstTransformNodeCreator('MemberAccess', ast_parameters)
        tree.add(left)
        tree.add(expect(ctx, 7)) # :dot
        tree.add(expect(ctx, 50)) # :identifier
    return tree
# END definitions for expression parser: e
# START definitions for expression parser: type_e
infix_binding_power_type_e = {
    46: 1000, # $type_e = :type <=> :lsquare list($type_e, :comma) :rsquare -> Type( name=$0, subtype=$2 )
    33: 2000, # $type_e = :type <=> :qmark -> OptionalType( innerType=$0 )
    11: 3000, # $type_e = :type <=> :plus -> NonEmptyType( innerType=$0 )
}
prefix_binding_power_type_e = {
}
def get_infix_binding_power_type_e(terminal_id):
    try:
        return infix_binding_power_type_e[terminal_id]
    except:
        return 0
def get_prefix_binding_power_type_e(terminal_id):
    try:
        return prefix_binding_power_type_e[terminal_id]
    except:
        return 0
def parse_type_e(ctx):
    return parse_type_e_internal(ctx, rbp=0)
def parse_type_e_internal(ctx, rbp=0):
    left = nud_type_e(ctx)
    if isinstance(left, ParseTree):
        left.isExpr = True
        left.isNud = True
    while ctx.tokens.current() and rbp < get_infix_binding_power_type_e(ctx.tokens.current().id):
        left = led_type_e(left, ctx)
    if left:
        left.isExpr = True
    return left
def nud_type_e(ctx):
    tree = ParseTree(NonTerminal(80, 'type_e'))
    current = ctx.tokens.current()
    ctx.nonterminal = "type_e"
    if not current:
        return tree
    if current.id in rule_first[76]:
        # rule first == type
        # e first == type_e, type
        # $type_e = :type <=> :lsquare $_gen17 :rsquare -> Type( name=$0, subtype=$2 )
        ctx.rule = rules[76]
        tree.astTransform = AstTransformSubstitution(0)
        tree.nudMorphemeCount = 1
        tree.add(expect(ctx, 48))
    elif current.id in rule_first[77]:
        # rule first == type
        # e first == type_e, type
        # $type_e = :type <=> :qmark -> OptionalType( innerType=$0 )
        ctx.rule = rules[77]
        tree.astTransform = AstTransformSubstitution(0)
        tree.nudMorphemeCount = 1
        tree.add(expect(ctx, 48))
    elif current.id in rule_first[78]:
        # rule first == type
        # e first == type_e, type
        # $type_e = :type <=> :plus -> NonEmptyType( innerType=$0 )
        ctx.rule = rules[78]
        tree.astTransform = AstTransformSubstitution(0)
        tree.nudMorphemeCount = 1
        tree.add(expect(ctx, 48))
    elif current.id in rule_first[79]:
        # rule first == type
        # e first == type_e, type
        # $type_e = :type
        ctx.rule = rules[79]
        tree.astTransform = AstTransformSubstitution(0)
        tree.nudMorphemeCount = 1
        tree.add(expect(ctx, 48))
    return tree
def led_type_e(left, ctx):
    tree = ParseTree(NonTerminal(80, 'type_e'))
    current = ctx.tokens.current()
    ctx.nonterminal = "type_e"
    if current.id == 46: # :lsquare
        # $type_e = :type <=> :lsquare $_gen17 :rsquare -> Type( name=$0, subtype=$2 )
        ctx.rule = rules[76]
        ast_parameters = OrderedDict([
            ('name', 0),
            ('subtype', 2),
        ])
        tree.astTransform = AstTransformNodeCreator('Type', ast_parameters)
        tree.add(left)
        tree.add(expect(ctx, 46)) # :lsquare
        tree.add(parse__gen17(ctx))
        tree.add(expect(ctx, 8)) # :rsquare
    if current.id == 33: # :qmark
        # $type_e = :type <=> :qmark -> OptionalType( innerType=$0 )
        ctx.rule = rules[77]
        ast_parameters = OrderedDict([
            ('innerType', 0),
        ])
        tree.astTransform = AstTransformNodeCreator('OptionalType', ast_parameters)
        tree.add(left)
        tree.add(expect(ctx, 33)) # :qmark
    if current.id == 11: # :plus
        # $type_e = :type <=> :plus -> NonEmptyType( innerType=$0 )
        ctx.rule = rules[78]
        ast_parameters = OrderedDict([
            ('innerType', 0),
        ])
        tree.astTransform = AstTransformNodeCreator('NonEmptyType', ast_parameters)
        tree.add(left)
        tree.add(expect(ctx, 11)) # :plus
    return tree
# END definitions for expression parser: type_e
def parse__gen0(ctx):
    tree = ParseTree(NonTerminal(59, '_gen0'))
    tree.list = True
    ctx.nonterminal = "_gen0"
    if ctx.tokens.current() is not None and \
       ctx.tokens.current().id not in nonterminal_first[59] and \
       ctx.tokens.current().id in nonterminal_follow[59]:
        return tree
    if ctx.tokens.current() is None:
        return tree
    minimum = 0
    while minimum > 0 or \
           (ctx.tokens.current() is not None and \
            ctx.tokens.current().id in nonterminal_first.get(59)):
        tree.add(parse_import(ctx))
        ctx.nonterminal = "_gen0" # Horrible -- because parse_* can reset this
        minimum = max(minimum - 1, 0)
    return tree
def parse__gen1(ctx):
    tree = ParseTree(NonTerminal(110, '_gen1'))
    tree.list = True
    ctx.nonterminal = "_gen1"
    if ctx.tokens.current() is not None and \
       ctx.tokens.current().id not in nonterminal_first[110] and \
       ctx.tokens.current().id in nonterminal_follow[110]:
        return tree
    if ctx.tokens.current() is None:
        return tree
    minimum = 0
    while minimum > 0 or \
           (ctx.tokens.current() is not None and \
            ctx.tokens.current().id in nonterminal_first.get(110)):
        tree.add(parse_workflow_or_task_or_decl(ctx))
        ctx.nonterminal = "_gen1" # Horrible -- because parse_* can reset this
        minimum = max(minimum - 1, 0)
    return tree
def parse__gen10(ctx):
    tree = ParseTree(NonTerminal(74, '_gen10'))
    tree.list = True
    ctx.nonterminal = "_gen10"
    if ctx.tokens.current() is not None and \
       ctx.tokens.current().id not in nonterminal_first[74] and \
       ctx.tokens.current().id in nonterminal_follow[74]:
        return tree
    if ctx.tokens.current() is None:
        return tree
    minimum = 0
    while minimum > 0 or \
           (ctx.tokens.current() is not None and \
            ctx.tokens.current().id in nonterminal_first.get(74)):
        tree.add(parse_wf_body_element(ctx))
        ctx.nonterminal = "_gen10" # Horrible -- because parse_* can reset this
        minimum = max(minimum - 1, 0)
    return tree
def parse__gen13(ctx):
    tree = ParseTree(NonTerminal(89, '_gen13'))
    tree.list = True
    ctx.nonterminal = "_gen13"
    if ctx.tokens.current() is not None and \
       ctx.tokens.current().id not in nonterminal_first[89] and \
       ctx.tokens.current().id in nonterminal_follow[89]:
        return tree
    if ctx.tokens.current() is None:
        return tree
    minimum = 0
    while minimum > 0 or \
           (ctx.tokens.current() is not None and \
            ctx.tokens.current().id in nonterminal_first.get(89)):
        tree.add(parse_call_input(ctx))
        ctx.nonterminal = "_gen13" # Horrible -- because parse_* can reset this
        minimum = max(minimum - 1, 0)
    return tree
def parse__gen14(ctx):
    tree = ParseTree(NonTerminal(84, '_gen14'))
    tree.list = True
    tree.list_separator_id = 43
    ctx.nonterminal = "_gen14"
    if ctx.tokens.current() is not None and \
       ctx.tokens.current().id not in nonterminal_first[84] and \
       ctx.tokens.current().id in nonterminal_follow[84]:
        return tree
    if ctx.tokens.current() is None:
        return tree
    minimum = 0
    while minimum > 0 or \
           (ctx.tokens.current() is not None and \
            ctx.tokens.current().id in nonterminal_first.get(84)):
        tree.add(parse_mapping(ctx))
        ctx.nonterminal = "_gen14" # Horrible -- because parse_* can reset this
        if ctx.tokens.current() is not None and ctx.tokens.current().id == 43:
            tree.add(expect(ctx, 43));
        else:
          break
        minimum = max(minimum - 1, 0)
    return tree
def parse__gen15(ctx):
    tree = ParseTree(NonTerminal(62, '_gen15'))
    tree.list = True
    ctx.nonterminal = "_gen15"
    if ctx.tokens.current() is not None and \
       ctx.tokens.current().id not in nonterminal_first[62] and \
       ctx.tokens.current().id in nonterminal_follow[62]:
        return tree
    if ctx.tokens.current() is None:
        return tree
    minimum = 0
    while minimum > 0 or \
           (ctx.tokens.current() is not None and \
            ctx.tokens.current().id in nonterminal_first.get(62)):
        tree.add(parse_wf_output(ctx))
        ctx.nonterminal = "_gen15" # Horrible -- because parse_* can reset this
        minimum = max(minimum - 1, 0)
    return tree
def parse__gen17(ctx):
    tree = ParseTree(NonTerminal(96, '_gen17'))
    tree.list = True
    tree.list_separator_id = 43
    ctx.nonterminal = "_gen17"
    if ctx.tokens.current() is not None and \
       ctx.tokens.current().id not in nonterminal_first[96] and \
       ctx.tokens.current().id in nonterminal_follow[96]:
        return tree
    if ctx.tokens.current() is None:
        return tree
    minimum = 0
    while minimum > 0 or \
           (ctx.tokens.current() is not None and \
            ctx.tokens.current().id in nonterminal_first.get(96)):
        tree.add(parse_type_e(ctx))
        ctx.nonterminal = "_gen17" # Horrible -- because parse_* can reset this
        if ctx.tokens.current() is not None and ctx.tokens.current().id == 43:
            tree.add(expect(ctx, 43));
        else:
          break
        minimum = max(minimum - 1, 0)
    return tree
def parse__gen18(ctx):
    tree = ParseTree(NonTerminal(118, '_gen18'))
    tree.list = True
    tree.list_separator_id = 43
    ctx.nonterminal = "_gen18"
    if ctx.tokens.current() is not None and \
       ctx.tokens.current().id not in nonterminal_first[118] and \
       ctx.tokens.current().id in nonterminal_follow[118]:
        return tree
    if ctx.tokens.current() is None:
        return tree
    minimum = 0
    while minimum > 0 or \
           (ctx.tokens.current() is not None and \
            ctx.tokens.current().id in nonterminal_first.get(118)):
        tree.add(parse_e(ctx))
        ctx.nonterminal = "_gen18" # Horrible -- because parse_* can reset this
        if ctx.tokens.current() is not None and ctx.tokens.current().id == 43:
            tree.add(expect(ctx, 43));
        else:
          break
        minimum = max(minimum - 1, 0)
    return tree
def parse__gen19(ctx):
    tree = ParseTree(NonTerminal(100, '_gen19'))
    tree.list = True
    tree.list_separator_id = 43
    ctx.nonterminal = "_gen19"
    if ctx.tokens.current() is not None and \
       ctx.tokens.current().id not in nonterminal_first[100] and \
       ctx.tokens.current().id in nonterminal_follow[100]:
        return tree
    if ctx.tokens.current() is None:
        return tree
    minimum = 0
    while minimum > 0 or \
           (ctx.tokens.current() is not None and \
            ctx.tokens.current().id in nonterminal_first.get(100)):
        tree.add(parse_object_kv(ctx))
        ctx.nonterminal = "_gen19" # Horrible -- because parse_* can reset this
        if ctx.tokens.current() is not None and ctx.tokens.current().id == 43:
            tree.add(expect(ctx, 43));
        else:
          break
        minimum = max(minimum - 1, 0)
    return tree
def parse__gen20(ctx):
    tree = ParseTree(NonTerminal(93, '_gen20'))
    tree.list = True
    tree.list_separator_id = 43
    ctx.nonterminal = "_gen20"
    if ctx.tokens.current() is not None and \
       ctx.tokens.current().id not in nonterminal_first[93] and \
       ctx.tokens.current().id in nonterminal_follow[93]:
        return tree
    if ctx.tokens.current() is None:
        return tree
    minimum = 0
    while minimum > 0 or \
           (ctx.tokens.current() is not None and \
            ctx.tokens.current().id in nonterminal_first.get(93)):
        tree.add(parse_map_kv(ctx))
        ctx.nonterminal = "_gen20" # Horrible -- because parse_* can reset this
        if ctx.tokens.current() is not None and ctx.tokens.current().id == 43:
            tree.add(expect(ctx, 43));
        else:
          break
        minimum = max(minimum - 1, 0)
    return tree
def parse__gen3(ctx):
    tree = ParseTree(NonTerminal(72, '_gen3'))
    tree.list = True
    ctx.nonterminal = "_gen3"
    if ctx.tokens.current() is not None and \
       ctx.tokens.current().id not in nonterminal_first[72] and \
       ctx.tokens.current().id in nonterminal_follow[72]:
        return tree
    if ctx.tokens.current() is None:
        return tree
    minimum = 0
    while minimum > 0 or \
           (ctx.tokens.current() is not None and \
            ctx.tokens.current().id in nonterminal_first.get(72)):
        tree.add(parse_declaration(ctx))
        ctx.nonterminal = "_gen3" # Horrible -- because parse_* can reset this
        minimum = max(minimum - 1, 0)
    return tree
def parse__gen4(ctx):
    tree = ParseTree(NonTerminal(91, '_gen4'))
    tree.list = True
    ctx.nonterminal = "_gen4"
    if ctx.tokens.current() is not None and \
       ctx.tokens.current().id not in nonterminal_first[91] and \
       ctx.tokens.current().id in nonterminal_follow[91]:
        return tree
    if ctx.tokens.current() is None:
        return tree
    minimum = 0
    while minimum > 0 or \
           (ctx.tokens.current() is not None and \
            ctx.tokens.current().id in nonterminal_first.get(91)):
        tree.add(parse_sections(ctx))
        ctx.nonterminal = "_gen4" # Horrible -- because parse_* can reset this
        minimum = max(minimum - 1, 0)
    return tree
def parse__gen5(ctx):
    tree = ParseTree(NonTerminal(106, '_gen5'))
    tree.list = True
    ctx.nonterminal = "_gen5"
    if ctx.tokens.current() is not None and \
       ctx.tokens.current().id not in nonterminal_first[106] and \
       ctx.tokens.current().id in nonterminal_follow[106]:
        return tree
    if ctx.tokens.current() is None:
        return tree
    minimum = 0
    while minimum > 0 or \
           (ctx.tokens.current() is not None and \
            ctx.tokens.current().id in nonterminal_first.get(106)):
        tree.add(parse_command_part(ctx))
        ctx.nonterminal = "_gen5" # Horrible -- because parse_* can reset this
        minimum = max(minimum - 1, 0)
    return tree
def parse__gen6(ctx):
    tree = ParseTree(NonTerminal(102, '_gen6'))
    tree.list = True
    ctx.nonterminal = "_gen6"
    if ctx.tokens.current() is not None and \
       ctx.tokens.current().id not in nonterminal_first[102] and \
       ctx.tokens.current().id in nonterminal_follow[102]:
        return tree
    if ctx.tokens.current() is None:
        return tree
    minimum = 0
    while minimum > 0 or \
           (ctx.tokens.current() is not None and \
            ctx.tokens.current().id in nonterminal_first.get(102)):
        tree.add(parse_cmd_param_kv(ctx))
        ctx.nonterminal = "_gen6" # Horrible -- because parse_* can reset this
        minimum = max(minimum - 1, 0)
    return tree
def parse__gen7(ctx):
    tree = ParseTree(NonTerminal(103, '_gen7'))
    tree.list = True
    ctx.nonterminal = "_gen7"
    if ctx.tokens.current() is not None and \
       ctx.tokens.current().id not in nonterminal_first[103] and \
       ctx.tokens.current().id in nonterminal_follow[103]:
        return tree
    if ctx.tokens.current() is None:
        return tree
    minimum = 0
    while minimum > 0 or \
           (ctx.tokens.current() is not None and \
            ctx.tokens.current().id in nonterminal_first.get(103)):
        tree.add(parse_output_kv(ctx))
        ctx.nonterminal = "_gen7" # Horrible -- because parse_* can reset this
        minimum = max(minimum - 1, 0)
    return tree
def parse__gen8(ctx):
    tree = ParseTree(NonTerminal(83, '_gen8'))
    tree.list = True
    ctx.nonterminal = "_gen8"
    if ctx.tokens.current() is not None and \
       ctx.tokens.current().id not in nonterminal_first[83] and \
       ctx.tokens.current().id in nonterminal_follow[83]:
        return tree
    if ctx.tokens.current() is None:
        return tree
    minimum = 0
    while minimum > 0 or \
           (ctx.tokens.current() is not None and \
            ctx.tokens.current().id in nonterminal_first.get(83)):
        tree.add(parse_kv(ctx))
        ctx.nonterminal = "_gen8" # Horrible -- because parse_* can reset this
        minimum = max(minimum - 1, 0)
    return tree
def parse__gen11(ctx):
    current = ctx.tokens.current()
    rule = table[46][current.id] if current else -1
    tree = ParseTree(NonTerminal(104, '_gen11'))
    ctx.nonterminal = "_gen11"
    if current != None and current.id in nonterminal_follow[104] and current.id not in nonterminal_first[104]:
        return tree
    if current == None:
        return tree
    if rule == 49: # $_gen11 = $alias
        ctx.rule = rules[49]
        tree.astTransform = AstTransformSubstitution(0)
        subtree = parse_alias(ctx)
        tree.add(subtree)
        return tree
    return tree
def parse__gen12(ctx):
    current = ctx.tokens.current()
    rule = table[5][current.id] if current else -1
    tree = ParseTree(NonTerminal(63, '_gen12'))
    ctx.nonterminal = "_gen12"
    if current != None and current.id in nonterminal_follow[63] and current.id not in nonterminal_first[63]:
        return tree
    if current == None:
        return tree
    if rule == 51: # $_gen12 = $call_body
        ctx.rule = rules[51]
        tree.astTransform = AstTransformSubstitution(0)
        subtree = parse_call_body(ctx)
        tree.add(subtree)
        return tree
    return tree
def parse__gen16(ctx):
    current = ctx.tokens.current()
    rule = table[9][current.id] if current else -1
    tree = ParseTree(NonTerminal(67, '_gen16'))
    ctx.nonterminal = "_gen16"
    if current != None and current.id in nonterminal_follow[67] and current.id not in nonterminal_first[67]:
        return tree
    if current == None:
        return tree
    if rule == 65: # $_gen16 = $wf_output_wildcard
        ctx.rule = rules[65]
        tree.astTransform = AstTransformSubstitution(0)
        subtree = parse_wf_output_wildcard(ctx)
        tree.add(subtree)
        return tree
    return tree
def parse__gen2(ctx):
    current = ctx.tokens.current()
    rule = table[0][current.id] if current else -1
    tree = ParseTree(NonTerminal(58, '_gen2'))
    ctx.nonterminal = "_gen2"
    if current != None and current.id in nonterminal_follow[58] and current.id not in nonterminal_first[58]:
        return tree
    if current == None:
        return tree
    if rule == 6: # $_gen2 = $import_namespace
        ctx.rule = rules[6]
        tree.astTransform = AstTransformSubstitution(0)
        subtree = parse_import_namespace(ctx)
        tree.add(subtree)
        return tree
    return tree
def parse__gen9(ctx):
    current = ctx.tokens.current()
    rule = table[53][current.id] if current else -1
    tree = ParseTree(NonTerminal(111, '_gen9'))
    ctx.nonterminal = "_gen9"
    if current != None and current.id in nonterminal_follow[111] and current.id not in nonterminal_first[111]:
        return tree
    if current == None:
        return tree
    if rule == 34: # $_gen9 = $setter
        ctx.rule = rules[34]
        tree.astTransform = AstTransformSubstitution(0)
        subtree = parse_setter(ctx)
        tree.add(subtree)
        return tree
    return tree
def parse_alias(ctx):
    current = ctx.tokens.current()
    rule = table[18][current.id] if current else -1
    tree = ParseTree(NonTerminal(76, 'alias'))
    ctx.nonterminal = "alias"
    if current == None:
        raise ctx.errors.unexpected_eof()
    if rule == 59: # $alias = :as :identifier -> $1
        ctx.rule = rules[59]
        tree.astTransform = AstTransformSubstitution(1)
        t = expect(ctx, 53) # :as
        tree.add(t)
        t = expect(ctx, 50) # :identifier
        tree.add(t)
        return tree
    raise ctx.errors.unexpected_symbol(
      ctx.nonterminal,
      ctx.tokens.current(),
      [terminals[x] for x in nonterminal_first[76] if x >=0],
      rules[59]
    )
def parse_call(ctx):
    current = ctx.tokens.current()
    rule = table[27][current.id] if current else -1
    tree = ParseTree(NonTerminal(85, 'call'))
    ctx.nonterminal = "call"
    if current == None:
        raise ctx.errors.unexpected_eof()
    if rule == 53: # $call = :call :fqn $_gen11 $_gen12 -> Call( task=$1, alias=$2, body=$3 )
        ctx.rule = rules[53]
        ast_parameters = OrderedDict([
            ('task', 1),
            ('alias', 2),
            ('body', 3),
        ])
        tree.astTransform = AstTransformNodeCreator('Call', ast_parameters)
        t = expect(ctx, 28) # :call
        tree.add(t)
        t = expect(ctx, 55) # :fqn
        tree.add(t)
        subtree = parse__gen11(ctx)
        tree.add(subtree)
        subtree = parse__gen12(ctx)
        tree.add(subtree)
        return tree
    raise ctx.errors.unexpected_symbol(
      ctx.nonterminal,
      ctx.tokens.current(),
      [terminals[x] for x in nonterminal_first[85] if x >=0],
      rules[53]
    )
def parse_call_body(ctx):
    current = ctx.tokens.current()
    rule = table[30][current.id] if current else -1
    tree = ParseTree(NonTerminal(88, 'call_body'))
    ctx.nonterminal = "call_body"
    if current == None:
        raise ctx.errors.unexpected_eof()
    if rule == 55: # $call_body = :lbrace $_gen3 $_gen13 :rbrace -> CallBody( declarations=$1, io=$2 )
        ctx.rule = rules[55]
        ast_parameters = OrderedDict([
            ('declarations', 1),
            ('io', 2),
        ])
        tree.astTransform = AstTransformNodeCreator('CallBody', ast_parameters)
        t = expect(ctx, 16) # :lbrace
        tree.add(t)
        subtree = parse__gen3(ctx)
        tree.add(subtree)
        subtree = parse__gen13(ctx)
        tree.add(subtree)
        t = expect(ctx, 44) # :rbrace
        tree.add(t)
        return tree
    raise ctx.errors.unexpected_symbol(
      ctx.nonterminal,
      ctx.tokens.current(),
      [terminals[x] for x in nonterminal_first[88] if x >=0],
      rules[55]
    )
def parse_call_input(ctx):
    current = ctx.tokens.current()
    rule = table[3][current.id] if current else -1
    tree = ParseTree(NonTerminal(61, 'call_input'))
    ctx.nonterminal = "call_input"
    if current == None:
        raise ctx.errors.unexpected_eof()
    if rule == 57: # $call_input = :input :colon $_gen14 -> Inputs( map=$2 )
        ctx.rule = rules[57]
        ast_parameters = OrderedDict([
            ('map', 2),
        ])
        tree.astTransform = AstTransformNodeCreator('Inputs', ast_parameters)
        t = expect(ctx, 34) # :input
        tree.add(t)
        t = expect(ctx, 54) # :colon
        tree.add(t)
        subtree = parse__gen14(ctx)
        tree.add(subtree)
        return tree
    raise ctx.errors.unexpected_symbol(
      ctx.nonterminal,
      ctx.tokens.current(),
      [terminals[x] for x in nonterminal_first[61] if x >=0],
      rules[57]
    )
def parse_cmd_param(ctx):
    current = ctx.tokens.current()
    rule = table[10][current.id] if current else -1
    tree = ParseTree(NonTerminal(68, 'cmd_param'))
    ctx.nonterminal = "cmd_param"
    if current == None:
        raise ctx.errors.unexpected_eof()
    if rule == 23: # $cmd_param = :cmd_param_start $_gen6 $e :cmd_param_end -> CommandParameter( attributes=$1, expr=$2 )
        ctx.rule = rules[23]
        ast_parameters = OrderedDict([
            ('attributes', 1),
            ('expr', 2),
        ])
        tree.astTransform = AstTransformNodeCreator('CommandParameter', ast_parameters)
        t = expect(ctx, 5) # :cmd_param_start
        tree.add(t)
        subtree = parse__gen6(ctx)
        tree.add(subtree)
        subtree = parse_e(ctx)
        tree.add(subtree)
        t = expect(ctx, 40) # :cmd_param_end
        tree.add(t)
        return tree
    raise ctx.errors.unexpected_symbol(
      ctx.nonterminal,
      ctx.tokens.current(),
      [terminals[x] for x in nonterminal_first[68] if x >=0],
      rules[23]
    )
def parse_cmd_param_kv(ctx):
    current = ctx.tokens.current()
    rule = table[13][current.id] if current else -1
    tree = ParseTree(NonTerminal(71, 'cmd_param_kv'))
    ctx.nonterminal = "cmd_param_kv"
    if current == None:
        raise ctx.errors.unexpected_eof()
    if rule == 24: # $cmd_param_kv = :cmd_attr_hint :identifier :equal $e -> CommandParameterAttr( key=$1, value=$3 )
        ctx.rule = rules[24]
        ast_parameters = OrderedDict([
            ('key', 1),
            ('value', 3),
        ])
        tree.astTransform = AstTransformNodeCreator('CommandParameterAttr', ast_parameters)
        t = expect(ctx, 27) # :cmd_attr_hint
        tree.add(t)
        t = expect(ctx, 50) # :identifier
        tree.add(t)
        t = expect(ctx, 14) # :equal
        tree.add(t)
        subtree = parse_e(ctx)
        tree.add(subtree)
        return tree
    raise ctx.errors.unexpected_symbol(
      ctx.nonterminal,
      ctx.tokens.current(),
      [terminals[x] for x in nonterminal_first[71] if x >=0],
      rules[24]
    )
def parse_command(ctx):
    current = ctx.tokens.current()
    rule = table[2][current.id] if current else -1
    tree = ParseTree(NonTerminal(60, 'command'))
    ctx.nonterminal = "command"
    if current == None:
        raise ctx.errors.unexpected_eof()
    if rule == 19: # $command = :raw_command :raw_cmd_start $_gen5 :raw_cmd_end -> RawCommand( parts=$2 )
        ctx.rule = rules[19]
        ast_parameters = OrderedDict([
            ('parts', 2),
        ])
        tree.astTransform = AstTransformNodeCreator('RawCommand', ast_parameters)
        t = expect(ctx, 19) # :raw_command
        tree.add(t)
        t = expect(ctx, 0) # :raw_cmd_start
        tree.add(t)
        subtree = parse__gen5(ctx)
        tree.add(subtree)
        t = expect(ctx, 30) # :raw_cmd_end
        tree.add(t)
        return tree
    raise ctx.errors.unexpected_symbol(
      ctx.nonterminal,
      ctx.tokens.current(),
      [terminals[x] for x in nonterminal_first[60] if x >=0],
      rules[19]
    )
def parse_command_part(ctx):
    current = ctx.tokens.current()
    rule = table[20][current.id] if current else -1
    tree = ParseTree(NonTerminal(78, 'command_part'))
    ctx.nonterminal = "command_part"
    if current == None:
        raise ctx.errors.unexpected_eof()
    if rule == 20: # $command_part = :cmd_part
        ctx.rule = rules[20]
        tree.astTransform = AstTransformSubstitution(0)
        t = expect(ctx, 26) # :cmd_part
        tree.add(t)
        return tree
    elif rule == 21: # $command_part = $cmd_param
        ctx.rule = rules[21]
        tree.astTransform = AstTransformSubstitution(0)
        subtree = parse_cmd_param(ctx)
        tree.add(subtree)
        return tree
    raise ctx.errors.unexpected_symbol(
      ctx.nonterminal,
      ctx.tokens.current(),
      [terminals[x] for x in nonterminal_first[78] if x >=0],
      rules[21]
    )
def parse_declaration(ctx):
    current = ctx.tokens.current()
    rule = table[41][current.id] if current else -1
    tree = ParseTree(NonTerminal(99, 'declaration'))
    ctx.nonterminal = "declaration"
    if current == None:
        raise ctx.errors.unexpected_eof()
    if rule == 36: # $declaration = $type_e :identifier $_gen9 -> Declaration( type=$0, name=$1, expression=$2 )
        ctx.rule = rules[36]
        ast_parameters = OrderedDict([
            ('type', 0),
            ('name', 1),
            ('expression', 2),
        ])
        tree.astTransform = AstTransformNodeCreator('Declaration', ast_parameters)
        subtree = parse_type_e(ctx)
        tree.add(subtree)
        t = expect(ctx, 50) # :identifier
        tree.add(t)
        subtree = parse__gen9(ctx)
        tree.add(subtree)
        return tree
    raise ctx.errors.unexpected_symbol(
      ctx.nonterminal,
      ctx.tokens.current(),
      [terminals[x] for x in nonterminal_first[99] if x >=0],
      rules[36]
    )
def parse_document(ctx):
    current = ctx.tokens.current()
    rule = table[50][current.id] if current else -1
    tree = ParseTree(NonTerminal(108, 'document'))
    ctx.nonterminal = "document"
    if current != None and current.id in nonterminal_follow[108] and current.id not in nonterminal_first[108]:
        return tree
    if current == None:
        return tree
    if rule == 2: # $document = $_gen0 $_gen1 -> Namespace( imports=$0, body=$1 )
        ctx.rule = rules[2]
        ast_parameters = OrderedDict([
            ('imports', 0),
            ('body', 1),
        ])
        tree.astTransform = AstTransformNodeCreator('Namespace', ast_parameters)
        subtree = parse__gen0(ctx)
        tree.add(subtree)
        subtree = parse__gen1(ctx)
        tree.add(subtree)
        return tree
    return tree
def parse_if_stmt(ctx):
    current = ctx.tokens.current()
    rule = table[17][current.id] if current else -1
    tree = ParseTree(NonTerminal(75, 'if_stmt'))
    ctx.nonterminal = "if_stmt"
    if current == None:
        raise ctx.errors.unexpected_eof()
    if rule == 72: # $if_stmt = :if :lparen $e :rparen :lbrace $_gen10 :rbrace -> If( expression=$2, body=$5 )
        ctx.rule = rules[72]
        ast_parameters = OrderedDict([
            ('expression', 2),
            ('body', 5),
        ])
        tree.astTransform = AstTransformNodeCreator('If', ast_parameters)
        t = expect(ctx, 18) # :if
        tree.add(t)
        t = expect(ctx, 20) # :lparen
        tree.add(t)
        subtree = parse_e(ctx)
        tree.add(subtree)
        t = expect(ctx, 45) # :rparen
        tree.add(t)
        t = expect(ctx, 16) # :lbrace
        tree.add(t)
        subtree = parse__gen10(ctx)
        tree.add(subtree)
        t = expect(ctx, 44) # :rbrace
        tree.add(t)
        return tree
    raise ctx.errors.unexpected_symbol(
      ctx.nonterminal,
      ctx.tokens.current(),
      [terminals[x] for x in nonterminal_first[75] if x >=0],
      rules[72]
    )
def parse_import(ctx):
    current = ctx.tokens.current()
    rule = table[39][current.id] if current else -1
    tree = ParseTree(NonTerminal(97, 'import'))
    ctx.nonterminal = "import"
    if current == None:
        raise ctx.errors.unexpected_eof()
    if rule == 8: # $import = :import :string $_gen2 -> Import( uri=$1, namespace=$2 )
        ctx.rule = rules[8]
        ast_parameters = OrderedDict([
            ('uri', 1),
            ('namespace', 2),
        ])
        tree.astTransform = AstTransformNodeCreator('Import', ast_parameters)
        t = expect(ctx, 41) # :import
        tree.add(t)
        t = expect(ctx, 42) # :string
        tree.add(t)
        subtree = parse__gen2(ctx)
        tree.add(subtree)
        return tree
    raise ctx.errors.unexpected_symbol(
      ctx.nonterminal,
      ctx.tokens.current(),
      [terminals[x] for x in nonterminal_first[97] if x >=0],
      rules[8]
    )
def parse_import_namespace(ctx):
    current = ctx.tokens.current()
    rule = table[47][current.id] if current else -1
    tree = ParseTree(NonTerminal(105, 'import_namespace'))
    ctx.nonterminal = "import_namespace"
    if current == None:
        raise ctx.errors.unexpected_eof()
    if rule == 9: # $import_namespace = :as :identifier -> $1
        ctx.rule = rules[9]
        tree.astTransform = AstTransformSubstitution(1)
        t = expect(ctx, 53) # :as
        tree.add(t)
        t = expect(ctx, 50) # :identifier
        tree.add(t)
        return tree
    raise ctx.errors.unexpected_symbol(
      ctx.nonterminal,
      ctx.tokens.current(),
      [terminals[x] for x in nonterminal_first[105] if x >=0],
      rules[9]
    )
def parse_kv(ctx):
    current = ctx.tokens.current()
    rule = table[56][current.id] if current else -1
    tree = ParseTree(NonTerminal(114, 'kv'))
    ctx.nonterminal = "kv"
    if current == None:
        raise ctx.errors.unexpected_eof()
    if rule == 33: # $kv = :identifier :colon $e -> RuntimeAttribute( key=$0, value=$2 )
        ctx.rule = rules[33]
        ast_parameters = OrderedDict([
            ('key', 0),
            ('value', 2),
        ])
        tree.astTransform = AstTransformNodeCreator('RuntimeAttribute', ast_parameters)
        t = expect(ctx, 50) # :identifier
        tree.add(t)
        t = expect(ctx, 54) # :colon
        tree.add(t)
        subtree = parse_e(ctx)
        tree.add(subtree)
        return tree
    raise ctx.errors.unexpected_symbol(
      ctx.nonterminal,
      ctx.tokens.current(),
      [terminals[x] for x in nonterminal_first[114] if x >=0],
      rules[33]
    )
def parse_map(ctx):
    current = ctx.tokens.current()
    rule = table[40][current.id] if current else -1
    tree = ParseTree(NonTerminal(98, 'map'))
    ctx.nonterminal = "map"
    if current == None:
        raise ctx.errors.unexpected_eof()
    if rule == 32: # $map = :lbrace $_gen8 :rbrace -> $1
        ctx.rule = rules[32]
        tree.astTransform = AstTransformSubstitution(1)
        t = expect(ctx, 16) # :lbrace
        tree.add(t)
        subtree = parse__gen8(ctx)
        tree.add(subtree)
        t = expect(ctx, 44) # :rbrace
        tree.add(t)
        return tree
    raise ctx.errors.unexpected_symbol(
      ctx.nonterminal,
      ctx.tokens.current(),
      [terminals[x] for x in nonterminal_first[98] if x >=0],
      rules[32]
    )
def parse_map_kv(ctx):
    current = ctx.tokens.current()
    rule = table[36][current.id] if current else -1
    tree = ParseTree(NonTerminal(94, 'map_kv'))
    ctx.nonterminal = "map_kv"
    if current == None:
        raise ctx.errors.unexpected_eof()
    if rule == 38: # $map_kv = $e :colon $e -> MapLiteralKv( key=$0, value=$2 )
        ctx.rule = rules[38]
        ast_parameters = OrderedDict([
            ('key', 0),
            ('value', 2),
        ])
        tree.astTransform = AstTransformNodeCreator('MapLiteralKv', ast_parameters)
        subtree = parse_e(ctx)
        tree.add(subtree)
        t = expect(ctx, 54) # :colon
        tree.add(t)
        subtree = parse_e(ctx)
        tree.add(subtree)
        return tree
    raise ctx.errors.unexpected_symbol(
      ctx.nonterminal,
      ctx.tokens.current(),
      [terminals[x] for x in nonterminal_first[94] if x >=0],
      rules[38]
    )
def parse_mapping(ctx):
    current = ctx.tokens.current()
    rule = table[32][current.id] if current else -1
    tree = ParseTree(NonTerminal(90, 'mapping'))
    ctx.nonterminal = "mapping"
    if current == None:
        raise ctx.errors.unexpected_eof()
    if rule == 58: # $mapping = :identifier :equal $e -> IOMapping( key=$0, value=$2 )
        ctx.rule = rules[58]
        ast_parameters = OrderedDict([
            ('key', 0),
            ('value', 2),
        ])
        tree.astTransform = AstTransformNodeCreator('IOMapping', ast_parameters)
        t = expect(ctx, 50) # :identifier
        tree.add(t)
        t = expect(ctx, 14) # :equal
        tree.add(t)
        subtree = parse_e(ctx)
        tree.add(subtree)
        return tree
    raise ctx.errors.unexpected_symbol(
      ctx.nonterminal,
      ctx.tokens.current(),
      [terminals[x] for x in nonterminal_first[90] if x >=0],
      rules[58]
    )
def parse_meta(ctx):
    current = ctx.tokens.current()
    rule = table[34][current.id] if current else -1
    tree = ParseTree(NonTerminal(92, 'meta'))
    ctx.nonterminal = "meta"
    if current == None:
        raise ctx.errors.unexpected_eof()
    if rule == 30: # $meta = :meta $map -> Meta( map=$1 )
        ctx.rule = rules[30]
        ast_parameters = OrderedDict([
            ('map', 1),
        ])
        tree.astTransform = AstTransformNodeCreator('Meta', ast_parameters)
        t = expect(ctx, 13) # :meta
        tree.add(t)
        subtree = parse_map(ctx)
        tree.add(subtree)
        return tree
    raise ctx.errors.unexpected_symbol(
      ctx.nonterminal,
      ctx.tokens.current(),
      [terminals[x] for x in nonterminal_first[92] if x >=0],
      rules[30]
    )
def parse_object_kv(ctx):
    current = ctx.tokens.current()
    rule = table[29][current.id] if current else -1
    tree = ParseTree(NonTerminal(87, 'object_kv'))
    ctx.nonterminal = "object_kv"
    if current == None:
        raise ctx.errors.unexpected_eof()
    if rule == 74: # $object_kv = :identifier :colon $e -> ObjectKV( key=$0, value=$2 )
        ctx.rule = rules[74]
        ast_parameters = OrderedDict([
            ('key', 0),
            ('value', 2),
        ])
        tree.astTransform = AstTransformNodeCreator('ObjectKV', ast_parameters)
        t = expect(ctx, 50) # :identifier
        tree.add(t)
        t = expect(ctx, 54) # :colon
        tree.add(t)
        subtree = parse_e(ctx)
        tree.add(subtree)
        return tree
    raise ctx.errors.unexpected_symbol(
      ctx.nonterminal,
      ctx.tokens.current(),
      [terminals[x] for x in nonterminal_first[87] if x >=0],
      rules[74]
    )
def parse_output_kv(ctx):
    current = ctx.tokens.current()
    rule = table[11][current.id] if current else -1
    tree = ParseTree(NonTerminal(69, 'output_kv'))
    ctx.nonterminal = "output_kv"
    if current == None:
        raise ctx.errors.unexpected_eof()
    if rule == 27: # $output_kv = $type_e :identifier :equal $e -> Output( type=$0, name=$1, expression=$3 )
        ctx.rule = rules[27]
        ast_parameters = OrderedDict([
            ('type', 0),
            ('name', 1),
            ('expression', 3),
        ])
        tree.astTransform = AstTransformNodeCreator('Output', ast_parameters)
        subtree = parse_type_e(ctx)
        tree.add(subtree)
        t = expect(ctx, 50) # :identifier
        tree.add(t)
        t = expect(ctx, 14) # :equal
        tree.add(t)
        subtree = parse_e(ctx)
        tree.add(subtree)
        return tree
    raise ctx.errors.unexpected_symbol(
      ctx.nonterminal,
      ctx.tokens.current(),
      [terminals[x] for x in nonterminal_first[69] if x >=0],
      rules[27]
    )
def parse_outputs(ctx):
    current = ctx.tokens.current()
    rule = table[28][current.id] if current else -1
    tree = ParseTree(NonTerminal(86, 'outputs'))
    ctx.nonterminal = "outputs"
    if current == None:
        raise ctx.errors.unexpected_eof()
    if rule == 26: # $outputs = :output :lbrace $_gen7 :rbrace -> Outputs( attributes=$2 )
        ctx.rule = rules[26]
        ast_parameters = OrderedDict([
            ('attributes', 2),
        ])
        tree.astTransform = AstTransformNodeCreator('Outputs', ast_parameters)
        t = expect(ctx, 22) # :output
        tree.add(t)
        t = expect(ctx, 16) # :lbrace
        tree.add(t)
        subtree = parse__gen7(ctx)
        tree.add(subtree)
        t = expect(ctx, 44) # :rbrace
        tree.add(t)
        return tree
    raise ctx.errors.unexpected_symbol(
      ctx.nonterminal,
      ctx.tokens.current(),
      [terminals[x] for x in nonterminal_first[86] if x >=0],
      rules[26]
    )
def parse_parameter_meta(ctx):
    current = ctx.tokens.current()
    rule = table[58][current.id] if current else -1
    tree = ParseTree(NonTerminal(116, 'parameter_meta'))
    ctx.nonterminal = "parameter_meta"
    if current == None:
        raise ctx.errors.unexpected_eof()
    if rule == 29: # $parameter_meta = :parameter_meta $map -> ParameterMeta( map=$1 )
        ctx.rule = rules[29]
        ast_parameters = OrderedDict([
            ('map', 1),
        ])
        tree.astTransform = AstTransformNodeCreator('ParameterMeta', ast_parameters)
        t = expect(ctx, 29) # :parameter_meta
        tree.add(t)
        subtree = parse_map(ctx)
        tree.add(subtree)
        return tree
    raise ctx.errors.unexpected_symbol(
      ctx.nonterminal,
      ctx.tokens.current(),
      [terminals[x] for x in nonterminal_first[116] if x >=0],
      rules[29]
    )
def parse_runtime(ctx):
    current = ctx.tokens.current()
    rule = table[21][current.id] if current else -1
    tree = ParseTree(NonTerminal(79, 'runtime'))
    ctx.nonterminal = "runtime"
    if current == None:
        raise ctx.errors.unexpected_eof()
    if rule == 28: # $runtime = :runtime $map -> Runtime( map=$1 )
        ctx.rule = rules[28]
        ast_parameters = OrderedDict([
            ('map', 1),
        ])
        tree.astTransform = AstTransformNodeCreator('Runtime', ast_parameters)
        t = expect(ctx, 32) # :runtime
        tree.add(t)
        subtree = parse_map(ctx)
        tree.add(subtree)
        return tree
    raise ctx.errors.unexpected_symbol(
      ctx.nonterminal,
      ctx.tokens.current(),
      [terminals[x] for x in nonterminal_first[79] if x >=0],
      rules[28]
    )
def parse_scatter(ctx):
    current = ctx.tokens.current()
    rule = table[55][current.id] if current else -1
    tree = ParseTree(NonTerminal(113, 'scatter'))
    ctx.nonterminal = "scatter"
    if current == None:
        raise ctx.errors.unexpected_eof()
    if rule == 73: # $scatter = :scatter :lparen :identifier :in $e :rparen :lbrace $_gen10 :rbrace -> Scatter( item=$2, collection=$4, body=$7 )
        ctx.rule = rules[73]
        ast_parameters = OrderedDict([
            ('item', 2),
            ('collection', 4),
            ('body', 7),
        ])
        tree.astTransform = AstTransformNodeCreator('Scatter', ast_parameters)
        t = expect(ctx, 51) # :scatter
        tree.add(t)
        t = expect(ctx, 20) # :lparen
        tree.add(t)
        t = expect(ctx, 50) # :identifier
        tree.add(t)
        t = expect(ctx, 9) # :in
        tree.add(t)
        subtree = parse_e(ctx)
        tree.add(subtree)
        t = expect(ctx, 45) # :rparen
        tree.add(t)
        t = expect(ctx, 16) # :lbrace
        tree.add(t)
        subtree = parse__gen10(ctx)
        tree.add(subtree)
        t = expect(ctx, 44) # :rbrace
        tree.add(t)
        return tree
    raise ctx.errors.unexpected_symbol(
      ctx.nonterminal,
      ctx.tokens.current(),
      [terminals[x] for x in nonterminal_first[113] if x >=0],
      rules[73]
    )
def parse_sections(ctx):
    current = ctx.tokens.current()
    rule = table[6][current.id] if current else -1
    tree = ParseTree(NonTerminal(64, 'sections'))
    ctx.nonterminal = "sections"
    if current == None:
        raise ctx.errors.unexpected_eof()
    if rule == 13: # $sections = $command
        ctx.rule = rules[13]
        tree.astTransform = AstTransformSubstitution(0)
        subtree = parse_command(ctx)
        tree.add(subtree)
        return tree
    elif rule == 14: # $sections = $outputs
        ctx.rule = rules[14]
        tree.astTransform = AstTransformSubstitution(0)
        subtree = parse_outputs(ctx)
        tree.add(subtree)
        return tree
    elif rule == 15: # $sections = $runtime
        ctx.rule = rules[15]
        tree.astTransform = AstTransformSubstitution(0)
        subtree = parse_runtime(ctx)
        tree.add(subtree)
        return tree
    elif rule == 16: # $sections = $parameter_meta
        ctx.rule = rules[16]
        tree.astTransform = AstTransformSubstitution(0)
        subtree = parse_parameter_meta(ctx)
        tree.add(subtree)
        return tree
    elif rule == 17: # $sections = $meta
        ctx.rule = rules[17]
        tree.astTransform = AstTransformSubstitution(0)
        subtree = parse_meta(ctx)
        tree.add(subtree)
        return tree
    raise ctx.errors.unexpected_symbol(
      ctx.nonterminal,
      ctx.tokens.current(),
      [terminals[x] for x in nonterminal_first[64] if x >=0],
      rules[17]
    )
def parse_setter(ctx):
    current = ctx.tokens.current()
    rule = table[15][current.id] if current else -1
    tree = ParseTree(NonTerminal(73, 'setter'))
    ctx.nonterminal = "setter"
    if current == None:
        raise ctx.errors.unexpected_eof()
    if rule == 37: # $setter = :equal $e -> $1
        ctx.rule = rules[37]
        tree.astTransform = AstTransformSubstitution(1)
        t = expect(ctx, 14) # :equal
        tree.add(t)
        subtree = parse_e(ctx)
        tree.add(subtree)
        return tree
    raise ctx.errors.unexpected_symbol(
      ctx.nonterminal,
      ctx.tokens.current(),
      [terminals[x] for x in nonterminal_first[73] if x >=0],
      rules[37]
    )
def parse_task(ctx):
    current = ctx.tokens.current()
    rule = table[37][current.id] if current else -1
    tree = ParseTree(NonTerminal(95, 'task'))
    ctx.nonterminal = "task"
    if current == None:
        raise ctx.errors.unexpected_eof()
    if rule == 12: # $task = :task :identifier :lbrace $_gen3 $_gen4 :rbrace -> Task( name=$1, declarations=$3, sections=$4 )
        ctx.rule = rules[12]
        ast_parameters = OrderedDict([
            ('name', 1),
            ('declarations', 3),
            ('sections', 4),
        ])
        tree.astTransform = AstTransformNodeCreator('Task', ast_parameters)
        t = expect(ctx, 6) # :task
        tree.add(t)
        t = expect(ctx, 50) # :identifier
        tree.add(t)
        t = expect(ctx, 16) # :lbrace
        tree.add(t)
        subtree = parse__gen3(ctx)
        tree.add(subtree)
        subtree = parse__gen4(ctx)
        tree.add(subtree)
        t = expect(ctx, 44) # :rbrace
        tree.add(t)
        return tree
    raise ctx.errors.unexpected_symbol(
      ctx.nonterminal,
      ctx.tokens.current(),
      [terminals[x] for x in nonterminal_first[95] if x >=0],
      rules[12]
    )
def parse_wf_body_element(ctx):
    current = ctx.tokens.current()
    rule = table[57][current.id] if current else -1
    tree = ParseTree(NonTerminal(115, 'wf_body_element'))
    ctx.nonterminal = "wf_body_element"
    if current == None:
        raise ctx.errors.unexpected_eof()
    if rule == 41: # $wf_body_element = $call
        ctx.rule = rules[41]
        tree.astTransform = AstTransformSubstitution(0)
        subtree = parse_call(ctx)
        tree.add(subtree)
        return tree
    elif rule == 42: # $wf_body_element = $declaration
        ctx.rule = rules[42]
        tree.astTransform = AstTransformSubstitution(0)
        subtree = parse_declaration(ctx)
        tree.add(subtree)
        return tree
    elif rule == 43: # $wf_body_element = $while_loop
        ctx.rule = rules[43]
        tree.astTransform = AstTransformSubstitution(0)
        subtree = parse_while_loop(ctx)
        tree.add(subtree)
        return tree
    elif rule == 44: # $wf_body_element = $if_stmt
        ctx.rule = rules[44]
        tree.astTransform = AstTransformSubstitution(0)
        subtree = parse_if_stmt(ctx)
        tree.add(subtree)
        return tree
    elif rule == 45: # $wf_body_element = $scatter
        ctx.rule = rules[45]
        tree.astTransform = AstTransformSubstitution(0)
        subtree = parse_scatter(ctx)
        tree.add(subtree)
        return tree
    elif rule == 46: # $wf_body_element = $wf_outputs
        ctx.rule = rules[46]
        tree.astTransform = AstTransformSubstitution(0)
        subtree = parse_wf_outputs(ctx)
        tree.add(subtree)
        return tree
    elif rule == 47: # $wf_body_element = $wf_parameter_meta
        ctx.rule = rules[47]
        tree.astTransform = AstTransformSubstitution(0)
        subtree = parse_wf_parameter_meta(ctx)
        tree.add(subtree)
        return tree
    elif rule == 48: # $wf_body_element = $wf_meta
        ctx.rule = rules[48]
        tree.astTransform = AstTransformSubstitution(0)
        subtree = parse_wf_meta(ctx)
        tree.add(subtree)
        return tree
    raise ctx.errors.unexpected_symbol(
      ctx.nonterminal,
      ctx.tokens.current(),
      [terminals[x] for x in nonterminal_first[115] if x >=0],
      rules[48]
    )
def parse_wf_meta(ctx):
    current = ctx.tokens.current()
    rule = table[23][current.id] if current else -1
    tree = ParseTree(NonTerminal(81, 'wf_meta'))
    ctx.nonterminal = "wf_meta"
    if current == None:
        raise ctx.errors.unexpected_eof()
    if rule == 70: # $wf_meta = :meta $map -> Meta( map=$1 )
        ctx.rule = rules[70]
        ast_parameters = OrderedDict([
            ('map', 1),
        ])
        tree.astTransform = AstTransformNodeCreator('Meta', ast_parameters)
        t = expect(ctx, 13) # :meta
        tree.add(t)
        subtree = parse_map(ctx)
        tree.add(subtree)
        return tree
    raise ctx.errors.unexpected_symbol(
      ctx.nonterminal,
      ctx.tokens.current(),
      [terminals[x] for x in nonterminal_first[81] if x >=0],
      rules[70]
    )
def parse_wf_output(ctx):
    current = ctx.tokens.current()
    rule = table[49][current.id] if current else -1
    tree = ParseTree(NonTerminal(107, 'wf_output'))
    ctx.nonterminal = "wf_output"
    if current == None:
        raise ctx.errors.unexpected_eof()
    if rule == 62: # $wf_output = $wf_output_declaration_syntax
        ctx.rule = rules[62]
        tree.astTransform = AstTransformSubstitution(0)
        subtree = parse_wf_output_declaration_syntax(ctx)
        tree.add(subtree)
        return tree
    elif rule == 63: # $wf_output = $wf_output_wildcard_syntax
        ctx.rule = rules[63]
        tree.astTransform = AstTransformSubstitution(0)
        subtree = parse_wf_output_wildcard_syntax(ctx)
        tree.add(subtree)
        return tree
    raise ctx.errors.unexpected_symbol(
      ctx.nonterminal,
      ctx.tokens.current(),
      [terminals[x] for x in nonterminal_first[107] if x >=0],
      rules[63]
    )
def parse_wf_output_declaration_syntax(ctx):
    current = ctx.tokens.current()
    rule = table[19][current.id] if current else -1
    tree = ParseTree(NonTerminal(77, 'wf_output_declaration_syntax'))
    ctx.nonterminal = "wf_output_declaration_syntax"
    if current == None:
        raise ctx.errors.unexpected_eof()
    if rule == 64: # $wf_output_declaration_syntax = $type_e :identifier :equal $e -> WorkflowOutputDeclaration( type=$0, name=$1, expression=$3 )
        ctx.rule = rules[64]
        ast_parameters = OrderedDict([
            ('type', 0),
            ('name', 1),
            ('expression', 3),
        ])
        tree.astTransform = AstTransformNodeCreator('WorkflowOutputDeclaration', ast_parameters)
        subtree = parse_type_e(ctx)
        tree.add(subtree)
        t = expect(ctx, 50) # :identifier
        tree.add(t)
        t = expect(ctx, 14) # :equal
        tree.add(t)
        subtree = parse_e(ctx)
        tree.add(subtree)
        return tree
    raise ctx.errors.unexpected_symbol(
      ctx.nonterminal,
      ctx.tokens.current(),
      [terminals[x] for x in nonterminal_first[77] if x >=0],
      rules[64]
    )
def parse_wf_output_wildcard(ctx):
    current = ctx.tokens.current()
    rule = table[8][current.id] if current else -1
    tree = ParseTree(NonTerminal(66, 'wf_output_wildcard'))
    ctx.nonterminal = "wf_output_wildcard"
    if current == None:
        raise ctx.errors.unexpected_eof()
    if rule == 68: # $wf_output_wildcard = :dot :asterisk -> $1
        ctx.rule = rules[68]
        tree.astTransform = AstTransformSubstitution(1)
        t = expect(ctx, 7) # :dot
        tree.add(t)
        t = expect(ctx, 17) # :asterisk
        tree.add(t)
        return tree
    raise ctx.errors.unexpected_symbol(
      ctx.nonterminal,
      ctx.tokens.current(),
      [terminals[x] for x in nonterminal_first[66] if x >=0],
      rules[68]
    )
def parse_wf_output_wildcard_syntax(ctx):
    current = ctx.tokens.current()
    rule = table[12][current.id] if current else -1
    tree = ParseTree(NonTerminal(70, 'wf_output_wildcard_syntax'))
    ctx.nonterminal = "wf_output_wildcard_syntax"
    if current == None:
        raise ctx.errors.unexpected_eof()
    if rule == 67: # $wf_output_wildcard_syntax = :fqn $_gen16 -> WorkflowOutputWildcard( fqn=$0, wildcard=$1 )
        ctx.rule = rules[67]
        ast_parameters = OrderedDict([
            ('fqn', 0),
            ('wildcard', 1),
        ])
        tree.astTransform = AstTransformNodeCreator('WorkflowOutputWildcard', ast_parameters)
        t = expect(ctx, 55) # :fqn
        tree.add(t)
        subtree = parse__gen16(ctx)
        tree.add(subtree)
        return tree
    raise ctx.errors.unexpected_symbol(
      ctx.nonterminal,
      ctx.tokens.current(),
      [terminals[x] for x in nonterminal_first[70] if x >=0],
      rules[67]
    )
def parse_wf_outputs(ctx):
    current = ctx.tokens.current()
    rule = table[43][current.id] if current else -1
    tree = ParseTree(NonTerminal(101, 'wf_outputs'))
    ctx.nonterminal = "wf_outputs"
    if current == None:
        raise ctx.errors.unexpected_eof()
    if rule == 61: # $wf_outputs = :output :lbrace $_gen15 :rbrace -> WorkflowOutputs( outputs=$2 )
        ctx.rule = rules[61]
        ast_parameters = OrderedDict([
            ('outputs', 2),
        ])
        tree.astTransform = AstTransformNodeCreator('WorkflowOutputs', ast_parameters)
        t = expect(ctx, 22) # :output
        tree.add(t)
        t = expect(ctx, 16) # :lbrace
        tree.add(t)
        subtree = parse__gen15(ctx)
        tree.add(subtree)
        t = expect(ctx, 44) # :rbrace
        tree.add(t)
        return tree
    raise ctx.errors.unexpected_symbol(
      ctx.nonterminal,
      ctx.tokens.current(),
      [terminals[x] for x in nonterminal_first[101] if x >=0],
      rules[61]
    )
def parse_wf_parameter_meta(ctx):
    current = ctx.tokens.current()
    rule = table[24][current.id] if current else -1
    tree = ParseTree(NonTerminal(82, 'wf_parameter_meta'))
    ctx.nonterminal = "wf_parameter_meta"
    if current == None:
        raise ctx.errors.unexpected_eof()
    if rule == 69: # $wf_parameter_meta = :parameter_meta $map -> ParameterMeta( map=$1 )
        ctx.rule = rules[69]
        ast_parameters = OrderedDict([
            ('map', 1),
        ])
        tree.astTransform = AstTransformNodeCreator('ParameterMeta', ast_parameters)
        t = expect(ctx, 29) # :parameter_meta
        tree.add(t)
        subtree = parse_map(ctx)
        tree.add(subtree)
        return tree
    raise ctx.errors.unexpected_symbol(
      ctx.nonterminal,
      ctx.tokens.current(),
      [terminals[x] for x in nonterminal_first[82] if x >=0],
      rules[69]
    )
def parse_while_loop(ctx):
    current = ctx.tokens.current()
    rule = table[51][current.id] if current else -1
    tree = ParseTree(NonTerminal(109, 'while_loop'))
    ctx.nonterminal = "while_loop"
    if current == None:
        raise ctx.errors.unexpected_eof()
    if rule == 71: # $while_loop = :while :lparen $e :rparen :lbrace $_gen10 :rbrace -> WhileLoop( expression=$2, body=$5 )
        ctx.rule = rules[71]
        ast_parameters = OrderedDict([
            ('expression', 2),
            ('body', 5),
        ])
        tree.astTransform = AstTransformNodeCreator('WhileLoop', ast_parameters)
        t = expect(ctx, 25) # :while
        tree.add(t)
        t = expect(ctx, 20) # :lparen
        tree.add(t)
        subtree = parse_e(ctx)
        tree.add(subtree)
        t = expect(ctx, 45) # :rparen
        tree.add(t)
        t = expect(ctx, 16) # :lbrace
        tree.add(t)
        subtree = parse__gen10(ctx)
        tree.add(subtree)
        t = expect(ctx, 44) # :rbrace
        tree.add(t)
        return tree
    raise ctx.errors.unexpected_symbol(
      ctx.nonterminal,
      ctx.tokens.current(),
      [terminals[x] for x in nonterminal_first[109] if x >=0],
      rules[71]
    )
def parse_workflow(ctx):
    current = ctx.tokens.current()
    rule = table[54][current.id] if current else -1
    tree = ParseTree(NonTerminal(112, 'workflow'))
    ctx.nonterminal = "workflow"
    if current == None:
        raise ctx.errors.unexpected_eof()
    if rule == 40: # $workflow = :workflow :identifier :lbrace $_gen10 :rbrace -> Workflow( name=$1, body=$3 )
        ctx.rule = rules[40]
        ast_parameters = OrderedDict([
            ('name', 1),
            ('body', 3),
        ])
        tree.astTransform = AstTransformNodeCreator('Workflow', ast_parameters)
        t = expect(ctx, 10) # :workflow
        tree.add(t)
        t = expect(ctx, 50) # :identifier
        tree.add(t)
        t = expect(ctx, 16) # :lbrace
        tree.add(t)
        subtree = parse__gen10(ctx)
        tree.add(subtree)
        t = expect(ctx, 44) # :rbrace
        tree.add(t)
        return tree
    raise ctx.errors.unexpected_symbol(
      ctx.nonterminal,
      ctx.tokens.current(),
      [terminals[x] for x in nonterminal_first[112] if x >=0],
      rules[40]
    )
def parse_workflow_or_task_or_decl(ctx):
    current = ctx.tokens.current()
    rule = table[7][current.id] if current else -1
    tree = ParseTree(NonTerminal(65, 'workflow_or_task_or_decl'))
    ctx.nonterminal = "workflow_or_task_or_decl"
    if current == None:
        raise ctx.errors.unexpected_eof()
    if rule == 3: # $workflow_or_task_or_decl = $workflow
        ctx.rule = rules[3]
        tree.astTransform = AstTransformSubstitution(0)
        subtree = parse_workflow(ctx)
        tree.add(subtree)
        return tree
    elif rule == 4: # $workflow_or_task_or_decl = $task
        ctx.rule = rules[4]
        tree.astTransform = AstTransformSubstitution(0)
        subtree = parse_task(ctx)
        tree.add(subtree)
        return tree
    elif rule == 5: # $workflow_or_task_or_decl = $declaration
        ctx.rule = rules[5]
        tree.astTransform = AstTransformSubstitution(0)
        subtree = parse_declaration(ctx)
        tree.add(subtree)
        return tree
    raise ctx.errors.unexpected_symbol(
      ctx.nonterminal,
      ctx.tokens.current(),
      [terminals[x] for x in nonterminal_first[65] if x >=0],
      rules[5]
    )
# Lexer Code #
# START USER CODE
def init():
    return {
        'context': None,
        'replacements': {
            re.compile(r"\\n"): 0x000A,
            re.compile(r"\\r"): 0x000D,
            re.compile(r"\\b"): 0x0008,
            re.compile(r"\\t"): 0x0009,
            re.compile(r"\\a"): 0x0007,
            re.compile(r"\\v"): 0x000B,
            re.compile(r'\\"'): 0x0022,
            re.compile(r"\\'"): 0x0027,
            re.compile(r"\\\?"): 0x003F
        },
        'escapes': {
            re.compile(r'(\\([0-7]{1,3}))'): 8,
            re.compile(r'(\\[xX]([0-9a-fA-F]{1,4}))'): 16,
            re.compile(r'(\\[uU]([0-9a-fA-F]{4}))'): 16
        }
    }
def workflow(ctx, terminal, source_string, line, col):
    ctx.user_context['context'] = 'workflow'
    default_action(ctx, terminal, source_string, line, col)
def task(ctx, terminal, source_string, line, col):
    ctx.user_context['context'] = 'task'
    default_action(ctx, terminal, source_string, line, col)
def output(ctx, terminal, source_string, line, col):
    if ctx.user_context['context'] == 'workflow':
        ctx.stack.append('wf_output')
    default_action(ctx, terminal, source_string, line, col)
def wdl_unescape(ctx, terminal, source_string, line, col):
    for regex, c in ctx.user_context['replacements'].items():
        source_string = regex.sub(chr(c).encode('utf-8'), source_string)
    source_string = source_string.replace("\u005C\u005C", "\u005C")
    for regex, base in ctx.user_context['escapes'].items():
        for escape_sequence, number in regex.findall(source_string):
            source_string = source_string.replace(escape_sequence, chr(int(number, base)).encode('utf-8'))
    default_action(ctx, terminal, source_string[1:-1], line, col)
# END USER CODE
def emit(ctx, terminal, source_string, line, col):
    if terminal:
        ctx.tokens.append(Terminal(terminals[terminal], terminal, source_string, ctx.resource, line, col))
def default_action(ctx, terminal, source_string, line, col):
    emit(ctx, terminal, source_string, line, col)
def post_filter(tokens):
    return tokens
def destroy(context):
    pass
class LexerStackPush:
    def __init__(self, mode):
        self.mode = mode
class LexerAction:
    def __init__(self, action):
        self.action = action
class LexerContext:
    def __init__(self, string, resource, errors, user_context):
        self.__dict__.update(locals())
        self.stack = ['default']
        self.line = 1
        self.col = 1
        self.tokens = []
        self.user_context = user_context
        self.re_match = None # https://docs.python.org/3/library/re.html#match-objects
class HermesLexer:
    regex = {
        'default': OrderedDict([
          (re.compile(r'\s+'), [
              # (terminal, group, function)
          ]),
          (re.compile(r'/\*(.*?)\*/', re.DOTALL), [
              # (terminal, group, function)
          ]),
          (re.compile(r'#.*'), [
              # (terminal, group, function)
          ]),
          (re.compile(r'task(?![a-zA-Z0-9_])'), [
              # (terminal, group, function)
              ('task', 0, task),
          ]),
          (re.compile(r'(call)\s+'), [
              # (terminal, group, function)
              ('call', 1, None),
              LexerStackPush('task_fqn'),
          ]),
          (re.compile(r'workflow(?![a-zA-Z0-9_])'), [
              # (terminal, group, function)
              ('workflow', 0, workflow),
          ]),
          (re.compile(r'import(?![a-zA-Z0-9_])'), [
              # (terminal, group, function)
              ('import', 0, None),
          ]),
          (re.compile(r'input(?![a-zA-Z0-9_])'), [
              # (terminal, group, function)
              ('input', 0, None),
          ]),
          (re.compile(r'output(?![a-zA-Z0-9_])'), [
              # (terminal, group, function)
              ('output', 0, output),
          ]),
          (re.compile(r'as(?![a-zA-Z0-9_])'), [
              # (terminal, group, function)
              ('as', 0, None),
          ]),
          (re.compile(r'if(?![a-zA-Z0-9_])'), [
              # (terminal, group, function)
              ('if', 0, None),
          ]),
          (re.compile(r'then(?![a-zA-Z0-9_])'), [
              # (terminal, group, function)
              ('then', 0, None),
          ]),
          (re.compile(r'else(?![a-zA-Z0-9_])'), [
              # (terminal, group, function)
              ('else', 0, None),
          ]),
          (re.compile(r'while(?![a-zA-Z0-9_])'), [
              # (terminal, group, function)
              ('while', 0, None),
          ]),
          (re.compile(r'runtime(?![a-zA-Z0-9_])'), [
              # (terminal, group, function)
              ('runtime', 0, None),
          ]),
          (re.compile(r'scatter(?![a-zA-Z0-9_])'), [
              # (terminal, group, function)
              ('scatter', 0, None),
              LexerStackPush('scatter'),
          ]),
          (re.compile(r'command\s*(?=<<<)'), [
              # (terminal, group, function)
              ('raw_command', 0, None),
              LexerStackPush('raw_command2'),
          ]),
          (re.compile(r'command\s*(?=\{)'), [
              # (terminal, group, function)
              ('raw_command', 0, None),
              LexerStackPush('raw_command'),
          ]),
          (re.compile(r'parameter_meta(?![a-zA-Z0-9_])'), [
              # (terminal, group, function)
              ('parameter_meta', 0, None),
          ]),
          (re.compile(r'meta(?![a-zA-Z0-9_])'), [
              # (terminal, group, function)
              ('meta', 0, None),
          ]),
          (re.compile(r'(true|false)(?![a-zA-Z0-9_])'), [
              # (terminal, group, function)
              ('boolean', 0, None),
          ]),
          (re.compile(r'(object)\s*(\{)'), [
              # (terminal, group, function)
              ('object', 0, None),
              ('lbrace', 0, None),
          ]),
          (re.compile(r'(Array|Map|Object|Pair|Boolean|Int|Float|Uri|File|String)(?![a-zA-Z0-9_])(?![a-zA-Z0-9_])'), [
              # (terminal, group, function)
              ('type', 0, None),
          ]),
          (re.compile(r'[a-zA-Z]([a-zA-Z0-9_])*'), [
              # (terminal, group, function)
              ('identifier', 0, None),
          ]),
          (re.compile(r'"([^\\\"\n]|\\[\\"\'nrbtfav\?]|\\[0-7]{1,3}|\\x[0-9a-fA-F]+|\\[uU]([0-9a-fA-F]{4})([0-9a-fA-F]{4})?)*"'), [
              # (terminal, group, function)
              ('string', 0, wdl_unescape),
          ]),
          (re.compile(r'\'([^\\\'\n]|\\[\\"\'nrbtfav\?]|\\[0-7]{1,3}|\\x[0-9a-fA-F]+|\\[uU]([0-9a-fA-F]{4})([0-9a-fA-F]{4})?)*\''), [
              # (terminal, group, function)
              ('string', 0, wdl_unescape),
          ]),
          (re.compile(r':'), [
              # (terminal, group, function)
              ('colon', 0, None),
          ]),
          (re.compile(r','), [
              # (terminal, group, function)
              ('comma', 0, None),
          ]),
          (re.compile(r'=='), [
              # (terminal, group, function)
              ('double_equal', 0, None),
          ]),
          (re.compile(r'\|\|'), [
              # (terminal, group, function)
              ('double_pipe', 0, None),
          ]),
          (re.compile(r'\&\&'), [
              # (terminal, group, function)
              ('double_ampersand', 0, None),
          ]),
          (re.compile(r'!='), [
              # (terminal, group, function)
              ('not_equal', 0, None),
          ]),
          (re.compile(r'='), [
              # (terminal, group, function)
              ('equal', 0, None),
          ]),
          (re.compile(r'\.'), [
              # (terminal, group, function)
              ('dot', 0, None),
          ]),
          (re.compile(r'\{'), [
              # (terminal, group, function)
              ('lbrace', 0, None),
          ]),
          (re.compile(r'\}'), [
              # (terminal, group, function)
              ('rbrace', 0, None),
          ]),
          (re.compile(r'\('), [
              # (terminal, group, function)
              ('lparen', 0, None),
          ]),
          (re.compile(r'\)'), [
              # (terminal, group, function)
              ('rparen', 0, None),
          ]),
          (re.compile(r'\['), [
              # (terminal, group, function)
              ('lsquare', 0, None),
          ]),
          (re.compile(r'\]'), [
              # (terminal, group, function)
              ('rsquare', 0, None),
          ]),
          (re.compile(r'\+'), [
              # (terminal, group, function)
              ('plus', 0, None),
          ]),
          (re.compile(r'\*'), [
              # (terminal, group, function)
              ('asterisk', 0, None),
          ]),
          (re.compile(r'-'), [
              # (terminal, group, function)
              ('dash', 0, None),
          ]),
          (re.compile(r'/'), [
              # (terminal, group, function)
              ('slash', 0, None),
          ]),
          (re.compile(r'%'), [
              # (terminal, group, function)
              ('percent', 0, None),
          ]),
          (re.compile(r'<='), [
              # (terminal, group, function)
              ('lteq', 0, None),
          ]),
          (re.compile(r'<'), [
              # (terminal, group, function)
              ('lt', 0, None),
          ]),
          (re.compile(r'>='), [
              # (terminal, group, function)
              ('gteq', 0, None),
          ]),
          (re.compile(r'>'), [
              # (terminal, group, function)
              ('gt', 0, None),
          ]),
          (re.compile(r'!'), [
              # (terminal, group, function)
              ('not', 0, None),
          ]),
          (re.compile(r'\?'), [
              # (terminal, group, function)
              ('qmark', 0, None),
          ]),
          (re.compile(r'-?[0-9]+\.[0-9]+'), [
              # (terminal, group, function)
              ('float', 0, None),
          ]),
          (re.compile(r'[0-9]+'), [
              # (terminal, group, function)
              ('integer', 0, None),
          ]),
        ]),
        'wf_output': OrderedDict([
          (re.compile(r'\s+'), [
              # (terminal, group, function)
          ]),
          (re.compile(r'#.*'), [
              # (terminal, group, function)
          ]),
          (re.compile(r'(Array|Map|Object|Pair|Boolean|Int|Float|Uri|File|String)(?![a-zA-Z0-9_])(?![a-zA-Z0-9_])'), [
              # (terminal, group, function)
              ('type', 0, None),
              LexerAction('pop'),
              LexerStackPush('wf_output_declaration'),
          ]),
          (re.compile(r'\{'), [
              # (terminal, group, function)
              ('lbrace', 0, None),
          ]),
          (re.compile(r'\}'), [
              # (terminal, group, function)
              ('rbrace', 0, None),
              LexerAction('pop'),
          ]),
          (re.compile(r','), [
              # (terminal, group, function)
              ('comma', 0, None),
          ]),
          (re.compile(r'\.'), [
              # (terminal, group, function)
              ('dot', 0, None),
          ]),
          (re.compile(r'\*'), [
              # (terminal, group, function)
              ('asterisk', 0, None),
          ]),
          (re.compile(r'[a-zA-Z]([a-zA-Z0-9_])*(\.[a-zA-Z]([a-zA-Z0-9_])*)*'), [
              # (terminal, group, function)
              ('fqn', 0, None),
          ]),
        ]),
        'wf_output_declaration': OrderedDict([
          (re.compile(r'\s+'), [
              # (terminal, group, function)
          ]),
          (re.compile(r'#.*'), [
              # (terminal, group, function)
          ]),
          (re.compile(r'\}'), [
              # (terminal, group, function)
              ('rbrace', 0, None),
              LexerAction('pop'),
          ]),
          (re.compile(r'\['), [
              # (terminal, group, function)
              ('lsquare', 0, None),
          ]),
          (re.compile(r'\]'), [
              # (terminal, group, function)
              ('rsquare', 0, None),
          ]),
          (re.compile(r'\+'), [
              # (terminal, group, function)
              ('plus', 0, None),
          ]),
          (re.compile(r'\*'), [
              # (terminal, group, function)
              ('asterisk', 0, None),
          ]),
          (re.compile(r'[0-9]+'), [
              # (terminal, group, function)
              ('integer', 0, None),
          ]),
          (re.compile(r'(true|false)(?![a-zA-Z0-9_])'), [
              # (terminal, group, function)
              ('boolean', 0, None),
          ]),
          (re.compile(r'if'), [
              # (terminal, group, function)
              ('if', 0, None),
          ]),
          (re.compile(r'else'), [
              # (terminal, group, function)
              ('else', 0, None),
          ]),
          (re.compile(r'then'), [
              # (terminal, group, function)
              ('then', 0, None),
          ]),
          (re.compile(r'(Array|Map|Object|Pair|Boolean|Int|Float|Uri|File|String)(?![a-zA-Z0-9_])(?![a-zA-Z0-9_])'), [
              # (terminal, group, function)
              ('type', 0, None),
          ]),
          (re.compile(r'[a-zA-Z]([a-zA-Z0-9_])*'), [
              # (terminal, group, function)
              ('identifier', 0, None),
          ]),
          (re.compile(r':'), [
              # (terminal, group, function)
              ('colon', 0, None),
          ]),
          (re.compile(r','), [
              # (terminal, group, function)
              ('comma', 0, None),
          ]),
          (re.compile(r'\.'), [
              # (terminal, group, function)
              ('dot', 0, None),
          ]),
          (re.compile(r'=='), [
              # (terminal, group, function)
              ('double_equal', 0, None),
          ]),
          (re.compile(r'='), [
              # (terminal, group, function)
              ('equal', 0, None),
          ]),
          (re.compile(r'\|\|'), [
              # (terminal, group, function)
              ('double_pipe', 0, None),
          ]),
          (re.compile(r'\&\&'), [
              # (terminal, group, function)
              ('double_ampersand', 0, None),
          ]),
          (re.compile(r'!='), [
              # (terminal, group, function)
              ('not_equal', 0, None),
          ]),
          (re.compile(r'='), [
              # (terminal, group, function)
              ('equal', 0, None),
          ]),
          (re.compile(r'\.'), [
              # (terminal, group, function)
              ('dot', 0, None),
          ]),
          (re.compile(r'\{'), [
              # (terminal, group, function)
              ('lbrace', 0, None),
          ]),
          (re.compile(r'\('), [
              # (terminal, group, function)
              ('lparen', 0, None),
          ]),
          (re.compile(r'\)'), [
              # (terminal, group, function)
              ('rparen', 0, None),
          ]),
          (re.compile(r'\['), [
              # (terminal, group, function)
              ('lsquare', 0, None),
          ]),
          (re.compile(r'\]'), [
              # (terminal, group, function)
              ('rsquare', 0, None),
          ]),
          (re.compile(r'\+'), [
              # (terminal, group, function)
              ('plus', 0, None),
          ]),
          (re.compile(r'\*'), [
              # (terminal, group, function)
              ('asterisk', 0, None),
          ]),
          (re.compile(r'-'), [
              # (terminal, group, function)
              ('dash', 0, None),
          ]),
          (re.compile(r'/'), [
              # (terminal, group, function)
              ('slash', 0, None),
          ]),
          (re.compile(r'%'), [
              # (terminal, group, function)
              ('percent', 0, None),
          ]),
          (re.compile(r'<='), [
              # (terminal, group, function)
              ('lteq', 0, None),
          ]),
          (re.compile(r'<'), [
              # (terminal, group, function)
              ('lt', 0, None),
          ]),
          (re.compile(r'>='), [
              # (terminal, group, function)
              ('gteq', 0, None),
          ]),
          (re.compile(r'>'), [
              # (terminal, group, function)
              ('gt', 0, None),
          ]),
          (re.compile(r'!'), [
              # (terminal, group, function)
              ('not', 0, None),
          ]),
          (re.compile(r'\?'), [
              # (terminal, group, function)
              ('qmark', 0, None),
          ]),
          (re.compile(r'"([^\\\"\n]|\\[\\"\'nrbtfav\?]|\\[0-7]{1,3}|\\x[0-9a-fA-F]+|\\[uU]([0-9a-fA-F]{4})([0-9a-fA-F]{4})?)*"'), [
              # (terminal, group, function)
              ('string', 0, wdl_unescape),
          ]),
          (re.compile(r'\'([^\\\'\n]|\\[\\"\'nrbtfav\?]|\\[0-7]{1,3}|\\x[0-9a-fA-F]+|\\[uU]([0-9a-fA-F]{4})([0-9a-fA-F]{4})?)*\''), [
              # (terminal, group, function)
              ('string', 0, wdl_unescape),
          ]),
          (re.compile(r'-?[0-9]+\.[0-9]+'), [
              # (terminal, group, function)
              ('float', 0, None),
          ]),
          (re.compile(r'[0-9]+'), [
              # (terminal, group, function)
              ('integer', 0, None),
          ]),
        ]),
        'task_fqn': OrderedDict([
          (re.compile(r'\s+'), [
              # (terminal, group, function)
          ]),
          (re.compile(r'[a-zA-Z]([a-zA-Z0-9_])*(\.[a-zA-Z]([a-zA-Z0-9_])*)*'), [
              # (terminal, group, function)
              ('fqn', 0, None),
              LexerAction('pop'),
          ]),
        ]),
        'scatter': OrderedDict([
          (re.compile(r'\s+'), [
              # (terminal, group, function)
          ]),
          (re.compile(r'\('), [
              # (terminal, group, function)
              ('lparen', 0, None),
          ]),
          (re.compile(r'in(?![a-zA-Z0-9_])'), [
              # (terminal, group, function)
              ('in', 0, None),
              LexerAction('pop'),
          ]),
          (re.compile(r'[a-zA-Z]([a-zA-Z0-9_])*'), [
              # (terminal, group, function)
              ('identifier', 0, None),
          ]),
        ]),
        'raw_command': OrderedDict([
          (re.compile(r'\{'), [
              # (terminal, group, function)
              ('raw_cmd_start', 0, None),
          ]),
          (re.compile(r'\}'), [
              # (terminal, group, function)
              ('raw_cmd_end', 0, None),
              LexerAction('pop'),
          ]),
          (re.compile(r'\$\{'), [
              # (terminal, group, function)
              ('cmd_param_start', 0, None),
              LexerStackPush('cmd_param'),
          ]),
          (re.compile(r'(.*?)(?=\$\{|\})', re.DOTALL), [
              # (terminal, group, function)
              ('cmd_part', 0, None),
          ]),
        ]),
        'raw_command2': OrderedDict([
          (re.compile(r'<<<'), [
              # (terminal, group, function)
              ('raw_cmd_start', 0, None),
          ]),
          (re.compile(r'>>>'), [
              # (terminal, group, function)
              ('raw_cmd_end', 0, None),
              LexerAction('pop'),
          ]),
          (re.compile(r'\$\{'), [
              # (terminal, group, function)
              ('cmd_param_start', 0, None),
              LexerStackPush('cmd_param'),
          ]),
          (re.compile(r'(.*?)(?=\$\{|>>>)', re.DOTALL), [
              # (terminal, group, function)
              ('cmd_part', 0, None),
          ]),
        ]),
        'cmd_param': OrderedDict([
          (re.compile(r'\s+'), [
              # (terminal, group, function)
          ]),
          (re.compile(r'\}'), [
              # (terminal, group, function)
              ('cmd_param_end', 0, None),
              LexerAction('pop'),
          ]),
          (re.compile(r'\['), [
              # (terminal, group, function)
              ('lsquare', 0, None),
          ]),
          (re.compile(r'\]'), [
              # (terminal, group, function)
              ('rsquare', 0, None),
          ]),
          (re.compile(r'='), [
              # (terminal, group, function)
              ('equal', 0, None),
          ]),
          (re.compile(r'\+'), [
              # (terminal, group, function)
              ('plus', 0, None),
          ]),
          (re.compile(r'\*'), [
              # (terminal, group, function)
              ('asterisk', 0, None),
          ]),
          (re.compile(r'[0-9]+'), [
              # (terminal, group, function)
              ('integer', 0, None),
          ]),
          (re.compile(r'if'), [
              # (terminal, group, function)
              ('if', 0, None),
          ]),
          (re.compile(r'else'), [
              # (terminal, group, function)
              ('else', 0, None),
          ]),
          (re.compile(r'then'), [
              # (terminal, group, function)
              ('then', 0, None),
          ]),
          (re.compile(r'[a-zA-Z]([a-zA-Z0-9_])*(?=\s*=)'), [
              # (terminal, group, function)
              ('cmd_attr_hint', None, None),
              ('identifier', 0, None),
          ]),
          (re.compile(r'(true|false)(?![a-zA-Z0-9_])'), [
              # (terminal, group, function)
              ('boolean', 0, None),
          ]),
          (re.compile(r'(Array|Map|Object|Pair|Boolean|Int|Float|Uri|File|String)(?![a-zA-Z0-9_])(?![a-zA-Z0-9_])'), [
              # (terminal, group, function)
              ('type', 0, None),
          ]),
          (re.compile(r'[a-zA-Z]([a-zA-Z0-9_])*'), [
              # (terminal, group, function)
              ('identifier', 0, None),
          ]),
          (re.compile(r':'), [
              # (terminal, group, function)
              ('colon', 0, None),
          ]),
          (re.compile(r','), [
              # (terminal, group, function)
              ('comma', 0, None),
          ]),
          (re.compile(r'\.'), [
              # (terminal, group, function)
              ('dot', 0, None),
          ]),
          (re.compile(r'=='), [
              # (terminal, group, function)
              ('double_equal', 0, None),
          ]),
          (re.compile(r'\|\|'), [
              # (terminal, group, function)
              ('double_pipe', 0, None),
          ]),
          (re.compile(r'\&\&'), [
              # (terminal, group, function)
              ('double_ampersand', 0, None),
          ]),
          (re.compile(r'!='), [
              # (terminal, group, function)
              ('not_equal', 0, None),
          ]),
          (re.compile(r'='), [
              # (terminal, group, function)
              ('equal', 0, None),
          ]),
          (re.compile(r'\.'), [
              # (terminal, group, function)
              ('dot', 0, None),
          ]),
          (re.compile(r'\{'), [
              # (terminal, group, function)
              ('lbrace', 0, None),
          ]),
          (re.compile(r'\('), [
              # (terminal, group, function)
              ('lparen', 0, None),
          ]),
          (re.compile(r'\)'), [
              # (terminal, group, function)
              ('rparen', 0, None),
          ]),
          (re.compile(r'\['), [
              # (terminal, group, function)
              ('lsquare', 0, None),
          ]),
          (re.compile(r'\]'), [
              # (terminal, group, function)
              ('rsquare', 0, None),
          ]),
          (re.compile(r'\+'), [
              # (terminal, group, function)
              ('plus', 0, None),
          ]),
          (re.compile(r'\*'), [
              # (terminal, group, function)
              ('asterisk', 0, None),
          ]),
          (re.compile(r'-'), [
              # (terminal, group, function)
              ('dash', 0, None),
          ]),
          (re.compile(r'/'), [
              # (terminal, group, function)
              ('slash', 0, None),
          ]),
          (re.compile(r'%'), [
              # (terminal, group, function)
              ('percent', 0, None),
          ]),
          (re.compile(r'<='), [
              # (terminal, group, function)
              ('lteq', 0, None),
          ]),
          (re.compile(r'<'), [
              # (terminal, group, function)
              ('lt', 0, None),
          ]),
          (re.compile(r'>='), [
              # (terminal, group, function)
              ('gteq', 0, None),
          ]),
          (re.compile(r'>'), [
              # (terminal, group, function)
              ('gt', 0, None),
          ]),
          (re.compile(r'!'), [
              # (terminal, group, function)
              ('not', 0, None),
          ]),
          (re.compile(r'"([^\\\"\n]|\\[\\"\'nrbtfav\?]|\\[0-7]{1,3}|\\x[0-9a-fA-F]+|\\[uU]([0-9a-fA-F]{4})([0-9a-fA-F]{4})?)*"'), [
              # (terminal, group, function)
              ('string', 0, wdl_unescape),
          ]),
          (re.compile(r'\'([^\\\'\n]|\\[\\"\'nrbtfav\?]|\\[0-7]{1,3}|\\x[0-9a-fA-F]+|\\[uU]([0-9a-fA-F]{4})([0-9a-fA-F]{4})?)*\''), [
              # (terminal, group, function)
              ('string', 0, wdl_unescape),
          ]),
          (re.compile(r'-?[0-9]+\.[0-9]+'), [
              # (terminal, group, function)
              ('float', 0, None),
          ]),
          (re.compile(r'[0-9]+'), [
              # (terminal, group, function)
              ('integer', 0, None),
          ]),
        ]),
    }
    def _advance_line_col(self, string, length, line, col):
        for i in range(length):
            if string[i] == '\n':
                line += 1
                col = 1
            else:
                col += 1
        return (line, col)
    def _advance_string(self, ctx, string):
        (ctx.line, ctx.col) = self._advance_line_col(string, len(string), ctx.line, ctx.col)
        ctx.string = ctx.string[len(string):]
    def _next(self, ctx, debug=False):
        for regex, outputs in self.regex[ctx.stack[-1]].items():
            if debug:
                from xtermcolor import colorize
                token_count = len(ctx.tokens)
                print('{1} ({2}, {3}) regex: {0}'.format(
                    colorize(regex.pattern, ansi=40), colorize(ctx.string[:20].replace('\n', '\\n'), ansi=15), ctx.line, ctx.col)
                )
            match = regex.match(ctx.string)
            if match:
                ctx.re_match = match
                for output in outputs:
                    if isinstance(output, tuple):
                        (terminal, group, function) = output
                        function = function if function else default_action
                        source_string = match.group(group) if group is not None else ''
                        (group_line, group_col) = self._advance_line_col(ctx.string, match.start(group) if group else 0, ctx.line, ctx.col)
                        function(
                            ctx,
                            terminal,
                            source_string,
                            group_line,
                            group_col
                        )
                        if debug:
                            print('    matched: {}'.format(colorize(match.group(0).replace('\n', '\\n'), ansi=3)))
                            for token in ctx.tokens[token_count:]:
                                print('    emit: [{}] [{}, {}] [{}] stack:{} context:{}'.format(
                                    colorize(token.str, ansi=9),
                                    colorize(str(token.line), ansi=5),
                                    colorize(str(token.col), ansi=5),
                                    colorize(token.source_string, ansi=3),
                                    colorize(str(ctx.stack), ansi=4),
                                    colorize(str(ctx.user_context), ansi=13)
                                ))
                            token_count = len(ctx.tokens)
                    if isinstance(output, LexerStackPush):
                        ctx.stack.append(output.mode)
                        if debug:
                            print('    push on stack: {}'.format(colorize(output.mode, ansi=4)))
                    if isinstance(output, LexerAction):
                        if output.action == 'pop':
                            mode = ctx.stack.pop()
                            if debug:
                                print('    pop off stack: {}'.format(colorize(mode, ansi=4)))
                self._advance_string(ctx, match.group(0))
                return len(match.group(0)) > 0
        return False
    def lex(self, string, resource, errors=None, debug=False):
        if errors is None:
            errors = DefaultSyntaxErrorHandler()
        string_copy = string
        user_context = init()
        ctx = LexerContext(string, resource, errors, user_context)
        while len(ctx.string):
            matched = self._next(ctx, debug)
            if matched == False:
                raise ctx.errors.unrecognized_token(string_copy, ctx.line, ctx.col)
        destroy(ctx.user_context)
        filtered = post_filter(ctx.tokens)
        return filtered
def lex(source, resource, errors=None, debug=False):
    return TokenStream(HermesLexer().lex(source, resource, errors, debug))
