sexp/input.go
2025-08-23 20:02:18 -03:00

96 lines
1.7 KiB
Go

package main
import (
"fmt"
"slices"
)
type Input struct {
index int
input []Lexeme
}
func (in Input) Index() int {
return in.index
}
func (in Input) String() string {
_ = in.input[in.index]
return fmt.Sprintf("%v", in.input[in.index:])
}
func (in *Input) Len() int {
// _ = in.input[in.index]
return len(in.input[in.index:])
}
func (in *Input) Peek(i int) Lexeme {
return in.input[in.index+i]
}
func (in *Input) Pop() (Lexeme, bool) {
if in.index > len(in.input)-1 {
return nil, false
}
v := in.input[in.index]
in.index++
return v, true
}
func (in *Input) Seek(i int) {
_ = in.input[i]
in.index = i
}
func (in *Input) Take(offset int) *Input {
var out = &Input{
index: 0,
input: in.input[in.index : in.index+offset],
}
in.index += offset
return out
}
func (in *Input) Find(open, close *Token) (int, bool) {
level := 1
_ = in.input[in.index]
idx := slices.IndexFunc(in.input[in.index:], func(a Lexeme) bool {
switch {
case a.Equals(open):
level++
case a.Equals(close):
level--
return level == 0
}
return false
})
if idx > -1 {
return idx, true
} else {
return 0, false
}
}
func (in *Input) TakeParens(open, close *Token) (*Input, error) {
if in.input[in.index].Equals(open) {
return nil, noMatch
}
start := in.index
level := 1
idx := slices.IndexFunc(in.input[start+1:], func(a Lexeme) bool {
switch {
case a.Equals(open):
level++
case a.Equals(close):
level--
return level == 0
}
return false
})
if idx > -1 {
_ = in.Take(idx + 1)
return &Input{index: 0, input: in.input[start+1 : idx]}, nil
} else {
return nil, fmt.Errorf("unmatched parenthesis starting at %s", in.Peek(start).Position())
}
}