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 }
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 }
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()) }