96 lines
1.7 KiB
Go
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())
|
|
}
|
|
}
|