package parse

import (
	
	
	
	
	
	
	

	
)

// parser maintains some mutable states of parsing.
//
// NOTE: The str member is assumed to be valid UF-8.
type parser struct {
	srcName string
	src     string
	pos     int
	overEOF int
	errors  Error
	warn    io.Writer
}

func ( *parser) ( Node) parsed {
	 := .pos
	.n().From = 
	.parse()
	.n().To = .pos
	.n().sourceText = .src[:.pos]
	return parsed{}
}

var nodeType = reflect.TypeOf((*Node)(nil)).Elem()

type parsed struct {
	n Node
}

func ( parsed) ( interface{},  Node) {
	 := reflect.ValueOf().Elem()
	.Set(reflect.ValueOf(.n)) // *ptr = p.n
	addChild(, .n)
}

func ( parsed) ( interface{},  Node) {
	 := reflect.ValueOf().Elem()
	.Set(reflect.Append(, reflect.ValueOf(.n))) // *ptr = append(*ptr, n)
	addChild(, .n)
}

// Tells the parser that parsing is done.
func ( *parser) () {
	if .pos != len(.src) {
		,  := utf8.DecodeRuneInString(.src[.pos:])
		.error(fmt.Errorf("unexpected rune %q", ))
	}
}

// Assembles all parsing errors as one, or returns nil if there were no errors.
func ( *parser) () error {
	if len(.errors.Entries) > 0 {
		return &.errors
	}
	return nil
}

const eof rune = -1

func ( *parser) () rune {
	if .pos == len(.src) {
		return eof
	}
	,  := utf8.DecodeRuneInString(.src[.pos:])
	return 
}

func ( *parser) ( string) bool {
	return strings.HasPrefix(.src[.pos:], )
}

func ( *parser) () rune {
	if .pos == len(.src) {
		.overEOF++
		return eof
	}
	,  := utf8.DecodeRuneInString(.src[.pos:])
	.pos += 
	return 
}

func ( *parser) () {
	if .overEOF > 0 {
		.overEOF--
		return
	}
	,  := utf8.DecodeLastRuneInString(.src[:.pos])
	.pos -= 
}

func ( *parser) ( diag.Ranger,  error) {
	.errors.add(.Error(), diag.NewContext(.srcName, .src, ))
}

func ( *parser) ( error) {
	 := .pos
	if  < len(.src) {
		++
	}
	.errorp(diag.Ranging{From: .pos, To: }, )
}

func ( string,  ...string) error {
	if len() == 0 {
		return errors.New()
	}
	var  bytes.Buffer
	if len() > 0 {
		.WriteString( + ", ")
	}
	.WriteString("should be " + [0])
	for ,  := range [1:] {
		if  == len()-2 {
			.WriteString(" or ")
		} else {
			.WriteString(", ")
		}
		.WriteString()
	}
	return errors.New(.String())
}