def condistmt(fabri=False): """Parses conditional statements.""" def brkunless(tokens): _, condexpr, _, body, _ = tokens return (condexpr and condexpr[1], body) def breakdown(tokens): _, _, condexpr, _, _, body, _, unlesses = tokens # Create list of flattened statements. stmtlist = [CondiJump([condexpr, len(body) + int(bool(unlesses))])] stmtlist.extend(body) if unlesses: # The offset created when due to the last UNLESS's lack of jumps. # The last UNLESS or a lone DEBATE will not jump off the end, # and if the last UNLESS has no clause, there will be no # conditional jump at the head of its body. jumpoffset = -2 + int(unlesses[-1][0] is not None) for idx, unless in enumerate(unlesses): # Check if this is a clauseless unless that isn't the last unless. if unless[0] is None and idx < len(unlesses) - 1: sys.stderr.write('SyntaxError: invalid unless format') sys.exit(SyntaxError) # Calculate jump length. bodylen = sum( map(lambda u: len(u[1]) + 2, unlesses[idx:]), jumpoffset ) # Add the jump that allows execution to jump to the end. stmtlist.append(CondiJump([None, bodylen])) # Add the jump at the head of this unless. if unless[0]: bodylen = len(unless[1]) + 3 + jumpoffset stmtlist.append(CondiJump([unless[0], bodylen])) # Add the body. stmtlist.extend(unless[1]) return stmtlist stmts = (stmtparser, funcstmts)[fabri] return ( kwdparser('DEBATE') + dlmparser('(') + exprparser() + dlmparser(')') + dlmparser('{') + LazierParser(stmts) + dlmparser('}') + OptionParser( RepeatParser( kwdparser('UNLESS') + OptionParser( dlmparser('(') + exprparser() + dlmparser(')') ) + dlmparser('{') + LazierParser(stmts) + dlmparser('}') ^ brkunless ) ) ^ breakdown )
def callparser(): """Parses a group of expressions.""" def cull_seps(tokens): return tokens[0] or tokens[1] return RepeatParser(exprparser() + OptionParser(dlmparser(',')) ^ cull_seps)
def exprparser(): """Parses an infix expression.""" def shunting_yard(tokens): val_stack = [tokens[0]] opr_stack = [] queue = list(chain(*tokens[1]))[::-1] while queue: # Consume token queue and group accordingly. item = queue.pop() if isinstance(item, str): while opr_stack: opr = opr_stack[-1] if (op_prec[item] < op_prec[opr] or op_prec[item] == op_prec[opr] == 0 ): break args = (val_stack.pop(), val_stack.pop(), opr_stack.pop()) val_stack.append(BnaryExpr(args[::-1])) opr_stack.append(item) else: val_stack.append(item) while opr_stack: # Group the rest after the tokens run out. args = (val_stack.pop(), val_stack.pop(), opr_stack.pop()) val_stack.append(BnaryExpr(args[::-1])) return val_stack[0] term = exprvalparser() | exprgrpparser() return term + RepeatParser(TagsParser('OPERATOR') + term) ^ shunting_yard
def fabristmt(): """Parses function declarations.""" def cull_seps(graft): return graft[0] or graft[1] def breakdown(tokens): kwd, name, _, args, _, _, body, _ = tokens body.pendant = name.name return AthTokenStatement( kwd, (AthCustomFunction(name.name, [arg.name for arg in args], body), )) return (kwdparser('FABRICATE') + varparser + dlmparser('(') + OptionParser( RepeatParser(varparser + OptionParser(dlmparser(',')) ^ cull_seps)) + dlmparser(')') + dlmparser('{') + LazierParser(funcstmts) + dlmparser('}') ^ breakdown)
def killfunc(): """Parses the kill function.""" def cull_seps(graft): return graft[0] or graft[1] def breakdown(tokens): if len(tokens) > 6: return AthTokenStatement(tokens[-4], tokens[1]) else: return AthTokenStatement(tokens[-4], [tokens[0]]) return ( (idnparser | (dlmparser('[') + RepeatParser(idnparser + OptionParser(dlmparser(',')) ^ cull_seps) + dlmparser(']'))) + dlmparser('.') + kwdparser('DIE') + dlmparser('(') + dlmparser(')') + dlmparser(';') ^ breakdown)