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_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_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_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_call_literal_argument(self, tag_dispenser): if self.at_type(Token.TAG): tag_value = self.expect_type(Token.TAG) tag = ast.Literal(tag_value) value = self.parse_expression(False) else: value_or_tag = self.parse_expression(False) if self.at_punctuation(':'): self.expect_punctuation(':') tag = value_or_tag value = self.parse_expression(False) else: tag = ast.Literal(tag_dispenser.get_next()) value = value_or_tag return ast.CallLiteralArgument(tag, value)
def vFunction(self, node): self.current_function_id = node.id self.p() proc = node.type.type == 'void' if proc: self.w('PROCEDURE') else: self.w('FUNCTION') self.w(node.id) self.visit(node.params) if not proc: self.w('RETURN') self.visit(node.type) self.p('IS') self.pi('BEGIN') if node.id == 'main': # hack for main block = copy.deepcopy(node.block) block.add(ast.ReturnStatement(ast.Literal(0))) self.visit(block) else: self.visit(node.block) self.uw('END') self.w(self.current_function_id) self.p(';') self.p() self.current_function_id = None
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_naked_selector(self, expect_delim): self.expect_word('op') if self.at_type(Token.OPERATION): (value, is_async) = self.expect_type(Token.OPERATION) if self.at_punctuation('('): self.expect_punctuation('(') self.expect_punctuation(')') op = data.Operation.infix(value) elif self.at_punctuation('('): self.expect_punctuation('(') self.expect_punctuation(')') op = data.Operation.call() elif self.at_punctuation('['): self.expect_punctuation('[') self.expect_punctuation(']') op = data.Operation.index() else: raise self.new_syntax_error() if self.at_punctuation(':='): self.expect_punctuation(':=') self.expect_punctuation('(') self.expect_punctuation(')') op = data.Operation.assign(op) self.expect_statement_delimiter(expect_delim) return ast.Literal(op)
def parse_functino_signature(self, subject, is_prefix, default_name=None): name = default_name is_async = False if self.at_punctuation("->"): is_async = True self.expect_punctuation("->") if (not is_prefix) and self.at_type(Token.OPERATION): (name, is_async) = self.expect_type(Token.OPERATION) if name: default_operation = data.Operation.infix(name) else: default_operation = Parser._SAUSAGES (params, param_operation, allow_extra, reified) = self.parse_parameters(default_operation) if is_prefix: op = data.Operation.prefix(name) params = [] elif params is None: params = [] if name is None: op = Parser._SAUSAGES else: op = data.Operation.infix(name) else: op = param_operation is_async_param = ast.Parameter(None, [data._TRANSPORT], ast.Guard.eq(ast.Literal(data._ASYNC if is_async else data._SYNC))) if self.at_punctuation(':='): self.expect_punctuation(':=') (assign_params, assign_op, allow_extra, reified) = self.parse_parameters(None, start_index=len(params)) params += assign_params op = data.Operation.assign(op) if allow_extra and (op.type == data.Operation._CALL): selector = self.any_selector() else: selector = self.name_as_selector(op) return ast.Signature(subject + [selector, is_async_param] + params, allow_extra, reified)
def parse_signature(self): prefix = [ self.name_as_subject(data.Identifier(0, data.Path(['self']))), self.name_as_selector(Parser._SAUSAGES), ast.Parameter(None, [data._TRANSPORT], ast.Guard.eq(ast.Literal(data._SYNC))) ] (params, operation, allow_extra, reified) = self.parse_parameters(None) if params is None: params = [] return ast.Signature(prefix + params, allow_extra, reified)
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_method_tail(self, expect_delim): if self.at_punctuation('=>'): self.expect_punctuation('=>') body = self.parse_expression(False) elif self.at_punctuation('{'): body = self.parse_sequence_expression() elif self.at_punctuation(';'): body = ast.Literal(None) else: raise self.new_syntax_error() self.expect_statement_delimiter(expect_delim) return body
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 primary(self): if self.match('int'): #this counts for ints and longs i = self.pop().val return (ast.Literal(i)) elif self.match('float'): #counts for floats and doubles f = self.pop().val return (ast.Literal(f)) elif self.match('true'): self.pop() return ast.Literal(True) elif self.match('false'): self.pop() return (ast.Literal(False)) elif self.match('char'): return ast.Literal(self.pop().val) elif self.match('string'): return ast.Literal(self.pop().val) elif self.match_val('['): self.pop() exprList = [] e = None while not self.match_val(']'): exprList.append(e := self.expr()) if not self.match_val(','): break self.pop() if not self.match_val(']'): raise ValueError( f"you ruined the array idiot! what's wrong with you? line {self.pop().line}" ) else: self.pop() return ast.Literal(exprList) elif self.match('ident'): name = self.pop().val if (self.match_val('(')): #name is passed for error reporting arg_list = self.tuple(name) return ast.Call(name, arg_list) return ast.Variable(name) elif self.match_val('('): line_num = self.pop().line expr = self.expr() self.consume(')', f"missing ')' in '('<expr>')' on line {line_num}") return expr else: tok = self.pop() raise ValueError( f"invalid token '{tok.val}' of type '{tok.type}' in expr on line {tok.line}" )
def parse_toplevel_declaration(self, annots): self.expect_word('def') subject = None is_prefix = False name = None allow_extra = False if self.at_type(Token.IDENTIFIER): # def <ident> ident = self.current().value name = self.expect_type(Token.IDENTIFIER) if self.at_punctuation(':='): # def <ident> := self.expect_punctuation(':=') value = self.parse_expression(True) return ast.NamespaceDeclaration(annots, name, value) else: if self.at_punctuation('('): # def <ident> ( subject = ast.Parameter(name, [data._SUBJECT], ast.Guard.eq(ast.Variable(name.shift_back()))) is_async = ast.Parameter(None, [data._TRANSPORT], ast.Guard.eq(ast.Literal(data._SYNC))) (params, operation, allow_extra, reified) = self.parse_parameters(Parser._SAUSAGES) body = self.parse_method_tail(True) selector = self.name_as_selector(operation) signature = ast.Signature([subject, selector, is_async] + params, allow_extra, reified) return ast.FunctionDeclaration(name, ast.Method(signature, body)) else: # def <ident> ... subject = ast.Parameter(name, [data._SUBJECT], ast.Guard.any()) elif self.at_word('type'): # def type <atomic> is <atomic> self.expect_word('type') subtype = self.parse_atomic_expression() self.expect_word('is') supertype = self.parse_atomic_expression() self.expect_statement_delimiter(True) return ast.IsDeclaration(subtype, supertype) elif self.at_type(Token.OPERATION): # def <operation> ... (name, is_async) = self.expect_type(Token.OPERATION) subject = self.parse_subject() is_prefix = True else: # def (<parameter>) subject = self.parse_subject() signature = self.parse_functino_signature([subject], is_prefix, name) body = self.parse_method_tail(True) stage = self.get_subject_stage(subject) return ast.MethodDeclaration(stage + 1, annots, ast.Method(signature, body))
def p_factor_string(p): "factor : STRING" p[0] = ast.Literal(p[1]) p[0].set_position(p.lineno(1), p.lexpos(1))
def p_num_expr_literal(p): '''num_expr : NUM''' p[0] = ast.Literal(p[1])
def p_bool_expr_literal(p): '''bool_expr : BOOL''' p[0] = ast.Literal(p[1])
def p_str_expr_literal(p): '''str_expr : STRING''' p[0] = ast.Literal(p[1])
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()
import formatter import ast arr = ast.Array( ast.Literal('1'), ast.Literal('"foo"'), ast.Object(ast.Member('"foo"', ast.Literal('3'))), ast.Array( ast.Literal('"33"'), ast.Object( ast.Member('"foo"', ast.Object(ast.Member('"foo"', ast.Literal('3'))))))) formatter.JsonFormatter(arr).print_formatted() print('') print('') obj = ast.Object( ast.Member( '"foo"', ast.Array( ast.Literal('1'), ast.Literal('"foo"'), ast.Object(ast.Member('"foo"', ast.Literal('3'))), ast.Array( ast.Literal('"33"'), ast.Object( ast.Member( '"foo"', ast.Object(ast.Member('"foo"', ast.Literal('3'))))))))) formatter.JsonFormatter(obj).print_formatted()
def name_as_selector(self, name): assert isinstance(name, data.Operation) return ast.Parameter(None, [data._SELECTOR], ast.Guard.eq(ast.Literal(name)))