func ParseBegin(tuple *ast.Tuple) *ast.Begin { // (begin <expression1> <expression2> ...) elements := tuple.Elements exprs := ParseList(elements[1:]) return ast.NewBegin(ast.NewBlock(exprs)) }
func ParseDefine(tuple *ast.Tuple) *ast.Define { elements := tuple.Elements if len(elements) < 3 { panic(fmt.Sprint("define: bad syntax (missing expressions) ", tuple)) } switch elements[1].(type) { case *ast.Name: // (define <variable> <expression>) if len(elements) > 3 { panic(fmt.Sprint("define: bad syntax (multiple expressions) ", tuple)) } pattern := elements[1].(*ast.Name) value := ParseNode(elements[2]) return ast.NewDefine(pattern, value) case *ast.Tuple: // (define (<variable> <formals>) <body>) // (define (<variable> . <formal>) <body>) tail := ast.NewBlock(ParseList(elements[2:])) function := ParseFunction(elements[1].(*ast.Tuple), tail) return ast.NewDefine(function.Caller, function) default: panic(fmt.Sprint("unsupported parser type ", elements[1])) } }
func ParseLambda(tuple *ast.Tuple) *ast.Lambda { // (lambda <formals> <body>) // switch <formals>: // (<variable1> ...) // <variable> // (<variable1> ... <variablen> . <variablen+1>) elements := tuple.Elements if len(elements) < 3 { panic(fmt.Sprint("lambda: bad syntax: ", tuple)) } pattern := elements[1] body := ast.NewBlock(ParseList(elements[2:])) switch pattern.(type) { case *ast.Name: return ast.NewLambda(pattern, body) case *ast.Tuple: formals := ExpandFormals(pattern.(*ast.Tuple).Elements) _, ok := formals.(*ast.Pair) if ok || formals == ast.NilPair { return ast.NewLambda(formals, body) } else { // (. <variable>) is not allowed panic(fmt.Sprint("lambda: illegal use of `.'")) } default: panic(fmt.Sprint("unsupported parser type ", pattern)) } }
func ParseLetFamily(tuple *ast.Tuple) ast.Node { // (let_ <bindings> <body>) // <bindings> should have the form -> // ((<variable1> <init1>) ...) // where each <init> is an expression elements := tuple.Elements if len(elements) < 3 { panic(fmt.Sprintf("%s: bad syntax, no expression in body", elements[0])) } if _, ok := elements[1].(*ast.Tuple); !ok { panic(fmt.Sprintf("%s: bad syntax, expected bindings, given: %s", elements[0], elements[1])) } bindings := elements[1].(*ast.Tuple).Elements patterns := make([]*ast.Name, len(bindings)) exprs := make([]ast.Node, len(bindings)) for i, binding := range bindings { if tuple, ok := binding.(*ast.Tuple); ok { if len(tuple.Elements) == 2 { if name, ok := tuple.Elements[0].(*ast.Name); ok { patterns[i] = name exprs[i] = ParseNode(tuple.Elements[1]) continue } } } panic(fmt.Sprintf("%s: bad syntax, not an identifer and expression for a binding %s", elements[0], binding)) } body := ast.NewBlock(ParseList(elements[2:])) name, _ := elements[0].(*ast.Name) switch name.Identifier { case constants.LET: return ast.NewLet(patterns, exprs, body) case constants.LET_STAR: return ast.NewLetStar(patterns, exprs, body) case constants.LET_REC: return ast.NewLetRec(patterns, exprs, body) default: panic(fmt.Sprintf("%s: should not be here", elements[0])) } }
func ParseBlock(tuple *ast.Tuple) *ast.Block { elements := tuple.Elements exprs := ParseList(elements) return ast.NewBlock(exprs) }