gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

parser.go (1754B)


      1 // Copyright 2013-2022 Frank Schroeder. All rights reserved.
      2 // Use of this source code is governed by a BSD-style
      3 // license that can be found in the LICENSE file.
      4 
      5 package properties
      6 
      7 import (
      8 	"fmt"
      9 	"runtime"
     10 )
     11 
     12 type parser struct {
     13 	lex *lexer
     14 }
     15 
     16 func parse(input string) (properties *Properties, err error) {
     17 	p := &parser{lex: lex(input)}
     18 	defer p.recover(&err)
     19 
     20 	properties = NewProperties()
     21 	key := ""
     22 	comments := []string{}
     23 
     24 	for {
     25 		token := p.expectOneOf(itemComment, itemKey, itemEOF)
     26 		switch token.typ {
     27 		case itemEOF:
     28 			goto done
     29 		case itemComment:
     30 			comments = append(comments, token.val)
     31 			continue
     32 		case itemKey:
     33 			key = token.val
     34 			if _, ok := properties.m[key]; !ok {
     35 				properties.k = append(properties.k, key)
     36 			}
     37 		}
     38 
     39 		token = p.expectOneOf(itemValue, itemEOF)
     40 		if len(comments) > 0 {
     41 			properties.c[key] = comments
     42 			comments = []string{}
     43 		}
     44 		switch token.typ {
     45 		case itemEOF:
     46 			properties.m[key] = ""
     47 			goto done
     48 		case itemValue:
     49 			properties.m[key] = token.val
     50 		}
     51 	}
     52 
     53 done:
     54 	return properties, nil
     55 }
     56 
     57 func (p *parser) errorf(format string, args ...interface{}) {
     58 	format = fmt.Sprintf("properties: Line %d: %s", p.lex.lineNumber(), format)
     59 	panic(fmt.Errorf(format, args...))
     60 }
     61 
     62 func (p *parser) expectOneOf(expected ...itemType) (token item) {
     63 	token = p.lex.nextItem()
     64 	for _, v := range expected {
     65 		if token.typ == v {
     66 			return token
     67 		}
     68 	}
     69 	p.unexpected(token)
     70 	panic("unexpected token")
     71 }
     72 
     73 func (p *parser) unexpected(token item) {
     74 	p.errorf(token.String())
     75 }
     76 
     77 // recover is the handler that turns panics into returns from the top level of Parse.
     78 func (p *parser) recover(errp *error) {
     79 	e := recover()
     80 	if e != nil {
     81 		if _, ok := e.(runtime.Error); ok {
     82 			panic(e)
     83 		}
     84 		*errp = e.(error)
     85 	}
     86 }