예제 #1
0
func (b *Builder) ParseAssignment(ctx *builderCtx) node.Node {
	symbol := b.NextNonSpace(ctx)
	if symbol.Type() != ItemIdentifier {
		b.Unexpected(ctx, "Expected identifier, got %s", symbol)
	}

	b.DeclareLocalVarIfNew(ctx, symbol)
	n := node.NewAssignmentNode(symbol.Pos(), symbol.Value())

	eq := b.NextNonSpace(ctx)
	switch eq.Type() {
	case ItemAssign:
		n.Expression = b.ParseExpression(ctx, false)
	case ItemAssignAdd:
		add := node.NewPlusNode(symbol.Pos())
		add.Left = b.LocalVarOrFetchSymbol(ctx, symbol)
		add.Right = b.ParseExpression(ctx, false)
		n.Expression = add
	case ItemAssignSub:
		sub := node.NewMinusNode(symbol.Pos())
		sub.Left = b.LocalVarOrFetchSymbol(ctx, symbol)
		sub.Right = b.ParseExpression(ctx, false)
		n.Expression = sub
	case ItemAssignMul:
		mul := node.NewMulNode(symbol.Pos())
		mul.Left = b.LocalVarOrFetchSymbol(ctx, symbol)
		mul.Right = b.ParseExpression(ctx, false)
		n.Expression = mul
	case ItemAssignDiv:
		div := node.NewDivNode(symbol.Pos())
		div.Left = b.LocalVarOrFetchSymbol(ctx, symbol)
		div.Right = b.ParseExpression(ctx, false)
		n.Expression = div
	default:
		b.Unexpected(ctx, "Expected assign, got %s", eq)
	}

	return n
}
예제 #2
0
func (b *Builder) ParseExpression(ctx *builderCtx, canPrint bool) (n node.Node) {
	defer func() {
		if n != nil && canPrint {
			n = node.NewPrintNode(n.Pos(), n)
		}
	}()

	switch b.PeekNonSpace(ctx).Type() {
	case ItemOpenParen:
		// Looks like a group of something
		n = b.ParseGroup(ctx)
	case ItemOpenSquareBracket:
		// Looks like an inline list def
		n = b.ParseMakeArray(ctx)
	default:
		// Otherwise it's a straight forward ... something
		n = b.ParseTerm(ctx)
		if n == nil {
			panic(fmt.Sprintf("Expected term but could not parse. Next is %s\n", b.PeekNonSpace(ctx)))
		}
	}

	next := b.PeekNonSpace(ctx)

	switch n.Type() {
	case node.LocalVar, node.FetchSymbol:
		switch next.Type() {
		case ItemPeriod:
			// It's either a method call, or a map lookup
			b.NextNonSpace(ctx)
			n = b.ParseMethodCallOrMapLookup(ctx, n)
		case ItemOpenSquareBracket:
			n = b.ParseArrayElementFetch(ctx, n)
		case ItemOpenParen:
			// A variable followed by an open paren is a function call
			n = b.ParseFunCall(ctx, n)
		}
	}

	next = b.NextNonSpace(ctx)
	switch next.Type() {
	case ItemPlus:
		tmp := node.NewPlusNode(next.Pos())
		tmp.Left = n
		tmp.Right = b.ParseExpression(ctx, false)
		n = tmp
		return
	case ItemMinus:
		// This is special...
		following := b.PeekNonSpace(ctx)
		if following.Type() == ItemTagEnd {
			b.Backup2(ctx, next)
			// Postchomp! not arithmetic!
			return
		}
		tmp := node.NewMinusNode(next.Pos())
		tmp.Left = n
		tmp.Right = b.ParseExpression(ctx, false)
		n = tmp
		return
	case ItemAsterisk:
		tmp := node.NewMulNode(next.Pos())
		tmp.Left = n
		tmp.Right = b.ParseExpression(ctx, false)
		n = tmp
		return
	case ItemSlash:
		tmp := node.NewDivNode(next.Pos())
		tmp.Left = n
		tmp.Right = b.ParseExpression(ctx, false)
		n = tmp
		return
	case ItemEquals:
		tmp := node.NewEqualsNode(next.Pos())
		tmp.Left = n
		tmp.Right = b.ParseExpression(ctx, false)
		n = tmp
	case ItemNotEquals:
		tmp := node.NewNotEqualsNode(next.Pos())
		tmp.Left = n
		tmp.Right = b.ParseExpression(ctx, false)
		n = tmp
	case ItemLT:
		tmp := node.NewLTNode(next.Pos())
		tmp.Left = n
		tmp.Right = b.ParseExpression(ctx, false)
		n = tmp
		return
	case ItemGT:
		tmp := node.NewGTNode(next.Pos())
		tmp.Left = n
		tmp.Right = b.ParseExpression(ctx, false)
		n = tmp
	case ItemVerticalSlash:
		b.Backup(ctx)
		n = b.ParseFilter(ctx, n)
	default:
		b.Backup(ctx)
	}

	return
}