def parse_call_expression(self): recv = self.parse_atomic_expression() while True: is_async = False if self.at_punctuation('->'): self.expect_punctuation('->') is_async = True elif self.at_punctuation('.'): self.expect_punctuation('.') if self.at_punctuation('('): selector = Parser._SAUSAGES start = '(' end = ')' elif self.at_punctuation('['): selector = Parser._SQUARE_SAUSAGES start = '[' end = ']' else: break prefix = [ ast.Argument(data._SUBJECT, recv), ast.Argument(data._SELECTOR, ast.Literal(selector)), ast.Argument(data._TRANSPORT, ast.Literal(data._ASYNC if is_async else data._SYNC)) ] rest = self.parse_arguments(start, end) recv = ast.Invocation(prefix + rest) return recv
def parse_atomic_expression(self): if self.at_type(Token.LITERAL): value = self.expect_type(Token.LITERAL) result = ast.Literal(value) if isinstance(value, data.DecimalFraction): # While the infrastructure is not in place to create floats without # magic we insert a new_float invocation in the parser. result = ast.Invocation([ ast.Argument(data._SUBJECT, ast.Variable(data.Identifier(-1, data.Path(["ctrino"])))), ast.Argument(data._SELECTOR, ast.Literal(data.Operation.infix("new_float_32"))), ast.Argument(data._TRANSPORT, ast.Literal(data._SYNC)), ast.Argument(0, result) ]) return result elif self.at_type(Token.IDENTIFIER): return self.parse_variable() elif self.at_punctuation('('): self.expect_punctuation('(') result = self.parse_expression(False) self.expect_punctuation(')') return result elif self.at_punctuation('['): return self.parse_array_expression() elif self.at_punctuation('{'): return self.parse_sequence_expression() elif self.at_word('null'): self.expect_word('null') return ast.Literal(None) elif self.at_word('true'): self.expect_word('true') return ast.Literal(True) elif self.at_word('false'): self.expect_word('false') return ast.Literal(False) elif self.at_word('subject'): self.expect_word('subject') return ast.Literal(data._SUBJECT) elif self.at_word('selector'): self.expect_word('selector') return ast.Literal(data._SELECTOR) elif self.at_word('transport'): self.expect_word('transport') return ast.Literal(data._TRANSPORT) elif self.at_word('async'): self.expect_word('async') return ast.Literal(data._ASYNC) elif self.at_word('sync'): self.expect_word('sync') return ast.Literal(data._SYNC) elif self.at_word('module'): self.expect_word('module') return ast.CurrentModule() elif self.at_type(Token.QUOTE): return self.parse_quote() else: raise self.new_syntax_error()
def parse_new_expression(self, expect_delim): self.expect_word('new') cons = self.parse_atomic_expression() args = self.parse_arguments('(', ')') self.expect_statement_delimiter(expect_delim) prefix = [ ast.Argument(data._SUBJECT, cons), ast.Argument(data._SELECTOR, ast.Literal(Parser._NEW)), ast.Argument(data._TRANSPORT, ast.Literal(data._SYNC)) ] return ast.Invocation(prefix + args)
def parse_operator_expression(self): left = self.parse_unary_expression() while self.at_type(Token.OPERATION): (selector, is_async, rest) = self.parse_operator_tail() prefix = [ ast.Argument(data._SUBJECT, left), ast.Argument(data._SELECTOR, ast.Literal(selector)), ast.Argument(data._TRANSPORT, ast.Literal(data._ASYNC if is_async else data._SYNC)) ] left = ast.Invocation(prefix + rest) return left
def parse_unary_expression(self): if self.at_type(Token.OPERATION): (name, is_async) = self.expect_type(Token.OPERATION) selector = data.Operation.prefix(name) subject = self.parse_unary_expression() args = [ ast.Argument(data._SUBJECT, subject), ast.Argument(data._SELECTOR, ast.Literal(selector)), ast.Argument(data._TRANSPORT, ast.Literal(data._ASYNC if is_async else data._SYNC)) ] return ast.Invocation(args) else: return self.parse_call_expression()
def parse_for_expression(self, expect_delim): self.expect_word('for') sig = self.parse_signature() self.expect_word('in') elms = self.parse_expression(False) self.expect_word('do') body = self.parse_expression(expect_delim) thunk = ast.Lambda([ast.Method(sig, body)]) return ast.Invocation([ ast.Argument(data._SUBJECT, ast.Variable(data.Identifier(-1, data.Path(["core", "for"])))), ast.Argument(data._SELECTOR, ast.Literal(Parser._SAUSAGES)), ast.Argument(data._TRANSPORT, ast.Literal(data._SYNC)), ast.Argument(0, elms), ast.Argument(1, thunk), ])
def parse_while_expression(self, expect_delim): self.expect_word('while') cond = self.parse_expression(False) self.expect_word('do') body = self.parse_expression(expect_delim) methods = [ ast.Lambda.method(cond, data.Operation.infix('keep_running?')), ast.Lambda.method(body, data.Operation.infix('run!')) ] return ast.Invocation([ ast.Argument(data._SUBJECT, ast.Variable(data.Identifier(-1, data.Path(["core", "while"])))), ast.Argument(data._SELECTOR, ast.Literal(Parser._SAUSAGES)), ast.Argument(data._TRANSPORT, ast.Literal(data._SYNC)), ast.Argument(0, ast.Lambda(methods)), ])
def parse_method_call(self, left): expr = ast.MethodCall(self.cur_tok, left, []) while self.peek_in(self.arg_tokens) or self.peek_in( token.keywords.values()): self.next() if self.cur_in(token.keywords.values()): expr.pattern.append(ast.Identifier(self.cur_tok)) continue arg = lambda val: ast.Argument(self.cur_tok, val) handlers = { token.ID: lambda: ast.Identifier(self.cur_tok), token.LPAREN: lambda: arg(self.parse_grouped_expr()), token.NUM: lambda: arg(self.parse_num()), token.NULL: lambda: arg(self.parse_null()), token.TRUE: lambda: arg(self.parse_bool()), token.FALSE: lambda: arg(self.parse_bool()), token.STR: lambda: arg(self.parse_string()), token.PARAM: lambda: arg(ast.Identifier(self.cur_tok)), token.LSQUARE: lambda: arg(self.parse_array_or_map()), token.LBRACE: lambda: arg(self.parse_block_literal()), } handler = handlers[self.cur_tok.type] expr.pattern.append(handler()) if len(expr.pattern) == 0: self.err("expected at least one item in a pattern") return None return expr
def parse_argument(self, default_tag): if self.at_type(Token.TAG): tag = self.expect_type(Token.TAG) else: tag = default_tag value = self.parse_expression(False) return ast.Argument(tag, value)
def parse_when_expression(self, expect_delim): self.expect_word('when') self.expect_word('def') sig = self.parse_signature() self.expect_punctuation(':=') value = self.parse_expression(False) self.expect_word('do') body = self.parse_expression(expect_delim) thunk = ast.Lambda([ast.Method(sig, body)]) return ast.Invocation([ ast.Argument(data._SUBJECT, ast.Variable(data.Identifier(-1, data.Path(["core", "when_def"])))), ast.Argument(data._SELECTOR, ast.Literal(Parser._SAUSAGES)), ast.Argument(data._TRANSPORT, ast.Literal(data._SYNC)), ast.Argument(0, value), ast.Argument(1, thunk), ])
def parse_signal_expression(self, expect_delim): if self.at_word('leave'): is_abort = True self.expect_word('leave') else: is_abort = False self.expect_word('signal') (selector, is_async, rest) = self.parse_operator_tail() if self.at_word('else'): self.expect_word('else') default = self.parse_expression(expect_delim) else: default = None self.expect_statement_delimiter(expect_delim) return ast.Signal(is_abort, [ ast.Argument(data._SUBJECT, ast.Literal(None)), ast.Argument(data._SELECTOR, ast.Literal(selector)), ast.Argument(data._TRANSPORT, ast.Literal(data._SYNC)) ] + rest, default)
def parse_if_expression(self, expect_delim): self.expect_word('if') cond = self.parse_expression(False) self.expect_word('then') then_part = self.parse_expression(expect_delim) if self.at_word('else'): self.expect_word('else') else_part = self.parse_expression(expect_delim) else: else_part = ast.Literal(None) methods = [ ast.Lambda.method(then_part, data.Operation.infix('then!')), ast.Lambda.method(else_part, data.Operation.infix('else!')) ] args = [ ast.Argument(data._SUBJECT, ast.Variable(data.Identifier(-1, data.Path(["core", "if"])))), ast.Argument(data._SELECTOR, ast.Literal(Parser._SAUSAGES)), ast.Argument(data._TRANSPORT, ast.Literal(data._SYNC)), ast.Argument(0, cond), ast.Argument(1, ast.Lambda(methods)) ] result = ast.Invocation(args) return result
def parse_arguments(self, start, end): args = [] if self.at_punctuation(start): self.expect_punctuation(start) if not self.at_punctuation(end): arg = self.parse_argument(0) args.append(arg) index = 1 while self.at_punctuation(','): self.expect_punctuation(',') arg = self.parse_argument(index) args.append(arg) index += 1 self.expect_punctuation(end) else: arg = self.parse_unary_expression() args.append(ast.Argument(0, arg)) return args
def parse_function_call(self, first=None): expr = ast.FunctionCall(self.cur_tok, []) if first != None: expr.pattern.append(first) # If the current token is a valid arg token, or a keyword while self.peek_in(self.arg_tokens) or self.peek_in( token.keywords.values()): self.next() if self.cur_in(token.keywords.values()): expr.pattern.append(ast.Identifier(self.cur_tok)) continue arg = lambda val: ast.Argument(self.cur_tok, val) handlers = { token.ID: lambda: ast.Identifier(self.cur_tok), token.PARAM: lambda: arg(ast.Identifier(self.cur_tok)) } found = False for k, v in self.prefixes.items(): if k in handlers.keys(): continue if k == self.cur_tok.type: expr.pattern.append(arg(v())) found = True if not found: handler = handlers[self.cur_tok.type] expr.pattern.append(handler()) if len(expr.pattern) == 0: self.err("expected at least one item in a pattern") return None return expr
def parse_function_call(self, first=None): expr = ast.FunctionCall(self.cur_tok, []) if first != None: expr.pattern.append(first) # If the current token is a valid arg token, or a keyword while self.peek_in(arg_tokens) or self.peek_in( token.keywords.values()): self.next() if self.cur_in(token.keywords.values()): expr.pattern.append(ast.Identifier(self.cur_tok)) continue arg = lambda val: ast.Argument(self.cur_tok, val) handlers = { token.ID: lambda: ast.Identifier(self.cur_tok), token.LPAREN: lambda: arg(self.parse_grouped_expr()), token.NUM: lambda: arg(self.parse_num()), token.NULL: lambda: arg(self.parse_null()), token.TRUE: lambda: arg(self.parse_bool()), token.FALSE: lambda: arg(self.parse_bool()), token.STR: lambda: arg(self.parse_string()), token.PARAM: lambda: arg(ast.Identifier(self.cur_tok)), token.LSQUARE: lambda: arg(self.parse_array_or_object()), token.LBRACE: lambda: arg(self.parse_block_literal()), } handler = handlers[self.cur_tok.type] expr.pattern.append(handler()) if len(expr.pattern) == 0: self.err("expected at least one item in a pattern") return None return expr