// nextUnit parses a unit. func (p *Parser) nextUnit() ssa.Node { p.enter() var regNode ssa.Node var reg *ssa.Register switch p.tok.Type { case token.IDENT: nameTok := p.tok fmt.Println(nameTok) p.next() if p.tok.Type == token.LPAREN { p.next() // '(' if p.tok.Type != token.RPAREN { paramNode := p.nextExpression() fmt.Println(paramNode) for p.tok.Type == token.COMMA { p.next() // ',' paramTok := p.tok fmt.Println(paramTok) p.nextExpression() } } p.nextExpected(token.RPAREN) } else if p.tok.Type == token.LBRACK { p.next() p.nextExpression() p.nextExpected(token.RBRACK) } case token.INT: reg = p.alloc.Request() // assembler.emit("li", reg, p.tok.String()); p.next() // int constant regNode = ssa.NewRegNode(types.Int, reg) case token.FLOAT: // p.tok.String() p.next() case token.CHAR: // p.tok.String() p.next() case token.STRING: reg = p.alloc.Request() // Label label = global.enterString(scanner.getString()); // assembler.emit("la", reg, label); p.next() // string constant regNode = ssa.NewRegNode(types.String, reg) default: log.Fatalf("term expected, got '%s'", p.tok) } p.exit() return regNode }
// nextFunctionSignature parses a function signature. func (p *Parser) nextFunctionSignature() { p.enter() // skip 'func' p.nextExpected(token.FUNC) // save the func name token funcNameTok := p.tok p.nextExpected(token.IDENT) // skip func name p.nextExpected(token.LPAREN) // skip '(' // create a new func signature type funcSigType := types.NewFunc() // look for func parameters if p.tok.Type != token.RPAREN { // save the parameter name token paramNameTok := p.tok // skip param name p.nextExpected(token.IDENT) // get the parameter type paramType := p.nextType() // add the parameter type to the func signature type funcSigType.AddParam(paramType) // allocate a register and create a new register node reg := p.alloc.Request() regNode := ssa.NewRegNode(paramType, reg) // add the parameter name token and register node to the current scope p.scope.Add(paramNameTok, regNode) // look for more parameters for p.tok.Type == token.COMMA { p.next() // skip ',' // save the parameter name token paramNameTok = p.tok // skip parameter name p.nextExpected(token.IDENT) // get the parameter type paramType = p.nextType() // add the parameter type to the func signature type funcSigType.AddParam(paramType) // allocate a register and create a new register node reg = p.alloc.Request() regNode = ssa.NewRegNode(paramType, reg) // add the parameter name token and register node to the current scope p.scope.Add(paramNameTok, regNode) } } // skip ')' p.nextExpected(token.RPAREN) // look for return value if p.tok.Type != token.LBRACE { // get the return value type paramType := p.nextType() // add the return value type to the func signature type funcSigType.AddValue(paramType) // look for more return types for p.tok.Type == token.COMMA { p.next() // skip ',' // get the return value type paramType = p.nextType() // add the return value type to the func signature type funcSigType.AddValue(paramType) } } // create a func signature label and node label := ssa.NewLabel(funcNameTok.String()) funcSigNode := ssa.NewFuncNode(funcSigType, label) // check any previous type declarations via TBV if ok, err := p.tbv.Verify(funcNameTok, funcSigNode); ok && err != nil { userErr(err, funcNameTok) } // set the func signature node to the global scope and check for user error if err := p.scope.Global(funcNameTok, funcSigNode); err != nil { userErr(err, funcNameTok) } p.exit() }