From a2a98dfdc9ccc65bc99a195bd2a1dd5ec803e72f Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Tue, 24 Nov 2015 09:58:30 -0500 Subject: [PATCH] Moving Python code to PyWDL repository --- python/README.md | 347 +-- python/generate.sh | 4 - python/scripts/wdl | 6 - python/setup.py | 30 - python/wdl/__init__.py | 24 - python/wdl/binding.py | 554 ----- python/wdl/engine.py | 658 ------ python/wdl/main.py | 80 - python/wdl/parser.py | 4080 ------------------------------------ python/wdl/spec.py | 57 - python/wdl/test/cases/0/ast | 418 ---- python/wdl/test/cases/0/parsetree | 937 --------- python/wdl/test/cases/0/wdl | 88 - python/wdl/test/cases/1/ast | 187 -- python/wdl/test/cases/1/parsetree | 417 ---- python/wdl/test/cases/1/wdl | 39 - python/wdl/test/cases/2/ast | 114 - python/wdl/test/cases/2/parsetree | 251 --- python/wdl/test/cases/2/wdl | 21 - python/wdl/test/cases/3/ast | 192 -- python/wdl/test/cases/3/parsetree | 417 ---- python/wdl/test/cases/3/wdl | 43 - python/wdl/test/cases/4/ast | 109 - python/wdl/test/cases/4/parsetree | 238 --- python/wdl/test/cases/4/wdl | 20 - python/wdl/test/cases/5/ast | 446 ---- python/wdl/test/cases/5/parsetree | 1001 --------- python/wdl/test/cases/5/wdl | 94 - python/wdl/test/test_binding.py | 153 -- python/wdl/test/test_expression.py | 296 --- python/wdl/test/test_parser.py | 31 - python/wdl/toc.py | 37 - python/wdl/types.py | 45 - python/wdl/util.py | 29 - python/wdl/values.py | 256 --- 35 files changed, 1 insertion(+), 11718 deletions(-) delete mode 100644 python/generate.sh delete mode 100755 python/scripts/wdl delete mode 100644 python/setup.py delete mode 100644 python/wdl/__init__.py delete mode 100644 python/wdl/binding.py delete mode 100644 python/wdl/engine.py delete mode 100644 python/wdl/main.py delete mode 100644 python/wdl/parser.py delete mode 100644 python/wdl/spec.py delete mode 100644 python/wdl/test/cases/0/ast delete mode 100644 python/wdl/test/cases/0/parsetree delete mode 100644 python/wdl/test/cases/0/wdl delete mode 100644 python/wdl/test/cases/1/ast delete mode 100644 python/wdl/test/cases/1/parsetree delete mode 100644 python/wdl/test/cases/1/wdl delete mode 100644 python/wdl/test/cases/2/ast delete mode 100644 python/wdl/test/cases/2/parsetree delete mode 100644 python/wdl/test/cases/2/wdl delete mode 100644 python/wdl/test/cases/3/ast delete mode 100644 python/wdl/test/cases/3/parsetree delete mode 100644 python/wdl/test/cases/3/wdl delete mode 100644 python/wdl/test/cases/4/ast delete mode 100644 python/wdl/test/cases/4/parsetree delete mode 100644 python/wdl/test/cases/4/wdl delete mode 100644 python/wdl/test/cases/5/ast delete mode 100644 python/wdl/test/cases/5/parsetree delete mode 100644 python/wdl/test/cases/5/wdl delete mode 100644 python/wdl/test/test_binding.py delete mode 100644 python/wdl/test/test_expression.py delete mode 100644 python/wdl/test/test_parser.py delete mode 100644 python/wdl/toc.py delete mode 100644 python/wdl/types.py delete mode 100644 python/wdl/util.py delete mode 100644 python/wdl/values.py diff --git a/python/README.md b/python/README.md index e9a8a87..764c848 100644 --- a/python/README.md +++ b/python/README.md @@ -2,349 +2,4 @@ A Python implementation of a WDL parser and language bindings. -For Scala language bindings, use [Cromwell](http://github.com/broadinstitute/cromwell). - - - -* [PyWDL](#pywdl) -* [Installation](#installation) -* [Language Bindings](#language-bindings) - * [Abstract syntax trees (ASTs)](#abstract-syntax-trees-asts) - * [wdl.parser.Ast](#wdlparserast) - * [wdl.parser.Terminal](#wdlparserterminal) - * [wdl.parser.AstList](#wdlparserastlist) - * [Working with expressions](#working-with-expressions) -* [Command Line Usage](#command-line-usage) - - - -# Installation - -PyWDL works with Python 2 or Python 3. Install via `setup.py`: - -``` -$ python setup.py install -``` - -Or via pip: - -``` -$ pip install wdl -``` - -# Language Bindings - -The main `wdl` package provides an interface to turn WDL source code into native Python objects. This means that a `workflow {}` block in WDL would become a `Workflow` object in Python and a `task {}` block becomes a `Task` object. - -To parse WDL source code into a `WdlDocument` object, import the `wdl` package and load a WDL string with `wdl.loads("wdl code")` or WDL from a file-like object using `wdl.load(fp, resource_name)`. - -For example: - -```python -import wdl -import wdl.values - -wdl_code = """ -task my_task { - File file - command { - ./my_binary --input=${file} > results - } - output { - File results = "results" - } -} - -workflow my_wf { - call my_task -} -""" - -# Use the language bindings to parse WDL into Python objects -wdl_namespace = wdl.loads(wdl_code) - -for workflow in wdl_namespace.workflows: - print('Workflow "{}":'.format(workflow.name)) - for call in workflow.calls(): - print(' Call: {} (task {})'.format(call.name, call.task.name)) - -for task in wdl_namespace.tasks: - name = task.name - abstract_command = task.command - def lookup(name): - if name == 'file': return wdl.values.WdlFile('/path/to/file.txt') - instantated_command = task.command.instantiate(lookup) - print('Task "{}":'.format(name)) - print(' Abstract Command: {}'.format(abstract_command)) - print(' Instantiated Command: {}'.format(instantated_command)) -``` - -Using the language bindings as shown above is the recommended way to use PyWDL. One can also directly access the parser to parse WDL source code into an abstract syntax tree using the `wdl.parser` package: - -```python -import wdl.parser - -wdl_code = """ -task my_task { - File file - command { - ./my_binary --input=${file} > results - } - output { - File results = "results" - } -} - -workflow my_wf { - call my_task -} -""" - -# Parse source code into abstract syntax tree -ast = wdl.parser.parse(wdl_code).ast() - -# Print out abstract syntax tree -print(ast.dumps(indent=2)) - -# Access the first task definition, print out its name -print(ast.attr('definitions')[0].attr('name').source_string) - -# Find all 'Task' ASTs -task_asts = wdl.find_asts(ast, 'Task') -for task_ast in task_asts: - print(task_ast.dumps(indent=2)) - -# Find all 'Workflow' ASTs -workflow_asts = wdl.find_asts(ast, 'Workflow') -for workflow_ast in workflow_asts: - print(workflow_ast.dumps(indent=2)) -``` - -## Abstract syntax trees (ASTs) - -An AST is the output of the parsing algorithm. It is a tree structure in which the root node is always a `Document` AST - -The best way to get started working with ASTs is to visualize them by using the `wdl parse` subcommand to see the AST as text. For example, consider the following WDL file - -example.wdl -``` -task a { - command {./foo_bin} -} -task b { - command {./bar_bin} -} -task c { - command {./baz_bin} -} -workflow w {} -``` - -Then, use the command line to parse and output the AST: - -``` -$ wdl parse example.wdl -(Document: - imports=[], - definitions=[ - (Task: - name=, - declarations=[], - sections=[ - (RawCommand: - parts=[ - - ] - ) - ] - ), - (Task: - name=, - declarations=[], - sections=[ - (RawCommand: - parts=[ - - ] - ) - ] - ), - (Task: - name=, - declarations=[], - sections=[ - (RawCommand: - parts=[ - - ] - ) - ] - ), - (Workflow: - name=, - body=[] - ) - ] -) -``` - -Programmatically, if one wanted to traverse this AST to pull out data: - -```python -import wdl.parser -import wdl - -with open('example.wdl') as fp: - ast = wdl.parser.parse(fp.read()).ast() - -task_a = ast.attr('definitions')[0] -task_b = ast.attr('definitions')[1] -task_c = ast.attr('definitions')[2] - -for ast in task_a.attr('sections'): - if ast.name == 'RawCommand': - task_a_command = ast - -for ast in task_a_command.attr('parts'): - if isinstance(ast, wdl.parser.Terminal): - print('command string: ' + ast.source_string) - else: - print('command parameter: ' + ast.dumps()) -``` - -### wdl.parser.Ast - -The `Ast` class is a syntax tree with a name and children nodes. - -Attributes: - -* `name` is a string that refers to the type of AST, (e.g. `Workflow`, `Task`, `Document`, `RawCommand`) -* `attributes` is a dictionary where the keys are the name of the attribute and the values can be one of three types: `Ast`, `AstList`, `Terminal`. - -Methods: - -* `def attr(self, name)`. `ast.attr('name')` is the same as `ast.attributes['name']`. -* `def dumps(self, indent=None, b64_source=True)` - returns a String representation of this AstList. the `indent` parameter takes an integer for the indent level. Omitting this value will cause there to be no new-lines in the resulting string. `b64_source` will be passed to recursive invocations of `dumps`. - -### wdl.parser.Terminal - -The `wdl.parser.Terminal` object represents a literal piece of the original source code. This always shows up as leaf nodes on `Ast` objects - -Attributes: - -* `source_string` - String segment from the source code. -* `line` - Line number where `source_string` was in source code. -* `col` - Column number where `source_string` was in source code. -* `resource` - Name of the location for the source code. Usually a file system path or perhaps URI. -* `id` - Numeric identifier, unique to the top level `Ast`. Used mostly internally. -* `str` - String identifier of this terminal. Used mostly internally. - -Methods: - -* `def dumps(self, b64_source=True, **kwargs)` - return a String representation of this terminal. `b64_source` means that the source code will be base64 encoded because sometimes the source contains newlines or special characters that make it difficult to read when a whole AST is string-ified. - -### wdl.parser.AstList - -`class AstList(list)` represents a sequence of `Ast`, `AstList`, and `Terminal` objects - -Methods: - -* `def dumps(self, indent=None, b64_source=True)` - returns a String representation of this AstList. the `indent` parameter takes an integer for the indent level. Omitting this value will cause there to be no new-lines in the resulting string. `b64_source` will be passed to recursive invocations of `dumps`. - -## Working with expressions - -Parsing a WDL file will result in unevaluated expressions. For example: - -``` -workflow test { - Int a = (1 + 2) * 3 - call my_task { - input: var=a*2, var2="file"+".txt" - } -} -``` - -This workflow definition has three expressions in it: `(1 + 2) * 3`, `a*2`, and `"file"+".txt"`. - -Expressions are stored in `wdl.binding.Expression` object. The AST for the expression is stored in this object. - -Expressions can be evaluated with the `eval()` method on the `Expression` class. - -```python -import wdl - -# Manually parse expression into wdl.binding.Expression -expression = wdl.parse_expr("(1 + 2) * 3") - -# Evaluate the expression. -# Returns a WdlValue, specifically a WdlIntegerValue(9) -evaluated = expression.eval() - -# Get the Python value -print(evaluated.value) -``` - -Sometimes expressions contain references to variables or functions. In order for these to be resolved, one must pass a lookup function and an implementation of the functions that you want to support: - -```python -import wdl -from wdl.values import WdlInteger, WdlUndefined - -def test_lookup(identifier): - if identifier == 'var': - return WdlInteger(4) - else: - return WdlUndefined - -def test_functions(): - def add_one(parameters): - # assume at least one parameter exists, for simplicity - return WdlInteger(parameters[0].value + 1) - def get_function(name): - if name == 'add_one': return add_one - else: raise EvalException("Function {} not defined".format(name)) - return get_function - -# WdlInteger(12) -print(wdl.parse_expr("var * 3").eval(test_lookup)) - -# WdlInteger(8) -print(wdl.parse_expr("var + var").eval(test_lookup)) - -# WdlInteger(9) -print(wdl.parse_expr("add_one(var + var)").eval(test_lookup, test_functions())) -``` - -# Command Line Usage - -``` -$ wdl --help -usage: wdl [-h] [--version] [--debug] [--no-color] {run,parse} ... - -Workflow Description Language (WDL) - -positional arguments: - {runarse} WDL Actions - run Run you a WDL - parse Parse a WDL file, print parse tree - -optional arguments: - -h, --help show this help message and exit - --version show program's version number and exit - --debug Open the floodgates - --no-color Don't colorize output -``` - -Parse a WDL file: - -``` -$ wdl parse examples/ex2.wdl -(Document: - definitions=[ - (Task: - name=, - declarations=[], - sections=[ - (RawCommand: -... -``` +**This repository has moved to https://github.com/broadinstitute/pywdl** diff --git a/python/generate.sh b/python/generate.sh deleted file mode 100644 index 1e2a977..0000000 --- a/python/generate.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/bash - -hermes generate ../grammar.hgr --name=wdl --directory=wdl --header -mv wdl/wdl_parser.py wdl/parser.py diff --git a/python/scripts/wdl b/python/scripts/wdl deleted file mode 100755 index 6647d17..0000000 --- a/python/scripts/wdl +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env python - -import sys -import wdl.main - -sys.exit(wdl.main.cli()) diff --git a/python/setup.py b/python/setup.py deleted file mode 100644 index 593510a..0000000 --- a/python/setup.py +++ /dev/null @@ -1,30 +0,0 @@ -from setuptools import setup - -version = '1.0.10' -long_description = 'Parse and Process WDL Files' - -setup( - name='wdl', - version=version, - description=long_description, - author='Scott Frazer', - author_email='sfrazer@broadinstitute.org', - packages=['wdl'], - install_requires=[ - "xtermcolor", - "pytest" - ], - scripts={ - 'scripts/wdl', - }, - license = 'MIT', - keywords = "Workflow, Task", - url = "http://github.com/broadinstitute/wdl", - classifiers=[ - 'License :: OSI Approved :: MIT License', - "Programming Language :: Python", - "Development Status :: 4 - Beta", - "Intended Audience :: Developers", - "Natural Language :: English" - ] -) diff --git a/python/wdl/__init__.py b/python/wdl/__init__.py deleted file mode 100644 index 4bb4b0a..0000000 --- a/python/wdl/__init__.py +++ /dev/null @@ -1,24 +0,0 @@ -from wdl.binding import parse_namespace, Expression -import wdl.parser - -def load(fp, resource): - return parse_namespace(fp.read(), resource) - -def loads(s): - return parse_namespace(s, "string") - -def find_asts(ast_root, name): - nodes = [] - if isinstance(ast_root, wdl.parser.AstList): - for node in ast_root: - nodes.extend(find_asts(node, name)) - elif isinstance(ast_root, wdl.parser.Ast): - if ast_root.name == name: - nodes.append(ast_root) - for attr_name, attr in ast_root.attributes.items(): - nodes.extend(find_asts(attr, name)) - return nodes - -def parse_expr(expr_string): - ctx = wdl.parser.ParserContext(wdl.parser.lex(expr_string, 'string'), wdl.parser.DefaultSyntaxErrorHandler()) - return Expression(wdl.parser.parse_e(ctx).ast()) diff --git a/python/wdl/binding.py b/python/wdl/binding.py deleted file mode 100644 index 3321fa9..0000000 --- a/python/wdl/binding.py +++ /dev/null @@ -1,554 +0,0 @@ -import wdl.parser -import wdl.util -from wdl.types import * -from wdl.values import * -import os -import json -import re - -def scope_hierarchy(scope): - if scope is None: return [] - return [scope] + scope_hierarchy(scope.parent) - -class BindingException(Exception): pass -class TaskNotFoundException(Exception): pass -class WdlValueException(Exception): pass -class EvalException(Exception): pass - -class FullyQualifiedName(object): - def __init__(self, fqn, namespace): - self.__dict__.update(locals()) - def __str__(self): - return '[FullyQualifiedName: {}, {}]'.format(self.fqn, str(namespace)) - -class WdlNamespace(object): - def __init__(self, source_location, source_wdl, tasks, workflows, ast): - self.__dict__.update(locals()) - def task(self, name): - for task in self.tasks: - if task.name == name: return task - raise TaskNotFoundException("Could not find task with name {}".format(name)) - def resolve(self, fqn): - # TODO: finish - try: - (name, sub_fqn) = fqn.split('.', 1) - except ValueError: - (name, sub_fqn) = (fqn, '') - - for task in tasks: - if task.name == name and sub_fqn == '': return FullyQualifiedName(fqn, task) - if workflow.name == name and sub_fqn == '': return FullyQualifiedName(fqn, workflow) - def __str__(self): - return '[WdlNamespace tasks={} workflows={}]'.format( - ','.join([t.name for t in self.tasks]), - ','.join([w.name for w in self.workflows]) - ) - -class Expression(object): - def __init__(self, ast): - self.__dict__.update(locals()) - def eval(self, lookup=lambda var: None, functions=None): - return eval(self.ast, lookup, functions) - def wdl_string(self): - return expr_str(self.ast) if self.ast else str(None) - def __str__(self): - return '[Expression {}]'.format(self.wdl_string()) - -class Task(object): - def __init__(self, name, declarations, command, outputs, runtime, parameter_meta, meta, ast): - self.__dict__.update(locals()) - def __getattr__(self, name): - if name == 'inputs': - return [decl for decl in self.declarations if decl.expression is not None] - def __str__(self): - return '[Task name={}]'.format(self.name) - -class Command(object): - def __init__(self, parts, ast): - self.__dict__.update(locals()) - def instantiate(self, lookup_function=None, wdl_functions=None): - cmd = [] - for part in self.parts: - if isinstance(part, CommandString): - cmd.append(part.string) - elif isinstance(part, CommandExpressionTag): - value = part.expression.eval(lookup_function, wdl_functions) - if isinstance(value, WdlValue) and isinstance(value.type, WdlPrimitiveType): - value = value.as_string() - elif isinstance(value, WdlArray) and isinstance(value.subtype, WdlPrimitiveType) and 'sep' in part.attributes: - value = parts.attributes['sep'].join(x.as_string() for x in value) - else: - raise EvalException('Could not string-ify: {}'.format(value)) - cmd.append(value) - return wdl.util.strip_leading_ws(''.join(cmd)) - def wdl_string(self): - return wdl.util.strip_leading_ws(''.join([part.wdl_string() for part in self.parts])) - def __str__(self): - return '[Command: {}]'.format(self.wdl_string().replace('\n', '\\n').replace('\r', '\\r')) - -class CommandPart: pass - -class CommandExpressionTag(CommandPart): - def __init__(self, attributes, expression, ast): - self.__dict__.update(locals()) - def wdl_string(self): - attr_string = ', '.join(self.attributes) - return '${' + '{}{}'.format(attr_string, self.expression.wdl_string()) + '}' - def __str__(self): - return '[CommandExpressionTag: {}]'.format(self.wdl_string()) - -class CommandString(CommandPart): - def __init__(self, string, terminal): - self.__dict__.update(locals()) - def wdl_string(self): - return self.string - def __str__(self): - return '[CommandString: {}]'.format(self.string) - -# Scope has: body, declarations, parent, prefix, name -class Scope(object): - def __init__(self, name, declarations, body): - self.__dict__.update(locals()) - self.parent = None - for element in body: - element.parent = self - def __getattr__(self, name): - if name == 'fully_qualified_name': - if self.parent is None: - return self.name - return self.parent.fully_qualified_name + '.' + self.name - def calls(self): - def calls_r(node): - if isinstance(node, Call): - return [node] - if isinstance(node, Scope): - call_list = [] - for element in node.body: - call_list.extend(calls_r(element)) - return call_list - return calls_r(self) - -class Workflow(Scope): - def __init__(self, name, declarations, body, ast): - self.__dict__.update(locals()) - super(Workflow, self).__init__(name, declarations, body) - def get(self, fqn): - def get_r(node, fqn): - if node.fully_qualified_name == fqn: - return node - for element in node.body: - if isinstance(element, Scope): - sub = get_r(element, fqn) - if sub: return sub - return get_r(self, fqn) - -class Call(Scope): - def __init__(self, task, alias, inputs, ast): - self.__dict__.update(locals()) - super(Call, self).__init__(alias if alias else task.name, [], []) - def upstream(self): - # TODO: this assumes MemberAccess always refers to other calls - up = [] - for expression in self.inputs.values(): - for node in wdl.find_asts(expression.ast, "MemberAccess"): - up.append(node.attr('lhs').source_string) - return up - def get_scatter_parent(self, node=None): - for parent in scope_hierarchy(self): - if isinstance(parent, Scatter): - return parent - def __self__(self): - return '[Call alias={}]'.format(self.alias) - -class Declaration(object): - def __init__(self, name, type, expression, ast): - self.__dict__.update(locals()) - def __str__(self): - return '[Declaration type={}, name={}, expr={}]'.format(self.type, self.name, expr_str(self.expression)) - def wdl_string(self): - return '{} {}{}'.format(self.type.wdl_string(), self.name, ' = {}'.format(self.expression.wdl_string()) if self.expression else '') - -class WhileLoop(Scope): - def __init__(self, expression, declarations, body, ast): - self.__dict__.update(locals()) - super(WhileLoop, self).__init__('_w' + str(ast.id), declarations, body) - -class Scatter(Scope): - def __init__(self, item, collection, declarations, body, ast): - self.__dict__.update(locals()) - super(Scatter, self).__init__('_s' + str(ast.id), declarations, body) - def get_flatten_count(self): - # TODO: revisit this algorithm - count = 0 - collection = self.collection.ast.source_string - for node in scope_hierarchy(self): - if isinstance(node, Scatter): - if node.item == collection: - collection = node.collection.ast.source_string - count += 1 - if isinstance(node, Scope): - for decl in node.declarations: - if decl.name == collection: - (var, type) = (decl.name, decl.type) - for i in range(count): - type = type.subtype - return (var, type, count) - -class WorkflowOutputs(list): - def __init__(self, arg=[]): - super(WorkflowOutputs, self).__init__(arg) - -class WorkflowOutput: - def __init__(self, fqn, wildcard): - self.__dict__.update(locals()) - -class WorkflowOutput: - def __init__(self, fqn, wildcard): - self.__dict__.update(locals()) - -def assign_ids(ast_root, id=0): - if isinstance(ast_root, wdl.parser.AstList): - ast_root.id = id - for index, node in enumerate(ast_root): - assign_ids(node, id+index) - elif isinstance(ast_root, wdl.parser.Ast): - ast_root.id = id - for index, attr in enumerate(ast_root.attributes.values()): - assign_ids(attr, id+index) - elif isinstance(ast_root, wdl.parser.Terminal): - ast_root.id = id - -# Binding functions - -def parse_namespace(string, resource): - errors = wdl.parser.DefaultSyntaxErrorHandler() - tokens = wdl.parser.lex(string, resource, errors) - ast = wdl.parser.parse(tokens).ast() - assign_ids(ast) - tasks = [parse_task(task_ast) for task_ast in wdl.find_asts(ast, 'Task')] - workflows = [parse_workflow(wf_ast, tasks) for wf_ast in wdl.find_asts(ast, 'Workflow')] - return WdlNamespace(resource, string, tasks, workflows, ast) - -def parse_task(ast): - name = ast.attr('name').source_string - declarations = [parse_declaration(d) for d in ast.attr('declarations')] - command_ast = wdl.find_asts(ast, 'RawCommand') - command = parse_command(command_ast[0]) - outputs = [parse_output(output_ast) for output_ast in wdl.find_asts(ast, 'Output')] - runtime_asts = wdl.find_asts(ast, 'Runtime') - runtime = parse_runtime(runtime_asts[0]) if len(runtime_asts) else {} - return Task(name, declarations, command, outputs, runtime, {}, {}, ast) - -def parse_workflow(ast, tasks): - body = [] - declarations = [] - name = ast.attr('name').source_string - for body_ast in ast.attr('body'): - if body_ast.name == 'Declaration': - declarations.append(parse_declaration(body_ast)) - else: - body.append(parse_body_element(body_ast, tasks)) - return Workflow(name, declarations, body, ast) - -def parse_runtime(ast): - if not isinstance(ast, wdl.parser.Ast) or ast.name != 'Runtime': - raise BindingException('Expecting a "Runtime" AST') - runtime = {} - for attr in ast.attr('map'): - runtime[attr.attr('key').source_string] = Expression(attr.attr('value')) - return runtime - -def parse_declaration(ast): - if not isinstance(ast, wdl.parser.Ast) or ast.name != 'Declaration': - raise BindingException('Expecting a "Declaration" AST') - type = parse_type(ast.attr('type')) - name = ast.attr('name').source_string - expression = Expression(ast.attr('expression')) if ast.attr('expression') else None - return Declaration(name, type, expression, ast) - -def parse_body_element(ast, tasks): - if ast.name == 'Call': - return parse_call(ast, tasks) - elif ast.name == 'Workflow': - return parse_workflow(ast, tasks) - elif ast.name == 'WhileLoop': - return parse_while_loop(ast, tasks) - elif ast.name == 'Scatter': - return parse_scatter(ast, tasks) - elif ast.name == 'WorkflowOutputs': - return parse_workflow_outputs(ast) - else: - raise BindingException("unknown ast: " + ast.name) - -def parse_while_loop(ast, tasks): - expression = Expression(ast.attr('expression')) - body = [] - declarations = [] - for body_ast in ast.attr('body'): - if body_ast.name == 'Declaration': - declarations.append(parse_declaration(body_ast)) - else: - body.append(parse_body_element(body_ast, tasks)) - return WhileLoop(expression, declarations, body, ast) - -def parse_scatter(ast, tasks): - collection = Expression(ast.attr('collection')) - item = ast.attr('item').source_string - body = [] - declarations = [] - for body_ast in ast.attr('body'): - if body_ast.name == 'Declaration': - declarations.append(parse_declaration(body_ast)) - else: - body.append(parse_body_element(body_ast, tasks)) - return Scatter(item, collection, declarations, body, ast) - -def parse_workflow_outputs(ast): - return WorkflowOutputs([parse_workflow_output(x) for x in ast.attr('outputs')]) - -def parse_workflow_output(ast): - return WorkflowOutput(ast.attr('fqn').source_string, ast.attr('wildcard').source_string if ast.attr('wildcard') else None) - -def parse_call(ast, tasks): - if not isinstance(ast, wdl.parser.Ast) or ast.name != 'Call': - raise BindingException('Expecting a "Call" AST') - task_name = ast.attr('task').source_string - alias = ast.attr('alias').source_string if ast.attr('alias') else None - - for task in tasks: - if task.name == task_name: - break - - if task is None: - raise BindingException('Could not find task with name: ' + task_name) - - inputs = {} - try: - for mapping in wdl.find_asts(ast, 'Inputs')[0].attr('map'): - inputs[mapping.attr('key').source_string] = Expression(mapping.attr('value')) - except IndexError: - pass - - return Call(task, alias, inputs, ast) - -def parse_command_line_expr_attrs(ast): - attrs = {} - for x in ast: - attrs[x.attr('key').source_string] = x.attr('value').source_string - return attrs - -def parse_command_line_expr(ast): - if not isinstance(ast, wdl.parser.Ast) or ast.name != 'CommandParameter': - raise BindingException('Expecting a "CommandParameter" AST') - return CommandExpressionTag( - parse_command_line_expr_attrs(ast.attr('attributes')), - Expression(ast.attr('expr')), - ast - ) - -def parse_command(ast): - if not isinstance(ast, wdl.parser.Ast) or ast.name != 'RawCommand': - raise BindingException('Expecting a "RawCommand" AST') - parts = [] - for node in ast.attr('parts'): - if isinstance(node, wdl.parser.Terminal): - parts.append(CommandString(node.source_string, node)) - if isinstance(node, wdl.parser.Ast) and node.name == 'CommandParameter': - parts.append(parse_command_line_expr(node)) - return Command(parts, ast) - -def parse_output(ast): - if not isinstance(ast, wdl.parser.Ast) or ast.name != 'Output': - raise BindingException('Expecting an "Output" AST') - type = parse_type(ast.attr('type')) - var = ast.attr('var').source_string - expression = Expression(ast.attr('expression')) - return Declaration(var, type, expression, ast) - -def parse_type(ast): - if isinstance(ast, wdl.parser.Terminal): - if ast.str != 'type': - raise BindingException('Expecting an "Type" AST') - if ast.source_string == 'Int': return WdlIntegerType() - elif ast.source_string == 'Boolean': return WdlBooleanType() - elif ast.source_string == 'Float': return WdlFloatType() - elif ast.source_string == 'String': return WdlStringType() - elif ast.source_string == 'File': return WdlFileType() - elif ast.source_string == 'Uri': return WdlUriType() - else: raise BindingException("Unsupported Type: {}".format(ast.source_string)) - elif isinstance(ast, wdl.parser.Ast) and ast.name == 'Type': - name = ast.attr('name').source_string - if name == 'Array': - subtypes = ast.attr('subtype') - if len(subtypes) != 1: - raise BindingException("Expecting only one subtype AST") - return WdlArrayType(parse_type(subtypes[0])) - if name == 'Map': - subtypes = ast.attr('subtype') - if len(subtypes) != 2: - raise BindingException("Expecting only two subtype AST") - return WdlMapType(parse_type(subtypes[0]), parse_type(subtypes[1])) - else: - raise BindingException('Expecting an "Type" AST') - -def python_to_wdl_value(py_value, wdl_type): - if isinstance(wdl_type, WdlStringType): - return WdlString(py_value) - if isinstance(wdl_type, WdlIntegerType): - return WdlInteger(py_value) - if isinstance(wdl_type, WdlFloatType): - return WdlFloat(py_value) - if isinstance(wdl_type, WdlBooleanType): - return WdlBoolean(py_value) - if isinstance(wdl_type, WdlFileType): - return WdlFile(py_value) - if isinstance(wdl_type, WdlUriType): - return WdlUri(py_value) - if isinstance(wdl_type, WdlArrayType): - if not isinstance(py_value, list): - raise WdlValueException("{} must be constructed from Python list, got {}".format(wdl_type, py_value)) - members = [python_to_wdl_value(x, wdl_type.subtype) for x in py_value] - return WdlArray(wdl_type.subtype, members) - if isinstance(wdl_type, WdlMapType): - if not isinstance(py_value, list): - raise WdlValueException("{} must be constructed from Python dict, got {}".format(wdl_type, py_value)) - members = {python_to_wdl_value(k): python_to_wdl_value(v) for k,v in py_value.items()} - return WdlMap(members) - -binary_operators = [ - 'Add', 'Subtract', 'Multiply', 'Divide', 'Remainder', 'Equals', - 'NotEquals', 'LessThan', 'LessThanOrEqual', 'GreaterThan', - 'GreaterThanOrEqual', 'LogicalAnd', 'LogicalOr' -] - -unary_operators = [ - 'LogicalNot', 'UnaryPlus', 'UnaryNegation' -] - -def interpolate(string, lookup, functions): - for expr_string in re.findall(r'\$\{.*?\}', string): - expr = wdl.parse_expr(expr_string[2:-1]) - value = expr.eval(lookup, functions) - string = string.replace(expr_string, value.as_string()) - return string - -def eval(ast, lookup=lambda var: None, functions=None): - if isinstance(ast, wdl.parser.Terminal): - if ast.str == 'integer': - return WdlInteger(int(ast.source_string)) - if ast.str == 'float': - return WdlFloat(float(ast.source_string)) - elif ast.str == 'string': - return WdlString(interpolate(ast.source_string, lookup, functions)) - elif ast.str == 'boolean': - return WdlBoolean(True if ast.source_string == 'true' else False) - elif ast.str == 'identifier': - symbol = lookup(ast.source_string) - if symbol is None: - return WdlUndefined() - return symbol - elif isinstance(ast, wdl.parser.Ast): - if ast.name in binary_operators: - lhs = eval(ast.attr('lhs'), lookup, functions) - if isinstance(lhs, WdlUndefined): return lhs - - rhs = eval(ast.attr('rhs'), lookup, functions) - if isinstance(rhs, WdlUndefined): return rhs - - if ast.name == 'Add': return lhs.add(rhs) - if ast.name == 'Subtract': return lhs.subtract(rhs) - if ast.name == 'Multiply': return lhs.multiply(rhs) - if ast.name == 'Divide': return lhs.divide(rhs) - if ast.name == 'Remainder': return lhs.mod(rhs) - if ast.name == 'Equals': return lhs.equal(rhs) - if ast.name == 'NotEquals': return lhs.not_equal(rhs) - if ast.name == 'LessThan': return lhs.less_than(rhs) - if ast.name == 'LessThanOrEqual': return lhs.less_than_or_equal(rhs) - if ast.name == 'GreaterThan': return lhs.greater_than(rhs) - if ast.name == 'GreaterThanOrEqual': return lhs.greater_than_or_equal(rhs) - if ast.name == 'LogicalAnd': return lhs.logical_and(rhs) - if ast.name == 'LogicalOr': return lhs.logical_or(rhs) - if ast.name in unary_operators: - expr = eval(ast.attr('expression'), lookup, functions) - if isinstance(expr, WdlUndefined): return expr - - if ast.name == 'LogicalNot': return expr.logical_not() - if ast.name == 'UnaryPlus': return expr.unary_plus() - if ast.name == 'UnaryNegation': return expr.unary_negation() - if ast.name == 'ObjectLiteral': - obj = WdlObject() - for member in ast.attr('map'): - key = member.attr('key').source_string - value = eval(member.attr('value'), lookup, functions) - if value is None or isinstance(value, WdlUndefined): - raise EvalException('Cannot evaluate expression') - obj.set(key, value) - return obj - if ast.name == 'ArrayOrMapLookup': - array_or_map = eval(ast.attr('lhs'), lookup, functions) - index = eval(ast.attr('rhs'), lookup, functions) - - if isinstance(array_or_map, WdlArray) and isinstance(index, WdlInteger): - return array_or_map.value[index.value] - elif isinstance(array_or_map, WdlArray): - raise EvalException('Cannot index array {} with {}'.format(array_or_map, index)) - elif isinstance(array_or_map, WdlMap) and isinstance(index.type, WdlPrimitiveType): - return array_or_map.value[index] - raise EvalException('ArrayOrMapLookup not implemented yet') - if ast.name == 'MemberAccess': - object = eval(ast.attr('lhs'), lookup, functions) - member = ast.attr('rhs') - - if isinstance(object, WdlUndefined): - return object - if not isinstance(member, wdl.parser.Terminal) or member.str != 'identifier': - # TODO: maybe enforce this in the grammar? - raise EvalException('rhs needs to be an identifier') - - member = member.source_string - return object.get(member) - if ast.name == 'FunctionCall': - function = ast.attr('name').source_string - parameters = [eval(x, lookup, functions) for x in ast.attr('params')] - return functions(function)(parameters) - -def expr_str(ast): - if isinstance(ast, wdl.parser.Terminal): - if ast.str == 'string': - return '"{}"'.format(ast.source_string) - return ast.source_string - elif isinstance(ast, wdl.parser.Ast): - if ast.name == 'Add': - return '{}+{}'.format(expr_str(ast.attr('lhs')), expr_str(ast.attr('rhs'))) - if ast.name == 'Subtract': - return '{}-{}'.format(expr_str(ast.attr('lhs')), expr_str(ast.attr('rhs'))) - if ast.name == 'Multiply': - return '{}*{}'.format(expr_str(ast.attr('lhs')), expr_str(ast.attr('rhs'))) - if ast.name == 'Divide': - return '{}/{}'.format(expr_str(ast.attr('lhs')), expr_str(ast.attr('rhs'))) - if ast.name == 'Remainder': - return '{}%{}'.format(expr_str(ast.attr('lhs')), expr_str(ast.attr('rhs'))) - if ast.name == 'Equals': - return '{}=={}'.format(expr_str(ast.attr('lhs')), expr_str(ast.attr('rhs'))) - if ast.name == 'NotEquals': - return '{}!={}'.format(expr_str(ast.attr('lhs')), expr_str(ast.attr('rhs'))) - if ast.name == 'LessThan': - return '{}<{}'.format(expr_str(ast.attr('lhs')), expr_str(ast.attr('rhs'))) - if ast.name == 'LessThanOrEqual': - return '{}<={}'.format(expr_str(ast.attr('lhs')), expr_str(ast.attr('rhs'))) - if ast.name == 'GreaterThan': - return '{}>{}'.format(expr_str(ast.attr('lhs')), expr_str(ast.attr('rhs'))) - if ast.name == 'GreaterThanOrEqual': - return '{}>={}'.format(expr_str(ast.attr('lhs')), expr_str(ast.attr('rhs'))) - if ast.name == 'LogicalNot': - return '!{}'.format(expr_str(ast.attr('expression'))) - if ast.name == 'UnaryPlus': - return '+{}'.format(expr_str(ast.attr('expression'))) - if ast.name == 'UnaryNegation': - return '-{}'.format(expr_str(ast.attr('expression'))) - if ast.name == 'FunctionCall': - return '{}({})'.format(expr_str(ast.attr('name')), ','.join([expr_str(param) for param in ast.attr('params')])) - if ast.name == 'ArrayIndex': - return '{}[{}]'.format(expr_str(ast.attr('lhs')), expr_str(ast.attr('rhs'))) - if ast.name == 'MemberAccess': - return '{}.{}'.format(expr_str(ast.attr('lhs')), expr_str(ast.attr('rhs'))) diff --git a/python/wdl/engine.py b/python/wdl/engine.py deleted file mode 100644 index 4eef035..0000000 --- a/python/wdl/engine.py +++ /dev/null @@ -1,658 +0,0 @@ -from wdl.binding import * -from wdl.util import * -import re -import subprocess -import tempfile -import uuid -import xml.etree.ElementTree as ETree -import time -from xtermcolor import colorize - -def lookup_function(symbol_table, scope, scatter_vars=[], index=None): - def lookup(var): - if var in scatter_vars: - for s in scope_hierarchy(scope): - val = symbol_table.get(s, var) - if not isinstance(val, WdlUndefined): - if var in scatter_vars: - return val.value[index] - return val - return WdlUndefined() - - for s in scope_hierarchy(scope): - for d in s.declarations: - if d.name == var: - return symbol_table.get(s, var) - for c in s.calls(): - if c.fully_qualified_name == '{}.{}'.format(c.parent.fully_qualified_name, var): - return symbol_table.get(c.parent.fully_qualified_name, var) - return WdlUndefined() - return lookup - -class MissingInputsException(Exception): - def __init__(self, missing): - self.__dict__.update(locals()) - -class EngineException(Exception): pass - -class ExecutionContext: - def __init__(self, fqn, call, index, pid, rc, stdout, stderr, cwd): - self.__dict__.update(locals()) - -class ScatterOutput(list): - def __str__(self): - return '[ScatterOutput: {}]'.format(', '.join([str(x) for x in self])) - -def engine_functions(execution_context=None): - def tsv(parameters): - if len(parameters) != 1 or not parameters[0].__class__ in [WdlFileValue, WdlStringValue]: - raise EvalException("tsv(): expecting one String or File parameter") - - def _tsv(abspath): - with open(abspath) as fp: - contents = fp.read().strip('\n') - lines = contents.split('\n') if len(contents) else [] - if len(lines) == 0: - if isinstance(execution_context.type, WdlArrayType): - return WdlArrayValue(execution_context.type.subtype, []) - if isinstance(execution_context.type, WdlMapType): - return WdlMapType(execution_context.type.key_type, execution_context.type.value_type, {}) - - # Determine number of columns, error if they do not match expected type. - rows = [line.split('\t') for line in lines] - columns = set([len(row) for row in rows]) - if len(columns) != 1: - raise EvalException("tsv(): File contains rows with mixed number of columns") - columns = next(iter(columns)) - if isinstance(execution_context.type, WdlArrayType): - if columns != 1: - raise EvalException("tsv(): Array types expect a one-column TSV") - array_elements = [python_to_wdl_value(row[0], execution_context.type.subtype) for row in rows] - return WdlArrayValue(execution_context.type.subtype, array_elements) - # Otherwise, if columns == 1, output an Array, columns == 2 output a Map - raise EvalException("Bad value") - - if isinstance(parameters[0], WdlStringValue): - return _tsv(os.path.join(execution_context.cwd, parameters[0].value)) - if isinstance(parameters[0], WdlFileValue): - return _tsv(parameters[0].value) - - def read_int(parameters): - if len(parameters) != 1 or not parameters[0].__class__ in [WdlFileValue, WdlStringValue]: - raise EvalException("read_int(): expecting one String or File parameter") - def _read_int(abspath): - with open(abspath) as fp: - contents = fp.read().strip('\n') - if len(contents): - try: - return WdlIntegerValue(int(contents.split('\n')[0])) - except ValueError: - raise EvalException("read_int(): First line of file is not an integer: " + abspath) - raise EvalException("read_int(): empty file found: " + abspath) - if isinstance(parameters[0], WdlStringValue): - return _read_int(os.path.join(execution_context.cwd, parameters[0].value)) - if isinstance(parameters[0], WdlFileValue): - return _read_int(parameters[0].value) - - def read_boolean(parameters): - if len(parameters) != 1 or not parameters[0].__class__ in [WdlFileValue, WdlStringValue]: - raise EvalException("read_boolean(): expecting one String or File parameter") - def _read_boolean(abspath): - with open(abspath) as fp: - contents = fp.read().strip('\n') - if len(contents): - line = contents.split('\n')[0].lower() - return WdlBooleanValue(True if line in ['1', 'true'] else False) - raise EvalException("read_boolean(): empty file found: " + abspath) - if isinstance(parameters[0], WdlStringValue): - return _read_boolean(os.path.join(execution_context.cwd, parameters[0].value)) - if isinstance(parameters[0], WdlFileValue): - return _read_boolean(parameters[0].value) - - def read_string(parameters): - if len(parameters) != 1 or not parameters[0].__class__ in [WdlFileValue, WdlStringValue]: - raise EvalException("read_string(): expecting one String or File parameter") - def _read_string(abspath): - with open(abspath) as fp: - contents = fp.read().strip('\n') - if len(contents): - return WdlStringValue(contents.split('\n')[0]) - raise EvalException("read_string(): empty file found: " + abspath) - if isinstance(parameters[0], WdlStringValue): - return _read_string(os.path.join(execution_context.cwd, parameters[0].value)) - if isinstance(parameters[0], WdlFileValue): - return _read_string(parameters[0].value) - - def stdout(parameters): - if len(parameters) != 0: - raise EvalException("stdout() expects zero parameters") - return WdlFileValue(os.path.join(execution_context.cwd, "stdout")) - - def stderr(parameters): - if len(parameters) != 0: - raise EvalException("stderr() expects zero parameters") - return WdlFileValue(os.path.join(execution_context.cwd, "stderr")) - - def strlen(parameters): - return WdlIntegerValue(len(parameters[0].value)) - - def get_function(name): - if name == 'tsv': return tsv - elif name == 'read_int': return read_int - elif name == 'read_boolean': return read_boolean - elif name == 'read_string': return read_string - elif name == 'stdout': return stdout - elif name == 'stderr': return stderr - elif name == 'strlen': return strlen - else: raise EvalException("Function {} not defined".format(name)) - - return get_function - -class LocalProcState: - def __init__(self, pid, cwd, outputs, proc): - self.__dict__.update(locals()) - -class SGEProcState: - def __init__(self, pid, cwd, outputs, retcode, status_file): - self.__dict__.update(locals()) - -class SGERunner: - def __init__(self, min_refresh_seconds=1): - self.__dict__.update(locals()) - self.last_state_refresh = None - self.pid_to_state = {} - - # TODO: this state should probably live in execution table, not in runner - def get_cwd(self, pid): - return self.pid_to_state[pid].cwd - - def run(self, cmd_string, docker, cwd): - if docker: - cmd_string = 'docker run -v {}:/root -w /root {} bash -c "{}"'.format(cwd, docker, cmd_string) - - # TODO: previously these files were having trailing whitespace stripped when written. Need to move that to when they're read - stdout_path = os.path.join(cwd, 'stdout') - stderr_path = os.path.join(cwd, 'stderr') - status_file = os.path.join(cwd, 'status') - - print(colorize(cmd_string, ansi=9)) - with tempfile.NamedTemporaryFile(prefix="command", suffix=".sh", dir=cwd, delete=False,mode='w+t') as fd: - script_name = fd.name - fd.write("#!/bin/sh\n") - fd.write(cmd_string) - fd.write("\necho $? > {}\n".format(status_file)) - - job_name = "job" - - cmd = ["qsub", "-N", job_name, "-V", "-b", "n", "-cwd", "-o", stdout_path, "-e", stderr_path, script_name] - print(colorize("executing qsub command: {}".format(" ".join(cmd)), ansi=9)) - handle = subprocess.Popen(cmd, stdout=subprocess.PIPE, cwd=cwd) - stdout, stderr = handle.communicate() - stdout = stdout.decode("utf-8") - - bjob_id_pattern = re.compile("Your job (\\d+) \\(.* has been submitted.*") - sge_job_id = None - for line in stdout.split("\n"): - m = bjob_id_pattern.match(line) - if m != None: - sge_job_id = m.group(1) - - if sge_job_id == None: - raise Exception("Could not parse output from qsub: %s" % stdout) - - - print(colorize("Started as SGE job {}".format(sge_job_id), ansi=9)) - self.pid_to_state[sge_job_id] = SGEProcState(sge_job_id, cwd, (stdout_path, stderr_path), None, status_file) - return sge_job_id - - def _get_job_states(self): - handle = subprocess.Popen(["qstat", "-xml"], stdout=subprocess.PIPE) - stdout, stderr = handle.communicate() - - doc = ETree.fromstring(stdout) - job_list = doc.findall(".//job_list") - - active_jobs = {} - for job in job_list: - job_id = job.find("JB_job_number").text - - state = job.attrib['state'] - if state == "running": - active_jobs[job_id] = "running" - elif state == "pending": - active_jobs[job_id] = "pending" - else: - active_jobs[job_id] = "queued-unknown" - return active_jobs - - def _update_job_states(self): - unseen = set(self.pid_to_state.keys()) - active_jobs = self._get_job_states() - for job_id, state in active_jobs.items(): - if not job_id in self.pid_to_state: - continue - state = self.pid_to_state[job_id] - state.status = state - unseen.remove(job_id) - - # those jobs which are not in the qstat output have either succeeded or failed - # look on the filesystem for status file which should be there if successful - for job_id in unseen: - state = self.pid_to_state[job_id] - with open(state.status_file, "rt") as fd: - retcode = int(fd.read().strip()) - if retcode == 0: - state.status = "successful" - else: - state.status = "failed" - state.retcode = retcode - - self.last_state_refresh = time.time() - - def get_rc(self, pid): - now = time.time() - if self.last_state_refresh is None or now - self.last_state_refresh > self.min_refresh_seconds: - self._update_job_states() - return self.pid_to_state[pid].retcode - - def get_outputs(self, pid): - return [open(x).read() for x in self.pid_to_state[pid].outputs] - - -class LocalRunner: - def __init__(self): - self.pid_to_state = {} - - # TODO: this state should probably live in execution table, not in runner - def get_cwd(self, pid): - return self.pid_to_state[pid].cwd - - def run(self, cmd_string, docker, cwd): - if docker: - cmd_string = 'docker run -v {}:/root -w /root {} bash -c "{}"'.format(cwd, docker, cmd_string) - - # TODO: previously these files were having trailing whitespace stripped when written. Need to move that to when they're read - stdout_path = os.path.join(cwd, 'stdout') - stderr_path = os.path.join(cwd, 'stderr') - stdout_file = open(stdout_path, 'w') - stderr_file = open(stderr_path, 'w') - - print(colorize(cmd_string, ansi=9)) - proc = subprocess.Popen( - cmd_string, - shell=True, - universal_newlines=True, - stdout=stdout_file, - stderr=stderr_file, - close_fds=True, - cwd=cwd - ) - - pid = proc.pid - print(colorize("Started as pid {}".format(pid), ansi=9)) - self.pid_to_state[pid] = LocalProcState(pid, cwd, (stdout_path, stderr_path), proc) - return pid - - def get_rc(self, pid): - proc = self.pid_to_state[pid].proc - return proc.poll() - - def get_outputs(self, pid): - outputs = self.pid_to_state[pid].outputs - return [open(x).read() for x in outputs] - -class WorkflowExecutor: - def __init__(self, workflow, inputs, runner): - self.dir = os.path.abspath('workflow_{}_{}'.format(workflow.name, str(uuid.uuid4()).split('-')[0])) - self.workflow = workflow - self.inputs = inputs - self.runner = runner - - # Construct the initial symbol table - self.symbol_table = SymbolTable(workflow) - - # Load user inputs into symbol table - for k, v in inputs.items(): - (scope, name) = k.rsplit('.', 1) - entry = self.symbol_table._get_entry(scope, name) - wdl_type = entry[4] - self.symbol_table.set(scope, name, python_to_wdl_value(v, wdl_type)) - - # Return error if any inputs are missing - missing_inputs = self.symbol_table.missing_inputs(workflow) - if missing_inputs: - raise MissingInputsException(missing_inputs) - - # Construct the initial execution table - self.execution_table = ExecutionTable(workflow, self.symbol_table, extra=2) - - print('\n -- symbol table (initial)') - print(self.symbol_table) - print('\n -- execution table (initial)') - print(self.execution_table) - - def _execute_next(self, ): - updates = 0 - - for (fqn, status, index, _, _, _) in self.execution_table: - if status == 'not_started': - call = self.symbol_table.resolve_fqn(fqn) - - skipped = False - upstream_calls = call.upstream() - print ("fqn {} upstream {}".format(fqn, upstream_calls)) - for upstream in upstream_calls: - upstream_call_status = self.execution_table.aggregate_status(upstream) - print ("upstream {} status {}".format(upstream, upstream_call_status)) - if upstream_call_status in ['failed', 'error', 'skipped', 'started']: - self.execution_table.set_status(fqn, None, 'skipped') - if upstream_call_status != 'successful': - skipped = True - if skipped: continue - - # Build up parameter list for this task - parameters = {} - for entry in self.symbol_table.get_inputs(fqn): - (scope, name, _, value, type, io) = entry - scatter_node = call.get_scatter_parent() - scatter_vars = [] if scatter_node is None else [scatter_node.item] - value = self.symbol_table.eval_entry(entry, scatter_vars, index) - parameters[name] = value - - print('\n -- Running task: {}'.format(colorize(call.name, ansi=26))) - job_cwd = os.path.join(self.dir, fqn, str(index) if index is not None else '') - os.makedirs(job_cwd) - cmd_string = call.task.command.instantiate(parameters, job_cwd) - docker = eval(call.task.runtime['docker'].ast, lookup_function(self.symbol_table, call)).value if 'docker' in call.task.runtime else None - pid = self.runner.run(cmd_string, docker=docker, cwd=job_cwd) - self.execution_table.set_status(fqn, index, "started") - self.execution_table.set_column(fqn, index, 4, pid) - updates += 1 - - return updates - - def _post_process_next(self): - updates = 0 - - for (fqn, status, index, _, pid, _) in self.execution_table: - if status == "started": - rc = self.runner.get_rc(pid) - if rc == None: # still running - continue - - stdout, stderr = self.runner.get_outputs(pid) - job_cwd = self.runner.get_cwd(pid) - call = self.symbol_table.resolve_fqn(fqn) - execution_context = ExecutionContext(fqn, call, index, pid, rc, stdout, stderr, job_cwd) - self.post_process(execution_context) - updates += 1 - - return updates - - def execute(self, max_sleep_secs=30): - print('\n -- running workflow: {}'.format(self.workflow.name)) - print('\n -- job dir: {}'.format(self.dir)) - os.mkdir(self.dir) - - sleep_secs = 1 - while not self.execution_table.is_finished(): - updates = 0 - - updates += self._execute_next() - updates += self._post_process_next() - print('\n -- symbols') - print(self.symbol_table) - print('\n -- exec table') - print(self.execution_table) - - if updates == 0: - print("\n {} sleeping for {} seconds\n".format(time.asctime(), sleep_secs)) - time.sleep(sleep_secs) - # backoff polling frequency if nothing has changed - sleep_secs = min(max_sleep_secs, sleep_secs * 2) - else: - sleep_secs = 1 - - def post_process(self, execution_context): - status = 'successful' if execution_context.rc == 0 else 'failed' - self.execution_table.set_status(execution_context.fqn, execution_context.index, status) - self.execution_table.set_column(execution_context.fqn, execution_context.index, 4, execution_context.pid) - self.execution_table.set_column(execution_context.fqn, execution_context.index, 5, execution_context.rc) - if status == 'successful': - for output in execution_context.call.task.outputs: - execution_context.type = output.type - value = eval(output.expression, functions=engine_functions(execution_context)) - if isinstance(value.type, WdlFileType): - value = WdlFileValue(os.path.join(execution_context.cwd, value.value)) - self.symbol_table.set(execution_context.call, output.name, value, execution_context.index, io='output') - -class ExecutionTable(list): - def __init__(self, root, symbol_table, extra=0): - self.__dict__.update(locals()) - self.populate(self.root) - self.terminal_states = ['successful', 'failed', 'error', 'skipped'] - def is_finished(self): - return all(map(lambda x: x in self.terminal_states, [entry[1] for entry in self])) - def populate(self, node=None): - if isinstance(node, Call): - index = None - scatter = node.get_scatter_parent() - if scatter: - scattered_item = self.symbol_table.get(scatter, scatter.item) - if isinstance(scattered_item, WdlArrayValue): - for call_output in node.task.outputs: - self.symbol_table.set(node, call_output.name, ScatterOutput([WdlUndefined()] * len(scattered_item.value))) - for index in range(len(scattered_item.value)): - self.add(node.fully_qualified_name, index) - else: - self.add(node.fully_qualified_name, None) - if isinstance(node, Workflow) or isinstance(node, Scatter): - for element in node.body: - self.populate(element) - def contains(self, fqn, index): - return any(map(lambda x: x[0] == fqn and x[2] == index, self)) - def add(self, fqn, index): - if not self.contains(fqn, index): - row = [fqn, 'not_started', index, None] - row.extend([None]*self.extra) - self.append(row) - def set_status(self, fqn, index, status): - for entry in self: - if entry[0] == fqn and entry[2] == index: - entry[1] = status - def set_column(self, fqn, index, column, value): - for entry in self: - if entry[0] == fqn and entry[2] == index: - entry[column] = value - def get(self, fqn): - for entry in self: - if entry[0] == fqn: - return entry - def aggregate_status(self, call_name): - statuses = [] - for entry in self: - if entry[0].endswith('.{}'.format(call_name)): - statuses.append(entry[1]) - # TODO: clean this up? - if 'failed' in statuses: return 'failed' - elif 'error' in statuses: return 'error' - elif 'skipped' in statuses: return 'skipped' - elif 'not_started' in statuses: return 'not_started' - elif 'started' in statuses: return 'started' - return 'successful' - def __str__(self): - return md_table(self, ['Name', 'Status', 'Index', 'Iter', 'PID', 'rc']) - -class SymbolTable(list): - def __init__(self, root): - self.id = 0 - self.root = root - def populate(node): - if isinstance(node, Scatter): - (var, type, flatten_count) = node.get_flatten_count() - self.append([node.fully_qualified_name, node.item, None, '%flatten:{}:{}'.format(flatten_count, var), type, 'input']) - if isinstance(node, Scope): - for decl in node.declarations: - if decl.expression.ast is None: - value = WdlUndefined() - else: - value = eval(decl.expression.ast, lookup_function(self, node), engine_functions()) - self.append([node.fully_qualified_name, decl.name, None, value, decl.type, 'input']) - for child in node.body: - populate(child) - if isinstance(node, Call): - for task_input in node.task.inputs: - value = '%expr:' + expr_str(node.inputs[task_input.name].ast) if task_input.name in node.inputs else WdlUndefined() - self.append([node.fully_qualified_name, task_input.name, None, value, task_input.type, 'input']) - for task_output in node.task.outputs: - value = '%expr:' + expr_str(node.outputs[task_output.name].ast) if task_output.name in node.outputs else WdlUndefined() - # TODO: Instead of constructing type like this, do something like parse_type('Array[{}]'.format(...)) ??? - type = WdlArrayType(task_output.type) if len(re.findall(r'\._s\d+', node.fully_qualified_name)) > 0 else task_output.type - self.append([node.fully_qualified_name, task_output.name, None, value, type, 'output']) - populate(root) - - def set(self, scope, name, value, index=None, io='all'): - entry = self._get_entry(scope, name, io) - if index is not None: - entry[3][index] = value - - # Once the ScatterOutput is fully populated, replace it with a WdlArrayValue - # TODO: this is probably not very scalable - if isinstance(entry[3], ScatterOutput): - if all(map(lambda x: not isinstance(x, WdlUndefined), entry[3])): - entry[3] = WdlArrayValue(entry[3][0].type, [x for x in entry[3]]) - else: - entry[3] = value - - # Get the evaluated value of a parameter - def get(self, scope, name): - if isinstance(scope, str): scope = self.resolve_fqn(scope) - - call_fqn = '{}.{}'.format(scope.fully_qualified_name, name) - call = self.resolve_fqn(call_fqn) - if isinstance(call, Call): - return self._get_call_as_object(call_fqn) - - entry = self._get_entry(scope, name) - if entry is not None: - return self.eval_entry(entry) - return WdlUndefined() - - # Traverse scope hierarchy starting from 'scope' until 'name' is found. - # Returns the scope object where 'name' is defined - def resolve_name(self, scope, name): - if isinstance(scope, str): scope = self.resolve_fqn(scope) - for node in scope_hierarchy(scope): - for entry in self._get_entries(node): - if entry[1] == name: - return self.resolve_fqn(entry[0]) - return None - - def get_inputs(self, scope): - return [entry for entry in self._get_entries(scope, io='input')] - - def missing_inputs(self, workflow): - missing = {} - for entry in [entry for entry in self if entry[5] == 'input']: - value = entry[3] - scope = workflow.get(entry[0]) - optional = False - if isinstance(scope, Call): - inputs = {i.name: i for i in scope.task.inputs} - if entry[1] in inputs: - optional = inputs[entry[1]].is_optional() - if isinstance(value, WdlUndefined) and not optional: - missing['{}.{}'.format(entry[0], entry[1])] = str(entry[4]) - return missing - - def is_scatter_var(self, call, var): - if isinstance(call, str): call = self.resolve_fqn(call) - scatter_node = call.get_scatter_parent() - if scatter_node is not None and scatter_node.item == var: - return True - return False - - def _get_entry(self, scope, name, io='all'): - if isinstance(scope, str): scope = self.resolve_fqn(scope) - if io not in ['all', 'input', 'output']: raise Exception('bad value') - lookup_entry = None - for entry in self: - if io != 'all' and io != entry[5]: - continue - if entry[0] == scope.fully_qualified_name and entry[1] == name: - if (lookup_entry is not None and lookup_entry[2] < entry[2]) or lookup_entry is None: - lookup_entry = entry - return lookup_entry - - def _get_entries(self, scope, io='all'): - if isinstance(scope, str): scope = self.resolve_fqn(scope) - if io not in ['all', 'input', 'output']: raise Exception('bad value') - entries = {} - for entry in self: - (entry_scope, entry_name, entry_iter, entry_io) = (entry[0], entry[1], entry[2], entry[5]) - if io != 'all' and io != entry_io: - continue - if entry_scope == scope.fully_qualified_name: - key = '{}_{}'.format(entry_name, entry_io) - if (key in entries and entries[key][2] < entry_iter) or key not in entries: - entries[key] = entry - return list(entries.values()) - - def _get_call_as_object(self, scope): - entries = self._get_entries(scope, io='output') - values = {e[1]: self.eval_entry(e) for e in entries} - for k, v in values.items(): - if isinstance(v, WdlUndefined): return WdlUndefined() - return WdlObject(values) - - def eval_entry(self, entry, scatter_vars=[], index=None): - value = entry[3] - scope = self.resolve_fqn(entry[0]) - if isinstance(value, str) and value.startswith('%expr:'): - expression = parse_expr(value.replace('%expr:', '')) - return eval(expression.ast, lookup_function(self, scope, scatter_vars, index)) - if isinstance(value, str) and value.startswith('%flatten:'): - match = re.match('^%flatten:(\d+):(.*)$', value) - count = int(match.group(1)) - expression = parse_expr(match.group(2)) - value = eval(expression.ast, lookup_function(self, scope, scatter_vars, index)) - if isinstance(value, WdlArrayValue): - for i in range(count): - value = value.flatten() - return value - return WdlUndefined() - if isinstance(value, list): - for item in value: - if isinstance(item, WdlUndefined): - return WdlUndefined() - return value - - def resolve_fqn(self, fqn): - def resolve_fqn_r(node): - if node.fully_qualified_name == fqn: return node - resolved = None - for child in node.body: - resolved = resolve_fqn_r(child) - if resolved is not None: break - return resolved - return resolve_fqn_r(self.root) - - def __str__(self): - return md_table(self, ['Scope', 'Name', 'Iter', 'Value', 'Type', 'I/O']) - -class CommandPartValue: - def __init__(self, name, type, value): - self.__dict__.update(locals()) - def __str__(self): - return 'CommandPartValue: {} {} = {}'.format(self.type, self.name, self.value) - -def run(wdl_file, run_service_name="local", inputs={}): - with open(wdl_file) as fp: - wdl_document = parse_document(fp.read(), wdl_file) - - workflow = wdl_document.workflows[0] - runner = {"local": LocalRunner, "sge": SGERunner}[run_service_name] - wf_exec = WorkflowExecutor(workflow, inputs, runner()) - wf_exec.execute() - print('\nWorkflow finished. Workflow directory is:') - print(wf_exec.dir) diff --git a/python/wdl/main.py b/python/wdl/main.py deleted file mode 100644 index 4f286c7..0000000 --- a/python/wdl/main.py +++ /dev/null @@ -1,80 +0,0 @@ -import wdl.engine -import wdl.parser -import argparse -import json -import sys -import os -import pkg_resources - -def cli(): - command_help = { - "run": "Run you a WDL", - "parse": "Parse a WDL file, print parse tree", - "expr": "Expression testing" - } - - parser = argparse.ArgumentParser(description='Workflow Description Language (WDL)') - parser.add_argument( - '--version', action='version', version=str(pkg_resources.get_distribution('wdl')) - ) - parser.add_argument( - '--debug', required=False, action='store_true', help='Open the floodgates' - ) - parser.add_argument( - '--no-color', default=False, required=False, action='store_true', help="Don't colorize output" - ) - - subparsers = parser.add_subparsers(help='WDL Actions', dest='action') - subparsers.required = True - commands = {} - commands['run'] = subparsers.add_parser( - 'run', description=command_help['run'], help=command_help['run'] - ) - commands['run'].add_argument( - 'wdl_file', help='Path to WDL File' - ) - commands['run'].add_argument( - '--inputs', help='Path to JSON file to define inputs' - ) - commands['run'].add_argument( - '--sge', action="store_true", help='Use SGE to execute tasks' - ) - commands['parse'] = subparsers.add_parser( - 'parse', description=command_help['parse'], help=command_help['parse'] - ) - commands['parse'].add_argument( - 'wdl_file', help='Path to WDL File' - ) - - cli = parser.parse_args() - - if cli.action == 'run': - sys.exit('Currently unsupported') - - inputs = {} - run_service_name = "local" - - if cli.sge: - run_service_name = "sge" - - if cli.inputs: - with open(cli.inputs) as fp: - inputs = json.loads(fp.read()) - - try: - wdl.engine.run(cli.wdl_file, run_service_name, inputs) - except wdl.engine.MissingInputsException as error: - print("Your workflow cannot be run because it is missing some inputs!") - if cli.inputs: - print("Add the following keys to your {} file and try again:".format(cli.inputs)) - else: - print("Use the template below to specify the inputs. Keep the keys as-is and change the values to match the type specified") - print("Then, pass this file in as the --inputs option:\n") - print(json.dumps(error.missing, indent=4)) - if cli.action == 'parse': - with open(cli.wdl_file) as fp: - ast = wdl.parser.parse(fp.read(), os.path.basename(cli.wdl_file)).ast() - print(ast.dumps(indent=2)) - -if __name__ == '__main__': - cli() diff --git a/python/wdl/parser.py b/python/wdl/parser.py deleted file mode 100644 index 57b1447..0000000 --- a/python/wdl/parser.py +++ /dev/null @@ -1,4080 +0,0 @@ - -# This file was generated by Hermes Parser Generator on Mon Nov 23 15:31:20 2015 -# -# Hermes command: hermes generate ../grammar.hgr --name=wdl --directory=wdl --header -# Run from: .. (relative to this file) -# Hermes version: hermes-parser 2.0rc4 -# -# !!! 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 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.listSeparator = 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 ast(self): - if self.list == True: - r = AstList() - if len(self.children) == 0: - return r - end = max(0, len(self.children) - 1) - for child in self.children[:end]: - if isinstance(child, Terminal) and self.listSeparator is not None and child.id == self.listSeparator.id: - continue - r.append(child.ast()) - r.extend(self.children[end].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 isinstance(self.children[0], ParseTree) and \ - self.children[0].isNud and \ - not self.children[0].isPrefix and \ - not self.isExprNud and \ - not self.isInfix: - 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)]) + '^' - )) -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_end', - 1: 'scatter', - 2: 'type_e', - 3: 'integer', - 4: 'dot', - 5: 'raw_command', - 6: 'type', - 7: 'dash', - 8: 'cmd_attr_hint', - 9: 'lparen', - 10: 'not', - 11: 'asterisk', - 12: 'gt', - 13: 'parameter_meta', - 14: 'double_equal', - 15: 'e', - 16: 'gteq', - 17: 'boolean', - 18: 'float', - 19: 'slash', - 20: 'rsquare', - 21: 'rparen', - 22: 'colon', - 23: 'lsquare', - 24: 'fqn', - 25: 'task', - 26: 'as', - 27: 'identifier', - 28: 'comma', - 29: 'string', - 30: 'cmd_param_start', - 31: 'if', - 32: 'lt', - 33: 'double_pipe', - 34: 'output', - 35: 'cmd_part', - 36: 'runtime', - 37: 'double_ampersand', - 38: 'equal', - 39: 'lteq', - 40: 'rbrace', - 41: 'qmark', - 42: 'percent', - 43: 'not_equal', - 44: 'object', - 45: 'in', - 46: 'plus', - 47: 'while', - 48: 'raw_cmd_start', - 49: 'meta', - 50: 'workflow', - 51: 'input', - 52: 'lbrace', - 53: 'call', - 54: 'import', - 55: 'cmd_param_end', - 'raw_cmd_end': 0, - 'scatter': 1, - 'type_e': 2, - 'integer': 3, - 'dot': 4, - 'raw_command': 5, - 'type': 6, - 'dash': 7, - 'cmd_attr_hint': 8, - 'lparen': 9, - 'not': 10, - 'asterisk': 11, - 'gt': 12, - 'parameter_meta': 13, - 'double_equal': 14, - 'e': 15, - 'gteq': 16, - 'boolean': 17, - 'float': 18, - 'slash': 19, - 'rsquare': 20, - 'rparen': 21, - 'colon': 22, - 'lsquare': 23, - 'fqn': 24, - 'task': 25, - 'as': 26, - 'identifier': 27, - 'comma': 28, - 'string': 29, - 'cmd_param_start': 30, - 'if': 31, - 'lt': 32, - 'double_pipe': 33, - 'output': 34, - 'cmd_part': 35, - 'runtime': 36, - 'double_ampersand': 37, - 'equal': 38, - 'lteq': 39, - 'rbrace': 40, - 'qmark': 41, - 'percent': 42, - 'not_equal': 43, - 'object': 44, - 'in': 45, - 'plus': 46, - 'while': 47, - 'raw_cmd_start': 48, - 'meta': 49, - 'workflow': 50, - 'input': 51, - 'lbrace': 52, - 'call': 53, - 'import': 54, - 'cmd_param_end': 55, -} -# table[nonterminal][terminal] = rule -table = [ - [-1, -1, -1, -1, -1, 20, -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, 20, -1, 20, -1, -1, -1, 21, -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, 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, 3, -1, -1, -1, 0, -1], - [-1, -1, -1, 65, -1, -1, -1, 65, -1, 65, 65, -1, -1, -1, -1, 65, -1, 65, 65, -1, -1, -1, -1, 65, -1, -1, -1, 65, -1, 65, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 65, -1, 65, -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, 10, -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, 35, -1, -1, -1, -1, 34, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], - [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -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, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], - [-1, -1, 16, -1, -1, 17, 16, -1, -1, -1, -1, -1, -1, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 17, -1, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 17, -1, 17, -1, -1, -1, -1], - [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 51, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 54, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], - [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 104, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], - [-1, -1, 47, -1, -1, -1, 47, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], - [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 63, -1, -1, -1, -1, 64, -1, -1, -1, -1, -1, -1, -1, -1, -1], - [-1, -1, 42, -1, -1, -1, 42, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 45, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], - [-1, -1, 61, -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, 62, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], - [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -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, 88, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 89, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 89, -1, -1, -1, -1], - [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 56, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], - [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 106, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], - [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], - [-1, 78, 78, -1, -1, -1, 78, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 77, -1, -1, -1, -1, 78, -1, -1, 78, -1, -1, -1, -1, -1, 78, -1, -1, -1, -1, -1, -1, 78, -1, -1, -1, -1, 78, 78, -1, -1], - [-1, -1, -1, 39, -1, -1, -1, 39, 36, 39, 39, -1, -1, -1, -1, 39, -1, 39, 39, -1, -1, -1, -1, 39, -1, -1, -1, 39, -1, 39, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 39, -1, 39, -1, -1, -1, -1, -1, 39, -1, -1, -1], - [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 85, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 82, -1, -1, -1, -1], - [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 93, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], - [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 95, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 96, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], - [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 81, -1, -1], - [-1, -1, -1, 129, -1, -1, -1, 129, -1, 129, 129, -1, -1, -1, -1, 129, -1, 129, 129, -1, 132, 132, -1, 129, -1, -1, -1, 129, -1, 129, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 129, -1, 129, -1, -1, -1, -1, -1, 129, -1, -1, -1], - [-1, -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, -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, -1, -1], - [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -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, 67, 67, -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, 67, -1, -1, 67, -1, -1, -1, -1, -1, 68, -1, -1, -1, -1, -1, -1, 67, -1, -1, -1, -1, -1, 67, -1, -1], - [-1, 60, 60, -1, -1, 60, 60, -1, -1, -1, -1, -1, -1, 60, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 60, -1, -1, 60, -1, 60, -1, 59, -1, 60, -1, -1, -1, -1, -1, -1, 60, -1, 60, -1, 60, -1, 60, -1, -1], - [-1, -1, -1, 38, -1, -1, -1, 38, 37, 38, 38, -1, -1, -1, -1, 38, -1, 38, 38, -1, -1, -1, -1, 38, -1, -1, -1, 38, -1, 38, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 38, -1, 38, -1, -1, -1, -1, -1, 38, -1, -1, -1], - [-1, -1, -1, -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, 57, -1, -1, -1, -1, 57, -1, -1, -1, -1, -1, -1, -1, -1, -1], - [-1, 66, 66, -1, -1, -1, 66, -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, 66, -1, -1, -1, -1, -1, 69, -1, -1, -1, -1, -1, -1, 66, -1, -1, -1, -1, -1, 66, -1, -1], - [-1, 105, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], - [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 94, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 97, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], - [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 84, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 83, -1, -1, -1, -1], - [-1, 80, 80, -1, -1, -1, 80, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 80, -1, -1, 80, -1, -1, -1, -1, -1, 80, -1, -1, -1, -1, -1, -1, 80, -1, -1, -1, -1, 79, 80, -1, -1], - [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 109, -1, -1, -1, -1, -1, -1, -1, 108, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], - [31, -1, -1, -1, -1, -1, -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, 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, 136, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 139, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], - [-1, -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, 8, -1, -1, -1, 8, -1], - [-1, 75, 72, -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, 74, -1, -1, 76, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 73, -1, -1, -1, -1, -1, 71, -1, -1], - [-1, -1, -1, -1, 102, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], - [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 12, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 12, -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, 103, -1, -1, -1, -1, -1, -1, -1, -1], - [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 87, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 90, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 90, -1, -1, -1, -1], - [-1, -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, -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, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 46, -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, 29, -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, 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, 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, 52, -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, 137, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 138, -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, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], - [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 91, -1, -1, -1, -1], - [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 13, -1], - [-1, -1, -1, -1, -1, -1, -1, -1, 41, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], - [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 131, 131, -1, -1, -1, -1, -1, -1, 130, -1, -1, -1, -1, -1, -1, -1, -1, -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, 27, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 25, -1, 26, -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, 50, -1, -1, -1, -1, -1, -1], - [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -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, 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, 101, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], - [-1, -1, -1, -1, 99, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 100, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 100, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], - [-1, -1, 107, -1, -1, -1, 107, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 110, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], - [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 143, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 144, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], - [-1, -1, -1, 142, -1, -1, -1, 142, -1, 142, 142, -1, -1, -1, -1, 142, -1, 142, 142, -1, -1, -1, -1, 142, -1, -1, -1, 142, -1, 142, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 145, -1, -1, -1, 142, -1, 142, -1, -1, -1, -1, -1, 142, -1, -1, -1], - [-1, -1, 15, -1, -1, 18, 15, -1, -1, -1, -1, -1, -1, 18, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 18, -1, 18, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 18, -1, 18, -1, -1, -1, -1], - [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 92, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], - [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 86, -1, -1, -1], - [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 14, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], - [-1, -1, 43, -1, -1, -1, 43, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 44, -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, 19, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 19, -1, 19, -1, -1, -1, 22, -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, 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, 98, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], -] -nonterminal_first = { - 56: [49, 13, 5, -1, 34, 36], - 57: [54, -1], - 58: [23, 10, 9, 27, 44, 3, 46, 29, 15, 17, 52, 18, 7], - 59: [50, 25], - 60: [30, 35], - 61: [36], - 62: [6, -1, 2], - 63: [-1, 27], - 64: [31], - 65: [6, 2], - 66: [46, 41], - 67: [6, -1, 2], - 68: [6, 2], - 69: [38], - 70: [50], - 71: [-1, 28], - 72: [27], - 73: [27], - 74: [23, 10, 9, 27, 44, 3, 46, 29, 15, 17, 52, 18, 7], - 75: [26, -1], - 76: [8, -1], - 77: [51, -1], - 78: [26], - 79: [-1, 28], - 80: [53], - 81: [23, 27, 3, 29, 7, 10, -1, 9, 44, 46, 15, 17, 52, 18], - 82: [50, 25, -1], - 83: [13], - 84: [-1, 2, 1, 47, 31, 53, 34, 6], - 85: [38, -1], - 86: [8, -1], - 87: [41, 46, -1], - 88: [-1, 2, 1, 47, 31, 53, 34, 6], - 89: [1], - 90: [24, -1], - 91: [51, -1], - 92: [52, -1], - 93: [-1, 28], - 94: [-1, 30, 35], - 95: [-1, 27], - 96: [54, 50, 25, -1], - 97: [47, 53, 2, 1, 34, 6, 31], - 98: [4], - 99: [26, -1], - 100: [47], - 101: [-1, 27], - 102: [50, 25, -1], - 103: [34], - 104: [-1, 30, 35], - 105: [54, -1], - 106: [-1, 27], - 107: [-1, 28], - 108: [5], - 109: [51], - 110: [54], - 111: [8], - 112: [-1, 28], - 113: [49, 13, 5, 36, 34], - 114: [49], - 115: [25], - 116: [30], - 117: [24], - 118: [4, -1], - 119: [6, -1, 2], - 120: [-1, 28], - 121: [23, 10, -1, 9, 27, 44, 3, 46, 29, 15, 17, 52, 18, 7], - 122: [6, -1, 2], - 123: [27], - 124: [52], - 125: [26], - 126: [6, -1, 2], - 127: [49, 13, 5, -1, 34, 36], - 128: [52], - 129: [6, 2], - 130: [34], -} -nonterminal_follow = { - 56: [40], - 57: [50, 25, -1], - 58: [40, 28], - 59: [50, 25, -1], - 60: [0, 35, 30], - 61: [40, 13, 49, 5, 34, 36], - 62: [49, 51, 13, 5, 34, 36], - 63: [40], - 64: [40, 2, 1, 47, 31, 53, 34, 6], - 65: [6, 40, 2], - 66: [27], - 67: [40], - 68: [40, 2, 1, 47, 13, 31, 49, 51, 5, 53, 34, 6, 36], - 69: [2, 1, 31, 5, 34, 6, 36, 40, 47, 13, 49, 51, 53], - 70: [50, 25, -1], - 71: [51, 40], - 72: [40, 27], - 73: [40, 28], - 74: [2, 3, 1, 5, 6, 7, 8, 10, 9, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 27, 28, 29, 32, 31, 33, 34, 36, 37, 39, 40, 44, 42, 43, 46, 47, 51, 49, 52, 53, 55], - 75: [40, 2, 1, 47, 31, 52, 53, 34, 6], - 76: [23, 10, 9, 27, 44, 3, 46, 29, 15, 17, 52, 18, 7], - 77: [40], - 78: [40, 2, 1, 47, 31, 52, 53, 34, 6], - 79: [40], - 80: [40, 2, 1, 47, 31, 53, 34, 6], - 81: [20, 21], - 82: [-1], - 83: [40, 13, 49, 5, 34, 36], - 84: [40], - 85: [2, 1, 31, 5, 34, 6, 36, 40, 47, 13, 49, 51, 53], - 86: [23, 10, 9, 27, 44, 3, 46, 29, 15, 17, 52, 18, 7], - 87: [27], - 88: [40], - 89: [40, 2, 1, 47, 31, 53, 34, 6], - 90: [40], - 91: [40], - 92: [40, 2, 1, 47, 31, 53, 34, 6], - 93: [20], - 94: [0], - 95: [40], - 96: [-1], - 97: [6, 40, 2, 1, 53, 34, 47, 31], - 98: [40, 28], - 99: [54, 50, 25, -1], - 100: [40, 2, 1, 47, 31, 53, 34, 6], - 101: [51, 40], - 102: [-1], - 103: [40, 13, 49, 5, 34, 36], - 104: [0], - 105: [50, 25, -1], - 106: [40], - 107: [40], - 108: [40, 13, 49, 5, 34, 36], - 109: [51, 40], - 110: [54, 50, 25, -1], - 111: [8, 23, 10, 9, 27, 44, 3, 46, 29, 15, 17, 52, 18, 7], - 112: [20, 21], - 113: [49, 13, 5, 40, 34, 36], - 114: [40, 13, 49, 5, 34, 36], - 115: [50, 25, -1], - 116: [0, 35, 30], - 117: [40, 28], - 118: [40, 28], - 119: [20], - 120: [40], - 121: [40], - 122: [49, 51, 13, 5, 34, 36], - 123: [51, 40, 28], - 124: [40, 2, 1, 47, 31, 53, 34, 6], - 125: [54, 50, 25, -1], - 126: [40], - 127: [40], - 128: [40, 13, 49, 5, 34, 36], - 129: [28, 20, 46, 41, 27], - 130: [40, 2, 1, 47, 31, 53, 34, 6], -} -rule_first = { - 0: [54], - 1: [54], - 2: [-1], - 3: [-1], - 4: [50, 25], - 5: [50, 25], - 6: [-1], - 7: [-1], - 8: [54, 50, -1, 25], - 9: [50], - 10: [25], - 11: [26], - 12: [-1], - 13: [54], - 14: [26], - 15: [6, 2], - 16: [6, 2], - 17: [-1], - 18: [-1], - 19: [49, 36, 5, 13, 34], - 20: [49, 36, 5, 13, 34], - 21: [-1], - 22: [-1], - 23: [25], - 24: [5], - 25: [34], - 26: [36], - 27: [13], - 28: [49], - 29: [35, 30], - 30: [35, 30], - 31: [-1], - 32: [-1], - 33: [5], - 34: [35], - 35: [30], - 36: [8], - 37: [8], - 38: [-1], - 39: [-1], - 40: [30], - 41: [8], - 42: [6, 2], - 43: [6, 2], - 44: [-1], - 45: [-1], - 46: [34], - 47: [6, 2], - 48: [36], - 49: [13], - 50: [49], - 51: [27], - 52: [27], - 53: [-1], - 54: [-1], - 55: [52], - 56: [27], - 57: [46, 41], - 58: [-1], - 59: [38], - 60: [-1], - 61: [6, 2], - 62: [38], - 63: [41], - 64: [46], - 65: [23, 10, 9, 27, 44, 3, 46, 29, 15, 17, 52, 18, 7], - 66: [6, 1, 2, 53, 34, 47, 31], - 67: [6, 1, 2, 53, 34, 47, 31], - 68: [-1], - 69: [-1], - 70: [50], - 71: [53], - 72: [6, 2], - 73: [47], - 74: [31], - 75: [1], - 76: [34], - 77: [26], - 78: [-1], - 79: [52], - 80: [-1], - 81: [53], - 82: [51], - 83: [51], - 84: [-1], - 85: [-1], - 86: [52], - 87: [27], - 88: [28], - 89: [-1], - 90: [-1], - 91: [51], - 92: [27], - 93: [26], - 94: [24], - 95: [28], - 96: [-1], - 97: [-1], - 98: [34], - 99: [4], - 100: [-1], - 101: [24], - 102: [4], - 103: [47], - 104: [31], - 105: [1], - 106: [27], - 107: [6, 2], - 108: [28], - 109: [-1], - 110: [-1], - 111: [6], - 112: [6], - 113: [23, 10, 9, 27, 44, 3, 46, 29, 15, 17, 52, 18, 7], - 114: [23, 10, 9, 27, 44, 3, 46, 29, 15, 17, 52, 18, 7], - 115: [23, 10, 9, 27, 44, 3, 46, 29, 15, 17, 52, 18, 7], - 116: [23, 10, 9, 27, 44, 3, 46, 29, 15, 17, 52, 18, 7], - 117: [23, 10, 9, 27, 44, 3, 46, 29, 15, 17, 52, 18, 7], - 118: [23, 10, 9, 27, 44, 3, 46, 29, 15, 17, 52, 18, 7], - 119: [23, 10, 9, 27, 44, 3, 46, 29, 15, 17, 52, 18, 7], - 120: [23, 10, 9, 27, 44, 3, 46, 29, 15, 17, 52, 18, 7], - 121: [23, 10, 9, 27, 44, 3, 46, 29, 15, 17, 52, 18, 7], - 122: [23, 10, 9, 27, 44, 3, 46, 29, 15, 17, 52, 18, 7], - 123: [23, 10, 9, 27, 44, 3, 46, 29, 15, 17, 52, 18, 7], - 124: [23, 10, 9, 27, 44, 3, 46, 29, 15, 17, 52, 18, 7], - 125: [23, 10, 9, 27, 44, 3, 46, 29, 15, 17, 52, 18, 7], - 126: [10], - 127: [46], - 128: [7], - 129: [23, 10, 9, 27, 44, 3, 46, 29, 15, 17, 52, 18, 7], - 130: [28], - 131: [-1], - 132: [-1], - 133: [27], - 134: [27], - 135: [27], - 136: [27], - 137: [28], - 138: [-1], - 139: [-1], - 140: [44], - 141: [23], - 142: [23, 10, 9, 27, 44, 3, 46, 29, 15, 17, 52, 18, 7], - 143: [28], - 144: [-1], - 145: [-1], - 146: [52], - 147: [9], - 148: [29], - 149: [27], - 150: [17], - 151: [3], - 152: [18], -} -nonterminal_rules = { - 56: [ - "$_gen8 = $sections $_gen8", - "$_gen8 = :_empty", - ], - 57: [ - "$_gen0 = $import $_gen1", - "$_gen0 = :_empty", - ], - 58: [ - "$map_kv = $e :colon $e -> MapLiteralKv( key=$0, value=$2 )", - ], - 59: [ - "$workflow_or_task = $workflow", - "$workflow_or_task = $task", - ], - 60: [ - "$command_part = :cmd_part", - "$command_part = $cmd_param", - ], - 61: [ - "$runtime = :runtime $map -> Runtime( map=$1 )", - ], - 62: [ - "$_gen6 = $declaration $_gen6", - "$_gen6 = :_empty", - ], - 63: [ - "$_gen15 = $kv $_gen16", - "$_gen15 = :_empty", - ], - 64: [ - "$if_stmt = :if :lparen $e :rparen :lbrace $_gen19 :rbrace -> If( expression=$2, body=$5 )", - ], - 65: [ - "$output_kv = $type_e :identifier :equal $e -> Output( type=$0, var=$1, expression=$3 )", - ], - 66: [ - "$postfix_quantifier = :qmark", - "$postfix_quantifier = :plus", - ], - 67: [ - "$_gen13 = $output_kv $_gen14", - "$_gen13 = :_empty", - ], - 68: [ - "$declaration = $type_e $_gen17 :identifier $_gen18 -> Declaration( type=$0, postfix=$1, name=$2, expression=$3 )", - ], - 69: [ - "$setter = :equal $e -> $1", - ], - 70: [ - "$workflow = :workflow :identifier :lbrace $_gen19 :rbrace -> Workflow( name=$1, body=$3 )", - ], - 71: [ - "$_gen26 = :comma $mapping $_gen26", - "$_gen26 = :_empty", - ], - 72: [ - "$kv = :identifier :colon $e -> RuntimeAttribute( key=$0, value=$2 )", - ], - 73: [ - "$object_kv = :identifier :colon $e -> ObjectKV( key=$0, value=$2 )", - ], - 74: [ - "$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 $_gen32 :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 $_gen34 :rbrace -> ObjectLiteral( map=$2 )", - "$e = :lsquare $_gen32 :rsquare -> ArrayLiteral( values=$1 )", - "$e = :lbrace $_gen36 :rbrace -> MapLiteral( map=$1 )", - "$e = :lparen $e :rparen -> $1", - "$e = :string", - "$e = :identifier", - "$e = :boolean", - "$e = :integer", - "$e = :float", - ], - 75: [ - "$_gen21 = $alias", - "$_gen21 = :_empty", - ], - 76: [ - "$_gen11 = $cmd_param_kv $_gen12", - "$_gen11 = :_empty", - ], - 77: [ - "$_gen23 = $call_input $_gen24", - "$_gen23 = :_empty", - ], - 78: [ - "$alias = :as :identifier -> $1", - ], - 79: [ - "$_gen28 = :comma $wf_output $_gen28", - "$_gen28 = :_empty", - ], - 80: [ - "$call = :call :fqn $_gen21 $_gen22 -> Call( task=$1, alias=$2, body=$3 )", - ], - 81: [ - "$_gen32 = $e $_gen33", - "$_gen32 = :_empty", - ], - 82: [ - "$_gen2 = $workflow_or_task $_gen3", - "$_gen2 = :_empty", - ], - 83: [ - "$parameter_meta = :parameter_meta $map -> ParameterMeta( map=$1 )", - ], - 84: [ - "$_gen20 = $wf_body_element $_gen20", - "$_gen20 = :_empty", - ], - 85: [ - "$_gen18 = $setter", - "$_gen18 = :_empty", - ], - 86: [ - "$_gen12 = $cmd_param_kv $_gen12", - "$_gen12 = :_empty", - ], - 87: [ - "$_gen17 = $postfix_quantifier", - "$_gen17 = :_empty", - ], - 88: [ - "$_gen19 = $wf_body_element $_gen20", - "$_gen19 = :_empty", - ], - 89: [ - "$scatter = :scatter :lparen :identifier :in $e :rparen :lbrace $_gen19 :rbrace -> Scatter( item=$2, collection=$4, body=$7 )", - ], - 90: [ - "$_gen27 = $wf_output $_gen28", - "$_gen27 = :_empty", - ], - 91: [ - "$_gen24 = $call_input $_gen24", - "$_gen24 = :_empty", - ], - 92: [ - "$_gen22 = $call_body", - "$_gen22 = :_empty", - ], - 93: [ - "$_gen31 = :comma $type_e $_gen31", - "$_gen31 = :_empty", - ], - 94: [ - "$_gen10 = $command_part $_gen10", - "$_gen10 = :_empty", - ], - 95: [ - "$_gen34 = $object_kv $_gen35", - "$_gen34 = :_empty", - ], - 96: [ - "$document = $_gen0 $_gen2 -> Document( imports=$0, definitions=$1 )", - ], - 97: [ - "$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", - ], - 98: [ - "$wf_output_wildcard = :dot :asterisk -> $1", - ], - 99: [ - "$_gen4 = $import_namespace", - "$_gen4 = :_empty", - ], - 100: [ - "$while_loop = :while :lparen $e :rparen :lbrace $_gen19 :rbrace -> WhileLoop( expression=$2, body=$5 )", - ], - 101: [ - "$_gen25 = $mapping $_gen26", - "$_gen25 = :_empty", - ], - 102: [ - "$_gen3 = $workflow_or_task $_gen3", - "$_gen3 = :_empty", - ], - 103: [ - "$outputs = :output :lbrace $_gen13 :rbrace -> Outputs( attributes=$2 )", - ], - 104: [ - "$_gen9 = $command_part $_gen10", - "$_gen9 = :_empty", - ], - 105: [ - "$_gen1 = $import $_gen1", - "$_gen1 = :_empty", - ], - 106: [ - "$_gen16 = $kv $_gen16", - "$_gen16 = :_empty", - ], - 107: [ - "$_gen35 = :comma $object_kv $_gen35", - "$_gen35 = :_empty", - ], - 108: [ - "$command = :raw_command :raw_cmd_start $_gen9 :raw_cmd_end -> RawCommand( parts=$2 )", - ], - 109: [ - "$call_input = :input :colon $_gen25 -> Inputs( map=$2 )", - ], - 110: [ - "$import = :import :string $_gen4 -> Import( uri=$1, namespace=$2 )", - ], - 111: [ - "$cmd_param_kv = :cmd_attr_hint :identifier :equal $e -> CommandParameterAttr( key=$1, value=$3 )", - ], - 112: [ - "$_gen33 = :comma $e $_gen33", - "$_gen33 = :_empty", - ], - 113: [ - "$sections = $command", - "$sections = $outputs", - "$sections = $runtime", - "$sections = $parameter_meta", - "$sections = $meta", - ], - 114: [ - "$meta = :meta $map -> Meta( map=$1 )", - ], - 115: [ - "$task = :task :identifier :lbrace $_gen5 $_gen7 :rbrace -> Task( name=$1, declarations=$3, sections=$4 )", - ], - 116: [ - "$cmd_param = :cmd_param_start $_gen11 $e :cmd_param_end -> CommandParameter( attributes=$1, expr=$2 )", - ], - 117: [ - "$wf_output = :fqn $_gen29 -> WorkflowOutput( fqn=$0, wildcard=$1 )", - ], - 118: [ - "$_gen29 = $wf_output_wildcard", - "$_gen29 = :_empty", - ], - 119: [ - "$_gen30 = $type_e $_gen31", - "$_gen30 = :_empty", - ], - 120: [ - "$_gen37 = :comma $map_kv $_gen37", - "$_gen37 = :_empty", - ], - 121: [ - "$_gen36 = $map_kv $_gen37", - "$_gen36 = :_empty", - ], - 122: [ - "$_gen5 = $declaration $_gen6", - "$_gen5 = :_empty", - ], - 123: [ - "$mapping = :identifier :equal $e -> IOMapping( key=$0, value=$2 )", - ], - 124: [ - "$call_body = :lbrace $_gen5 $_gen23 :rbrace -> CallBody( declarations=$1, io=$2 )", - ], - 125: [ - "$import_namespace = :as :identifier -> $1", - ], - 126: [ - "$_gen14 = $output_kv $_gen14", - "$_gen14 = :_empty", - ], - 127: [ - "$_gen7 = $sections $_gen8", - "$_gen7 = :_empty", - ], - 128: [ - "$map = :lbrace $_gen15 :rbrace -> $1", - ], - 129: [ - "$type_e = :type <=> :lsquare $_gen30 :rsquare -> Type( name=$0, subtype=$2 )", - "$type_e = :type", - ], - 130: [ - "$wf_outputs = :output :lbrace $_gen27 :rbrace -> WorkflowOutputs( outputs=$2 )", - ], -} -rules = { - 0: "$_gen0 = $import $_gen1", - 1: "$_gen1 = $import $_gen1", - 2: "$_gen1 = :_empty", - 3: "$_gen0 = :_empty", - 4: "$_gen2 = $workflow_or_task $_gen3", - 5: "$_gen3 = $workflow_or_task $_gen3", - 6: "$_gen3 = :_empty", - 7: "$_gen2 = :_empty", - 8: "$document = $_gen0 $_gen2 -> Document( imports=$0, definitions=$1 )", - 9: "$workflow_or_task = $workflow", - 10: "$workflow_or_task = $task", - 11: "$_gen4 = $import_namespace", - 12: "$_gen4 = :_empty", - 13: "$import = :import :string $_gen4 -> Import( uri=$1, namespace=$2 )", - 14: "$import_namespace = :as :identifier -> $1", - 15: "$_gen5 = $declaration $_gen6", - 16: "$_gen6 = $declaration $_gen6", - 17: "$_gen6 = :_empty", - 18: "$_gen5 = :_empty", - 19: "$_gen7 = $sections $_gen8", - 20: "$_gen8 = $sections $_gen8", - 21: "$_gen8 = :_empty", - 22: "$_gen7 = :_empty", - 23: "$task = :task :identifier :lbrace $_gen5 $_gen7 :rbrace -> Task( name=$1, declarations=$3, sections=$4 )", - 24: "$sections = $command", - 25: "$sections = $outputs", - 26: "$sections = $runtime", - 27: "$sections = $parameter_meta", - 28: "$sections = $meta", - 29: "$_gen9 = $command_part $_gen10", - 30: "$_gen10 = $command_part $_gen10", - 31: "$_gen10 = :_empty", - 32: "$_gen9 = :_empty", - 33: "$command = :raw_command :raw_cmd_start $_gen9 :raw_cmd_end -> RawCommand( parts=$2 )", - 34: "$command_part = :cmd_part", - 35: "$command_part = $cmd_param", - 36: "$_gen11 = $cmd_param_kv $_gen12", - 37: "$_gen12 = $cmd_param_kv $_gen12", - 38: "$_gen12 = :_empty", - 39: "$_gen11 = :_empty", - 40: "$cmd_param = :cmd_param_start $_gen11 $e :cmd_param_end -> CommandParameter( attributes=$1, expr=$2 )", - 41: "$cmd_param_kv = :cmd_attr_hint :identifier :equal $e -> CommandParameterAttr( key=$1, value=$3 )", - 42: "$_gen13 = $output_kv $_gen14", - 43: "$_gen14 = $output_kv $_gen14", - 44: "$_gen14 = :_empty", - 45: "$_gen13 = :_empty", - 46: "$outputs = :output :lbrace $_gen13 :rbrace -> Outputs( attributes=$2 )", - 47: "$output_kv = $type_e :identifier :equal $e -> Output( type=$0, var=$1, expression=$3 )", - 48: "$runtime = :runtime $map -> Runtime( map=$1 )", - 49: "$parameter_meta = :parameter_meta $map -> ParameterMeta( map=$1 )", - 50: "$meta = :meta $map -> Meta( map=$1 )", - 51: "$_gen15 = $kv $_gen16", - 52: "$_gen16 = $kv $_gen16", - 53: "$_gen16 = :_empty", - 54: "$_gen15 = :_empty", - 55: "$map = :lbrace $_gen15 :rbrace -> $1", - 56: "$kv = :identifier :colon $e -> RuntimeAttribute( key=$0, value=$2 )", - 57: "$_gen17 = $postfix_quantifier", - 58: "$_gen17 = :_empty", - 59: "$_gen18 = $setter", - 60: "$_gen18 = :_empty", - 61: "$declaration = $type_e $_gen17 :identifier $_gen18 -> Declaration( type=$0, postfix=$1, name=$2, expression=$3 )", - 62: "$setter = :equal $e -> $1", - 63: "$postfix_quantifier = :qmark", - 64: "$postfix_quantifier = :plus", - 65: "$map_kv = $e :colon $e -> MapLiteralKv( key=$0, value=$2 )", - 66: "$_gen19 = $wf_body_element $_gen20", - 67: "$_gen20 = $wf_body_element $_gen20", - 68: "$_gen20 = :_empty", - 69: "$_gen19 = :_empty", - 70: "$workflow = :workflow :identifier :lbrace $_gen19 :rbrace -> Workflow( name=$1, body=$3 )", - 71: "$wf_body_element = $call", - 72: "$wf_body_element = $declaration", - 73: "$wf_body_element = $while_loop", - 74: "$wf_body_element = $if_stmt", - 75: "$wf_body_element = $scatter", - 76: "$wf_body_element = $wf_outputs", - 77: "$_gen21 = $alias", - 78: "$_gen21 = :_empty", - 79: "$_gen22 = $call_body", - 80: "$_gen22 = :_empty", - 81: "$call = :call :fqn $_gen21 $_gen22 -> Call( task=$1, alias=$2, body=$3 )", - 82: "$_gen23 = $call_input $_gen24", - 83: "$_gen24 = $call_input $_gen24", - 84: "$_gen24 = :_empty", - 85: "$_gen23 = :_empty", - 86: "$call_body = :lbrace $_gen5 $_gen23 :rbrace -> CallBody( declarations=$1, io=$2 )", - 87: "$_gen25 = $mapping $_gen26", - 88: "$_gen26 = :comma $mapping $_gen26", - 89: "$_gen26 = :_empty", - 90: "$_gen25 = :_empty", - 91: "$call_input = :input :colon $_gen25 -> Inputs( map=$2 )", - 92: "$mapping = :identifier :equal $e -> IOMapping( key=$0, value=$2 )", - 93: "$alias = :as :identifier -> $1", - 94: "$_gen27 = $wf_output $_gen28", - 95: "$_gen28 = :comma $wf_output $_gen28", - 96: "$_gen28 = :_empty", - 97: "$_gen27 = :_empty", - 98: "$wf_outputs = :output :lbrace $_gen27 :rbrace -> WorkflowOutputs( outputs=$2 )", - 99: "$_gen29 = $wf_output_wildcard", - 100: "$_gen29 = :_empty", - 101: "$wf_output = :fqn $_gen29 -> WorkflowOutput( fqn=$0, wildcard=$1 )", - 102: "$wf_output_wildcard = :dot :asterisk -> $1", - 103: "$while_loop = :while :lparen $e :rparen :lbrace $_gen19 :rbrace -> WhileLoop( expression=$2, body=$5 )", - 104: "$if_stmt = :if :lparen $e :rparen :lbrace $_gen19 :rbrace -> If( expression=$2, body=$5 )", - 105: "$scatter = :scatter :lparen :identifier :in $e :rparen :lbrace $_gen19 :rbrace -> Scatter( item=$2, collection=$4, body=$7 )", - 106: "$object_kv = :identifier :colon $e -> ObjectKV( key=$0, value=$2 )", - 107: "$_gen30 = $type_e $_gen31", - 108: "$_gen31 = :comma $type_e $_gen31", - 109: "$_gen31 = :_empty", - 110: "$_gen30 = :_empty", - 111: "$type_e = :type <=> :lsquare $_gen30 :rsquare -> Type( name=$0, subtype=$2 )", - 112: "$type_e = :type", - 113: "$e = $e :double_pipe $e -> LogicalOr( lhs=$0, rhs=$2 )", - 114: "$e = $e :double_ampersand $e -> LogicalAnd( lhs=$0, rhs=$2 )", - 115: "$e = $e :double_equal $e -> Equals( lhs=$0, rhs=$2 )", - 116: "$e = $e :not_equal $e -> NotEquals( lhs=$0, rhs=$2 )", - 117: "$e = $e :lt $e -> LessThan( lhs=$0, rhs=$2 )", - 118: "$e = $e :lteq $e -> LessThanOrEqual( lhs=$0, rhs=$2 )", - 119: "$e = $e :gt $e -> GreaterThan( lhs=$0, rhs=$2 )", - 120: "$e = $e :gteq $e -> GreaterThanOrEqual( lhs=$0, rhs=$2 )", - 121: "$e = $e :plus $e -> Add( lhs=$0, rhs=$2 )", - 122: "$e = $e :dash $e -> Subtract( lhs=$0, rhs=$2 )", - 123: "$e = $e :asterisk $e -> Multiply( lhs=$0, rhs=$2 )", - 124: "$e = $e :slash $e -> Divide( lhs=$0, rhs=$2 )", - 125: "$e = $e :percent $e -> Remainder( lhs=$0, rhs=$2 )", - 126: "$e = :not $e -> LogicalNot( expression=$1 )", - 127: "$e = :plus $e -> UnaryPlus( expression=$1 )", - 128: "$e = :dash $e -> UnaryNegation( expression=$1 )", - 129: "$_gen32 = $e $_gen33", - 130: "$_gen33 = :comma $e $_gen33", - 131: "$_gen33 = :_empty", - 132: "$_gen32 = :_empty", - 133: "$e = :identifier <=> :lparen $_gen32 :rparen -> FunctionCall( name=$0, params=$2 )", - 134: "$e = :identifier <=> :lsquare $e :rsquare -> ArrayOrMapLookup( lhs=$0, rhs=$2 )", - 135: "$e = :identifier <=> :dot :identifier -> MemberAccess( lhs=$0, rhs=$2 )", - 136: "$_gen34 = $object_kv $_gen35", - 137: "$_gen35 = :comma $object_kv $_gen35", - 138: "$_gen35 = :_empty", - 139: "$_gen34 = :_empty", - 140: "$e = :object :lbrace $_gen34 :rbrace -> ObjectLiteral( map=$2 )", - 141: "$e = :lsquare $_gen32 :rsquare -> ArrayLiteral( values=$1 )", - 142: "$_gen36 = $map_kv $_gen37", - 143: "$_gen37 = :comma $map_kv $_gen37", - 144: "$_gen37 = :_empty", - 145: "$_gen36 = :_empty", - 146: "$e = :lbrace $_gen36 :rbrace -> MapLiteral( map=$1 )", - 147: "$e = :lparen $e :rparen -> $1", - 148: "$e = :string", - 149: "$e = :identifier", - 150: "$e = :boolean", - 151: "$e = :integer", - 152: "$e = :float", -} -def is_terminal(id): return isinstance(id, int) and 0 <= id <= 55 -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: type_e -infix_binding_power_type_e = { - 23: 1000, # $type_e = :type <=> :lsquare list(nt=$type_e, sep=:comma, min=0, sep_terminates=False) :rsquare -> Type( name=$0, subtype=$2 ) -} -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(129, 'type_e')) - current = ctx.tokens.current() - ctx.nonterminal = "type_e" - if not current: - return tree - if current.id in rule_first[111]: - # $type_e = :type <=> :lsquare $_gen30 :rsquare -> Type( name=$0, subtype=$2 ) - ctx.rule = rules[111] - tree.astTransform = AstTransformSubstitution(0) - tree.nudMorphemeCount = 1 - tree.add(expect(ctx, 6)) - elif current.id in rule_first[112]: - # $type_e = :type - ctx.rule = rules[112] - tree.astTransform = AstTransformSubstitution(0) - tree.nudMorphemeCount = 1 - tree.add(expect(ctx, 6)) - return tree -def led_type_e(left, ctx): - tree = ParseTree(NonTerminal(129, 'type_e')) - current = ctx.tokens.current() - ctx.nonterminal = "type_e" - if current.id == 23: # :lsquare - # $type_e = :type <=> :lsquare $_gen30 :rsquare -> Type( name=$0, subtype=$2 ) - ctx.rule = rules[111] - ast_parameters = OrderedDict([ - ('name', 0), - ('subtype', 2), - ]) - tree.astTransform = AstTransformNodeCreator('Type', ast_parameters) - tree.add(left) - tree.add(expect(ctx, 23)) # :lsquare - tree.add(parse__gen30(ctx)) - tree.add(expect(ctx, 20)) # :rsquare - return tree -# END definitions for expression parser: type_e -# START definitions for expression parser: e -infix_binding_power_e = { - 33: 2000, # $e = $e :double_pipe $e -> LogicalOr( lhs=$0, rhs=$2 ) - 37: 3000, # $e = $e :double_ampersand $e -> LogicalAnd( lhs=$0, rhs=$2 ) - 14: 4000, # $e = $e :double_equal $e -> Equals( lhs=$0, rhs=$2 ) - 43: 4000, # $e = $e :not_equal $e -> NotEquals( lhs=$0, rhs=$2 ) - 32: 5000, # $e = $e :lt $e -> LessThan( lhs=$0, rhs=$2 ) - 39: 5000, # $e = $e :lteq $e -> LessThanOrEqual( lhs=$0, rhs=$2 ) - 12: 5000, # $e = $e :gt $e -> GreaterThan( lhs=$0, rhs=$2 ) - 16: 5000, # $e = $e :gteq $e -> GreaterThanOrEqual( lhs=$0, rhs=$2 ) - 46: 6000, # $e = $e :plus $e -> Add( lhs=$0, rhs=$2 ) - 7: 6000, # $e = $e :dash $e -> Subtract( lhs=$0, rhs=$2 ) - 11: 7000, # $e = $e :asterisk $e -> Multiply( lhs=$0, rhs=$2 ) - 19: 7000, # $e = $e :slash $e -> Divide( lhs=$0, rhs=$2 ) - 42: 7000, # $e = $e :percent $e -> Remainder( lhs=$0, rhs=$2 ) - 9: 9000, # $e = :identifier <=> :lparen list(nt=$e, sep=:comma, min=0, sep_terminates=False) :rparen -> FunctionCall( name=$0, params=$2 ) - 23: 10000, # $e = :identifier <=> :lsquare $e :rsquare -> ArrayOrMapLookup( lhs=$0, rhs=$2 ) - 4: 11000, # $e = :identifier <=> :dot :identifier -> MemberAccess( lhs=$0, rhs=$2 ) -} -prefix_binding_power_e = { - 10: 8000, # $e = :not $e -> LogicalNot( expression=$1 ) - 46: 8000, # $e = :plus $e -> UnaryPlus( expression=$1 ) - 7: 8000, # $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(74, 'e')) - current = ctx.tokens.current() - ctx.nonterminal = "e" - if not current: - return tree - elif current.id in rule_first[126]: - # $e = :not $e -> LogicalNot( expression=$1 ) - ctx.rule = rules[126] - ast_parameters = OrderedDict([ - ('expression', 1), - ]) - tree.astTransform = AstTransformNodeCreator('LogicalNot', ast_parameters) - tree.nudMorphemeCount = 2 - tree.add(expect(ctx, 10)) - tree.add(parse_e_internal(ctx, get_prefix_binding_power_e(10))) - tree.isPrefix = True - elif current.id in rule_first[127]: - # $e = :plus $e -> UnaryPlus( expression=$1 ) - ctx.rule = rules[127] - ast_parameters = OrderedDict([ - ('expression', 1), - ]) - tree.astTransform = AstTransformNodeCreator('UnaryPlus', ast_parameters) - tree.nudMorphemeCount = 2 - tree.add(expect(ctx, 46)) - tree.add(parse_e_internal(ctx, get_prefix_binding_power_e(46))) - tree.isPrefix = True - elif current.id in rule_first[128]: - # $e = :dash $e -> UnaryNegation( expression=$1 ) - ctx.rule = rules[128] - ast_parameters = OrderedDict([ - ('expression', 1), - ]) - tree.astTransform = AstTransformNodeCreator('UnaryNegation', ast_parameters) - tree.nudMorphemeCount = 2 - tree.add(expect(ctx, 7)) - tree.add(parse_e_internal(ctx, get_prefix_binding_power_e(7))) - tree.isPrefix = True - elif current.id in rule_first[133]: - # $e = :identifier <=> :lparen $_gen32 :rparen -> FunctionCall( name=$0, params=$2 ) - ctx.rule = rules[133] - tree.astTransform = AstTransformSubstitution(0) - tree.nudMorphemeCount = 1 - tree.add(expect(ctx, 27)) - elif current.id in rule_first[134]: - # $e = :identifier <=> :lsquare $e :rsquare -> ArrayOrMapLookup( lhs=$0, rhs=$2 ) - ctx.rule = rules[134] - tree.astTransform = AstTransformSubstitution(0) - tree.nudMorphemeCount = 1 - tree.add(expect(ctx, 27)) - elif current.id in rule_first[135]: - # $e = :identifier <=> :dot :identifier -> MemberAccess( lhs=$0, rhs=$2 ) - ctx.rule = rules[135] - tree.astTransform = AstTransformSubstitution(0) - tree.nudMorphemeCount = 1 - tree.add(expect(ctx, 27)) - elif current.id in rule_first[140]: - # $e = :object :lbrace $_gen34 :rbrace -> ObjectLiteral( map=$2 ) - ctx.rule = rules[140] - ast_parameters = OrderedDict([ - ('map', 2), - ]) - tree.astTransform = AstTransformNodeCreator('ObjectLiteral', ast_parameters) - tree.nudMorphemeCount = 4 - tree.add(expect(ctx, 44)) - tree.add(expect(ctx, 52)) - tree.add(parse__gen34(ctx)) - tree.add(expect(ctx, 40)) - elif current.id in rule_first[141]: - # $e = :lsquare $_gen32 :rsquare -> ArrayLiteral( values=$1 ) - ctx.rule = rules[141] - ast_parameters = OrderedDict([ - ('values', 1), - ]) - tree.astTransform = AstTransformNodeCreator('ArrayLiteral', ast_parameters) - tree.nudMorphemeCount = 3 - tree.add(expect(ctx, 23)) - tree.add(parse__gen32(ctx)) - tree.add(expect(ctx, 20)) - elif current.id in rule_first[146]: - # $e = :lbrace $_gen36 :rbrace -> MapLiteral( map=$1 ) - ctx.rule = rules[146] - ast_parameters = OrderedDict([ - ('map', 1), - ]) - tree.astTransform = AstTransformNodeCreator('MapLiteral', ast_parameters) - tree.nudMorphemeCount = 3 - tree.add(expect(ctx, 52)) - tree.add(parse__gen36(ctx)) - tree.add(expect(ctx, 40)) - elif current.id in rule_first[147]: - # $e = :lparen $e :rparen -> $1 - ctx.rule = rules[147] - tree.astTransform = AstTransformSubstitution(1) - tree.nudMorphemeCount = 3 - tree.add(expect(ctx, 9)) - tree.add(parse_e(ctx)) - tree.add(expect(ctx, 21)) - elif current.id in rule_first[148]: - # $e = :string - ctx.rule = rules[148] - tree.astTransform = AstTransformSubstitution(0) - tree.nudMorphemeCount = 1 - tree.add(expect(ctx, 29)) - elif current.id in rule_first[149]: - # $e = :identifier - ctx.rule = rules[149] - tree.astTransform = AstTransformSubstitution(0) - tree.nudMorphemeCount = 1 - tree.add(expect(ctx, 27)) - elif current.id in rule_first[150]: - # $e = :boolean - ctx.rule = rules[150] - tree.astTransform = AstTransformSubstitution(0) - tree.nudMorphemeCount = 1 - tree.add(expect(ctx, 17)) - elif current.id in rule_first[151]: - # $e = :integer - ctx.rule = rules[151] - tree.astTransform = AstTransformSubstitution(0) - tree.nudMorphemeCount = 1 - tree.add(expect(ctx, 3)) - elif current.id in rule_first[152]: - # $e = :float - ctx.rule = rules[152] - tree.astTransform = AstTransformSubstitution(0) - tree.nudMorphemeCount = 1 - tree.add(expect(ctx, 18)) - return tree -def led_e(left, ctx): - tree = ParseTree(NonTerminal(74, 'e')) - current = ctx.tokens.current() - ctx.nonterminal = "e" - if current.id == 33: # :double_pipe - # $e = $e :double_pipe $e -> LogicalOr( lhs=$0, rhs=$2 ) - ctx.rule = rules[113] - ast_parameters = OrderedDict([ - ('lhs', 0), - ('rhs', 2), - ]) - tree.astTransform = AstTransformNodeCreator('LogicalOr', ast_parameters) - tree.isExprNud = True - tree.add(left) - tree.add(expect(ctx, 33)) # :double_pipe - modifier = 0 - tree.isInfix = True - tree.add(parse_e_internal(ctx, get_infix_binding_power_e(33) - modifier)) - if current.id == 37: # :double_ampersand - # $e = $e :double_ampersand $e -> LogicalAnd( lhs=$0, rhs=$2 ) - ctx.rule = rules[114] - ast_parameters = OrderedDict([ - ('lhs', 0), - ('rhs', 2), - ]) - tree.astTransform = AstTransformNodeCreator('LogicalAnd', ast_parameters) - tree.isExprNud = True - tree.add(left) - tree.add(expect(ctx, 37)) # :double_ampersand - modifier = 0 - tree.isInfix = True - tree.add(parse_e_internal(ctx, get_infix_binding_power_e(37) - modifier)) - if current.id == 14: # :double_equal - # $e = $e :double_equal $e -> Equals( lhs=$0, rhs=$2 ) - ctx.rule = rules[115] - ast_parameters = OrderedDict([ - ('lhs', 0), - ('rhs', 2), - ]) - tree.astTransform = AstTransformNodeCreator('Equals', ast_parameters) - tree.isExprNud = True - tree.add(left) - tree.add(expect(ctx, 14)) # :double_equal - modifier = 0 - tree.isInfix = True - tree.add(parse_e_internal(ctx, get_infix_binding_power_e(14) - modifier)) - if current.id == 43: # :not_equal - # $e = $e :not_equal $e -> NotEquals( lhs=$0, rhs=$2 ) - ctx.rule = rules[116] - ast_parameters = OrderedDict([ - ('lhs', 0), - ('rhs', 2), - ]) - tree.astTransform = AstTransformNodeCreator('NotEquals', ast_parameters) - tree.isExprNud = True - tree.add(left) - tree.add(expect(ctx, 43)) # :not_equal - modifier = 0 - tree.isInfix = True - tree.add(parse_e_internal(ctx, get_infix_binding_power_e(43) - modifier)) - if current.id == 32: # :lt - # $e = $e :lt $e -> LessThan( lhs=$0, rhs=$2 ) - ctx.rule = rules[117] - ast_parameters = OrderedDict([ - ('lhs', 0), - ('rhs', 2), - ]) - tree.astTransform = AstTransformNodeCreator('LessThan', ast_parameters) - tree.isExprNud = True - tree.add(left) - tree.add(expect(ctx, 32)) # :lt - modifier = 0 - tree.isInfix = True - tree.add(parse_e_internal(ctx, get_infix_binding_power_e(32) - modifier)) - if current.id == 39: # :lteq - # $e = $e :lteq $e -> LessThanOrEqual( lhs=$0, rhs=$2 ) - ctx.rule = rules[118] - ast_parameters = OrderedDict([ - ('lhs', 0), - ('rhs', 2), - ]) - tree.astTransform = AstTransformNodeCreator('LessThanOrEqual', ast_parameters) - tree.isExprNud = True - tree.add(left) - tree.add(expect(ctx, 39)) # :lteq - modifier = 0 - tree.isInfix = True - tree.add(parse_e_internal(ctx, get_infix_binding_power_e(39) - modifier)) - if current.id == 12: # :gt - # $e = $e :gt $e -> GreaterThan( lhs=$0, rhs=$2 ) - ctx.rule = rules[119] - ast_parameters = OrderedDict([ - ('lhs', 0), - ('rhs', 2), - ]) - tree.astTransform = AstTransformNodeCreator('GreaterThan', ast_parameters) - tree.isExprNud = True - tree.add(left) - tree.add(expect(ctx, 12)) # :gt - modifier = 0 - tree.isInfix = True - tree.add(parse_e_internal(ctx, get_infix_binding_power_e(12) - modifier)) - if current.id == 16: # :gteq - # $e = $e :gteq $e -> GreaterThanOrEqual( lhs=$0, rhs=$2 ) - ctx.rule = rules[120] - ast_parameters = OrderedDict([ - ('lhs', 0), - ('rhs', 2), - ]) - tree.astTransform = AstTransformNodeCreator('GreaterThanOrEqual', ast_parameters) - tree.isExprNud = True - tree.add(left) - tree.add(expect(ctx, 16)) # :gteq - modifier = 0 - tree.isInfix = True - tree.add(parse_e_internal(ctx, get_infix_binding_power_e(16) - modifier)) - if current.id == 46: # :plus - # $e = $e :plus $e -> Add( lhs=$0, rhs=$2 ) - ctx.rule = rules[121] - ast_parameters = OrderedDict([ - ('lhs', 0), - ('rhs', 2), - ]) - tree.astTransform = AstTransformNodeCreator('Add', ast_parameters) - tree.isExprNud = True - tree.add(left) - tree.add(expect(ctx, 46)) # :plus - modifier = 0 - tree.isInfix = True - tree.add(parse_e_internal(ctx, get_infix_binding_power_e(46) - modifier)) - if current.id == 7: # :dash - # $e = $e :dash $e -> Subtract( lhs=$0, rhs=$2 ) - ctx.rule = rules[122] - ast_parameters = OrderedDict([ - ('lhs', 0), - ('rhs', 2), - ]) - tree.astTransform = AstTransformNodeCreator('Subtract', ast_parameters) - tree.isExprNud = True - tree.add(left) - tree.add(expect(ctx, 7)) # :dash - modifier = 0 - tree.isInfix = True - tree.add(parse_e_internal(ctx, get_infix_binding_power_e(7) - modifier)) - if current.id == 11: # :asterisk - # $e = $e :asterisk $e -> Multiply( lhs=$0, rhs=$2 ) - ctx.rule = rules[123] - ast_parameters = OrderedDict([ - ('lhs', 0), - ('rhs', 2), - ]) - tree.astTransform = AstTransformNodeCreator('Multiply', ast_parameters) - tree.isExprNud = True - tree.add(left) - tree.add(expect(ctx, 11)) # :asterisk - modifier = 0 - tree.isInfix = True - tree.add(parse_e_internal(ctx, get_infix_binding_power_e(11) - modifier)) - if current.id == 19: # :slash - # $e = $e :slash $e -> Divide( lhs=$0, rhs=$2 ) - ctx.rule = rules[124] - ast_parameters = OrderedDict([ - ('lhs', 0), - ('rhs', 2), - ]) - tree.astTransform = AstTransformNodeCreator('Divide', ast_parameters) - tree.isExprNud = True - tree.add(left) - tree.add(expect(ctx, 19)) # :slash - modifier = 0 - tree.isInfix = True - tree.add(parse_e_internal(ctx, get_infix_binding_power_e(19) - modifier)) - if current.id == 42: # :percent - # $e = $e :percent $e -> Remainder( lhs=$0, rhs=$2 ) - ctx.rule = rules[125] - ast_parameters = OrderedDict([ - ('lhs', 0), - ('rhs', 2), - ]) - tree.astTransform = AstTransformNodeCreator('Remainder', ast_parameters) - tree.isExprNud = True - tree.add(left) - tree.add(expect(ctx, 42)) # :percent - modifier = 0 - tree.isInfix = True - tree.add(parse_e_internal(ctx, get_infix_binding_power_e(42) - modifier)) - if current.id == 9: # :lparen - # $e = :identifier <=> :lparen $_gen32 :rparen -> FunctionCall( name=$0, params=$2 ) - ctx.rule = rules[133] - ast_parameters = OrderedDict([ - ('name', 0), - ('params', 2), - ]) - tree.astTransform = AstTransformNodeCreator('FunctionCall', ast_parameters) - tree.add(left) - tree.add(expect(ctx, 9)) # :lparen - tree.add(parse__gen32(ctx)) - tree.add(expect(ctx, 21)) # :rparen - if current.id == 23: # :lsquare - # $e = :identifier <=> :lsquare $e :rsquare -> ArrayOrMapLookup( lhs=$0, rhs=$2 ) - ctx.rule = rules[134] - ast_parameters = OrderedDict([ - ('lhs', 0), - ('rhs', 2), - ]) - tree.astTransform = AstTransformNodeCreator('ArrayOrMapLookup', ast_parameters) - tree.add(left) - tree.add(expect(ctx, 23)) # :lsquare - modifier = 0 - tree.add(parse_e_internal(ctx, get_infix_binding_power_e(23) - modifier)) - tree.add(expect(ctx, 20)) # :rsquare - if current.id == 4: # :dot - # $e = :identifier <=> :dot :identifier -> MemberAccess( lhs=$0, rhs=$2 ) - ctx.rule = rules[135] - ast_parameters = OrderedDict([ - ('lhs', 0), - ('rhs', 2), - ]) - tree.astTransform = AstTransformNodeCreator('MemberAccess', ast_parameters) - tree.add(left) - tree.add(expect(ctx, 4)) # :dot - tree.add(expect(ctx, 27)) # :identifier - return tree -# END definitions for expression parser: e -def parse__gen8(ctx): - current = ctx.tokens.current() - rule = table[0][current.id] if current else -1 - tree = ParseTree(NonTerminal(56, '_gen8')) - ctx.nonterminal = "_gen8" - tree.list = True - if current != None and current.id in nonterminal_follow[56] and current.id not in nonterminal_first[56]: - return tree - if current == None: - return tree - if rule == 20: # $_gen8 = $sections $_gen8 - ctx.rule = rules[20] - tree.astTransform = AstTransformSubstitution(0) - subtree = parse_sections(ctx) - tree.add(subtree) - subtree = parse__gen8(ctx) - tree.add(subtree) - return tree - return tree -def parse__gen0(ctx): - current = ctx.tokens.current() - rule = table[1][current.id] if current else -1 - tree = ParseTree(NonTerminal(57, '_gen0')) - ctx.nonterminal = "_gen0" - tree.list = True - if current != None and current.id in nonterminal_follow[57] and current.id not in nonterminal_first[57]: - return tree - if current == None: - return tree - if rule == 0: # $_gen0 = $import $_gen1 - ctx.rule = rules[0] - tree.astTransform = AstTransformSubstitution(0) - subtree = parse_import(ctx) - tree.add(subtree) - subtree = parse__gen1(ctx) - tree.add(subtree) - return tree - return tree -def parse_map_kv(ctx): - current = ctx.tokens.current() - rule = table[2][current.id] if current else -1 - tree = ParseTree(NonTerminal(58, 'map_kv')) - ctx.nonterminal = "map_kv" - tree.list = False - if current == None: - raise ctx.errors.unexpected_eof() - if rule == 65: # $map_kv = $e :colon $e -> MapLiteralKv( key=$0, value=$2 ) - ctx.rule = rules[65] - ast_parameters = OrderedDict([ - ('key', 0), - ('value', 2), - ]) - tree.astTransform = AstTransformNodeCreator('MapLiteralKv', ast_parameters) - subtree = parse_e(ctx) - tree.add(subtree) - t = expect(ctx, 22) # :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[58] if x >=0], - rules[65] - ) -def parse_workflow_or_task(ctx): - current = ctx.tokens.current() - rule = table[3][current.id] if current else -1 - tree = ParseTree(NonTerminal(59, 'workflow_or_task')) - ctx.nonterminal = "workflow_or_task" - tree.list = False - if current == None: - raise ctx.errors.unexpected_eof() - if rule == 9: # $workflow_or_task = $workflow - ctx.rule = rules[9] - tree.astTransform = AstTransformSubstitution(0) - subtree = parse_workflow(ctx) - tree.add(subtree) - return tree - elif rule == 10: # $workflow_or_task = $task - ctx.rule = rules[10] - tree.astTransform = AstTransformSubstitution(0) - subtree = parse_task(ctx) - tree.add(subtree) - return tree - raise ctx.errors.unexpected_symbol( - ctx.nonterminal, - ctx.tokens.current(), - [terminals[x] for x in nonterminal_first[59] if x >=0], - rules[10] - ) -def parse_command_part(ctx): - current = ctx.tokens.current() - rule = table[4][current.id] if current else -1 - tree = ParseTree(NonTerminal(60, 'command_part')) - ctx.nonterminal = "command_part" - tree.list = False - if current == None: - raise ctx.errors.unexpected_eof() - if rule == 34: # $command_part = :cmd_part - ctx.rule = rules[34] - tree.astTransform = AstTransformSubstitution(0) - t = expect(ctx, 35) # :cmd_part - tree.add(t) - return tree - elif rule == 35: # $command_part = $cmd_param - ctx.rule = rules[35] - 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[60] if x >=0], - rules[35] - ) -def parse_runtime(ctx): - current = ctx.tokens.current() - rule = table[5][current.id] if current else -1 - tree = ParseTree(NonTerminal(61, 'runtime')) - ctx.nonterminal = "runtime" - tree.list = False - if current == None: - raise ctx.errors.unexpected_eof() - if rule == 48: # $runtime = :runtime $map -> Runtime( map=$1 ) - ctx.rule = rules[48] - ast_parameters = OrderedDict([ - ('map', 1), - ]) - tree.astTransform = AstTransformNodeCreator('Runtime', ast_parameters) - t = expect(ctx, 36) # :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[61] if x >=0], - rules[48] - ) -def parse__gen6(ctx): - current = ctx.tokens.current() - rule = table[6][current.id] if current else -1 - tree = ParseTree(NonTerminal(62, '_gen6')) - ctx.nonterminal = "_gen6" - tree.list = True - if current != None and current.id in nonterminal_follow[62] and current.id not in nonterminal_first[62]: - return tree - if current == None: - return tree - if rule == 16: # $_gen6 = $declaration $_gen6 - ctx.rule = rules[16] - tree.astTransform = AstTransformSubstitution(0) - subtree = parse_declaration(ctx) - tree.add(subtree) - subtree = parse__gen6(ctx) - tree.add(subtree) - return tree - return tree -def parse__gen15(ctx): - current = ctx.tokens.current() - rule = table[7][current.id] if current else -1 - tree = ParseTree(NonTerminal(63, '_gen15')) - ctx.nonterminal = "_gen15" - tree.list = True - 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: # $_gen15 = $kv $_gen16 - ctx.rule = rules[51] - tree.astTransform = AstTransformSubstitution(0) - subtree = parse_kv(ctx) - tree.add(subtree) - subtree = parse__gen16(ctx) - tree.add(subtree) - return tree - return tree -def parse_if_stmt(ctx): - current = ctx.tokens.current() - rule = table[8][current.id] if current else -1 - tree = ParseTree(NonTerminal(64, 'if_stmt')) - ctx.nonterminal = "if_stmt" - tree.list = False - if current == None: - raise ctx.errors.unexpected_eof() - if rule == 104: # $if_stmt = :if :lparen $e :rparen :lbrace $_gen19 :rbrace -> If( expression=$2, body=$5 ) - ctx.rule = rules[104] - ast_parameters = OrderedDict([ - ('expression', 2), - ('body', 5), - ]) - tree.astTransform = AstTransformNodeCreator('If', ast_parameters) - t = expect(ctx, 31) # :if - tree.add(t) - t = expect(ctx, 9) # :lparen - tree.add(t) - subtree = parse_e(ctx) - tree.add(subtree) - t = expect(ctx, 21) # :rparen - tree.add(t) - t = expect(ctx, 52) # :lbrace - tree.add(t) - subtree = parse__gen19(ctx) - tree.add(subtree) - t = expect(ctx, 40) # :rbrace - tree.add(t) - return tree - raise ctx.errors.unexpected_symbol( - ctx.nonterminal, - ctx.tokens.current(), - [terminals[x] for x in nonterminal_first[64] if x >=0], - rules[104] - ) -def parse_output_kv(ctx): - current = ctx.tokens.current() - rule = table[9][current.id] if current else -1 - tree = ParseTree(NonTerminal(65, 'output_kv')) - ctx.nonterminal = "output_kv" - tree.list = False - if current == None: - raise ctx.errors.unexpected_eof() - if rule == 47: # $output_kv = $type_e :identifier :equal $e -> Output( type=$0, var=$1, expression=$3 ) - ctx.rule = rules[47] - ast_parameters = OrderedDict([ - ('type', 0), - ('var', 1), - ('expression', 3), - ]) - tree.astTransform = AstTransformNodeCreator('Output', ast_parameters) - subtree = parse_type_e(ctx) - tree.add(subtree) - t = expect(ctx, 27) # :identifier - tree.add(t) - t = expect(ctx, 38) # :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[65] if x >=0], - rules[47] - ) -def parse_postfix_quantifier(ctx): - current = ctx.tokens.current() - rule = table[10][current.id] if current else -1 - tree = ParseTree(NonTerminal(66, 'postfix_quantifier')) - ctx.nonterminal = "postfix_quantifier" - tree.list = False - if current == None: - raise ctx.errors.unexpected_eof() - if rule == 63: # $postfix_quantifier = :qmark - ctx.rule = rules[63] - tree.astTransform = AstTransformSubstitution(0) - t = expect(ctx, 41) # :qmark - tree.add(t) - return tree - elif rule == 64: # $postfix_quantifier = :plus - ctx.rule = rules[64] - tree.astTransform = AstTransformSubstitution(0) - t = expect(ctx, 46) # :plus - 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[64] - ) -def parse__gen13(ctx): - current = ctx.tokens.current() - rule = table[11][current.id] if current else -1 - tree = ParseTree(NonTerminal(67, '_gen13')) - ctx.nonterminal = "_gen13" - tree.list = True - 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 == 42: # $_gen13 = $output_kv $_gen14 - ctx.rule = rules[42] - tree.astTransform = AstTransformSubstitution(0) - subtree = parse_output_kv(ctx) - tree.add(subtree) - subtree = parse__gen14(ctx) - tree.add(subtree) - return tree - return tree -def parse_declaration(ctx): - current = ctx.tokens.current() - rule = table[12][current.id] if current else -1 - tree = ParseTree(NonTerminal(68, 'declaration')) - ctx.nonterminal = "declaration" - tree.list = False - if current == None: - raise ctx.errors.unexpected_eof() - if rule == 61: # $declaration = $type_e $_gen17 :identifier $_gen18 -> Declaration( type=$0, postfix=$1, name=$2, expression=$3 ) - ctx.rule = rules[61] - ast_parameters = OrderedDict([ - ('type', 0), - ('postfix', 1), - ('name', 2), - ('expression', 3), - ]) - tree.astTransform = AstTransformNodeCreator('Declaration', ast_parameters) - subtree = parse_type_e(ctx) - tree.add(subtree) - subtree = parse__gen17(ctx) - tree.add(subtree) - t = expect(ctx, 27) # :identifier - tree.add(t) - subtree = parse__gen18(ctx) - tree.add(subtree) - return tree - raise ctx.errors.unexpected_symbol( - ctx.nonterminal, - ctx.tokens.current(), - [terminals[x] for x in nonterminal_first[68] if x >=0], - rules[61] - ) -def parse_setter(ctx): - current = ctx.tokens.current() - rule = table[13][current.id] if current else -1 - tree = ParseTree(NonTerminal(69, 'setter')) - ctx.nonterminal = "setter" - tree.list = False - if current == None: - raise ctx.errors.unexpected_eof() - if rule == 62: # $setter = :equal $e -> $1 - ctx.rule = rules[62] - tree.astTransform = AstTransformSubstitution(1) - t = expect(ctx, 38) # :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[62] - ) -def parse_workflow(ctx): - current = ctx.tokens.current() - rule = table[14][current.id] if current else -1 - tree = ParseTree(NonTerminal(70, 'workflow')) - ctx.nonterminal = "workflow" - tree.list = False - if current == None: - raise ctx.errors.unexpected_eof() - if rule == 70: # $workflow = :workflow :identifier :lbrace $_gen19 :rbrace -> Workflow( name=$1, body=$3 ) - ctx.rule = rules[70] - ast_parameters = OrderedDict([ - ('name', 1), - ('body', 3), - ]) - tree.astTransform = AstTransformNodeCreator('Workflow', ast_parameters) - t = expect(ctx, 50) # :workflow - tree.add(t) - t = expect(ctx, 27) # :identifier - tree.add(t) - t = expect(ctx, 52) # :lbrace - tree.add(t) - subtree = parse__gen19(ctx) - tree.add(subtree) - t = expect(ctx, 40) # :rbrace - tree.add(t) - return tree - raise ctx.errors.unexpected_symbol( - ctx.nonterminal, - ctx.tokens.current(), - [terminals[x] for x in nonterminal_first[70] if x >=0], - rules[70] - ) -def parse__gen26(ctx): - current = ctx.tokens.current() - rule = table[15][current.id] if current else -1 - tree = ParseTree(NonTerminal(71, '_gen26')) - ctx.nonterminal = "_gen26" - tree.list = True - if current != None and current.id in nonterminal_follow[71] and current.id not in nonterminal_first[71]: - return tree - if current == None: - return tree - if rule == 88: # $_gen26 = :comma $mapping $_gen26 - ctx.rule = rules[88] - tree.astTransform = AstTransformSubstitution(0) - t = expect(ctx, 28) # :comma - tree.add(t) - tree.listSeparator = t - subtree = parse_mapping(ctx) - tree.add(subtree) - subtree = parse__gen26(ctx) - tree.add(subtree) - return tree - return tree -def parse_kv(ctx): - current = ctx.tokens.current() - rule = table[16][current.id] if current else -1 - tree = ParseTree(NonTerminal(72, 'kv')) - ctx.nonterminal = "kv" - tree.list = False - if current == None: - raise ctx.errors.unexpected_eof() - if rule == 56: # $kv = :identifier :colon $e -> RuntimeAttribute( key=$0, value=$2 ) - ctx.rule = rules[56] - ast_parameters = OrderedDict([ - ('key', 0), - ('value', 2), - ]) - tree.astTransform = AstTransformNodeCreator('RuntimeAttribute', ast_parameters) - t = expect(ctx, 27) # :identifier - tree.add(t) - t = expect(ctx, 22) # :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[72] if x >=0], - rules[56] - ) -def parse_object_kv(ctx): - current = ctx.tokens.current() - rule = table[17][current.id] if current else -1 - tree = ParseTree(NonTerminal(73, 'object_kv')) - ctx.nonterminal = "object_kv" - tree.list = False - if current == None: - raise ctx.errors.unexpected_eof() - if rule == 106: # $object_kv = :identifier :colon $e -> ObjectKV( key=$0, value=$2 ) - ctx.rule = rules[106] - ast_parameters = OrderedDict([ - ('key', 0), - ('value', 2), - ]) - tree.astTransform = AstTransformNodeCreator('ObjectKV', ast_parameters) - t = expect(ctx, 27) # :identifier - tree.add(t) - t = expect(ctx, 22) # :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[73] if x >=0], - rules[106] - ) -def parse__gen21(ctx): - current = ctx.tokens.current() - rule = table[19][current.id] if current else -1 - tree = ParseTree(NonTerminal(75, '_gen21')) - ctx.nonterminal = "_gen21" - tree.list = False - if current != None and current.id in nonterminal_follow[75] and current.id not in nonterminal_first[75]: - return tree - if current == None: - return tree - if rule == 77: # $_gen21 = $alias - ctx.rule = rules[77] - tree.astTransform = AstTransformSubstitution(0) - subtree = parse_alias(ctx) - tree.add(subtree) - return tree - return tree -def parse__gen11(ctx): - current = ctx.tokens.current() - rule = table[20][current.id] if current else -1 - tree = ParseTree(NonTerminal(76, '_gen11')) - ctx.nonterminal = "_gen11" - tree.list = True - if current != None and current.id in nonterminal_follow[76] and current.id not in nonterminal_first[76]: - return tree - if current == None: - return tree - if rule == 36: # $_gen11 = $cmd_param_kv $_gen12 - ctx.rule = rules[36] - tree.astTransform = AstTransformSubstitution(0) - subtree = parse_cmd_param_kv(ctx) - tree.add(subtree) - subtree = parse__gen12(ctx) - tree.add(subtree) - return tree - return tree -def parse__gen23(ctx): - current = ctx.tokens.current() - rule = table[21][current.id] if current else -1 - tree = ParseTree(NonTerminal(77, '_gen23')) - ctx.nonterminal = "_gen23" - tree.list = True - if current != None and current.id in nonterminal_follow[77] and current.id not in nonterminal_first[77]: - return tree - if current == None: - return tree - if rule == 82: # $_gen23 = $call_input $_gen24 - ctx.rule = rules[82] - tree.astTransform = AstTransformSubstitution(0) - subtree = parse_call_input(ctx) - tree.add(subtree) - subtree = parse__gen24(ctx) - tree.add(subtree) - return tree - return tree -def parse_alias(ctx): - current = ctx.tokens.current() - rule = table[22][current.id] if current else -1 - tree = ParseTree(NonTerminal(78, 'alias')) - ctx.nonterminal = "alias" - tree.list = False - if current == None: - raise ctx.errors.unexpected_eof() - if rule == 93: # $alias = :as :identifier -> $1 - ctx.rule = rules[93] - tree.astTransform = AstTransformSubstitution(1) - t = expect(ctx, 26) # :as - tree.add(t) - t = expect(ctx, 27) # :identifier - tree.add(t) - return tree - raise ctx.errors.unexpected_symbol( - ctx.nonterminal, - ctx.tokens.current(), - [terminals[x] for x in nonterminal_first[78] if x >=0], - rules[93] - ) -def parse__gen28(ctx): - current = ctx.tokens.current() - rule = table[23][current.id] if current else -1 - tree = ParseTree(NonTerminal(79, '_gen28')) - ctx.nonterminal = "_gen28" - tree.list = True - if current != None and current.id in nonterminal_follow[79] and current.id not in nonterminal_first[79]: - return tree - if current == None: - return tree - if rule == 95: # $_gen28 = :comma $wf_output $_gen28 - ctx.rule = rules[95] - tree.astTransform = AstTransformSubstitution(0) - t = expect(ctx, 28) # :comma - tree.add(t) - tree.listSeparator = t - subtree = parse_wf_output(ctx) - tree.add(subtree) - subtree = parse__gen28(ctx) - tree.add(subtree) - return tree - return tree -def parse_call(ctx): - current = ctx.tokens.current() - rule = table[24][current.id] if current else -1 - tree = ParseTree(NonTerminal(80, 'call')) - ctx.nonterminal = "call" - tree.list = False - if current == None: - raise ctx.errors.unexpected_eof() - if rule == 81: # $call = :call :fqn $_gen21 $_gen22 -> Call( task=$1, alias=$2, body=$3 ) - ctx.rule = rules[81] - ast_parameters = OrderedDict([ - ('task', 1), - ('alias', 2), - ('body', 3), - ]) - tree.astTransform = AstTransformNodeCreator('Call', ast_parameters) - t = expect(ctx, 53) # :call - tree.add(t) - t = expect(ctx, 24) # :fqn - tree.add(t) - subtree = parse__gen21(ctx) - tree.add(subtree) - subtree = parse__gen22(ctx) - tree.add(subtree) - return tree - raise ctx.errors.unexpected_symbol( - ctx.nonterminal, - ctx.tokens.current(), - [terminals[x] for x in nonterminal_first[80] if x >=0], - rules[81] - ) -def parse__gen32(ctx): - current = ctx.tokens.current() - rule = table[25][current.id] if current else -1 - tree = ParseTree(NonTerminal(81, '_gen32')) - ctx.nonterminal = "_gen32" - tree.list = True - if current != None and current.id in nonterminal_follow[81] and current.id not in nonterminal_first[81]: - return tree - if current == None: - return tree - if rule == 129: # $_gen32 = $e $_gen33 - ctx.rule = rules[129] - tree.astTransform = AstTransformSubstitution(0) - subtree = parse_e(ctx) - tree.add(subtree) - subtree = parse__gen33(ctx) - tree.add(subtree) - return tree - return tree -def parse__gen2(ctx): - current = ctx.tokens.current() - rule = table[26][current.id] if current else -1 - tree = ParseTree(NonTerminal(82, '_gen2')) - ctx.nonterminal = "_gen2" - tree.list = True - if current != None and current.id in nonterminal_follow[82] and current.id not in nonterminal_first[82]: - return tree - if current == None: - return tree - if rule == 4: # $_gen2 = $workflow_or_task $_gen3 - ctx.rule = rules[4] - tree.astTransform = AstTransformSubstitution(0) - subtree = parse_workflow_or_task(ctx) - tree.add(subtree) - subtree = parse__gen3(ctx) - tree.add(subtree) - return tree - return tree -def parse_parameter_meta(ctx): - current = ctx.tokens.current() - rule = table[27][current.id] if current else -1 - tree = ParseTree(NonTerminal(83, 'parameter_meta')) - ctx.nonterminal = "parameter_meta" - tree.list = False - if current == None: - raise ctx.errors.unexpected_eof() - if rule == 49: # $parameter_meta = :parameter_meta $map -> ParameterMeta( map=$1 ) - ctx.rule = rules[49] - ast_parameters = OrderedDict([ - ('map', 1), - ]) - tree.astTransform = AstTransformNodeCreator('ParameterMeta', ast_parameters) - t = expect(ctx, 13) # :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[83] if x >=0], - rules[49] - ) -def parse__gen20(ctx): - current = ctx.tokens.current() - rule = table[28][current.id] if current else -1 - tree = ParseTree(NonTerminal(84, '_gen20')) - ctx.nonterminal = "_gen20" - tree.list = True - if current != None and current.id in nonterminal_follow[84] and current.id not in nonterminal_first[84]: - return tree - if current == None: - return tree - if rule == 67: # $_gen20 = $wf_body_element $_gen20 - ctx.rule = rules[67] - tree.astTransform = AstTransformSubstitution(0) - subtree = parse_wf_body_element(ctx) - tree.add(subtree) - subtree = parse__gen20(ctx) - tree.add(subtree) - return tree - return tree -def parse__gen18(ctx): - current = ctx.tokens.current() - rule = table[29][current.id] if current else -1 - tree = ParseTree(NonTerminal(85, '_gen18')) - ctx.nonterminal = "_gen18" - tree.list = False - if current != None and current.id in nonterminal_follow[85] and current.id not in nonterminal_first[85]: - return tree - if current == None: - return tree - if rule == 59: # $_gen18 = $setter - ctx.rule = rules[59] - tree.astTransform = AstTransformSubstitution(0) - subtree = parse_setter(ctx) - tree.add(subtree) - return tree - return tree -def parse__gen12(ctx): - current = ctx.tokens.current() - rule = table[30][current.id] if current else -1 - tree = ParseTree(NonTerminal(86, '_gen12')) - ctx.nonterminal = "_gen12" - tree.list = True - if current != None and current.id in nonterminal_follow[86] and current.id not in nonterminal_first[86]: - return tree - if current == None: - return tree - if rule == 37: # $_gen12 = $cmd_param_kv $_gen12 - ctx.rule = rules[37] - tree.astTransform = AstTransformSubstitution(0) - subtree = parse_cmd_param_kv(ctx) - tree.add(subtree) - subtree = parse__gen12(ctx) - tree.add(subtree) - return tree - return tree -def parse__gen17(ctx): - current = ctx.tokens.current() - rule = table[31][current.id] if current else -1 - tree = ParseTree(NonTerminal(87, '_gen17')) - ctx.nonterminal = "_gen17" - tree.list = False - if current != None and current.id in nonterminal_follow[87] and current.id not in nonterminal_first[87]: - return tree - if current == None: - return tree - if rule == 57: # $_gen17 = $postfix_quantifier - ctx.rule = rules[57] - tree.astTransform = AstTransformSubstitution(0) - subtree = parse_postfix_quantifier(ctx) - tree.add(subtree) - return tree - return tree -def parse__gen19(ctx): - current = ctx.tokens.current() - rule = table[32][current.id] if current else -1 - tree = ParseTree(NonTerminal(88, '_gen19')) - ctx.nonterminal = "_gen19" - tree.list = True - if current != None and current.id in nonterminal_follow[88] and current.id not in nonterminal_first[88]: - return tree - if current == None: - return tree - if rule == 66: # $_gen19 = $wf_body_element $_gen20 - ctx.rule = rules[66] - tree.astTransform = AstTransformSubstitution(0) - subtree = parse_wf_body_element(ctx) - tree.add(subtree) - subtree = parse__gen20(ctx) - tree.add(subtree) - return tree - return tree -def parse_scatter(ctx): - current = ctx.tokens.current() - rule = table[33][current.id] if current else -1 - tree = ParseTree(NonTerminal(89, 'scatter')) - ctx.nonterminal = "scatter" - tree.list = False - if current == None: - raise ctx.errors.unexpected_eof() - if rule == 105: # $scatter = :scatter :lparen :identifier :in $e :rparen :lbrace $_gen19 :rbrace -> Scatter( item=$2, collection=$4, body=$7 ) - ctx.rule = rules[105] - ast_parameters = OrderedDict([ - ('item', 2), - ('collection', 4), - ('body', 7), - ]) - tree.astTransform = AstTransformNodeCreator('Scatter', ast_parameters) - t = expect(ctx, 1) # :scatter - tree.add(t) - t = expect(ctx, 9) # :lparen - tree.add(t) - t = expect(ctx, 27) # :identifier - tree.add(t) - t = expect(ctx, 45) # :in - tree.add(t) - subtree = parse_e(ctx) - tree.add(subtree) - t = expect(ctx, 21) # :rparen - tree.add(t) - t = expect(ctx, 52) # :lbrace - tree.add(t) - subtree = parse__gen19(ctx) - tree.add(subtree) - t = expect(ctx, 40) # :rbrace - tree.add(t) - return tree - raise ctx.errors.unexpected_symbol( - ctx.nonterminal, - ctx.tokens.current(), - [terminals[x] for x in nonterminal_first[89] if x >=0], - rules[105] - ) -def parse__gen27(ctx): - current = ctx.tokens.current() - rule = table[34][current.id] if current else -1 - tree = ParseTree(NonTerminal(90, '_gen27')) - ctx.nonterminal = "_gen27" - tree.list = True - if current != None and current.id in nonterminal_follow[90] and current.id not in nonterminal_first[90]: - return tree - if current == None: - return tree - if rule == 94: # $_gen27 = $wf_output $_gen28 - ctx.rule = rules[94] - tree.astTransform = AstTransformSubstitution(0) - subtree = parse_wf_output(ctx) - tree.add(subtree) - subtree = parse__gen28(ctx) - tree.add(subtree) - return tree - return tree -def parse__gen24(ctx): - current = ctx.tokens.current() - rule = table[35][current.id] if current else -1 - tree = ParseTree(NonTerminal(91, '_gen24')) - ctx.nonterminal = "_gen24" - tree.list = True - if current != None and current.id in nonterminal_follow[91] and current.id not in nonterminal_first[91]: - return tree - if current == None: - return tree - if rule == 83: # $_gen24 = $call_input $_gen24 - ctx.rule = rules[83] - tree.astTransform = AstTransformSubstitution(0) - subtree = parse_call_input(ctx) - tree.add(subtree) - subtree = parse__gen24(ctx) - tree.add(subtree) - return tree - return tree -def parse__gen22(ctx): - current = ctx.tokens.current() - rule = table[36][current.id] if current else -1 - tree = ParseTree(NonTerminal(92, '_gen22')) - ctx.nonterminal = "_gen22" - tree.list = False - if current != None and current.id in nonterminal_follow[92] and current.id not in nonterminal_first[92]: - return tree - if current == None: - return tree - if rule == 79: # $_gen22 = $call_body - ctx.rule = rules[79] - tree.astTransform = AstTransformSubstitution(0) - subtree = parse_call_body(ctx) - tree.add(subtree) - return tree - return tree -def parse__gen31(ctx): - current = ctx.tokens.current() - rule = table[37][current.id] if current else -1 - tree = ParseTree(NonTerminal(93, '_gen31')) - ctx.nonterminal = "_gen31" - tree.list = True - if current != None and current.id in nonterminal_follow[93] and current.id not in nonterminal_first[93]: - return tree - if current == None: - return tree - if rule == 108: # $_gen31 = :comma $type_e $_gen31 - ctx.rule = rules[108] - tree.astTransform = AstTransformSubstitution(0) - t = expect(ctx, 28) # :comma - tree.add(t) - tree.listSeparator = t - subtree = parse_type_e(ctx) - tree.add(subtree) - subtree = parse__gen31(ctx) - tree.add(subtree) - return tree - return tree -def parse__gen10(ctx): - current = ctx.tokens.current() - rule = table[38][current.id] if current else -1 - tree = ParseTree(NonTerminal(94, '_gen10')) - ctx.nonterminal = "_gen10" - tree.list = True - if current != None and current.id in nonterminal_follow[94] and current.id not in nonterminal_first[94]: - return tree - if current == None: - return tree - if rule == 30: # $_gen10 = $command_part $_gen10 - ctx.rule = rules[30] - tree.astTransform = AstTransformSubstitution(0) - subtree = parse_command_part(ctx) - tree.add(subtree) - subtree = parse__gen10(ctx) - tree.add(subtree) - return tree - return tree -def parse__gen34(ctx): - current = ctx.tokens.current() - rule = table[39][current.id] if current else -1 - tree = ParseTree(NonTerminal(95, '_gen34')) - ctx.nonterminal = "_gen34" - tree.list = True - if current != None and current.id in nonterminal_follow[95] and current.id not in nonterminal_first[95]: - return tree - if current == None: - return tree - if rule == 136: # $_gen34 = $object_kv $_gen35 - ctx.rule = rules[136] - tree.astTransform = AstTransformSubstitution(0) - subtree = parse_object_kv(ctx) - tree.add(subtree) - subtree = parse__gen35(ctx) - tree.add(subtree) - return tree - return tree -def parse_document(ctx): - current = ctx.tokens.current() - rule = table[40][current.id] if current else -1 - tree = ParseTree(NonTerminal(96, 'document')) - ctx.nonterminal = "document" - tree.list = False - if current != None and current.id in nonterminal_follow[96] and current.id not in nonterminal_first[96]: - return tree - if current == None: - return tree - if rule == 8: # $document = $_gen0 $_gen2 -> Document( imports=$0, definitions=$1 ) - ctx.rule = rules[8] - ast_parameters = OrderedDict([ - ('imports', 0), - ('definitions', 1), - ]) - tree.astTransform = AstTransformNodeCreator('Document', ast_parameters) - subtree = parse__gen0(ctx) - tree.add(subtree) - subtree = parse__gen2(ctx) - tree.add(subtree) - return tree - return tree -def parse_wf_body_element(ctx): - current = ctx.tokens.current() - rule = table[41][current.id] if current else -1 - tree = ParseTree(NonTerminal(97, 'wf_body_element')) - ctx.nonterminal = "wf_body_element" - tree.list = False - if current == None: - raise ctx.errors.unexpected_eof() - if rule == 71: # $wf_body_element = $call - ctx.rule = rules[71] - tree.astTransform = AstTransformSubstitution(0) - subtree = parse_call(ctx) - tree.add(subtree) - return tree - elif rule == 72: # $wf_body_element = $declaration - ctx.rule = rules[72] - tree.astTransform = AstTransformSubstitution(0) - subtree = parse_declaration(ctx) - tree.add(subtree) - return tree - elif rule == 73: # $wf_body_element = $while_loop - ctx.rule = rules[73] - tree.astTransform = AstTransformSubstitution(0) - subtree = parse_while_loop(ctx) - tree.add(subtree) - return tree - elif rule == 74: # $wf_body_element = $if_stmt - ctx.rule = rules[74] - tree.astTransform = AstTransformSubstitution(0) - subtree = parse_if_stmt(ctx) - tree.add(subtree) - return tree - elif rule == 75: # $wf_body_element = $scatter - ctx.rule = rules[75] - tree.astTransform = AstTransformSubstitution(0) - subtree = parse_scatter(ctx) - tree.add(subtree) - return tree - elif rule == 76: # $wf_body_element = $wf_outputs - ctx.rule = rules[76] - tree.astTransform = AstTransformSubstitution(0) - subtree = parse_wf_outputs(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[76] - ) -def parse_wf_output_wildcard(ctx): - current = ctx.tokens.current() - rule = table[42][current.id] if current else -1 - tree = ParseTree(NonTerminal(98, 'wf_output_wildcard')) - ctx.nonterminal = "wf_output_wildcard" - tree.list = False - if current == None: - raise ctx.errors.unexpected_eof() - if rule == 102: # $wf_output_wildcard = :dot :asterisk -> $1 - ctx.rule = rules[102] - tree.astTransform = AstTransformSubstitution(1) - t = expect(ctx, 4) # :dot - tree.add(t) - t = expect(ctx, 11) # :asterisk - 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[102] - ) -def parse__gen4(ctx): - current = ctx.tokens.current() - rule = table[43][current.id] if current else -1 - tree = ParseTree(NonTerminal(99, '_gen4')) - ctx.nonterminal = "_gen4" - tree.list = False - if current != None and current.id in nonterminal_follow[99] and current.id not in nonterminal_first[99]: - return tree - if current == None: - return tree - if rule == 11: # $_gen4 = $import_namespace - ctx.rule = rules[11] - tree.astTransform = AstTransformSubstitution(0) - subtree = parse_import_namespace(ctx) - tree.add(subtree) - return tree - return tree -def parse_while_loop(ctx): - current = ctx.tokens.current() - rule = table[44][current.id] if current else -1 - tree = ParseTree(NonTerminal(100, 'while_loop')) - ctx.nonterminal = "while_loop" - tree.list = False - if current == None: - raise ctx.errors.unexpected_eof() - if rule == 103: # $while_loop = :while :lparen $e :rparen :lbrace $_gen19 :rbrace -> WhileLoop( expression=$2, body=$5 ) - ctx.rule = rules[103] - ast_parameters = OrderedDict([ - ('expression', 2), - ('body', 5), - ]) - tree.astTransform = AstTransformNodeCreator('WhileLoop', ast_parameters) - t = expect(ctx, 47) # :while - tree.add(t) - t = expect(ctx, 9) # :lparen - tree.add(t) - subtree = parse_e(ctx) - tree.add(subtree) - t = expect(ctx, 21) # :rparen - tree.add(t) - t = expect(ctx, 52) # :lbrace - tree.add(t) - subtree = parse__gen19(ctx) - tree.add(subtree) - t = expect(ctx, 40) # :rbrace - tree.add(t) - return tree - raise ctx.errors.unexpected_symbol( - ctx.nonterminal, - ctx.tokens.current(), - [terminals[x] for x in nonterminal_first[100] if x >=0], - rules[103] - ) -def parse__gen25(ctx): - current = ctx.tokens.current() - rule = table[45][current.id] if current else -1 - tree = ParseTree(NonTerminal(101, '_gen25')) - ctx.nonterminal = "_gen25" - tree.list = True - if current != None and current.id in nonterminal_follow[101] and current.id not in nonterminal_first[101]: - return tree - if current == None: - return tree - if rule == 87: # $_gen25 = $mapping $_gen26 - ctx.rule = rules[87] - tree.astTransform = AstTransformSubstitution(0) - subtree = parse_mapping(ctx) - tree.add(subtree) - subtree = parse__gen26(ctx) - tree.add(subtree) - return tree - return tree -def parse__gen3(ctx): - current = ctx.tokens.current() - rule = table[46][current.id] if current else -1 - tree = ParseTree(NonTerminal(102, '_gen3')) - ctx.nonterminal = "_gen3" - tree.list = True - if current != None and current.id in nonterminal_follow[102] and current.id not in nonterminal_first[102]: - return tree - if current == None: - return tree - if rule == 5: # $_gen3 = $workflow_or_task $_gen3 - ctx.rule = rules[5] - tree.astTransform = AstTransformSubstitution(0) - subtree = parse_workflow_or_task(ctx) - tree.add(subtree) - subtree = parse__gen3(ctx) - tree.add(subtree) - return tree - return tree -def parse_outputs(ctx): - current = ctx.tokens.current() - rule = table[47][current.id] if current else -1 - tree = ParseTree(NonTerminal(103, 'outputs')) - ctx.nonterminal = "outputs" - tree.list = False - if current == None: - raise ctx.errors.unexpected_eof() - if rule == 46: # $outputs = :output :lbrace $_gen13 :rbrace -> Outputs( attributes=$2 ) - ctx.rule = rules[46] - ast_parameters = OrderedDict([ - ('attributes', 2), - ]) - tree.astTransform = AstTransformNodeCreator('Outputs', ast_parameters) - t = expect(ctx, 34) # :output - tree.add(t) - t = expect(ctx, 52) # :lbrace - tree.add(t) - subtree = parse__gen13(ctx) - tree.add(subtree) - t = expect(ctx, 40) # :rbrace - tree.add(t) - return tree - raise ctx.errors.unexpected_symbol( - ctx.nonterminal, - ctx.tokens.current(), - [terminals[x] for x in nonterminal_first[103] if x >=0], - rules[46] - ) -def parse__gen9(ctx): - current = ctx.tokens.current() - rule = table[48][current.id] if current else -1 - tree = ParseTree(NonTerminal(104, '_gen9')) - ctx.nonterminal = "_gen9" - tree.list = True - 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 == 29: # $_gen9 = $command_part $_gen10 - ctx.rule = rules[29] - tree.astTransform = AstTransformSubstitution(0) - subtree = parse_command_part(ctx) - tree.add(subtree) - subtree = parse__gen10(ctx) - tree.add(subtree) - return tree - return tree -def parse__gen1(ctx): - current = ctx.tokens.current() - rule = table[49][current.id] if current else -1 - tree = ParseTree(NonTerminal(105, '_gen1')) - ctx.nonterminal = "_gen1" - tree.list = True - if current != None and current.id in nonterminal_follow[105] and current.id not in nonterminal_first[105]: - return tree - if current == None: - return tree - if rule == 1: # $_gen1 = $import $_gen1 - ctx.rule = rules[1] - tree.astTransform = AstTransformSubstitution(0) - subtree = parse_import(ctx) - tree.add(subtree) - subtree = parse__gen1(ctx) - tree.add(subtree) - return tree - return tree -def parse__gen16(ctx): - current = ctx.tokens.current() - rule = table[50][current.id] if current else -1 - tree = ParseTree(NonTerminal(106, '_gen16')) - ctx.nonterminal = "_gen16" - tree.list = True - if current != None and current.id in nonterminal_follow[106] and current.id not in nonterminal_first[106]: - return tree - if current == None: - return tree - if rule == 52: # $_gen16 = $kv $_gen16 - ctx.rule = rules[52] - tree.astTransform = AstTransformSubstitution(0) - subtree = parse_kv(ctx) - tree.add(subtree) - subtree = parse__gen16(ctx) - tree.add(subtree) - return tree - return tree -def parse__gen35(ctx): - current = ctx.tokens.current() - rule = table[51][current.id] if current else -1 - tree = ParseTree(NonTerminal(107, '_gen35')) - ctx.nonterminal = "_gen35" - tree.list = True - if current != None and current.id in nonterminal_follow[107] and current.id not in nonterminal_first[107]: - return tree - if current == None: - return tree - if rule == 137: # $_gen35 = :comma $object_kv $_gen35 - ctx.rule = rules[137] - tree.astTransform = AstTransformSubstitution(0) - t = expect(ctx, 28) # :comma - tree.add(t) - tree.listSeparator = t - subtree = parse_object_kv(ctx) - tree.add(subtree) - subtree = parse__gen35(ctx) - tree.add(subtree) - return tree - return tree -def parse_command(ctx): - current = ctx.tokens.current() - rule = table[52][current.id] if current else -1 - tree = ParseTree(NonTerminal(108, 'command')) - ctx.nonterminal = "command" - tree.list = False - if current == None: - raise ctx.errors.unexpected_eof() - if rule == 33: # $command = :raw_command :raw_cmd_start $_gen9 :raw_cmd_end -> RawCommand( parts=$2 ) - ctx.rule = rules[33] - ast_parameters = OrderedDict([ - ('parts', 2), - ]) - tree.astTransform = AstTransformNodeCreator('RawCommand', ast_parameters) - t = expect(ctx, 5) # :raw_command - tree.add(t) - t = expect(ctx, 48) # :raw_cmd_start - tree.add(t) - subtree = parse__gen9(ctx) - tree.add(subtree) - t = expect(ctx, 0) # :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[108] if x >=0], - rules[33] - ) -def parse_call_input(ctx): - current = ctx.tokens.current() - rule = table[53][current.id] if current else -1 - tree = ParseTree(NonTerminal(109, 'call_input')) - ctx.nonterminal = "call_input" - tree.list = False - if current == None: - raise ctx.errors.unexpected_eof() - if rule == 91: # $call_input = :input :colon $_gen25 -> Inputs( map=$2 ) - ctx.rule = rules[91] - ast_parameters = OrderedDict([ - ('map', 2), - ]) - tree.astTransform = AstTransformNodeCreator('Inputs', ast_parameters) - t = expect(ctx, 51) # :input - tree.add(t) - t = expect(ctx, 22) # :colon - tree.add(t) - subtree = parse__gen25(ctx) - tree.add(subtree) - return tree - raise ctx.errors.unexpected_symbol( - ctx.nonterminal, - ctx.tokens.current(), - [terminals[x] for x in nonterminal_first[109] if x >=0], - rules[91] - ) -def parse_import(ctx): - current = ctx.tokens.current() - rule = table[54][current.id] if current else -1 - tree = ParseTree(NonTerminal(110, 'import')) - ctx.nonterminal = "import" - tree.list = False - if current == None: - raise ctx.errors.unexpected_eof() - if rule == 13: # $import = :import :string $_gen4 -> Import( uri=$1, namespace=$2 ) - ctx.rule = rules[13] - ast_parameters = OrderedDict([ - ('uri', 1), - ('namespace', 2), - ]) - tree.astTransform = AstTransformNodeCreator('Import', ast_parameters) - t = expect(ctx, 54) # :import - tree.add(t) - t = expect(ctx, 29) # :string - tree.add(t) - subtree = parse__gen4(ctx) - tree.add(subtree) - return tree - raise ctx.errors.unexpected_symbol( - ctx.nonterminal, - ctx.tokens.current(), - [terminals[x] for x in nonterminal_first[110] if x >=0], - rules[13] - ) -def parse_cmd_param_kv(ctx): - current = ctx.tokens.current() - rule = table[55][current.id] if current else -1 - tree = ParseTree(NonTerminal(111, 'cmd_param_kv')) - ctx.nonterminal = "cmd_param_kv" - tree.list = False - if current == None: - raise ctx.errors.unexpected_eof() - if rule == 41: # $cmd_param_kv = :cmd_attr_hint :identifier :equal $e -> CommandParameterAttr( key=$1, value=$3 ) - ctx.rule = rules[41] - ast_parameters = OrderedDict([ - ('key', 1), - ('value', 3), - ]) - tree.astTransform = AstTransformNodeCreator('CommandParameterAttr', ast_parameters) - t = expect(ctx, 8) # :cmd_attr_hint - tree.add(t) - t = expect(ctx, 27) # :identifier - tree.add(t) - t = expect(ctx, 38) # :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[111] if x >=0], - rules[41] - ) -def parse__gen33(ctx): - current = ctx.tokens.current() - rule = table[56][current.id] if current else -1 - tree = ParseTree(NonTerminal(112, '_gen33')) - ctx.nonterminal = "_gen33" - tree.list = True - if current != None and current.id in nonterminal_follow[112] and current.id not in nonterminal_first[112]: - return tree - if current == None: - return tree - if rule == 130: # $_gen33 = :comma $e $_gen33 - ctx.rule = rules[130] - tree.astTransform = AstTransformSubstitution(0) - t = expect(ctx, 28) # :comma - tree.add(t) - tree.listSeparator = t - subtree = parse_e(ctx) - tree.add(subtree) - subtree = parse__gen33(ctx) - tree.add(subtree) - return tree - return tree -def parse_sections(ctx): - current = ctx.tokens.current() - rule = table[57][current.id] if current else -1 - tree = ParseTree(NonTerminal(113, 'sections')) - ctx.nonterminal = "sections" - tree.list = False - if current == None: - raise ctx.errors.unexpected_eof() - if rule == 24: # $sections = $command - ctx.rule = rules[24] - tree.astTransform = AstTransformSubstitution(0) - subtree = parse_command(ctx) - tree.add(subtree) - return tree - elif rule == 25: # $sections = $outputs - ctx.rule = rules[25] - tree.astTransform = AstTransformSubstitution(0) - subtree = parse_outputs(ctx) - tree.add(subtree) - return tree - elif rule == 26: # $sections = $runtime - ctx.rule = rules[26] - tree.astTransform = AstTransformSubstitution(0) - subtree = parse_runtime(ctx) - tree.add(subtree) - return tree - elif rule == 27: # $sections = $parameter_meta - ctx.rule = rules[27] - tree.astTransform = AstTransformSubstitution(0) - subtree = parse_parameter_meta(ctx) - tree.add(subtree) - return tree - elif rule == 28: # $sections = $meta - ctx.rule = rules[28] - 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[113] if x >=0], - rules[28] - ) -def parse_meta(ctx): - current = ctx.tokens.current() - rule = table[58][current.id] if current else -1 - tree = ParseTree(NonTerminal(114, 'meta')) - ctx.nonterminal = "meta" - tree.list = False - if current == None: - raise ctx.errors.unexpected_eof() - if rule == 50: # $meta = :meta $map -> Meta( map=$1 ) - ctx.rule = rules[50] - ast_parameters = OrderedDict([ - ('map', 1), - ]) - tree.astTransform = AstTransformNodeCreator('Meta', ast_parameters) - t = expect(ctx, 49) # :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[114] if x >=0], - rules[50] - ) -def parse_task(ctx): - current = ctx.tokens.current() - rule = table[59][current.id] if current else -1 - tree = ParseTree(NonTerminal(115, 'task')) - ctx.nonterminal = "task" - tree.list = False - if current == None: - raise ctx.errors.unexpected_eof() - if rule == 23: # $task = :task :identifier :lbrace $_gen5 $_gen7 :rbrace -> Task( name=$1, declarations=$3, sections=$4 ) - ctx.rule = rules[23] - ast_parameters = OrderedDict([ - ('name', 1), - ('declarations', 3), - ('sections', 4), - ]) - tree.astTransform = AstTransformNodeCreator('Task', ast_parameters) - t = expect(ctx, 25) # :task - tree.add(t) - t = expect(ctx, 27) # :identifier - tree.add(t) - t = expect(ctx, 52) # :lbrace - tree.add(t) - subtree = parse__gen5(ctx) - tree.add(subtree) - subtree = parse__gen7(ctx) - tree.add(subtree) - t = expect(ctx, 40) # :rbrace - tree.add(t) - return tree - raise ctx.errors.unexpected_symbol( - ctx.nonterminal, - ctx.tokens.current(), - [terminals[x] for x in nonterminal_first[115] if x >=0], - rules[23] - ) -def parse_cmd_param(ctx): - current = ctx.tokens.current() - rule = table[60][current.id] if current else -1 - tree = ParseTree(NonTerminal(116, 'cmd_param')) - ctx.nonterminal = "cmd_param" - tree.list = False - if current == None: - raise ctx.errors.unexpected_eof() - if rule == 40: # $cmd_param = :cmd_param_start $_gen11 $e :cmd_param_end -> CommandParameter( attributes=$1, expr=$2 ) - ctx.rule = rules[40] - ast_parameters = OrderedDict([ - ('attributes', 1), - ('expr', 2), - ]) - tree.astTransform = AstTransformNodeCreator('CommandParameter', ast_parameters) - t = expect(ctx, 30) # :cmd_param_start - tree.add(t) - subtree = parse__gen11(ctx) - tree.add(subtree) - subtree = parse_e(ctx) - tree.add(subtree) - t = expect(ctx, 55) # :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[116] if x >=0], - rules[40] - ) -def parse_wf_output(ctx): - current = ctx.tokens.current() - rule = table[61][current.id] if current else -1 - tree = ParseTree(NonTerminal(117, 'wf_output')) - ctx.nonterminal = "wf_output" - tree.list = False - if current == None: - raise ctx.errors.unexpected_eof() - if rule == 101: # $wf_output = :fqn $_gen29 -> WorkflowOutput( fqn=$0, wildcard=$1 ) - ctx.rule = rules[101] - ast_parameters = OrderedDict([ - ('fqn', 0), - ('wildcard', 1), - ]) - tree.astTransform = AstTransformNodeCreator('WorkflowOutput', ast_parameters) - t = expect(ctx, 24) # :fqn - tree.add(t) - subtree = parse__gen29(ctx) - tree.add(subtree) - return tree - raise ctx.errors.unexpected_symbol( - ctx.nonterminal, - ctx.tokens.current(), - [terminals[x] for x in nonterminal_first[117] if x >=0], - rules[101] - ) -def parse__gen29(ctx): - current = ctx.tokens.current() - rule = table[62][current.id] if current else -1 - tree = ParseTree(NonTerminal(118, '_gen29')) - ctx.nonterminal = "_gen29" - tree.list = False - if current != None and current.id in nonterminal_follow[118] and current.id not in nonterminal_first[118]: - return tree - if current == None: - return tree - if rule == 99: # $_gen29 = $wf_output_wildcard - ctx.rule = rules[99] - tree.astTransform = AstTransformSubstitution(0) - subtree = parse_wf_output_wildcard(ctx) - tree.add(subtree) - return tree - return tree -def parse__gen30(ctx): - current = ctx.tokens.current() - rule = table[63][current.id] if current else -1 - tree = ParseTree(NonTerminal(119, '_gen30')) - ctx.nonterminal = "_gen30" - tree.list = True - if current != None and current.id in nonterminal_follow[119] and current.id not in nonterminal_first[119]: - return tree - if current == None: - return tree - if rule == 107: # $_gen30 = $type_e $_gen31 - ctx.rule = rules[107] - tree.astTransform = AstTransformSubstitution(0) - subtree = parse_type_e(ctx) - tree.add(subtree) - subtree = parse__gen31(ctx) - tree.add(subtree) - return tree - return tree -def parse__gen37(ctx): - current = ctx.tokens.current() - rule = table[64][current.id] if current else -1 - tree = ParseTree(NonTerminal(120, '_gen37')) - ctx.nonterminal = "_gen37" - tree.list = True - if current != None and current.id in nonterminal_follow[120] and current.id not in nonterminal_first[120]: - return tree - if current == None: - return tree - if rule == 143: # $_gen37 = :comma $map_kv $_gen37 - ctx.rule = rules[143] - tree.astTransform = AstTransformSubstitution(0) - t = expect(ctx, 28) # :comma - tree.add(t) - tree.listSeparator = t - subtree = parse_map_kv(ctx) - tree.add(subtree) - subtree = parse__gen37(ctx) - tree.add(subtree) - return tree - return tree -def parse__gen36(ctx): - current = ctx.tokens.current() - rule = table[65][current.id] if current else -1 - tree = ParseTree(NonTerminal(121, '_gen36')) - ctx.nonterminal = "_gen36" - tree.list = True - if current != None and current.id in nonterminal_follow[121] and current.id not in nonterminal_first[121]: - return tree - if current == None: - return tree - if rule == 142: # $_gen36 = $map_kv $_gen37 - ctx.rule = rules[142] - tree.astTransform = AstTransformSubstitution(0) - subtree = parse_map_kv(ctx) - tree.add(subtree) - subtree = parse__gen37(ctx) - tree.add(subtree) - return tree - return tree -def parse__gen5(ctx): - current = ctx.tokens.current() - rule = table[66][current.id] if current else -1 - tree = ParseTree(NonTerminal(122, '_gen5')) - ctx.nonterminal = "_gen5" - tree.list = True - if current != None and current.id in nonterminal_follow[122] and current.id not in nonterminal_first[122]: - return tree - if current == None: - return tree - if rule == 15: # $_gen5 = $declaration $_gen6 - ctx.rule = rules[15] - tree.astTransform = AstTransformSubstitution(0) - subtree = parse_declaration(ctx) - tree.add(subtree) - subtree = parse__gen6(ctx) - tree.add(subtree) - return tree - return tree -def parse_mapping(ctx): - current = ctx.tokens.current() - rule = table[67][current.id] if current else -1 - tree = ParseTree(NonTerminal(123, 'mapping')) - ctx.nonterminal = "mapping" - tree.list = False - if current == None: - raise ctx.errors.unexpected_eof() - if rule == 92: # $mapping = :identifier :equal $e -> IOMapping( key=$0, value=$2 ) - ctx.rule = rules[92] - ast_parameters = OrderedDict([ - ('key', 0), - ('value', 2), - ]) - tree.astTransform = AstTransformNodeCreator('IOMapping', ast_parameters) - t = expect(ctx, 27) # :identifier - tree.add(t) - t = expect(ctx, 38) # :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[123] if x >=0], - rules[92] - ) -def parse_call_body(ctx): - current = ctx.tokens.current() - rule = table[68][current.id] if current else -1 - tree = ParseTree(NonTerminal(124, 'call_body')) - ctx.nonterminal = "call_body" - tree.list = False - if current == None: - raise ctx.errors.unexpected_eof() - if rule == 86: # $call_body = :lbrace $_gen5 $_gen23 :rbrace -> CallBody( declarations=$1, io=$2 ) - ctx.rule = rules[86] - ast_parameters = OrderedDict([ - ('declarations', 1), - ('io', 2), - ]) - tree.astTransform = AstTransformNodeCreator('CallBody', ast_parameters) - t = expect(ctx, 52) # :lbrace - tree.add(t) - subtree = parse__gen5(ctx) - tree.add(subtree) - subtree = parse__gen23(ctx) - tree.add(subtree) - t = expect(ctx, 40) # :rbrace - tree.add(t) - return tree - raise ctx.errors.unexpected_symbol( - ctx.nonterminal, - ctx.tokens.current(), - [terminals[x] for x in nonterminal_first[124] if x >=0], - rules[86] - ) -def parse_import_namespace(ctx): - current = ctx.tokens.current() - rule = table[69][current.id] if current else -1 - tree = ParseTree(NonTerminal(125, 'import_namespace')) - ctx.nonterminal = "import_namespace" - tree.list = False - if current == None: - raise ctx.errors.unexpected_eof() - if rule == 14: # $import_namespace = :as :identifier -> $1 - ctx.rule = rules[14] - tree.astTransform = AstTransformSubstitution(1) - t = expect(ctx, 26) # :as - tree.add(t) - t = expect(ctx, 27) # :identifier - tree.add(t) - return tree - raise ctx.errors.unexpected_symbol( - ctx.nonterminal, - ctx.tokens.current(), - [terminals[x] for x in nonterminal_first[125] if x >=0], - rules[14] - ) -def parse__gen14(ctx): - current = ctx.tokens.current() - rule = table[70][current.id] if current else -1 - tree = ParseTree(NonTerminal(126, '_gen14')) - ctx.nonterminal = "_gen14" - tree.list = True - if current != None and current.id in nonterminal_follow[126] and current.id not in nonterminal_first[126]: - return tree - if current == None: - return tree - if rule == 43: # $_gen14 = $output_kv $_gen14 - ctx.rule = rules[43] - tree.astTransform = AstTransformSubstitution(0) - subtree = parse_output_kv(ctx) - tree.add(subtree) - subtree = parse__gen14(ctx) - tree.add(subtree) - return tree - return tree -def parse__gen7(ctx): - current = ctx.tokens.current() - rule = table[71][current.id] if current else -1 - tree = ParseTree(NonTerminal(127, '_gen7')) - ctx.nonterminal = "_gen7" - tree.list = True - if current != None and current.id in nonterminal_follow[127] and current.id not in nonterminal_first[127]: - return tree - if current == None: - return tree - if rule == 19: # $_gen7 = $sections $_gen8 - ctx.rule = rules[19] - tree.astTransform = AstTransformSubstitution(0) - subtree = parse_sections(ctx) - tree.add(subtree) - subtree = parse__gen8(ctx) - tree.add(subtree) - return tree - return tree -def parse_map(ctx): - current = ctx.tokens.current() - rule = table[72][current.id] if current else -1 - tree = ParseTree(NonTerminal(128, 'map')) - ctx.nonterminal = "map" - tree.list = False - if current == None: - raise ctx.errors.unexpected_eof() - if rule == 55: # $map = :lbrace $_gen15 :rbrace -> $1 - ctx.rule = rules[55] - tree.astTransform = AstTransformSubstitution(1) - t = expect(ctx, 52) # :lbrace - tree.add(t) - subtree = parse__gen15(ctx) - tree.add(subtree) - t = expect(ctx, 40) # :rbrace - tree.add(t) - return tree - raise ctx.errors.unexpected_symbol( - ctx.nonterminal, - ctx.tokens.current(), - [terminals[x] for x in nonterminal_first[128] if x >=0], - rules[55] - ) -def parse_wf_outputs(ctx): - current = ctx.tokens.current() - rule = table[74][current.id] if current else -1 - tree = ParseTree(NonTerminal(130, 'wf_outputs')) - ctx.nonterminal = "wf_outputs" - tree.list = False - if current == None: - raise ctx.errors.unexpected_eof() - if rule == 98: # $wf_outputs = :output :lbrace $_gen27 :rbrace -> WorkflowOutputs( outputs=$2 ) - ctx.rule = rules[98] - ast_parameters = OrderedDict([ - ('outputs', 2), - ]) - tree.astTransform = AstTransformNodeCreator('WorkflowOutputs', ast_parameters) - t = expect(ctx, 34) # :output - tree.add(t) - t = expect(ctx, 52) # :lbrace - tree.add(t) - subtree = parse__gen27(ctx) - tree.add(subtree) - t = expect(ctx, 40) # :rbrace - tree.add(t) - return tree - raise ctx.errors.unexpected_symbol( - ctx.nonterminal, - ctx.tokens.current(), - [terminals[x] for x in nonterminal_first[130] if x >=0], - rules[98] - ) -# 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 unescape(ctx, terminal, source_string, line, col): - for regex, c in ctx.user_context['replacements'].items(): - source_string = regex.sub(chr(c), 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, unichr(int(number, base))) - 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 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'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|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, 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, 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) - ('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), - ]), - ]), - '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) - ('rparen', 0, None), - LexerAction('pop'), - ]), - (re.compile(r'\('), [ - # (terminal, group, function) - ('lparen', 0, None), - ]), - (re.compile(r'\.'), [ - # (terminal, group, function) - ('dot', 0, None), - ]), - (re.compile(r'\['), [ - # (terminal, group, function) - ('lsquare', 0, None), - ]), - (re.compile(r'\]'), [ - # (terminal, group, function) - ('rsquare', 0, None), - ]), - (re.compile(r'in(?![a-zA-Z0-9_])'), [ - # (terminal, group, function) - ('in', 0, None), - ]), - (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'(true|false)(?![a-zA-Z0-9_])'), [ - # (terminal, group, function) - ('boolean', 0, None), - ]), - (re.compile(r'(Array|Map|Object|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_])*(?=\s*=)'), [ - # (terminal, group, function) - ('cmd_attr_hint', None, None), - ('identifier', 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, 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, 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) - return ctx.tokens -def lex(source, resource, errors=None, debug=False): - return TokenStream(HermesLexer().lex(source, resource, errors, debug)) diff --git a/python/wdl/spec.py b/python/wdl/spec.py deleted file mode 100644 index 1790566..0000000 --- a/python/wdl/spec.py +++ /dev/null @@ -1,57 +0,0 @@ -import subprocess -import re -import os -import tempfile -import toc - -def run(command, cwd=None): - proc = subprocess.Popen( - command, - shell=True, - universal_newlines=True, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - close_fds=True, - cwd=cwd - ) - stdout, stderr = proc.communicate() - return (proc.returncode, stdout.strip(' \n'), stderr.strip(' \n')) - -def write_and_close(contents): - (fd, path) = tempfile.mkstemp() - with os.fdopen(fd, 'w') as fp: - fp.write(wdl_source) - return path - -with open('SPEC.md') as fp: - contents = fp.read() - -toc.modify_and_write("SPEC.md") - -source_regex = re.compile(r'```wdl(.*?)```', re.DOTALL) -count = 0 -wdl_lines = 0 - -def lines(string, index=None): - string = string[:index] if index else string - return sum([1 for c in string if c == '\n']) + 1 - -for match in source_regex.finditer(contents): - count += 1 - wdl_source = match.group(1) - wdl_lines += lines(wdl_source) - line = lines(contents, match.start(1)) - wdl_file = write_and_close(wdl_source) - cmd = 'java -jar ../cromwell/target/scala-2.11/cromwell-0.9.jar parse ' + wdl_file - (rc, stdout, stderr) = run(cmd) - if rc != 0: - print("Line {}: Failure".format(line)) - print(" rc: " + str(rc)) - print(" stdout: " + write_and_close(stdout)) - print(" stderr: " + write_and_close(stderr)) - print(" WDL: " + wdl_file) - print(" Command: " + cmd) - else: - print("Line {}: Success".format(line)) - os.unlink(wdl_file) -print('Total: {}'.format(wdl_lines)) diff --git a/python/wdl/test/cases/0/ast b/python/wdl/test/cases/0/ast deleted file mode 100644 index ca8fb09..0000000 --- a/python/wdl/test/cases/0/ast +++ /dev/null @@ -1,418 +0,0 @@ -(Document: - imports=[], - definitions=[ - (Task: - name=, - declarations=[ - (Declaration: - type=, - postfix=None, - name=, - expression=None - ), - (Declaration: - type=, - postfix=None, - name=, - expression=None - ) - ], - sections=[ - (RawCommand: - parts=[ - - ), - , - value= - ) - ] - ) - ] - ), - (Task: - name=, - postfix=None, - name=, - expression=None - ), - (Declaration: - type=, - postfix=None, - name=, - expression=None - ) - ], - sections=[ - (RawCommand: - parts=[ - , - (CommandParameter: - attributes=[], - expr= - ), - - ] - ), - (Outputs: - attributes=[ - (Output: - type=(Type: - name= - ] - ), - var=, - expression=(FunctionCall: - name=, - params=[ - (FunctionCall: - name=, - params=[] - ) - ] - ) - ), - (Output: - type=, - var=, - expression=(Add: - lhs=, - rhs= - ) - ) - ] - ), - (Runtime: - map=[ - (RuntimeAttribute: - key=, - value= - ) - ] - ) - ] - ), - (Task: - name=, - postfix=None, - name=, - expression=None - ), - (Declaration: - type=, - postfix=None, - name=, - expression=None - ) - ], - sections=[ - (RawCommand: - parts=[ - , - (CommandParameter: - attributes=[], - expr= - ), - - ] - ), - (Outputs: - attributes=[ - (Output: - type=(Type: - name= - ] - ), - var=, - expression=(FunctionCall: - name=, - params=[ - (FunctionCall: - name=, - params=[] - ) - ] - ) - ) - ] - ), - (Runtime: - map=[ - (RuntimeAttribute: - key=, - value= - ) - ] - ) - ] - ), - (Task: - name=, - postfix=None, - name=, - expression=None - ), - (Declaration: - type=, - postfix=None, - name=, - expression=None - ) - ], - sections=[ - (RawCommand: - parts=[ - - ), - - ] - ), - (Outputs: - attributes=[ - (Output: - type=(Type: - name= - ] - ), - var=, - expression=(FunctionCall: - name=, - params=[ - (FunctionCall: - name=, - params=[] - ) - ] - ) - ) - ] - ), - (Runtime: - map=[ - (RuntimeAttribute: - key=, - value= - ) - ] - ) - ] - ), - (Workflow: - name=, - body=[ - (Declaration: - type=(Type: - name= - ] - ) - ] - ) - ] - ), - postfix=None, - name=, - expression=None - ), - (Declaration: - type=, - postfix=None, - name=, - expression=None - ), - (Declaration: - type=, - postfix=None, - name=, - rhs= - ), - rhs= - ), - rhs= - ), - rhs= - ) - ), - (Declaration: - type=, - postfix=None, - name=, - expression=(Add: - lhs=, - rhs=, - postfix=None, - name=, - expression=, - value= - ), - (IOMapping: - key=, - value= - ) - ] - ) - ] - ) - ), - (Call: - task=, - value= - ), - (IOMapping: - key=, - value= - ) - ] - ) - ] - ) - ), - (Call: - task=, - value=(Add: - lhs=, - rhs=, - value= - ) - ] - ) - ] - ) - ), - (Call: - task=, - alias=None, - body=(CallBody: - declarations=[], - io=[ - (Inputs: - map=[ - (IOMapping: - key=, - value= - ), - (IOMapping: - key=, - value= - ) - ] - ) - ] - ) - ), - (Scatter: - item=, - collection=, - body=[ - (Scatter: - item=, - collection=, - body=[ - (Scatter: - item=, - collection=, - body=[ - (Call: - task=, - body=(CallBody: - declarations=[], - io=[ - (Inputs: - map=[ - (IOMapping: - key=, - value= - ), - (IOMapping: - key=, - value= - ) - ] - ) - ] - ) - ) - ] - ) - ] - ) - ] - ) - ] - ) - ] -) \ No newline at end of file diff --git a/python/wdl/test/cases/0/parsetree b/python/wdl/test/cases/0/parsetree deleted file mode 100644 index 2e09acc..0000000 --- a/python/wdl/test/cases/0/parsetree +++ /dev/null @@ -1,937 +0,0 @@ -(document: - (_gen0: ), - (_gen2: - (workflow_or_task: - (task: - , - , - , - (_gen5: - (declaration: - (type_e: - - ), - (_gen17: ), - , - (_gen18: ) - ), - (_gen6: - (declaration: - (type_e: - - ), - (_gen17: ), - , - (_gen18: ) - ), - (_gen6: ) - ) - ), - (_gen7: - (sections: - (command: - , - , - (_gen9: - (command_part: - - ), - - ) - ), - (_gen10: - (command_part: - - ) - ), - (_gen8: - (sections: - (runtime: - , - (map: - , - (_gen15: - (kv: - , - , - (e: - - ) - ), - (_gen16: ) - ), - - ) - ) - ), - (_gen8: ) - ) - ), - - ) - ), - (_gen3: - (workflow_or_task: - (task: - , - , - (_gen5: - (declaration: - (type_e: - - ), - (_gen17: ), - , - (_gen18: ) - ), - (_gen6: - (declaration: - (type_e: - - ), - (_gen17: ), - , - (_gen18: ) - ), - (_gen6: ) - ) - ), - (_gen7: - (sections: - (command: - , - (_gen9: - (command_part: - - ), - (_gen10: - (command_part: - (cmd_param: - - ), - - ) - ), - (_gen10: - (command_part: - - ), - (_gen10: ) - ) - ) - ), - - ) - ), - (_gen8: - (sections: - (outputs: - , - , - (_gen13: - (output_kv: - (type_e: - (type_e: - , - (_gen30: - (type_e: - - ), - (_gen31: ) - ), - - ), - , - , - (e: - (e: - - ), - , - (_gen32: - (e: - (e: - - ), - , - (_gen32: ), - - ), - (_gen33: ) - ), - - ) - ), - (_gen14: - (output_kv: - (type_e: - - ), - , - , - (e: - (e: - - ), - , - (e: - - ) - ) - ), - (_gen14: ) - ) - ), - - ) - ), - (_gen8: - (sections: - (runtime: - , - (map: - , - (_gen15: - (kv: - , - , - (e: - - ) - ), - (_gen16: ) - ), - - ) - ) - ), - (_gen8: ) - ) - ) - ), - - ) - ), - (_gen3: - (workflow_or_task: - (task: - , - , - (_gen5: - (declaration: - (type_e: - - ), - (_gen17: ), - , - (_gen18: ) - ), - (_gen6: - (declaration: - (type_e: - - ), - (_gen17: ), - , - (_gen18: ) - ), - (_gen6: ) - ) - ), - (_gen7: - (sections: - (command: - , - (_gen9: - (command_part: - - ), - (_gen10: - (command_part: - (cmd_param: - - ), - - ) - ), - (_gen10: - (command_part: - - ), - (_gen10: ) - ) - ) - ), - - ) - ), - (_gen8: - (sections: - (outputs: - , - , - (_gen13: - (output_kv: - (type_e: - (type_e: - , - (_gen30: - (type_e: - - ), - (_gen31: ) - ), - - ), - , - , - (e: - (e: - - ), - , - (_gen32: - (e: - (e: - - ), - , - (_gen32: ), - - ), - (_gen33: ) - ), - - ) - ), - (_gen14: ) - ), - - ) - ), - (_gen8: - (sections: - (runtime: - , - (map: - , - (_gen15: - (kv: - , - , - (e: - - ) - ), - (_gen16: ) - ), - - ) - ) - ), - (_gen8: ) - ) - ) - ), - - ) - ), - (_gen3: - (workflow_or_task: - (task: - , - , - (_gen5: - (declaration: - (type_e: - - ), - (_gen17: ), - , - (_gen18: ) - ), - (_gen6: - (declaration: - (type_e: - - ), - (_gen17: ), - , - (_gen18: ) - ), - (_gen6: ) - ) - ), - (_gen7: - (sections: - (command: - , - (_gen9: - (command_part: - - ), - - ) - ), - (_gen10: - (command_part: - - ), - (_gen10: ) - ) - ) - ), - - ) - ), - (_gen8: - (sections: - (outputs: - , - , - (_gen13: - (output_kv: - (type_e: - (type_e: - , - (_gen30: - (type_e: - - ), - (_gen31: ) - ), - - ), - , - , - (e: - (e: - - ), - , - (_gen32: - (e: - (e: - - ), - , - (_gen32: ), - - ), - (_gen33: ) - ), - - ) - ), - (_gen14: ) - ), - - ) - ), - (_gen8: - (sections: - (runtime: - , - (map: - , - (_gen15: - (kv: - , - , - (e: - - ) - ), - (_gen16: ) - ), - - ) - ) - ), - (_gen8: ) - ) - ) - ), - - ) - ), - (_gen3: - (workflow_or_task: - (workflow: - , - , - (_gen19: - (wf_body_element: - (declaration: - (type_e: - (type_e: - , - (_gen30: - (type_e: - (type_e: - , - (_gen30: - (type_e: - (type_e: - , - (_gen30: - (type_e: - - ), - (_gen31: ) - ), - - ), - (_gen31: ) - ), - - ), - (_gen31: ) - ), - - ), - (_gen17: ), - , - (_gen18: ) - ) - ), - (_gen20: - (wf_body_element: - (declaration: - (type_e: - - ), - (_gen17: ), - , - (_gen18: ) - ) - ), - (_gen20: - (wf_body_element: - (declaration: - (type_e: - - ), - (_gen17: ), - , - (e: - (e: - (e: - (e: - (e: - - ), - , - (e: - - ) - ), - , - (e: - - ) - ), - , - (e: - - ) - ), - , - (e: - - ) - ) - ) - ) - ) - ), - (_gen20: - (wf_body_element: - (declaration: - (type_e: - - ), - (_gen17: ), - , - (_gen18: - (setter: - , - (e: - (e: - - ), - , - (e: - - ), - (_gen17: ), - , - (_gen18: - (setter: - , - (e: - , - , - (_gen5: ), - (_gen23: - (call_input: - , - (_gen25: - (mapping: - , - , - (e: - - ) - ), - (_gen26: - , - (mapping: - , - , - (e: - - ) - ), - (_gen26: ) - ) - ) - ), - (_gen24: ) - ), - - ) - ) - ) - ), - (_gen20: - (wf_body_element: - (call: - , - , - (_gen5: ), - (_gen23: - (call_input: - , - (_gen25: - (mapping: - , - , - (e: - - ) - ), - (_gen26: - , - (mapping: - , - , - (e: - - ) - ), - (_gen26: ) - ) - ) - ), - (_gen24: ) - ), - - ) - ) - ) - ), - (_gen20: - (wf_body_element: - (call: - , - , - (_gen5: ), - (_gen23: - (call_input: - , - (_gen25: - (mapping: - , - , - (e: - (e: - - ), - , - (e: - , - (mapping: - , - , - (e: - - ) - ), - (_gen26: ) - ) - ) - ), - (_gen24: ) - ), - - ) - ) - ) - ), - (_gen20: - (wf_body_element: - (call: - , - , - (_gen21: ), - (_gen22: - (call_body: - , - (_gen5: ), - (_gen23: - (call_input: - , - (_gen25: - (mapping: - , - , - (e: - - ) - ), - (_gen26: - , - (mapping: - , - , - (e: - - ) - ), - (_gen26: ) - ) - ) - ), - (_gen24: ) - ), - - ) - ) - ) - ), - (_gen20: - (wf_body_element: - (scatter: - , - , - , - - ), - , - , - (_gen19: - (wf_body_element: - (scatter: - , - , - , - - ), - , - , - (_gen19: - (wf_body_element: - (scatter: - , - , - , - - ), - , - , - (_gen19: - (wf_body_element: - (call: - , - - ) - ), - (_gen22: - (call_body: - , - (_gen5: ), - (_gen23: - (call_input: - , - (_gen25: - (mapping: - , - , - (e: - - ) - ), - (_gen26: - , - (mapping: - , - , - (e: - - ) - ), - (_gen26: ) - ) - ) - ), - (_gen24: ) - ), - - ) - ) - ) - ), - (_gen20: ) - ), - - ) - ), - (_gen20: ) - ), - - ) - ), - (_gen20: ) - ), - - ) - ), - (_gen20: ) - ) - ) - ) - ) - ) - ) - ) - ) - ) - ), - - ) - ), - (_gen3: ) - ) - ) - ) - ) - ) -) \ No newline at end of file diff --git a/python/wdl/test/cases/0/wdl b/python/wdl/test/cases/0/wdl deleted file mode 100644 index ca9f4c8..0000000 --- a/python/wdl/test/cases/0/wdl +++ /dev/null @@ -1,88 +0,0 @@ -task inline { - File path - String docker - command<<< - python3 <>> - runtime { - docker: "${docker}" - } -} - -task task1 { - File infile - String docker - command { - grep '^aberran' ${infile} - } - output { - Array[String] words_a = read_lines(stdout()) - Int foo = 1+1 - } - runtime { - docker: "${docker}" - } -} - -task task2 { - File infile - String docker - command { - grep '^backbone' ${infile} - } - output { - Array[String] words_b = read_lines(stdout()) - } - runtime { - docker: "${docker}" - } -} - -task task3 { - File infile - String docker - command { - grep '^xyl' ${infile} || exit 0 - } - output { - Array[String] words_x = read_lines(stdout()) - } - runtime { - docker: "${docker}" - } -} - -workflow simple { - Array[Array[Array[File]]] scatter_files - String docker - String words = "w"+"o"+"r"+"d"+"s" - File dict_file = "/usr/share/dict/" + words - Boolean b = false - - call task1 { - input: docker=docker, infile=dict_file - } - call task2 { - input: infile=dict_file, docker=docker - } - call task3 as alias { - input: infile="/usr/share/dict/" + words, docker=docker - } - call inline { - input: path=dict_file, docker=docker - } - scatter(x in scatter_files) { - scatter(y in x) { - scatter(z in y) { - call task2 as alias2 { - input: infile=z, docker=docker - } - } - } - } -} diff --git a/python/wdl/test/cases/1/ast b/python/wdl/test/cases/1/ast deleted file mode 100644 index c2e47eb..0000000 --- a/python/wdl/test/cases/1/ast +++ /dev/null @@ -1,187 +0,0 @@ -(Document: - imports=[], - definitions=[ - (Task: - name=, - declarations=[ - (Declaration: - type=, - postfix=None, - name=, - expression=None - ), - (Declaration: - type=, - postfix=, - name=, - postfix=None, - name=, - expression=None - ) - ], - sections=[ - (RawCommand: - parts=[ - - ), - , - (CommandParameter: - attributes=[], - expr= - ), - - ] - ), - (Outputs: - attributes=[ - (Output: - type=, - var=, - expression=(FunctionCall: - name=, - params=[] - ) - ) - ] - ), - (Runtime: - map=[ - (RuntimeAttribute: - key=, - value= - ), - (RuntimeAttribute: - key= - ), - (RuntimeAttribute: - key=, - value= - ) - ] - ) - ] - ), - (Task: - name= - ] - ), - postfix=, - name=, - value= - ) - ], - expr= - ] - ), - (Outputs: - attributes=[ - (Output: - type=, - var=, - params=[] - ) - ] - ) - ) - ] - ) - ] - ), - (Workflow: - name=, - body=[ - (Declaration: - type=(Type: - name= - ] - ), - postfix=None, - name=, - collection=, - alias=None, - body=(CallBody: - declarations=[], - io=[ - (Inputs: - map=[ - (IOMapping: - key=, - value= - ) - ] - ) - ] - ) - ) - ] - ), - (Call: - task=, - rhs= - ) - ) - ] - ) - ] - ) - ) - ] - ) - ] -) \ No newline at end of file diff --git a/python/wdl/test/cases/1/parsetree b/python/wdl/test/cases/1/parsetree deleted file mode 100644 index 798c914..0000000 --- a/python/wdl/test/cases/1/parsetree +++ /dev/null @@ -1,417 +0,0 @@ -(document: - (_gen0: ), - (_gen2: - (workflow_or_task: - (task: - , - , - , - (_gen5: - (declaration: - (type_e: - - ), - (_gen17: ), - , - (_gen18: ) - ), - (_gen6: - (declaration: - (type_e: - - ), - (_gen17: - (postfix_quantifier: - - ) - ), - - ), - (_gen17: ), - , - (_gen18: ) - ), - (_gen6: ) - ) - ) - ), - (_gen7: - (sections: - (command: - , - (_gen9: - (command_part: - - ), - - ) - ), - (_gen10: - (command_part: - - ) - ), - (_gen10: - (command_part: - - ), - (_gen10: - (command_part: - (cmd_param: - - ), - - ) - ), - (_gen10: - (command_part: - - ), - (_gen10: ) - ) - ) - ) - ) - ) - ) - ), - - ) - ), - (_gen8: - (sections: - (outputs: - , - , - (_gen13: - (output_kv: - (type_e: - - ), - , - , - (e: - (e: - - ), - , - (_gen32: ), - - ) - ), - (_gen14: ) - ), - - ) - ), - (_gen8: - (sections: - (runtime: - , - (map: - , - (_gen15: - (kv: - , - , - (e: - - ) - ), - (_gen16: - (kv: - , - (e: - - ) - ), - (_gen16: - (kv: - , - , - (e: - - ) - ), - (_gen16: ) - ) - ) - ), - - ) - ) - ), - (_gen8: ) - ) - ) - ), - - ) - ), - (_gen3: - (workflow_or_task: - (task: - , - , - (_gen5: - (declaration: - (type_e: - (type_e: - , - (_gen30: - (type_e: - - ), - (_gen31: ) - ), - - ), - (_gen17: - (postfix_quantifier: - - ) - ), - , - (_gen9: - (command_part: - , - , - , - (e: - - ) - ), - (_gen12: ) - ), - (e: - - ) - ), - (_gen10: - (command_part: - - ), - (_gen10: ) - ) - ) - ), - - ) - ), - (_gen8: - (sections: - (outputs: - , - , - (_gen13: - (output_kv: - (type_e: - - ), - , - (e: - (e: - , - (_gen32: - (e: - (e: - - ), - , - (_gen32: ), - - ), - (_gen33: ) - ), - - ) - ), - (_gen14: ) - ), - - ) - ), - (_gen8: ) - ) - ), - - ) - ), - (_gen3: - (workflow_or_task: - (workflow: - , - , - (_gen19: - (wf_body_element: - (declaration: - (type_e: - (type_e: - , - (_gen30: - (type_e: - - ), - (_gen31: ) - ), - - ), - (_gen17: ), - , - , - , - , - , - (_gen19: - (wf_body_element: - (call: - , - , - (_gen21: ), - (_gen22: - (call_body: - , - (_gen5: ), - (_gen23: - (call_input: - , - (_gen25: - (mapping: - , - , - (e: - - ) - ), - (_gen26: ) - ) - ), - (_gen24: ) - ), - - ) - ) - ) - ), - (_gen20: ) - ), - - ) - ), - (_gen20: - (wf_body_element: - (call: - , - , - (_gen5: ), - (_gen23: - (call_input: - , - (_gen25: - (mapping: - , - (e: - (e: - - ), - , - - ) - ), - (_gen26: ) - ) - ), - (_gen24: ) - ), - - ) - ) - ) - ), - (_gen20: ) - ) - ) - ), - - ) - ), - (_gen3: ) - ) - ) - ) -) \ No newline at end of file diff --git a/python/wdl/test/cases/1/wdl b/python/wdl/test/cases/1/wdl deleted file mode 100644 index 8ce1499..0000000 --- a/python/wdl/test/cases/1/wdl +++ /dev/null @@ -1,39 +0,0 @@ -task grep { - String pattern - String? flags - File file_name - - command { - grep '${pattern}' ${flags} ${file_name} - } - output { - File out = stdout() - } - runtime { - memory: "2MB" - cores: 1 - disk: "3MB" - } -} - -task wc { - Array[File]+ files - command { - wc -l ${sep=' ' files} | tail -1 | tr -s ' ' | cut -d' ' -f 2 - } - output { - Int count = read_int(stdout()) - } -} - -workflow scatter_gather_grep_wc { - Array[File] input_files - scatter(f in input_files) { - call grep { - input: file_name = f - } - } - call wc { - input: files = grep.out - } -} diff --git a/python/wdl/test/cases/2/ast b/python/wdl/test/cases/2/ast deleted file mode 100644 index bf27fe5..0000000 --- a/python/wdl/test/cases/2/ast +++ /dev/null @@ -1,114 +0,0 @@ -(Document: - imports=[], - definitions=[ - (Task: - name=, - declarations=[ - (Declaration: - type=, - postfix=None, - name=, - postfix=None, - name=, - expression=None - ) - ], - sections=[ - (RawCommand: - parts=[ - , - (CommandParameter: - attributes=[], - expr= - ), - - ] - ), - (Outputs: - attributes=[ - (Output: - type=(Type: - name= - ] - ), - var=, - params=[ - (FunctionCall: - name=, - params=[] - ) - ] - ) - ) - ] - ) - ] - ), - (Workflow: - name=, - postfix=None, - name=, - expression=None - ), - (Call: - task=, - alias=, - body=(CallBody: - declarations=[], - io=[ - (Inputs: - map=[ - (IOMapping: - key=, - value= - ) - ] - ) - ] - ) - ), - (Call: - task=, - alias=, - body=(CallBody: - declarations=[], - io=[ - (Inputs: - map=[ - (IOMapping: - key=, - value= - ) - ] - ) - ] - ) - ) - ] - ) - ] -) \ No newline at end of file diff --git a/python/wdl/test/cases/2/parsetree b/python/wdl/test/cases/2/parsetree deleted file mode 100644 index 5bcdd32..0000000 --- a/python/wdl/test/cases/2/parsetree +++ /dev/null @@ -1,251 +0,0 @@ -(document: - (_gen0: ), - (_gen2: - (workflow_or_task: - (task: - , - , - , - (_gen5: - (declaration: - (type_e: - - ), - (_gen17: ), - - ), - (_gen17: ), - , - (_gen18: ) - ), - (_gen6: ) - ) - ), - (_gen7: - (sections: - (command: - , - (_gen9: - (command_part: - - ), - (_gen10: - (command_part: - (cmd_param: - - ) - ), - (_gen10: - (command_part: - - ), - - ) - ), - (_gen10: - (command_part: - - ), - (_gen10: ) - ) - ) - ) - ) - ), - - ) - ), - (_gen8: - (sections: - (outputs: - , - , - (_gen13: - (output_kv: - (type_e: - (type_e: - , - (_gen30: - (type_e: - - ), - (_gen31: ) - ), - - ), - , - (e: - (e: - - ), - , - (_gen32: - (e: - (e: - - ), - , - (_gen32: ), - - ), - (_gen33: ) - ), - - ) - ), - (_gen14: ) - ), - - ) - ), - (_gen8: ) - ) - ), - - ) - ), - (_gen3: - (workflow_or_task: - (workflow: - , - (_gen19: - (wf_body_element: - (declaration: - (type_e: - - ), - (_gen17: ), - , - (_gen18: ) - ) - ), - (_gen20: - (wf_body_element: - (call: - , - , - (_gen21: - (alias: - - ) - ), - (_gen22: - (call_body: - , - (_gen5: ), - (_gen23: - (call_input: - , - (_gen25: - (mapping: - , - (e: - , - (mapping: - , - , - (e: - - ) - ), - (_gen26: ) - ) - ) - ), - (_gen24: ) - ), - - ) - ) - ) - ), - (_gen20: - (wf_body_element: - (call: - , - , - (_gen21: - (alias: - - ) - ), - (_gen22: - (call_body: - , - (_gen5: ), - (_gen23: - (call_input: - , - (_gen25: - (mapping: - , - (e: - , - (mapping: - , - , - (e: - - ) - ), - (_gen26: ) - ) - ) - ), - (_gen24: ) - ), - - ) - ) - ) - ), - (_gen20: ) - ) - ) - ), - - ) - ), - (_gen3: ) - ) - ) -) \ No newline at end of file diff --git a/python/wdl/test/cases/2/wdl b/python/wdl/test/cases/2/wdl deleted file mode 100644 index d62c636..0000000 --- a/python/wdl/test/cases/2/wdl +++ /dev/null @@ -1,21 +0,0 @@ -task grep_words { - String start - File infile - - command { - grep '^${start}' ${infile} - } - output { - Array[String] words = read_lines(stdout()) - } -} -workflow wf { - File dictionary - - call grep_words as grep_pythonic_words { - input: start="pythonic", infile=dictionary - } - call grep_words as grep_workf_words { - input: start="workf", infile=dictionary - } -} diff --git a/python/wdl/test/cases/3/ast b/python/wdl/test/cases/3/ast deleted file mode 100644 index c6498fc..0000000 --- a/python/wdl/test/cases/3/ast +++ /dev/null @@ -1,192 +0,0 @@ -(Document: - imports=[], - definitions=[ - (Task: - name=, - declarations=[ - (Declaration: - type=, - postfix=None, - name=, - postfix=None, - name=, - (CommandParameter: - attributes=[], - expr= - ] - ), - (Outputs: - attributes=[ - (Output: - type=(Type: - name= - ] - ), - var=, - params=[ - (FunctionCall: - name=, - params=[] - ) - ] - ) - ) - ] - ) - ] - ), - (Task: - name=, - postfix=None, - name= - ] - ) - ] - ), - postfix=None, - name=, - expression=None - ) - ], - sections=[ - (RawCommand: - parts=[ - , - (CommandParameter: - attributes=[], - expr=, - (CommandParameter: - attributes=[], - expr= - ), - , - var= - ] - ), - postfix=None, - name=, - postfix=None, - name=, - alias=None, - body=(CallBody: - declarations=[], - io=[ - (Inputs: - map=[ - (IOMapping: - key=, - value=(MemberAccess: - lhs=, - rhs=, - , - , - (_gen5: - (declaration: - (type_e: - - ), - (_gen17: ), - - ), - (_gen17: ), - , - (_gen9: - (command_part: - - ) - ), - (_gen10: - (command_part: - - ), - (_gen10: - (command_part: - (cmd_param: - - ) - ), - (_gen10: - (command_part: - - ), - (_gen10: ) - ) - ) - ) - ) - ), - - ) - ), - (_gen8: - (sections: - (outputs: - , - , - (_gen13: - (output_kv: - (type_e: - (type_e: - , - (_gen30: - (type_e: - - ), - (_gen31: ) - ), - - ), - , - (e: - (e: - - ), - , - (_gen32: - (e: - (e: - - ), - , - (_gen32: ), - - ), - (_gen33: ) - ), - - ) - ), - (_gen14: ) - ), - - ) - ), - (_gen8: ) - ) - ), - - ) - ), - (_gen3: - (workflow_or_task: - (task: - , - , - (_gen5: - (declaration: - (type_e: - - ), - (_gen17: ), - , - (_gen30: - (type_e: - (type_e: - , - (_gen30: - (type_e: - - ), - (_gen31: ) - ), - - ), - (_gen31: ) - ), - - ), - (_gen17: ), - , - (_gen18: ) - ), - (_gen6: ) - ) - ), - (_gen7: - (sections: - (command: - , - (_gen9: - (command_part: - - ), - (_gen10: - (command_part: - (cmd_param: - - ) - ), - (_gen10: - (command_part: - - ), - (_gen10: - (command_part: - (cmd_param: - - ), - - ) - ), - (_gen10: - (command_part: - - ) - ), - (_gen8: - (sections: - (outputs: - , - , - (_gen13: - (output_kv: - (type_e: - - ), - , - (e: - (e: - , - (_gen32: - (e: - - ) - ), - (_gen14: ) - ), - - ) - ), - (_gen8: ) - ) - ), - - ) - ), - (_gen3: - (workflow_or_task: - (workflow: - , - (_gen19: - (wf_body_element: - (declaration: - (type_e: - (type_e: - , - (_gen30: - (type_e: - - ), - (_gen31: ) - ), - - ), - (_gen17: ), - - ), - (_gen17: ), - , - , - , - , - (_gen19: - (wf_body_element: - (call: - , - , - (_gen21: ), - (_gen22: - (call_body: - , - (_gen5: ), - (_gen23: - (call_input: - , - (_gen25: - (mapping: - , - (e: - , - (mapping: - , - (e: - - ) - ) - ) - ), - (_gen20: ) - ), - - ) - ), - (_gen20: - (wf_body_element: - (call: - , - , - (_gen5: ), - (_gen23: - (call_input: - , - (_gen25: - (mapping: - , - (e: - , - (mapping: - , - , - (e: - (e: - - ), - , - - ) - ) - ) - ), - (_gen20: ) - ) - ) - ) - ), - - ) - ), - (_gen3: ) - ) - ) - ) -) \ No newline at end of file diff --git a/python/wdl/test/cases/3/wdl b/python/wdl/test/cases/3/wdl deleted file mode 100644 index 47e595a..0000000 --- a/python/wdl/test/cases/3/wdl +++ /dev/null @@ -1,43 +0,0 @@ -task scatter_task { - Int count - File in - - command <<< - egrep ^.{${count}}$ ${in} || exit 0 - >>> - output { - Array[String] words = read_lines(stdout()) - } -} - -task gather_task { - Int count - Array[Array[String]] word_lists - - command { - python3 <, - postfix=None, - name=, - expression=None - ) - ], - sections=[ - (RawCommand: - parts=[ - - ), - - ] - ), - (Outputs: - attributes=[ - (Output: - type=, - var=, - params=[] - ) - ] - ), - rhs= - ) - ) - ] - ) - ] - ), - (Workflow: - name= - ] - ) - ] - ) - ] - ), - postfix=None, - name=, - expression=None - ), - (Scatter: - item=, - collection=, - body=[ - (Scatter: - item=, - collection=, - body=[ - (Scatter: - item=, - collection=, - body=[ - (Call: - task=, - value= - ) - ] - ) - ] - ) - ) - ] - ) - ] - ) - ] - ) - ] - ) - ] -) \ No newline at end of file diff --git a/python/wdl/test/cases/4/parsetree b/python/wdl/test/cases/4/parsetree deleted file mode 100644 index 2933c33..0000000 --- a/python/wdl/test/cases/4/parsetree +++ /dev/null @@ -1,238 +0,0 @@ -(document: - (_gen0: ), - (_gen2: - (workflow_or_task: - (task: - , - , - (_gen5: - (declaration: - (type_e: - - ), - (_gen17: ), - , - (_gen18: ) - ), - (_gen6: ) - ), - (_gen7: - (sections: - (command: - , - (_gen9: - (command_part: - - ), - - ) - ), - (_gen10: - (command_part: - - ), - (_gen10: ) - ) - ) - ), - - ) - ), - (_gen8: - (sections: - (outputs: - , - , - (_gen13: - (output_kv: - (type_e: - - ), - , - (e: - (e: - (e: - , - (_gen32: - (e: - (e: - - ), - , - (_gen32: ), - - ), - (_gen33: ) - ), - - ), - , - (e: - - ) - ) - ), - (_gen14: ) - ), - - ) - ), - (_gen8: ) - ) - ), - - ) - ), - (_gen3: - (workflow_or_task: - (workflow: - , - (_gen19: - (wf_body_element: - (declaration: - (type_e: - (type_e: - , - (_gen30: - (type_e: - (type_e: - , - (_gen30: - (type_e: - (type_e: - , - (_gen30: - (type_e: - - ), - (_gen31: ) - ), - - ), - (_gen31: ) - ), - - ), - (_gen31: ) - ), - - ), - (_gen17: ), - , - (_gen18: ) - ) - ), - (_gen20: - (wf_body_element: - (scatter: - , - , - , - - ), - , - , - (_gen19: - (wf_body_element: - (scatter: - , - , - , - - ), - , - , - (_gen19: - (wf_body_element: - (scatter: - , - , - , - - ), - , - , - (_gen19: - (wf_body_element: - (call: - , - , - (_gen5: ), - (_gen23: - (call_input: - , - (_gen25: - (mapping: - , - , - (e: - - ) - ), - (_gen26: ) - ) - ), - (_gen24: ) - ), - - ) - ) - ) - ), - (_gen20: ) - ), - - ) - ), - (_gen20: ) - ), - - ) - ), - (_gen20: ) - ), - - ) - ), - (_gen20: ) - ) - ), - - ) - ), - (_gen3: ) - ) - ) -) \ No newline at end of file diff --git a/python/wdl/test/cases/4/wdl b/python/wdl/test/cases/4/wdl deleted file mode 100644 index 3c7faf9..0000000 --- a/python/wdl/test/cases/4/wdl +++ /dev/null @@ -1,20 +0,0 @@ -task wc { - String str - command { - echo "${str}" | wc -c - } - output { - Int count = read_int(stdout()) - 1 - } -} - -workflow wf { - Array[Array[Array[String]]] triple_array - scatter(double_array in triple_array) { - scatter(single_array in double_array) { - scatter(item in single_array) { - call wc{input: str=item} - } - } - } -} diff --git a/python/wdl/test/cases/5/ast b/python/wdl/test/cases/5/ast deleted file mode 100644 index 7a48e91..0000000 --- a/python/wdl/test/cases/5/ast +++ /dev/null @@ -1,446 +0,0 @@ -(Document: - imports=[], - definitions=[ - (Task: - name=, - postfix=, - name= - ] - ), - (Outputs: - attributes=[ - (Output: - type=, - var=, - params=[] - ) - ) - ] - ) - ] - ), - (Task: - name=, - declarations=[ - (Declaration: - type=, - postfix=None, - name=, - expression=None - ), - (Declaration: - type=, - postfix=, - name=, - expression=None - ), - (Declaration: - type=, - postfix=None, - name=, - expression=None - ) - ], - sections=[ - (RawCommand: - parts=[ - , - (CommandParameter: - attributes=[], - expr= - ), - , - (CommandParameter: - attributes=[], - expr=(Add: - lhs=, - rhs= - ) - ), - , - (CommandParameter: - attributes=[], - expr= - ), - - ] - ), - (Outputs: - attributes=[ - (Output: - type=(Type: - name= - ] - ), - var=, - params=[ - (FunctionCall: - name=, - params=[] - ) - ] - ) - ) - ] - ) - ] - ), - (Task: - name=, - declarations=[ - (Declaration: - type=(Type: - name= - ] - ), - postfix=, - name=, - postfix=None, - name=, - expression=None - ) - ], - sections=[ - (RawCommand: - parts=[ - , - (CommandParameter: - attributes=[ - (CommandParameterAttr: - key=, - value= - ) - ], - expr=, - (CommandParameter: - attributes=[], - expr= - ), - - ] - ), - (Outputs: - attributes=[ - (Output: - type=, - var=, - expression= - ) - ] - ) - ] - ), - (Task: - name=, - declarations=[ - (Declaration: - type=(Type: - name= - ] - ), - postfix=, - name=, - (CommandParameter: - attributes=[ - (CommandParameterAttr: - key=, - value= - ) - ], - expr=, - var=, - params=[] - ) - ] - ) - ) - ] - ) - ] - ), - (Task: - name=, - declarations=[ - (Declaration: - type=(Type: - name= - ] - ), - postfix=, - name=, - (CommandParameter: - attributes=[ - (CommandParameterAttr: - key=, - value= - ) - ], - expr=, - var=, - params=[] - ) - ] - ) - ) - ] - ) - ] - ), - (Workflow: - name=, - body=[ - (Declaration: - type=(Type: - name= - ] - ), - postfix=None, - name=, - postfix=None, - name=, - expression=None - ), - (Call: - task= - ) - ] - ) - ] - ) - ), - (Call: - task=, - alias=, - alias=, - alias=None, - body=(CallBody: - declarations=[], - io=[ - (Inputs: - map=[ - (IOMapping: - key=, - alias=, - body=(CallBody: - declarations=[], - io=[ - (Inputs: - map=[ - (IOMapping: - key=, - value= - ) - ] - ) - ] - ) - ), - (Call: - task=, - alias=, - value= - ), - (IOMapping: - key=, - value= - ) - ] - ) - ] - ) - ), - (Call: - task=, - alias=, - body=(CallBody: - declarations=[], - io=[ - (Inputs: - map=[ - (IOMapping: - key=, - alias=, - body=(CallBody: - declarations=[], - io=[ - (Inputs: - map=[ - (IOMapping: - key=, - , - (_gen5: - (declaration: - (type_e: - - ), - (_gen17: - (postfix_quantifier: - - ) - ), - , - (_gen9: - (command_part: - - ) - ), - (_gen10: - (command_part: - - ), - (_gen10: ) - ) - ) - ), - - ) - ), - (_gen8: - (sections: - (outputs: - , - , - (_gen13: - (output_kv: - (type_e: - - ), - , - (e: - (e: - - ), - , - (_gen32: ), - - ) - ), - (_gen14: ) - ), - - ) - ), - (_gen8: ) - ) - ), - - ) - ), - (_gen3: - (workflow_or_task: - (task: - , - , - , - (_gen5: - (declaration: - (type_e: - - ), - (_gen17: ), - , - (_gen18: ) - ), - (_gen6: - (declaration: - (type_e: - - ), - (_gen17: - (postfix_quantifier: - - ) - ), - , - (_gen18: ) - ), - (_gen6: - (declaration: - (type_e: - - ), - (_gen17: ), - , - (_gen18: ) - ), - (_gen6: ) - ) - ) - ), - (_gen7: - (sections: - (command: - , - (_gen9: - (command_part: - - ), - (_gen10: - (command_part: - (cmd_param: - - ), - - ) - ), - (_gen10: - (command_part: - - ), - (_gen10: - (command_part: - (cmd_param: - - ), - , - (e: - - ) - ), - - ) - ), - (_gen10: - (command_part: - - ), - (_gen10: - (command_part: - (cmd_param: - - ), - - ) - ), - (_gen10: - (command_part: - - ), - (_gen10: ) - ) - ) - ) - ) - ) - ) - ), - - ) - ), - (_gen8: - (sections: - (outputs: - , - , - (_gen13: - (output_kv: - (type_e: - (type_e: - , - (_gen30: - (type_e: - - ), - (_gen31: ) - ), - - ), - , - (e: - (e: - - ), - , - (_gen32: - (e: - (e: - - ), - , - (_gen32: ), - - ), - (_gen33: ) - ), - - ) - ), - (_gen14: ) - ), - - ) - ), - (_gen8: ) - ) - ), - - ) - ), - (_gen3: - (workflow_or_task: - (task: - , - , - , - (_gen5: - (declaration: - (type_e: - (type_e: - , - (_gen30: - (type_e: - - ), - (_gen31: ) - ), - - ), - (_gen17: - (postfix_quantifier: - - ) - ), - - ), - (_gen17: ), - , - (_gen18: ) - ), - (_gen6: ) - ) - ), - (_gen7: - (sections: - (command: - , - (_gen9: - (command_part: - - ), - (_gen10: - (command_part: - (cmd_param: - , - , - , - (e: - - ) - ), - (_gen12: ) - ), - (e: - - ) - ), - (_gen10: - (command_part: - - ), - (_gen10: - (command_part: - (cmd_param: - - ), - - ) - ), - (_gen10: - (command_part: - - ), - (_gen10: ) - ) - ) - ) - ) - ), - - ) - ), - (_gen8: - (sections: - (outputs: - , - , - (_gen13: - (output_kv: - (type_e: - - ), - , - , - (e: - - ) - ), - (_gen14: ) - ), - - ) - ), - (_gen8: ) - ) - ), - - ) - ), - (_gen3: - (workflow_or_task: - (task: - , - , - , - (_gen5: - (declaration: - (type_e: - (type_e: - , - (_gen30: - (type_e: - - ), - (_gen31: ) - ), - - ), - (_gen17: - (postfix_quantifier: - - ) - ), - , - (_gen9: - (command_part: - - ), - (_gen10: - (command_part: - (cmd_param: - , - , - , - (e: - - ) - ), - (_gen12: ) - ), - (e: - - ) - ), - (_gen10: - (command_part: - - ) - ), - (_gen8: - (sections: - (outputs: - , - , - (_gen13: - (output_kv: - (type_e: - - ), - , - (e: - (e: - , - (_gen32: - (e: - (e: - - ), - , - (_gen32: ), - - ), - (_gen33: ) - ), - - ) - ), - (_gen14: ) - ), - - ) - ), - (_gen8: ) - ) - ), - - ) - ), - (_gen3: - (workflow_or_task: - (task: - , - , - , - (_gen5: - (declaration: - (type_e: - (type_e: - , - (_gen30: - (type_e: - - ), - (_gen31: ) - ), - - ), - (_gen17: - (postfix_quantifier: - - ) - ), - , - (_gen9: - (command_part: - - ), - (_gen10: - (command_part: - (cmd_param: - , - , - , - (e: - - ) - ), - (_gen12: ) - ), - (e: - - ) - ), - (_gen10: - (command_part: - - ) - ), - (_gen8: - (sections: - (outputs: - , - , - (_gen13: - (output_kv: - (type_e: - - ), - , - (e: - (e: - , - (_gen32: - (e: - (e: - - ), - , - (_gen32: ), - - ), - (_gen33: ) - ), - - ) - ), - (_gen14: ) - ), - - ) - ), - (_gen8: ) - ) - ), - - ) - ), - (_gen3: - (workflow_or_task: - (workflow: - , - , - (_gen19: - (wf_body_element: - (declaration: - (type_e: - (type_e: - , - (_gen30: - (type_e: - - ), - (_gen31: ) - ), - - ), - (_gen17: ), - - ), - (_gen17: ), - , - (_gen18: ) - ) - ), - (_gen20: - (wf_body_element: - (call: - , - , - , - (_gen5: ), - (_gen23: - (call_input: - , - (_gen25: - (mapping: - , - (e: - - ) - ), - (_gen26: ) - ) - ), - (_gen24: ) - ), - - ) - ) - ) - ), - (_gen20: - (wf_body_element: - (call: - , - , - (_gen21: - (alias: - , - (_gen5: ), - (_gen23: - (call_input: - , - (_gen25: - (mapping: - , - (e: - (e: - , - - ) - ) - ) - ), - (_gen20: - (wf_body_element: - (call: - , - , - (_gen21: - (alias: - , - (_gen5: ), - (_gen23: - (call_input: - , - (_gen25: - (mapping: - , - (e: - (e: - , - - ) - ) - ) - ), - (_gen20: - (wf_body_element: - (call: - , - , - (_gen21: ), - (_gen22: - (call_body: - , - (_gen5: ), - (_gen23: - (call_input: - , - (_gen25: - (mapping: - , - (e: - - ) - ) - ) - ), - (_gen20: - (wf_body_element: - (call: - , - , - (_gen21: - (alias: - - ) - ), - (_gen22: - (call_body: - , - (_gen5: ), - (_gen23: - (call_input: - , - (_gen25: - (mapping: - , - (e: - , - (mapping: - , - , - (e: - - ) - ), - (_gen26: ) - ) - ) - ), - (_gen24: ) - ), - - ) - ) - ) - ), - (_gen20: - (wf_body_element: - (call: - , - , - (_gen21: - (alias: - , - (_gen5: ), - (_gen23: - (call_input: - , - (_gen25: - (mapping: - , - , - (e: - - ) - ), - (_gen26: - , - (mapping: - , - , - (e: - - ) - ), - (_gen26: ) - ) - ) - ), - (_gen24: ) - ), - - ) - ) - ) - ), - (_gen20: - (wf_body_element: - (call: - , - , - (_gen21: - (alias: - - ) - ), - (_gen22: - (call_body: - , - (_gen5: ), - (_gen23: - (call_input: - , - (_gen25: - (mapping: - , - (e: - (e: - , - - ) - ) - ) - ), - (_gen20: - (wf_body_element: - (call: - , - , - (_gen21: - (alias: - - ) - ), - (_gen22: - (call_body: - , - (_gen5: ), - (_gen23: - (call_input: - , - (_gen25: - (mapping: - , - (e: - (e: - , - - ) - ) - ) - ), - (_gen20: ) - ) - ) - ) - ) - ) - ) - ) - ) - ) - ) - ), - - ) - ), - (_gen3: ) - ) - ) - ) - ) - ) - ) -) \ No newline at end of file diff --git a/python/wdl/test/cases/5/wdl b/python/wdl/test/cases/5/wdl deleted file mode 100644 index 2d7edc1..0000000 --- a/python/wdl/test/cases/5/wdl +++ /dev/null @@ -1,94 +0,0 @@ -task ps { - String? flags - command { - ps ${flags} - } - output { - File procs = stdout() - } -} - -task find_files { - File dir - Int? max_depth - String pattern - - command { - find ${dir} ${'-maxdepth ' + max_depth} | grep '${pattern}' - } - output { - Array[File] files = read_lines(stdout()) - } -} - -task concat { - Array[File]+ files - String outfile - - command { - cat ${sep=" " files} > ${outfile} - } - output { - File concatenated = outfile - } -} - -task bytecount { - Array[File]+ files - command { - cat ${sep=" " files} | wc -c - } - output { - Int bytes = read_int(stdout()) - } -} - -task linecount { - Array[File]+ files - command { - cat ${sep=" " files} | wc -l - } - output { - Int lines = read_int(stdout()) - } -} - -workflow sloc { - Array[File] files - File source_dir - - # Run 'ps', get the byte count of the output - call ps - call ps as ps_flags { - input: flags="-ef" - } - call bytecount as ps_bytes { - input: files=ps.procs - } - call bytecount as ps_flags_bytes { - input: files=ps_flags.procs - } - - # Test out default parameters. - # First 'concat' should output to file called "concatenated". - # Second 'concat' should output to a file called "redirected". - call concat { - input: files=files - } - call concat as concat2 { - input:files=files, outfile="redirected" - } - - # Find all Java and Scala files, count lines in each - # and then compute the total file size - call find_files as find_python_files { - input: dir=source_dir, pattern="\\.py$" - } - call bytecount as python_src_bytes { - input: files=find_python_files.files - } - call linecount as python_src_lines { - input: files=find_python_files.files - } -} - diff --git a/python/wdl/test/test_binding.py b/python/wdl/test/test_binding.py deleted file mode 100644 index b66c5a4..0000000 --- a/python/wdl/test/test_binding.py +++ /dev/null @@ -1,153 +0,0 @@ -import wdl -import wdl.binding -from wdl.binding import * - -with open('wdl/test/cases/0/wdl') as fp: - wdl_document = wdl.load(fp, '') - workflow = wdl_document.workflows[0] - -def test_document(): - assert len(wdl_document.workflows) == 1 - assert len(wdl_document.tasks) == 4 - -def test_workflow(): - assert workflow.name == 'simple' - assert len([c for c in workflow.body if isinstance(c, wdl.binding.Call)]) == 4 - assert len([s for s in workflow.body if isinstance(s, wdl.binding.Scatter)]) == 1 - -def test_workflow_declarations(): - decls = workflow.declarations - assert len(decls) == 5 - assert decls[0].wdl_string() == 'Array[Array[Array[File]]] scatter_files' - assert decls[0].name == 'scatter_files' - assert decls[0].expression is None - assert decls[0].type == WdlArrayType(WdlArrayType(WdlArrayType(WdlFileType()))) - assert decls[0].type.wdl_string() == 'Array[Array[Array[File]]]' - assert decls[1].wdl_string() == 'String docker' - assert decls[1].name == 'docker' - assert decls[1].expression is None - assert decls[1].type == WdlStringType() - assert decls[1].type.wdl_string() == 'String' - assert decls[2].wdl_string() == 'String words = "w"+"o"+"r"+"d"+"s"' - assert decls[2].name == 'words' - assert decls[2].expression.wdl_string() == '"w"+"o"+"r"+"d"+"s"' - assert decls[2].type == WdlStringType() - assert decls[2].type.wdl_string() == 'String' - assert decls[3].wdl_string() == 'File dict_file = "/usr/share/dict/"+words' - assert decls[3].name == 'dict_file' - assert decls[3].expression.wdl_string() == '"/usr/share/dict/"+words' - assert decls[3].type == WdlFileType() - assert decls[3].type.wdl_string() == 'File' - assert decls[4].wdl_string() == 'Boolean b = false' - assert decls[4].name == 'b' - assert decls[4].expression.wdl_string() == 'false' - assert decls[4].type == WdlBooleanType() - assert decls[4].type.wdl_string() == 'Boolean' - -def test_workflow_calls(): - assert len(workflow.body) == 5 - assert workflow.body[0].name == 'task1' - assert workflow.body[0].task.name == 'task1' - assert workflow.body[0].alias == None - assert workflow.body[0].parent == workflow - assert workflow.body[0].inputs['docker'].wdl_string() == 'docker' - assert workflow.body[0].inputs['infile'].wdl_string() == 'dict_file' - assert workflow.body[1].name == 'task2' - assert workflow.body[1].task.name == 'task2' - assert workflow.body[1].alias == None - assert workflow.body[1].parent == workflow - assert workflow.body[1].inputs['docker'].wdl_string() == 'docker' - assert workflow.body[1].inputs['infile'].wdl_string() == 'dict_file' - assert workflow.body[2].name == 'alias' - assert workflow.body[2].task.name == 'task3' - assert workflow.body[2].inputs['docker'].wdl_string() == 'docker' - assert workflow.body[2].inputs['infile'].wdl_string() == '"/usr/share/dict/"+words' - assert workflow.body[2].alias == 'alias' - assert workflow.body[2].parent == workflow - assert workflow.body[3].name == 'inline' - assert workflow.body[3].task.name == 'inline' - assert workflow.body[3].alias == None - assert workflow.body[3].parent == workflow - assert workflow.body[3].inputs['docker'].wdl_string() == 'docker' - assert workflow.body[3].inputs['path'].wdl_string() == 'dict_file' - -def test_workflow_scatters(): - assert workflow.body[4].name == '_s15' - assert workflow.body[4].body[0].name == '_s17' - assert workflow.body[4].body[0].body[0].name == '_s19' - -def test_task_inline(): - task = wdl_document.task('inline') - assert task.name == 'inline' - assert len(task.declarations) == 2 - assert task.declarations[0].name == 'path' - assert task.declarations[0].expression is None - assert task.declarations[0].type == WdlFileType() - assert task.declarations[0].type.wdl_string() == 'File' - assert task.declarations[1].name == 'docker' - assert task.declarations[1].expression is None - assert task.declarations[1].type == WdlStringType() - assert task.declarations[1].type.wdl_string() == 'String' - assert task.command.wdl_string() == """python3 < 3", WdlBoolean(True)), - ("4 > 3.0", WdlBoolean(True)), - ("4 >= 4", WdlBoolean(True)), - ("4 >= 4.0", WdlBoolean(True)), - ("-1 + -3", WdlInteger(-4)), - ("+1", WdlInteger(1)), - - # Floats - ("1.0+2", WdlFloat(3.0)), - (' 1.0 + "String" ', WdlString("1.0String")), - ("1.0+2.3", WdlFloat(3.3)), - ("3.0-5", WdlFloat(-2.0)), - ("10.0-6.7", WdlFloat(3.3)), - ("8.0 * 7", WdlFloat(56.0)), - ("5.0 * 7.2", WdlFloat(36.0)), - ("25.0 / 4", WdlFloat(6.25)), - ("25.0/2.0", WdlFloat(12.5)), - ("10.0 % 3", WdlFloat(1.0)), - ("10.0 % 3.5", WdlFloat(3.0)), - ("24.0 == 24 ", WdlBoolean(True)), - ("24.0 == 24.0 ", WdlBoolean(True)), - ("24.0 == 26 ", WdlBoolean(False)), - ("1.0 != 0 ", WdlBoolean(True)), - ("1.0 != 0.0 ", WdlBoolean(True)), - ("1.0 != 1 ", WdlBoolean(False)), - ("4.0 < 3", WdlBoolean(False)), - ("4.0 < 3.0", WdlBoolean(False)), - ("3.0 < 4", WdlBoolean(True)), - ("4.0 < 5.0", WdlBoolean(True)), - ("3.0 <= 4", WdlBoolean(True)), - ("3.0 <= 3.0", WdlBoolean(True)), - ("4.0 > 3", WdlBoolean(True)), - ("4.0 > 3.0", WdlBoolean(True)), - ("4.0 >= 4", WdlBoolean(True)), - ("4.0 >= 4.0", WdlBoolean(True)), - ("+1.0", WdlFloat(1.0)), - ("-1.0", WdlFloat(-1.0)), - - # Booleans - ("false == false ", WdlBoolean(True)), - ("false == true ", WdlBoolean(False)), - ("true != false ", WdlBoolean(True)), - ("true != true ", WdlBoolean(False)), - ("true < false", WdlBoolean(False)), - ("false <= false ", WdlBoolean(True)), - ("true <= false", WdlBoolean(False)), - ("true > false", WdlBoolean(True)), - ("false >= false ", WdlBoolean(True)), - ("false >= true ", WdlBoolean(False)), - ("false || true ", WdlBoolean(True)), - ("false || false ", WdlBoolean(False)), - ("false && true ", WdlBoolean(False)), - ("true && true ", WdlBoolean(True)), - ("!true", WdlBoolean(False)), - ("!false", WdlBoolean(True)), - - # Strings - (' "String" + 456 ', WdlString("String456")), - (' "hello" + " world" ', WdlString("hello world")), - (' "hello" + 2.1 ', WdlString("hello2.1")), - (' "hello" == "hello" ', WdlBoolean(True)), - (' "hello" == "hello2" ', WdlBoolean(False)), - (' "hello" != "hello" ', WdlBoolean(False)), - (' "hello" != "hello2" ', WdlBoolean(True)), - (' "abc" < "def" ', WdlBoolean(True)), - (' "abc" <= "def" ', WdlBoolean(True)), - (' "abc" > "def" ', WdlBoolean(False)), - (' "abc" >= "def" ', WdlBoolean(False)), - - # Order of Operations - ("1+2*3", WdlInteger(7)), - ("1+2==3", WdlBoolean(True)), - ("(1+2)*3", WdlInteger(9)) -] - -bad_expressions = [ - # Integers - ("1+true"), - ("1-true"), - (' 1-"s" '), - ("1*true"), - (' 1*"s" '), - ("1 / 0"), - ("1 / 0.0"), - ("25/0.0"), - ("1/true"), - (' 1/"s" '), - ("1%false"), - (' 1%"s" '), - ("1%0"), - (" 24 == false "), - (' 1 == "s" '), - (" 24 != false "), - (' 1 != "s" '), - (" 24 < false "), - (' 1 < "s" '), - (" 24 <= false "), - (' 1 <= "s" '), - ("4 > false"), - (' 1 > "s" '), - ("4 >= false"), - (' 1 >= "s" '), - - # Floats - ("1.0+true"), - ("1.0-true"), - (' 1.0-"s" '), - ("1.0*true"), - (' 1.0*"s" '), - ("1.0/true"), - ("1.0/0.0"), - ("1.0/0"), - (' 1.0/"s" '), - ("10.0 % 0"), - ("10.0 % 0.0"), - ("1.0%false"), - (' 1.0%"s" '), - ("24.0 == false "), - (' 1.0 == "s" '), - ("24.0 != false "), - (' 1.0 != "s" '), - ("24.0 < false "), - (' 1.0 < "s" '), - ("24.0 <= false "), - (' 1.0 <= "s" '), - ("4.0 > false"), - (' 1.0 > "s" '), - ("4.0 >= false"), - (' 1.0 >= "s" '), - - # Booleans - (' true + "String" '), - ("true+2"), - ("true+2.3"), - ("false+true"), - ("false-5"), - ("false-6.6"), - ("true-true"), - (' true-"s" '), - ("false * 7"), - ("false * 7.2"), - ("false*true"), - (' false*"s" '), - ("false / 4"), - ("false/2.0"), - ("false/true"), - (' true/"s" '), - ("true % 3"), - ("true % 3.5"), - ("false%false"), - (' true % "s" '), - ("true == 24 "), - ("true == 24.0 "), - ('true == "s" '), - ("true != 0 "), - ("true != 0.0 "), - ('true != "s" '), - ("true < 3"), - ("true < 3.0"), - ("true < 5.0"), - ('true < "s" '), - ("true <= 4"), - ("true <= 3.0"), - ('true <= "s" '), - ("true > 3"), - ("true > 3.0"), - ("true >= 4"), - ("true >= 4.0"), - ('true >= "s" '), - ("true || 4"), - ("true || 4.0"), - ('true || "s" '), - ("true && 4"), - ("true && 4.0"), - ('true && "s" '), - - # Strings - (' "hello" + true '), - (' "hello" == true '), - (' "hello" != true '), - (' "hello" < true '), - (' "hello" > true ') -] - -identifier_expressions = [ - # Lookup Variables - ("a", WdlInteger(1)), - ("a + 10", WdlInteger(11)), - ("a + b", WdlInteger(3)), - ("s + a", WdlString("s1")), - ("o.key1", WdlString("value1")), - ("o.key2", WdlInteger(9)), - - # Call Functions - ("b(1)", WdlInteger(2)), - ("b(1) + 10", WdlInteger(12)), - (' append("hello ", "world") ', WdlString("hello world")), - (' append("a", "b", "c", "d") ', WdlString("abcd")), - - # String Interpolation - ("\"prefix.${a}.suffix\"", WdlString("prefix.1.suffix")), - ("\"prefix.${a}${a}.suffix${a}\"", WdlString("prefix.11.suffix1")), - ("\"${b}prefix.${b}${a}${a}.suffix${a}\"", WdlString("2prefix.211.suffix1")), - ("\"${s}...${s}\"", WdlString("s...s")), - - # Array Indexing - ("array_str[0]", WdlString("foo")), - ("array_str[1]", WdlString("bar")), - ("array_str[2]", WdlString("baz")), - - # Map Indexing - ('map_str_int["a"]', WdlInteger(0)), - ('map_str_int["b"]', WdlInteger(1)), - ('map_str_int["c"]', WdlInteger(2)), - - # Files -- 'etc_f', 'etc2_f', and 'sudoers_f' are all variables that resolve to WdlFile - ("etc_f + sudoers_s", WdlFile("/etc/sudoers")), - (' "/foo" + etc_f ', WdlString("/foo/etc")), - ("etc_f == etc_f", WdlBoolean(True)), - ("etc_f == etc2_f", WdlBoolean(False)), - ("etc_f != etc2_f", WdlBoolean(True)), - ("etc_f == etc_s", WdlBoolean(True)), - - # String escaping - (' "abc" ', WdlString("abc")), - (' "a\\nb" ', WdlString("a\nb")), - (' "a\\nb\\t" ', WdlString("a\nb\t")), - (' "a\\n\\"b\\t\\"" ', WdlString("a\n\"b\t\"")), - (' "be \u266f or be \u266e, just don\'t be \u266d" ', WdlString(u"be \u266f or be \u266e, just don't be \u266d")) -] - -@pytest.mark.parametrize("expression,value", static_expressions) -def test_static_expressions(expression, value): - assert wdl.parse_expr(expression).eval() == value - -@pytest.mark.parametrize("expression", bad_expressions) -def test_bad_expressions(expression): - with pytest.raises(Exception): - assert wdl.parse_expr(expression).eval() - -def lookup(name): - if name == "a": return WdlInteger(1) - if name == "b": return WdlInteger(2) - if name == "s": return WdlString("s") - if name == "array_str": return WdlArray(WdlStringType(), [WdlString(x) for x in ["foo", "bar", "baz"]]) - if name == "map_str_int": return WdlMap(WdlStringType(), WdlIntegerType(), { - WdlString("a"): WdlInteger(0), - WdlString("b"): WdlInteger(1), - WdlString("c"): WdlInteger(2) - }) - if name == "o": return WdlObject({"key1": WdlString("value1"), "key2": WdlInteger(9)}) - if name == "etc_f": return WdlFile("/etc") - if name == "etc2_f": return WdlFile("/etc2") - if name == "etc_s": return WdlString("/etc") - if name == "sudoers_f": return WdlFile("/sudoers") - if name == "sudoers_s": return WdlString("/sudoers") - -def function(name): - def append(parameters): - return WdlString(''.join([p.value for p in parameters])) - def b(parameters): - return WdlInteger(parameters[0].value + 1) - if name == 'append': return append - elif name == 'b': return b - -@pytest.mark.parametrize("expression,value", identifier_expressions) -def test_identifier_expressions(expression, value): - actual = wdl.parse_expr(expression).eval(lookup, function) - #print(actual.value, value.value) - assert actual == value diff --git a/python/wdl/test/test_parser.py b/python/wdl/test/test_parser.py deleted file mode 100644 index 035347f..0000000 --- a/python/wdl/test/test_parser.py +++ /dev/null @@ -1,31 +0,0 @@ -import wdl.binding -import wdl.parser -import glob -import pytest -import os - -@pytest.mark.parametrize(("test_case_dir",), [[x] for x in glob.glob("wdl/test/cases/*")] ) -def test_parse(test_case_dir): - wdl_file = os.path.join(test_case_dir, "wdl") - parsetree_file = os.path.join(test_case_dir, "parsetree") - parsetree = wdl.parser.parse(open(wdl_file).read(), os.path.basename(wdl_file)) - - if not os.path.exists(parsetree_file): - with open(parsetree_file, 'w') as fp: - fp.write(parsetree.dumps(indent=2)) - - with open(parsetree_file) as fp: - assert fp.read() == parsetree.dumps(indent=2) - -@pytest.mark.parametrize(("test_case_dir",), [[x] for x in glob.glob("wdl/test/cases/*")] ) -def test_ast(test_case_dir): - wdl_file = os.path.join(test_case_dir, "wdl") - ast_file = os.path.join(test_case_dir, "ast") - parsetree = wdl.parser.parse(open(wdl_file).read(), os.path.basename(wdl_file)) - - if not os.path.exists(ast_file): - with open(ast_file, 'w') as fp: - fp.write(parsetree.ast().dumps(indent=2)) - - with open(ast_file) as fp: - assert fp.read() == parsetree.ast().dumps(indent=2) diff --git a/python/wdl/toc.py b/python/wdl/toc.py deleted file mode 100644 index 5afaaef..0000000 --- a/python/wdl/toc.py +++ /dev/null @@ -1,37 +0,0 @@ -import re -import sys - -as_link = lambda x: re.sub(r'[^a-zA-Z0-9-_]', '', x.lower().replace(' ', '-')) -escape = lambda x: x.replace('[', '\\[').replace(']', '\\]') - -def modify_and_write(path): - toc = [] - is_comment_block = False - with open(path) as fp: - contents = fp.read() - for line in contents.split('\n'): - if line.startswith('```'): is_comment_block = not is_comment_block - if is_comment_block: continue - header = re.match(r'^(#+)(.*)', line) - if header: - level = len(header.group(1)) - header = header.group(2).strip() - toc.append('{spaces}* [{header}](#{link})'.format( - spaces=' ' * (level-1), - header=escape(header), - link=as_link(header) - )) - toc_re = re.compile(r'<\!---toc start-->(.*?)<\!---toc end-->', flags=re.DOTALL) - (contents, replacements) = toc_re.subn('\n\n{}\n\n'.format('\n'.join(toc)), contents) - with open(path, 'w') as fp: - fp.write(contents) - -if __name__ == '__main__': - if len(sys.argv) < 2: - print("Replaces contents between delimiters:\n") - print("<\!---toc start--->") - print("<\!---toc end--->\n") - print("With the table of contents for the file\n") - print("Usage: toc.py [markdown file]") - sys.exit(-1) - modify_and_write(sys.argv[1]) diff --git a/python/wdl/types.py b/python/wdl/types.py deleted file mode 100644 index 166a08b..0000000 --- a/python/wdl/types.py +++ /dev/null @@ -1,45 +0,0 @@ -class WdlType: pass - -class WdlPrimitiveType(WdlType): - def __init__(self): pass - def is_primitive(self): return True - def __eq__(self, other): return isinstance(other, self.__class__) - def __str__(self): return repr(self) - -class WdlCompoundType(WdlType): - def is_primitive(self): return False - def __str__(self): return repr(self) - -class WdlBooleanType(WdlPrimitiveType): - def wdl_string(self): return 'Boolean' - def __eq__(self, other): return isinstance(other, WdlBooleanType) - -class WdlIntegerType(WdlPrimitiveType): - def wdl_string(self): return 'Int' - -class WdlFloatType(WdlPrimitiveType): - def wdl_string(self): return 'Float' - -class WdlStringType(WdlPrimitiveType): - def wdl_string(self): return 'String' - -class WdlFileType(WdlPrimitiveType): - def wdl_string(self): return 'File' - -class WdlUriType(WdlPrimitiveType): - def wdl_string(self): return 'Uri' - -class WdlArrayType(WdlCompoundType): - def __init__(self, subtype): - self.subtype = subtype - def __eq__(self, other): - return isinstance(other, WdlArrayType) and other.subtype == self.subtype - def wdl_string(self): return 'Array[{0}]'.format(self.subtype.wdl_string()) - -class WdlMapType(WdlCompoundType): - def __init__(self, key_type, value_type): - self.__dict__.update(locals()) - def wdl_string(self): return 'Map[{0}, {1}]'.format(self.key_type.wdl_string(), self.value_type.wdl_string()) - -class WdlObjectType(WdlCompoundType): - def wdl_string(self): return 'Object' diff --git a/python/wdl/util.py b/python/wdl/util.py deleted file mode 100644 index 778151f..0000000 --- a/python/wdl/util.py +++ /dev/null @@ -1,29 +0,0 @@ -import re - -def md_table(table, header): - max_len = 64 - col_size = [len(x) for x in header] - def trunc(s): - return s[:max_len-3] + '...' if len(s) >= max_len else s - for row in table: - for index, cell in enumerate(row): - if len(str(cell)) > col_size[index]: - col_size[index] = min(len(str(cell)), max_len) - def make_row(row): - return '|{}|'.format('|'.join([trunc(str(x)).ljust(col_size[i]) if x is not None else ' ' * col_size[i] for i,x in enumerate(row)])) - r = make_row(header) + '\n' - r += '|{}|'.format('|'.join(['-' * col_size[i] for i,x in enumerate(col_size)])) + '\n' - r += '\n'.join([make_row(x) for x in table]) - return r - -def strip_leading_ws(string): - string = string.strip('\n').rstrip(' \n') - ws_count = [] - for line in string.split('\n'): - match = re.match('^[\ \t]+', line) - if match: - ws_count.append(len(match.group(0))) - if len(ws_count): - trim_amount = min(ws_count) - return '\n'.join([line[trim_amount:] for line in string.split('\n')]) - return string diff --git a/python/wdl/values.py b/python/wdl/values.py deleted file mode 100644 index 00b30dd..0000000 --- a/python/wdl/values.py +++ /dev/null @@ -1,256 +0,0 @@ -from wdl.types import * - -class EvalException(Exception): pass - -def assert_type(value, types): return value.type.__class__ in types - -class WdlValue(object): - def __init__(self, value): - self.value = value - self.check_compatible(value) - def __str__(self): - return '[{}: {}]'.format(self.type, str(self.value)) - def as_string(self): return str(self.value) - def __str__(self): return '[Wdl{}: {}]'.format(self.type.wdl_string(), self.as_string()) - def __eq__(self, rhs): return (self.__class__, self.value) == (rhs.__class__, rhs.value) - def __hash__(self): return hash((self.__class__, self.value)) - def __invalid(self, symbol, rhs): raise EvalException('Cannot perform operation: {} {} {}'.format(self.type.wdl_string(), symbol, rhs.type.wdl_string())) - def __invalid_unary(self, symbol): raise EvalException('Cannot perform operation: {} {}'.format(symbol, self.type.wdl_string())) - def add(self, rhs): return self.__invalid('+', rhs) - def subtract(self, rhs): return self.__invalid('-', rhs) - def multiply(self, rhs): return self.__invalid('*', rhs) - def divide(self, rhs): return self.__invalid('/', rhs) - def mod(self, rhs): return self.__invalid('%', rhs) - def equal(self, rhs): return self.__invalid('==', rhs) - def not_equal(self, rhs): return self.equal(rhs).logical_not() - def greater_than(self, rhs): return self.__invalid('>', rhs) - def greater_than_or_equal(self, rhs): return self.greater_than(rhs).logical_or(self.equal(rhs)) - def less_than(self, rhs): return self.__invalid('<', rhs) - def less_than_or_equal(self, rhs): return self.less_than(rhs).logical_or(self.equal(rhs)) - def logical_or(self, rhs): return self.__invalid('||', rhs) - def logical_and(self, rhs): return self.__invalid('&&', rhs) - def logical_not(self): return self.__invalid_unary('!') - def unary_plus(self): return self.__invalid_unary('+') - def unary_negation(self): return self.__invalid_unary('-') - -class WdlUndefined(WdlValue): - def __init__(self): self.type = None - def __str__(self): return repr(self) - -class WdlString(WdlValue): - type = WdlStringType() - def check_compatible(self, value): - if isinstance(value, unicode): value = value.encode('utf-8') - if not isinstance(value, str): - raise EvalException("WdlString must hold a python 'str': {}".format(value.encode('utf-8'))) - def add(self, rhs): - if assert_type(rhs, [WdlIntegerType, WdlFloatType, WdlStringType, WdlFileType]): - return WdlString(self.value + str(rhs.value)) - super(WdlString, self).add(rhs) - def equal(self, rhs): - if assert_type(rhs, [WdlStringType]): - return WdlBoolean(self.value == rhs.value) - super(WdlString, self).equal(rhs) - def greater_than(self, rhs): - if assert_type(rhs, [WdlStringType]): - return WdlBoolean(self.value > rhs.value) - super(WdlString, self).equal(rhs) - def less_than(self, rhs): - if assert_type(rhs, [WdlStringType]): - return WdlBoolean(self.value < rhs.value) - super(WdlString, self).equal(rhs) - -class WdlInteger(WdlValue): - type = WdlIntegerType() - def check_compatible(self, value): - if not isinstance(value, int): - raise EvalException("WdlInteger must hold a python 'int'") - def add(self, rhs): - if assert_type(rhs, [WdlIntegerType]): - return WdlInteger(self.value + rhs.value) - if assert_type(rhs, [WdlFloatType]): - return WdlFloat(self.value + rhs.value) - if assert_type(rhs, [WdlStringType]): - return WdlString(str(self.value) + rhs.value) - super(WdlInteger, self).add(rhs) - def subtract(self, rhs): - if assert_type(rhs, [WdlIntegerType]): - return WdlInteger(self.value - rhs.value) - if assert_type(rhs, [WdlFloatType]): - return WdlFloat(self.value - rhs.value) - super(WdlInteger, self).subtract(rhs) - def multiply(self, rhs): - if assert_type(rhs, [WdlIntegerType]): - return WdlInteger(self.value * rhs.value) - if assert_type(rhs, [WdlFloatType]): - return WdlFloat(self.value * rhs.value) - super(WdlInteger, self).multiply(rhs) - def divide(self, rhs): - if assert_type(rhs, [WdlIntegerType]): - return WdlInteger(self.value / rhs.value) - if assert_type(rhs, [WdlFloatType]): - return WdlFloat(self.value / rhs.value) - super(WdlInteger, self).divide(rhs) - def mod(self, rhs): - if assert_type(rhs, [WdlIntegerType, WdlBooleanType]): - return WdlInteger(self.value % rhs.value) - if assert_type(rhs, [WdlFloatType]): - return WdlFloat(self.value % rhs.value) - super(WdlInteger, self).mod(rhs) - def equal(self, rhs): - if assert_type(rhs, [WdlIntegerType, WdlFloatType]): - return WdlBoolean(self.value == rhs.value) - super(WdlInteger, self).equal(rhs) - def greater_than(self, rhs): - if assert_type(rhs, [WdlIntegerType, WdlFloatType]): - return WdlBoolean(self.value > rhs.value) - super(WdlInteger, self).greater_than(rhs) - def less_than(self, rhs): - if assert_type(rhs, [WdlIntegerType, WdlFloatType]): - return WdlBoolean(self.value < rhs.value) - super(WdlInteger, self).less_than(rhs) - def unary_negation(self): - return WdlInteger(-self.value) - def unary_plus(self): - return WdlInteger(+self.value) - -class WdlBoolean(WdlValue): - type = WdlBooleanType() - def check_compatible(self, value): - if not isinstance(value, bool): - raise EvalException("WdlBoolean must hold a python 'bool'") - def greater_than(self, rhs): - if assert_type(rhs, [WdlBooleanType]): - return WdlBoolean(self.value > rhs.value) - super(WdlBoolean, self).greater_than(rhs) - def less_than(self, rhs): - if assert_type(rhs, [WdlBooleanType]): - return WdlBoolean(self.value < rhs.value) - super(WdlBoolean, self).less_than(rhs) - def equal(self, rhs): - if assert_type(rhs, [WdlBooleanType]): - return WdlBoolean(self.value == rhs.value) - super(WdlBoolean, self).equal(rhs) - def logical_or(self, rhs): - if assert_type(rhs, [WdlBooleanType]): - return WdlBoolean(self.value or rhs.value) - super(WdlBoolean, self).logical_or(rhs) - def logical_and(self, rhs): - if assert_type(rhs, [WdlBooleanType]): - return WdlBoolean(self.value and rhs.value) - super(WdlBoolean, self).logical_and(rhs) - def logical_not(self): - return WdlBoolean(not self.value) - -class WdlFloat(WdlValue): - type = WdlFloatType() - def check_compatible(self, value): - if not isinstance(value, float): - raise EvalException("WdlFloat must hold a python 'float'") - def add(self, rhs): - if assert_type(rhs, [WdlIntegerType, WdlFloatType]): - return WdlFloat(self.value + rhs.value) - if assert_type(rhs, [WdlStringType]): - return WdlString(str(self.value) + rhs.value) - super(WdlFloat, self).add(rhs) - def subtract(self, rhs): - if assert_type(rhs, [WdlIntegerType, WdlFloatType]): - return WdlFloat(self.value - rhs.value) - super(WdlFloat, self).subtract(rhs) - def multiply(self, rhs): - if assert_type(rhs, [WdlIntegerType, WdlFloatType]): - return WdlFloat(self.value * rhs.value) - super(WdlFloat, self).multiply(rhs) - def divide(self, rhs): - if assert_type(rhs, [WdlIntegerType, WdlFloatType]): - return WdlFloat(self.value / rhs.value) - super(WdlFloat, self).divide(rhs) - def mod(self, rhs): - if assert_type(rhs, [WdlIntegerType, WdlFloatType]): - return WdlFloat(self.value % rhs.value) - super(WdlFloat, self).mod(rhs) - def equal(self, rhs): - if assert_type(rhs, [WdlIntegerType, WdlFloatType]): - return WdlBoolean(self.value == rhs.value) - super(WdlFloat, self).greater_than(rhs) - def greater_than(self, rhs): - if assert_type(rhs, [WdlIntegerType, WdlFloatType]): - return WdlBoolean(self.value > rhs.value) - super(WdlFloat, self).greater_than(rhs) - def less_than(self, rhs): - if assert_type(rhs, [WdlIntegerType, WdlFloatType]): - return WdlBoolean(self.value < rhs.value) - super(WdlFloat, self).less_than(rhs) - def unary_negation(self): - return WdlFloat(-self.value) - def unary_plus(self): - return WdlFloat(+self.value) - -class WdlFile(WdlString): - type = WdlFileType() - def check_compatible(self, value): - if isinstance(value, unicode): value = value.encode('utf-8') - if not isinstance(value, str): - raise EvalException("WdlFile must hold a python 'str': {}".format(value.encode('utf-8'))) - def add(self, rhs): - if assert_type(rhs, [WdlFileType, WdlStringType]): - return WdlFile(self.value + str(rhs.value)) - super(WdlFile, self).add(rhs) - def equal(self, rhs): - if assert_type(rhs, [WdlFileType, WdlStringType]): - return WdlBoolean(self.value == rhs.value) - super(WdlFile, self).equal(rhs) - def greater_than(self, rhs): - if assert_type(rhs, [WdlFileType]): - return WdlBoolean(self.value > rhs.value) - super(WdlFile, self).equal(rhs) - def less_than(self, rhs): - if assert_type(rhs, [WdlFileType]): - return WdlBoolean(self.value < rhs.value) - super(WdlFile, self).equal(rhs) - -class WdlUri(WdlValue): - type = WdlUriType() - def check_compatible(self, value): - pass # TODO: implement - -class WdlArray(WdlValue): - def __init__(self, subtype, value): - if not isinstance(value, list): - raise EvalException("WdlArray must be a Python 'list'") - if not all(type(x.type) == type(subtype) for x in value): - raise EvalException("WdlArray must contain elements of the same type: {}".format(value)) - self.type = WdlArrayType(subtype) - self.subtype = subtype - self.value = value - def __str__(self): - return '[{}: {}]'.format(self.type, ', '.join([str(x) for x in self.value])) - -class WdlMap(WdlValue): - def __init__(self, key_type, value_type, value): - if not isinstance(value, dict): - raise EvalException("WdlMap must be a Python 'dict'") - if not isinstance(key_type, WdlPrimitiveType): - raise EvalException("WdlMap must contain WdlPrimitive keys") - if not isinstance(value_type, WdlPrimitiveType): - raise EvalException("WdlMap must contain WdlPrimitive values") - if not all(isinstance(k.type, key_type.__class__) for k in value.keys()): - raise EvalException("WdlMap must contain keys of the same type: {}".format(value)) - if not all(isinstance(v.type, value_type.__class__) for v in value.values()): - raise EvalException("WdlMap must contain values of the same type: {}".format(value)) - (k, v) = list(value.items())[0] - self.type = WdlMapType(key_type, value_type) - self.key_type = key_type - self.value_type = value_type - self.value = value - -class WdlObject(WdlValue): - def __init__(self, dictionary): - for k, v in dictionary.items(): - self.set(k, v) - def set(self, key, value): - self.__dict__[key] = value - def get(self, key): - return self.__dict__[key] - def __str__(self): - return '[WdlObject: {}]'.format(str(self.__dict__))