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)
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)
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)