예제 #1
0
 def f(tokens, s):
     result = []
     for _ in range(lo):
         (v, s) = parser.run(tokens, s)
         result.append(v)
     end = s.max
     try:
         for _ in (repeat(1) if isinf(hi) else range(hi - lo)):
             (v, s) = parser.run(tokens, s)
             result.append(v)
     except NoParseError as e:
         end = e.state.max
     return result, State(s.pos, end)
예제 #2
0
def parse(seq, translate=lambda x, y: y):
    """Parse the given sequence of tokens into a StateMachine object

    Args:
        seq (list): List of lexer.Token tokens to parse
        translate (function): Translation function applied to Lambda/Activity names.
                              Arguments are ("Lambda"|"Activity", arn)

    Returns
        sfn.StateMachine: StateMachine object
    """
    state = forward_decl()

    # Primatives
    array = op_('[') + maybe(string + many(op_(',') + string)) + op_(']') >> make_array

    block = block_s + many(state) + block_e
    comment_block = block_s + maybe(string) + many(state) + block_e
    retry_block = n('retry') + (array|string) + integer_pos + integer_nn + number >> make(ASTModRetry)
    catch_block = n('catch') + (array|string) + op_(':') + maybe(string) + block >> make(ASTModCatch)


    # Simple States
    state_modifier = ((n('timeout') + op_(':') + integer_pos >> make(ASTModTimeout)) |
                      (n('heartbeat') + op_(':') + integer_pos >> make(ASTModHeartbeat)) |
                      (n('input') + op_(':') + string >> make(ASTModInput)) |
                      (n('result') + op_(':') + string >> make(ASTModResult)) |
                      (n('output') + op_(':') + string >> make(ASTModOutput)) |
                      (n('data') + op_(':') + block_s + json_text() + block_e >> make(ASTModData)) |
                      retry_block | catch_block)

    state_modifiers = state_modifier + many(state_modifier) >> make(ASTModifiers)
    state_block = maybe(block_s + maybe(string) + maybe(state_modifiers) + block_e)

    pass_ = n('Pass') + op_('(') + op_(')') + state_block >> make(ASTStatePass)
    success = n('Success') + op_('(') + op_(')') + state_block >> make(ASTStateSuccess)
    fail = n('Fail') + op_('(') + string + op_(',') + string + op_(')') + state_block >> make(ASTStateFail)
    task = (n('Lambda') | n('Activity')) + op_('(') + string + op_(')') + state_block >> make(ASTStateTask)
    wait_types = n('seconds') | n('seconds_path') | n('timestamp') | n('timestamp_path')
    wait = n('Wait') + op_('(') + wait_types + op_('=') + (integer_pos|timestamp_or_string) + op_(')') + state_block >> make(ASTStateWait)
    simple_state = pass_ | success | fail | task | wait

    # Flow Control States
    transform_modifier = ((n('input') + op_(':') + string >> make(ASTModInput)) |
                          (n('result') + op_(':') + string >> make(ASTModResult)) |
                          (n('output') + op_(':') + string >> make(ASTModOutput)))
    transform_modifiers = transform_modifier + many(transform_modifier) >> make(ASTModifiers)
    transform_block = maybe(n_('transform') + op_(':') + block_s + maybe(transform_modifiers) + block_e)

    while_ = n('while') + comparison + op_(':') + comment_block + transform_block >> make(ASTStateWhile)
    if_else = (n('if') + comparison + op_(':') + comment_block +
               many(n_('elif') + comparison + op_(':') + block) +
               maybe(n_('else') + op_(':') + block) + transform_block) >> make(ASTStateIfElse)
    switch_case = n('case') + (boolean|number|timestamp_or_string) + op_(':') + block
    switch = (n('switch') + string + op_(':') +
              block_s + maybe(string) + many(switch_case) +
              maybe(n('default') + op_(':') + block) +
              block_e + transform_block) >> make(ASTStateSwitch)
    choice_state = while_ | if_else | switch

    error_modifier = (retry_block|catch_block) + many(retry_block|catch_block) >> make(ASTModifiers)
    error_block = maybe(n_('error') + op_(':') + block_s + maybe(error_modifier) + block_e)
    parallel = (n('parallel') + op_(':') + comment_block +
                many(n('parallel') + op_(':') + block) +
                transform_block + error_block) >> make(ASTStateParallel)

    state.define(simple_state | choice_state | parallel)

    # State Machine
    version = maybe(n('version') + op_(':') + string >> make(ASTModVersion))
    timeout = maybe(n('timeout') + op_(':') + integer_pos >> make(ASTModTimeout))
    machine = maybe(string) + version + timeout + many(state) + end >> make(ASTStepFunction)

    try:
        # DP NOTE: calling run() directly to have better control of error handling
        (tree, _) = machine.run(seq, State())
        link_branch(tree)
        check_names(tree)
        resolve_arns(tree, translate)
        function = StepFunction(tree)
        #import code
        #code.interact(local=locals())

        return function
    except NoParseError as e:
        max = e.state.max
        tok = seq[max] if len(seq) > max else Token('EOF', '<EOF>')

        if tok.code == 'ERRORTOKEN':
            msg = "Unterminated quote"
        else:
            msg = "Invalid syntax"
            # DP ???: Should the actual token be used in the error message?

        raise CompileError.from_token(tok, msg)
