Ejemplo n.º 1
0
// 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
}
Ejemplo n.º 2
0
// 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()
}