func (p *Parser) parseFor() ast.Expression {
	expression := &ast.For{Token: p.token}
	expression.Arguments = &ast.IdentifierList{}
	arguments := []*ast.Identifier{}
	p.advance()
loop:
	for !p.match(token.DO, token.NEWLINE, token.EOF) {
		switch p.token.Type {
		case token.COMMA:  
		case token.IN:
			p.advance()
			expression.Arguments.Elements = arguments
			expression.Enumerable = p.parseExpression(LOWEST)
			if expression.Enumerable == nil {
				p.reportError("Missing enumerable in FOR loop")
				return nil
			}
			break loop
		default:
			arguments = append(arguments, &ast.Identifier{Token: p.token, Value: p.token.Lexeme})
		}
		p.advance()
	}
	if p.peekMatch(token.DO) {
		p.advance()
	}
	expression.Body = p.parseBlockBody()
	if len(expression.Body.Statements) == 0 {
		p.reportError("Empty body in FOR loop")
		return nil
	}
	if !p.match(token.END) {
		p.reportError("Missing END closing statement in FOR loop")
		return nil
	}
	return expression
}
for IDENT1, IDENT2 in IDENT3 STATEMENTS end
package parser
import (
	"fmt"
	"github.com/fadion/aria/ast"
	"github.com/fadion/aria/lexer"
	"github.com/fadion/aria/reporter"
	"github.com/fadion/aria/token"
	"reflect"
	"strconv"
	"strings"
)
type Parser struct {
	lex             *lexer.Lexer
	token           token.Token
	peekToken       token.Token
	prefixFunctions map[token.TokenType]prefixParseFn
	infixFunctions  map[token.TokenType]infixParseFn
}
type (
	prefixParseFn func() ast.Expression
	infixParseFn  func(ast.Expression) ast.Expression
)
func New(l *lexer.Lexer) *Parser {
	p := &Parser{lex: l}
	p.prefixFunctions = make(map[token.TokenType]prefixParseFn)
	p.infixFunctions = make(map[token.TokenType]infixParseFn)
	p.prefix(token.LET, p.parseLet)
	p.prefix(token.VAR, p.parseVar)
	p.prefix(token.MODULE, p.parseModule)
	p.prefix(token.IF, p.parseIf)
	p.prefix(token.SWITCH, p.parseSwitch)
	p.prefix(token.FOR, p.parseFor)
	p.prefix(token.FUNCTION, p.parseFunction)
	p.prefix(token.IMPORT, p.parseImport)
	p.prefix(token.LBRACK, p.parseArrayOrDictionary)
	p.prefix(token.IDENTIFIER, p.parseIdentifier)
	p.prefix(token.INTEGER, p.parseInteger)
	p.prefix(token.FLOAT, p.parseFloat)
	p.prefix(token.STRING, p.parseString)
	p.prefix(token.BOOLEAN, p.parseBoolean)
	p.prefix(token.NIL, p.parseNil)
	p.prefix(token.UNDERSCORE, p.parsePlaceholder)
	p.prefix(token.COLON, p.parseAtom)
	p.prefix(token.BANG, p.parsePrefix)
	p.prefix(token.BITNOT, p.parsePrefix)
	p.prefix(token.MINUS, p.parsePrefix)
	p.prefix(token.LPAREN, p.parseGroup)
	p.infix(token.ASSIGN, p.parseAssign)
	p.infix(token.ASSIGNPLUS, p.parseAssign)
	p.infix(token.ASSIGNMIN, p.parseAssign)
	p.infix(token.ASSIGNMULT, p.parseAssign)
	p.infix(token.ASSIGNDIV, p.parseAssign)
	p.infix(token.DOT, p.parseModuleAccess)
	p.infix(token.LPAREN, p.parseFunctionCall)
	p.infix(token.LBRACK, p.parseSubscript)
	p.infix(token.PIPE, p.parsePipe)
	p.infix(token.ARROW, p.parseArrowFunction)
	p.infix(token.QUESTION, p.parseTernary)
	p.infix(token.IS, p.parseIs)
	p.infix(token.AS, p.parseAs)
	p.infix(token.RANGE, p.parseInfix)
	p.infix(token.PLUS, p.parseInfix)
	p.infix(token.MINUS, p.parseInfix)
	p.infix(token.SLASH, p.parseInfix)
	p.infix(token.ASTERISK, p.parseInfix)
	p.infix(token.MODULO, p.parseInfix)
	p.infix(token.POWER, p.parseInfix)
	p.infix(token.EQ, p.parseInfix)
	p.infix(token.UNEQ, p.parseInfix)
	p.infix(token.LT, p.parseInfix)
	p.infix(token.LTE, p.parseInfix)
	p.infix(token.GT, p.parseInfix)
	p.infix(token.GTE, p.parseInfix)
	p.infix(token.OR, p.parseInfixRight)
	p.infix(token.AND, p.parseInfixRight)
	p.infix(token.BITAND, p.parseInfix)
	p.infix(token.BITOR, p.parseInfix)
	p.infix(token.BITSHLEFT, p.parseInfix)
	p.infix(token.BITSHRIGHT, p.parseInfix)
	p.advance()
	p.advance()
	return p
}
func (p *Parser) advance() {
	p.token = p.peekToken
	p.peekToken = p.lex.NextToken()
}
func (p *Parser) match(t ...token.TokenType) bool {
	for _, v := range t {
		if p.token.Type == v {
			return true
		}
	}
	return false
}
func (p *Parser) peekMatch(t ...token.TokenType) bool {
	for _, v := range t {
		if p.peekToken.Type == v {
			return true
		}
	}
	return false
}
func (p *Parser) prefix(tokenType token.TokenType, fn prefixParseFn) {
	p.prefixFunctions[tokenType] = fn
}
func (p *Parser) infix(tokenType token.TokenType, fn infixParseFn) {
	p.infixFunctions[tokenType] = fn
}
func (p *Parser) precedence() int {
	if p, ok := precedences[p.token.Type]; ok {
		return p
	}
	return LOWEST
}
func (p *Parser) peekPrecedence() int {
	if p, ok := precedences[p.peekToken.Type]; ok {
		return p
	}
	return LOWEST
}
func (p *Parser) Parse() *ast.Program {
	program := &ast.Program{}
	program.Statements = []ast.Statement{}
	for !p.match(token.EOF) {
		statement := p.parseStatement()
		if reflect.ValueOf(statement).IsValid() {
			program.Statements = append(program.Statements, statement)
		}
		p.advance()
	}
	return program
}
func (p *Parser) parseStatement() ast.Statement {
	switch p.token.Type {
	case token.RETURN:
		return p.parseReturn()
	case token.BREAK:
		return p.parseBreak()
	case token.CONTINUE:
		return p.parseContinue()
	case token.COMMENT:  
		return nil
	case token.NEWLINE:  
		return nil
	default:
		return p.parseExpressionStatement()
	}
}
func (p *Parser) parseLet() ast.Expression {
	expression := &ast.Let{Token: p.token}
	if !p.peekMatch(token.IDENTIFIER) {
		p.reportError("LET expects an identifier")
		return nil
	}
	p.advance()
	expression.Name = &ast.Identifier{Token: p.token, Value: p.token.Lexeme}
	if !p.peekMatch(token.ASSIGN) {
		p.reportError("Missing assignment in LET")
		return nil
	}
	p.advance()
	p.advance()
	expression.Value = p.parseExpression(LOWEST)
	return expression
}
func (p *Parser) parseVar() ast.Expression {
	expression := &ast.Var{Token: p.token}
	if !p.peekMatch(token.IDENTIFIER) {
		p.reportError("VAR expects an identifier")
		return nil
	}
	p.advance()
	expression.Name = &ast.Identifier{Token: p.token, Value: p.token.Lexeme}
	if !p.peekMatch(token.ASSIGN) {
		p.reportError("Missing assignment in VAR")
		return nil
	}
	p.advance()
	p.advance()
	expression.Value = p.parseExpression(LOWEST)
	return expression
}
func (p *Parser) parseModule() ast.Expression {
	expression := &ast.Module{Token: p.token}
	if !p.peekMatch(token.IDENTIFIER) {
		p.reportError("Expecting an identifier as MODULE name")
		return nil
	}
	p.advance()
	expression.Name = &ast.Identifier{Token: p.token, Value: p.token.Lexeme}
	if p.match(token.DO) {
		p.advance()
	}
	expression.Body = p.parseBlockBody()
	if !p.match(token.END) {
		p.reportError("Missing END closing statement in MODULE")
		return nil
	}
	return expression
}
func (p *Parser) parseModuleAccess(left ast.Expression) ast.Expression {
	switch object := left.(type) {
	case *ast.Identifier:  
		expression := &ast.ModuleAccess{Token: p.token, Object: object}
		if p.peekMatch(token.IDENTIFIER) {
			p.advance()
			expression.Parameter = &ast.Identifier{Token: p.token, Value: p.token.Lexeme}
			return expression
		}
	default:
		p.reportError(fmt.Sprintf("Cannot use '%s' as MODULE caller", object.TokenLexeme()))
	}
	return nil
}
func (p *Parser) parseIdentifier() ast.Expression {
	return &ast.Identifier{Token: p.token, Value: p.token.Lexeme}
}
func (p *Parser) parseInteger() ast.Expression {
	literal := &ast.Integer{Token: p.token}
	lexeme := p.token.Lexeme
	var value int64
	var err error
	if strings.HasPrefix(lexeme, "0b") {
		value, err = strconv.ParseInt(lexeme[2:], 2, 64)
	} else if strings.HasPrefix(lexeme, "0x") {
		value, err = strconv.ParseInt(lexeme, 0, 64)
	} else if strings.HasPrefix(lexeme, "0o") {
		value, err = strconv.ParseInt(lexeme[:1]+lexeme[2:], 0, 64)
	} else {
		value, err = strconv.ParseInt(lexeme, 0, 64)
	}
	if err != nil {
		p.reportError(fmt.Sprintf("Couldn't parse %s as Integer", p.token.Lexeme))
		return nil
	}
	literal.Value = value
	return literal
}
func (p *Parser) parseFloat() ast.Expression {
	literal := &ast.Float{Token: p.token}
	value, err := strconv.ParseFloat(p.token.Lexeme, 64)
	if err != nil {
		p.reportError(fmt.Sprintf("Couldn't parse %s as Float", p.token.Lexeme))
		return nil
	}
	literal.Value = value
	return literal
}
func (p *Parser) parseString() ast.Expression {
	return &ast.String{Token: p.token, Value: p.token.Lexeme}
}
func (p *Parser) parseBoolean() ast.Expression {
	return &ast.Boolean{Token: p.token, Value: p.token.Lexeme == "true"}
}
func (p *Parser) parseNil() ast.Expression {
	return &ast.Nil{Token: p.token}
}
func (p *Parser) parseIf() ast.Expression {
	expression := &ast.If{Token: p.token}
	p.advance()
	expression.Condition = p.parseExpression(LOWEST)
	if expression.Condition == nil {
		p.reportError("Missing condition expression in IF")
		return nil
	}
	p.advance()
	if p.match(token.THEN, token.DO) {
		p.advance()
	}
	block := &ast.BlockStatement{Token: p.token}
	block.Statements = []ast.Statement{}
	for !p.match(token.END, token.ELSE, token.EOF) {
		statement := p.parseStatement()
		if statement != nil {
			block.Statements = append(block.Statements, statement)
		}
		p.advance()
	}
	if len(block.Statements) == 0 {
		p.reportError("Empty body in IF")
		return nil
	}
	expression.Then = block
	if p.match(token.ELSE) {
		elseBody := p.parseBlockBody()
		if len(elseBody.Statements) == 0 {
			p.reportError("Empty ELSE body in IF")
			return nil
		}
		expression.Else = elseBody
	}
	if !p.match(token.END) {
		p.reportError("Missing END closing statement in IF")
		return nil
	}
	return expression
}
func (p *Parser) parseSwitch() ast.Expression {
	expression := &ast.Switch{Token: p.token}
	p.advance()
	expression.Control = p.parseExpression(LOWEST)
	if expression.Control != nil {
		p.advance()
	}
	if !p.match(token.DO, token.NEWLINE) {
		p.reportError("Missing DO statement in inline SWITCH")
	}
	p.advance()
	var cases []*ast.SwitchCase
	for !p.match(token.END, token.EOF) {
		switch p.token.Type {
		case token.CASE:  
			switchcase := &ast.SwitchCase{Token: p.token}
			list := &ast.ExpressionList{Token: p.token}
			p.advance()
			list.Elements = p.parseDelimited(token.COMMA, token.NEWLINE, token.THEN)
			if len(list.Elements) == 0 {
				p.reportError("Missing expression in SWITCH CASE")
				break
			}
			switchcase.Values = list
			switchcase.Body = p.parseSwitchCase()
			cases = append(cases, switchcase)
		case token.DEFAULT:  
			if !p.peekMatch(token.THEN, token.NEWLINE) {
				p.reportError("DEFAULT case in SWITCH can't have parameters")
				return nil
			}
			p.advance()
			expression.Default = p.parseSwitchCase()
			if len(expression.Default.Statements) == 0 {
				p.reportError("Missing DEFAULT case body in SWITCH")
				return nil
			}
		}
		p.advance()
	}
	expression.Cases = cases
	if !p.match(token.END) {
		p.reportError("Missing END closing statement in SWITCH")
		return nil
	}
	return expression
}
func (p *Parser) parseSwitchCase() *ast.BlockStatement {
	block := &ast.BlockStatement{Token: p.token}
	block.Statements = []ast.Statement{}
	for !p.peekMatch(token.CASE, token.DEFAULT, token.END, token.EOF) {
		p.advance()
		statement := p.parseStatement()
		if statement != nil {
			block.Statements = append(block.Statements, statement)
		}
	}
	return block
}