package parser import ( "fmt" "git.maximhutz.com/max/lambda/pkg/iterator" "git.maximhutz.com/max/lambda/pkg/lambda" "git.maximhutz.com/max/lambda/pkg/tokenizer" ) func ParseExpression(i *iterator.Iterator[tokenizer.Token]) (lambda.Expression, error) { token, err := i.Next() if err != nil { return nil, fmt.Errorf("Could not get next token: %w", err) } switch token.Type { case tokenizer.TokenAtom: return lambda.NewAtom(token.Value), nil case tokenizer.TokenDot: return nil, fmt.Errorf("Token '.' found without a corresponding slash (column %d).", token.Index) case tokenizer.TokenSlash: atom, atom_err := i.Next() if atom_err != nil { return nil, fmt.Errorf("Could not find parameter of function: %w", atom_err) } else if atom.Type != tokenizer.TokenAtom { return nil, fmt.Errorf("Expected function parameter, got '%v' (column %d).", atom.Value, atom.Index) } dot, dot_err := i.Next() if dot_err != nil { return nil, fmt.Errorf("Could not find function parameter terminator: %w", dot_err) } else if dot.Type != tokenizer.TokenDot { return nil, fmt.Errorf("Expected function parameter terminator, got '%v' (column %v).", dot.Value, dot.Index) } body, body_err := ParseExpression(i) if body_err != nil { return nil, fmt.Errorf("Could not parse function body: %w", body_err) } return lambda.NewFunction(atom.Value, body), nil case tokenizer.TokenOpenParen: fn, fn_err := ParseExpression(i) if fn_err != nil { return nil, fmt.Errorf("Could not parse call function: %w", fn_err) } arg, arg_err := ParseExpression(i) if arg_err != nil { return nil, fmt.Errorf("Could not parse call argument: %w", arg_err) } close, close_err := i.Next() if close_err != nil { return nil, fmt.Errorf("Could not parse call terminating parenthesis: %w", close_err) } else if close.Type != tokenizer.TokenCloseParen { return nil, fmt.Errorf("Expected call terminating parenthesis, got '%v' (column %v).", close.Value, close.Index) } return lambda.NewCall(fn, arg), nil case tokenizer.TokenCloseParen: return nil, fmt.Errorf("Token ')' found without a corresponding openning parenthesis (column %d).", token.Index) default: return nil, fmt.Errorf("Unknown token '%v' (column %d).", token.Value, token.Index) } } func GetTree(tokens []tokenizer.Token) (lambda.Expression, error) { i := iterator.New(tokens) return ParseExpression(&i) }