예제 #3
0
def parse(seq, region='', account_id='', visitors=[]):
    """Parse the given sequence of tokens into a StateMachine object

    Args:
        seq (list): List of lexer.Token tokens to parse
        region (string): AWS Region where Lambdas and Activities are located
        account_id (string): AWS Account ID where where Lambdas and Activities are located
        visitors (list[ast.StateVisitor]): List of StateVisitors that can be used modify
                                           Task states

    Returns
        sfn.StateMachine: StateMachine object
    """
    state = forward_decl()

    # Primatives
    array = op_('[') + maybe(string +
                             many(op_(',') + string)) + op_(']') >> make_array

    block = block_s + many(state) + block_e
    comment_block = block_s + maybe(string) + many(state) + block_e
    parameter_kv = name + maybe(op_('.') + e('$')) + op_(':') + json_text
    parameter_block = n('parameters') + op_(
        ':') + block_s + parameter_kv + many(parameter_kv) + block_e >> make(
            ASTModParameters)
    retry_block = n('retry') + (
        array
        | string) + integer_pos + integer_nn + number >> make(ASTModRetry)
    catch_block = n('catch') + (
        array | string) + op_(':') + maybe(string) + block >> make(ASTModCatch)

    # Simple States
    # DP Note: The 'next' modifier is not allowed in general usage, must use the 'Goto'
    #          state to create that modifier. If 'next' should be allowed from any state
    #          just add it to 'state_modifier' and 'transform_modifier'
    state_modifier = (
        (n('timeout') + op_(':') + integer_pos >> make(ASTModTimeout)) |
        (n('heartbeat') + op_(':') + integer_pos >> make(ASTModHeartbeat)) |
        (n('input') + op_(':') + string >> make(ASTModInput)) |
        (n('result') + op_(':') + string >> make(ASTModResult)) |
        (n('output') + op_(':') + string >> make(ASTModOutput)) |
        (n('data') + op_(':') + block_s + json_text + block_e >>
         make(ASTModData)) | parameter_block | retry_block | catch_block)

    state_modifiers = state_modifier + many(state_modifier) >> make(
        ASTModifiers)
    state_block = maybe(block_s + maybe(string) + maybe(state_modifiers) +
                        block_e)

    pass_ = n('Pass') + op_('(') + op_(')') + state_block >> make(ASTStatePass)
    success = n('Success') + op_('(') + op_(')') + state_block >> make(
        ASTStateSuccess)
    fail = n('Fail') + op_('(') + string + op_(',') + string + op_(
        ')') + state_block >> make(ASTStateFail)
    wait_types = n('seconds') | n('seconds_path') | n('timestamp') | n(
        'timestamp_path')
    wait = n('Wait') + op_('(') + wait_types + op_('=') + (
        integer_pos
        | timestamp_or_string) + op_(')') + state_block >> make(ASTStateWait)
    task = name + maybe(op_('.') + name) + op_('(') + maybe(string) + op_(
        ')') + state_block >> make(ASTStateTask)
    simple_state = pass_ | success | fail | wait | task

    # Flow Control States
    transform_modifier = (
        (n('input') + op_(':') + string >> make(ASTModInput)) |
        (n('result') + op_(':') + string >> make(ASTModResult)) |
        (n('output') + op_(':') + string >> make(ASTModOutput)))
    transform_modifiers = transform_modifier + many(
        transform_modifier) >> make(ASTModifiers)
    transform_block = maybe(
        n_('transform') + op_(':') + block_s + maybe(transform_modifiers) +
        block_e)

    while_ = n('while') + comparison + op_(
        ':') + comment_block + transform_block >> make(ASTStateWhile)
    if_else = (n('if') + comparison + op_(':') + comment_block +
               many(n_('elif') + comparison + op_(':') + block) +
               maybe(n_('else') + op_(':') + block) +
               transform_block) >> make(ASTStateIfElse)
    switch_case = n('case') + (boolean | number
                               | timestamp_or_string) + op_(':') + block
    switch = (n('switch') + string + op_(':') + block_s + maybe(string) +
              many(switch_case) + maybe(n('default') + op_(':') + block) +
              block_e + transform_block) >> make(ASTStateSwitch)
    choice_state = while_ | if_else | switch

    error_modifier = (retry_block | catch_block
                      ) + many(retry_block | catch_block) >> make(ASTModifiers)
    error_block = maybe(
        n_('error') + op_(':') + block_s + maybe(error_modifier) + block_e)
    parallel = (n('parallel') + op_(':') + comment_block +
                many(n('parallel') + op_(':') + block) + transform_block +
                error_block) >> make(ASTStateParallel)

    goto = n('goto') + string >> make(ASTStateGoto)

    state.define(simple_state | choice_state | parallel | goto)

    # State Machine
    version = maybe(n('version') + op_(':') + string >> make(ASTModVersion))
    timeout = maybe(
        n('timeout') + op_(':') + integer_pos >> make(ASTModTimeout))
    machine = maybe(string) + version + timeout + many(state) + end >> make(
        ASTStepFunction)

    try:
        # DP NOTE: calling run() directly to have better control of error handling
        (tree, _) = machine.run(seq, State())
        link_branch(tree)
        check_names(tree)
        resolve_arns(tree, region, account_id)
        verify_goto_targets(tree)
        for visitor in visitors:
            visitor.visit(tree)
        function = StepFunction(tree)
        #import code
        #code.interact(local=locals())

        return function
    except NoParseError as ex:
        max = ex.state.max
        tok = seq[max] if len(seq) > max else Token('EOF', '<EOF>')

        if tok.code == 'ERRORTOKEN':
            msg = "Unterminated quote"
        else:
            msg = "Invalid syntax"
            # DP ???: Should the actual token be used in the error message?

        raise CompileError.from_token(tok, msg)