blob: 2dfd2e41863a1f761283689fa65f59500e982c5d [file] [log] [blame]
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package symbolize
import (
"fmt"
"reflect"
"strconv"
"strings"
)
type ParserState string
type Parser func(*ParserState) interface{}
func (b *ParserState) peek(what string) bool {
if len(*b) < len(what) {
return false
}
return (*b)[:len(what)] == ParserState(what)
}
func (b *ParserState) expect(what string) bool {
if b.peek(what) {
*b = (*b)[len(what):]
return true
}
return false
}
func (b *ParserState) before(what string) (string, error) {
idx := strings.Index(string(*b), what)
if idx == -1 {
return "", fmt.Errorf("expected '%s'", what)
}
str := (*b)[:idx]
*b = (*b)[idx+len(what):]
return string(str), nil
}
func (b *ParserState) decBefore(what string) (uint64, error) {
out, err := b.before(what)
if err != nil {
return 0, err
}
return strconv.ParseUint(out, 10, 64)
}
func (b *ParserState) intBefore(what string) (uint64, error) {
out, err := b.before(what)
if err != nil {
return 0, err
}
return strconv.ParseUint(out, 0, 64)
}
func (b *ParserState) floatBefore(what string) (float64, error) {
out, err := b.before(what)
if err != nil {
return 0.0, err
}
return strconv.ParseFloat(out, 64)
}
func (b *ParserState) try(p Parser) interface{} {
save := *b
out := p(b)
if out == nil {
*b = save
}
return out
}
func (b *ParserState) prefix(prefix string, p Parser) interface{} {
return b.try(func(b *ParserState) interface{} {
if b.expect(prefix) {
return p(b)
}
return nil
})
}
func (b *ParserState) choice(toTry ...Parser) interface{} {
for _, parser := range toTry {
if node := parser(b); node != nil {
return node
}
}
return nil
}
func (b *ParserState) many(out interface{}, p Parser) {
iout := reflect.ValueOf(out).Elem()
for n := p(b); n != nil; n = p(b) {
iout.Set(reflect.Append(iout, reflect.ValueOf(n)))
}
}
func (b *ParserState) whitespace() {
*b = ParserState(strings.TrimLeft(string(*b), " \t\n\r\v\f"))
}