예제 #1
0
func (b *Builder) ParseMacro(ctx *builderCtx) node.Node {
	macroToken := b.NextNonSpace(ctx)
	if macroToken.Type() != ItemMacro {
		b.Unexpected(ctx, "Expected 'MACRO', got %s", macroToken)
	}

	// Parse name, and arguments.
	nameToken := b.NextNonSpace(ctx)
	if nameToken.Type() != ItemIdentifier {
		b.Unexpected(ctx, "Expected identifier, got %s", nameToken)
	}

	idx := ctx.DeclareLocalVar(nameToken.Value())

	macro := node.NewMacroNode(nameToken.Pos(), nameToken.Value())
	macro.LocalVar = node.NewLocalVarNode(nameToken.Pos(), nameToken.Value(), idx)
	ctx.CurrentParentNode().Append(macro)
	ctx.PushParentNode(macro)

	// either a '(' followed by argument list, or BLOCK
	if b.PeekNonSpace(ctx).Type() == ItemOpenParen {
		b.NextNonSpace(ctx) // discard open paren
		// Can't use ParseList() here, because we want a list of only identifiers
		for {
			next := b.NextNonSpace(ctx)
			if next.Type() != ItemIdentifier {
				b.Backup(ctx)
				break
			}

			//      idx := ctx.DeclareLocalVar(next.Value())
			//      macro.AppendArg(node.NewLocalVarNode(next.Pos(), next.Value(), idx))

			next = b.NextNonSpace(ctx)
			if next.Type() != ItemComma {
				b.Backup(ctx)
				break
			}
		}
		if closeParen := b.NextNonSpace(ctx); closeParen.Type() != ItemCloseParen {
			b.Unexpected(ctx, "Expected ')', got %s", closeParen)
		}
	}

	// Then we need a BLOCK
	if block := b.NextNonSpace(ctx); block.Type() != ItemBlock {
		b.Unexpected(ctx, "Expected BLOCK, got %s", block)
	}

	return nil
}
예제 #2
0
func (b *Builder) ParseListVariableOrMakeArray(ctx *builderCtx) node.Node {
	list := b.PeekNonSpace(ctx)

	var n node.Node
	switch list.Type() {
	case ItemIdentifier:
		b.NextNonSpace(ctx)
		if idx, ok := ctx.HasLocalVar(list.Value()); ok {
			n = node.NewLocalVarNode(list.Pos(), list.Value(), idx)
		} else {
			n = node.NewFetchSymbolNode(list.Pos(), list.Value())
		}
		if b.PeekNonSpace(ctx).Type() == ItemPeriod {
			b.NextNonSpace(ctx)
			n = b.ParseMethodCallOrMapLookup(ctx, n)
		}
	case ItemOpenSquareBracket:
		n = b.ParseMakeArray(ctx)
	default:
		panic("f**k")
	}
	return n
}
예제 #3
0
func (b *Builder) LocalVarOrFetchSymbol(ctx *builderCtx, token lex.LexItem) node.Node {
	if idx, ok := ctx.HasLocalVar(token.Value()); ok {
		return node.NewLocalVarNode(token.Pos(), token.Value(), idx)
	}
	return node.NewFetchSymbolNode(token.Pos(), token.Value())
}