treerack/boot.go

258 lines
4.4 KiB
Go
Raw Normal View History

2017-07-15 21:49:08 +02:00
package treerack
2017-06-25 17:51:08 +02:00
import (
"errors"
"os"
"strconv"
2017-06-25 23:38:32 +02:00
"strings"
2017-06-25 17:51:08 +02:00
)
var errInvalidDefinition = errors.New("invalid syntax definition")
func stringToCommitType(s string) CommitType {
switch s {
case "alias":
return Alias
2017-12-29 18:20:06 +01:00
case "ws":
return Whitespace
case "nows":
return NoWhitespace
case "failpass":
return FailPass
2017-06-25 17:51:08 +02:00
case "root":
return Root
default:
return None
}
}
2017-10-29 16:46:17 +01:00
func parseClass(class []rune) (not bool, chars []rune, ranges [][]rune, err error) {
if class[0] == '^' {
2017-06-25 17:51:08 +02:00
not = true
2017-10-29 16:46:17 +01:00
class = class[1:]
2017-06-25 17:51:08 +02:00
}
for {
2017-10-29 16:46:17 +01:00
if len(class) == 0 {
2017-06-25 17:51:08 +02:00
return
}
var c0 rune
2017-10-29 16:46:17 +01:00
c0, class = class[0], class[1:]
2017-06-25 17:51:08 +02:00
2017-11-05 03:28:36 +01:00
/*
this doesn't happen:
switch c0 {
case '[', ']', '^', '-':
2017-06-25 17:51:08 +02:00
err = errInvalidDefinition
return
}
2017-11-05 03:28:36 +01:00
*/
if c0 == '\\' {
/*
this doesn't happen:
if len(class) == 0 {
err = errInvalidDefinition
return
}
*/
2017-06-25 17:51:08 +02:00
2017-10-29 16:46:17 +01:00
c0, class = unescapeChar(class[0]), class[1:]
2017-06-25 17:51:08 +02:00
}
2017-10-29 16:46:17 +01:00
if len(class) < 2 || class[0] != '-' {
2017-06-25 17:51:08 +02:00
chars = append(chars, c0)
continue
}
var c1 rune
2017-10-29 16:46:17 +01:00
c1, class = class[1], class[2:]
2017-11-05 03:28:36 +01:00
/*
this doesn't happen:
switch c1 {
case '[', ']', '^', '-':
2017-06-25 17:51:08 +02:00
err = errInvalidDefinition
return
}
2017-11-05 03:28:36 +01:00
if c1 == '\\' {
if len(class) == 0 {
err = errInvalidDefinition
return
}
c1, class = unescapeChar(class[0]), class[1:]
}
*/
2017-06-25 17:51:08 +02:00
ranges = append(ranges, []rune{c0, c1})
}
}
func defineBootAnything(s *Syntax, d []string) error {
ct := stringToCommitType(d[2])
2017-10-31 21:53:09 +01:00
return s.anyChar(d[1], ct)
2017-06-25 17:51:08 +02:00
}
func defineBootClass(s *Syntax, d []string) error {
2017-10-29 16:46:17 +01:00
name := d[1]
2017-06-25 17:51:08 +02:00
ct := stringToCommitType(d[2])
2017-11-05 03:28:36 +01:00
/*
never fails:
not, chars, ranges, err := parseClass([]rune(d[3]))
if err != nil {
return err
}
*/
not, chars, ranges, _ := parseClass([]rune(d[3]))
2017-06-25 17:51:08 +02:00
2017-10-31 21:53:09 +01:00
return s.class(name, ct, not, chars, ranges)
2017-06-25 17:51:08 +02:00
}
func defineBootCharSequence(s *Syntax, d []string) error {
2017-10-29 16:46:17 +01:00
name := d[1]
2017-06-25 17:51:08 +02:00
ct := stringToCommitType(d[2])
2017-11-05 03:28:36 +01:00
/*
never fails:
chars, err := unescapeCharSequence(d[3])
if err != nil {
return err
}
*/
chars, _ := unescapeCharSequence(d[3])
2017-06-25 17:51:08 +02:00
2017-10-31 21:53:09 +01:00
return s.charSequence(name, ct, chars)
2017-06-25 17:51:08 +02:00
}
2017-10-29 16:46:17 +01:00
func splitQuantifiedSymbol(s string) (string, int, int) {
ssplit := strings.Split(s, ":")
if len(ssplit) != 3 {
return s, 0, 0
}
2017-06-25 17:51:08 +02:00
2017-10-29 16:46:17 +01:00
name := ssplit[0]
2017-11-05 03:28:36 +01:00
/*
never fails:
min, err := strconv.Atoi(ssplit[1])
if err != nil {
panic(err)
}
2017-06-25 17:51:08 +02:00
2017-11-05 03:28:36 +01:00
max, err := strconv.Atoi(ssplit[2])
if err != nil {
panic(err)
}
*/
min, _ := strconv.Atoi(ssplit[1])
max, _ := strconv.Atoi(ssplit[2])
2017-10-29 16:46:17 +01:00
return name, min, max
2017-06-25 23:38:32 +02:00
}
2017-06-25 17:51:08 +02:00
2017-10-29 16:46:17 +01:00
func namesToSequenceItemsQuantify(n []string) []SequenceItem {
si := make([]SequenceItem, len(n))
for i, ni := range n {
name, min, max := splitQuantifiedSymbol(ni)
si[i] = SequenceItem{Name: name, Min: min, Max: max}
}
return si
2017-06-25 17:51:08 +02:00
}
2017-10-29 16:46:17 +01:00
func defineBootSequence(s *Syntax, defs []string) error {
name := defs[1]
ct := stringToCommitType(defs[2])
items := namesToSequenceItemsQuantify(defs[3:])
2017-10-31 21:53:09 +01:00
return s.sequence(name, ct, items...)
2017-06-25 17:51:08 +02:00
}
2017-10-29 16:46:17 +01:00
func defineBootChoice(s *Syntax, defs []string) error {
name := defs[1]
ct := stringToCommitType(defs[2])
items := defs[3:]
2017-10-31 21:53:09 +01:00
return s.choice(name, ct, items...)
2017-06-25 17:51:08 +02:00
}
2017-10-29 16:46:17 +01:00
func defineBoot(s *Syntax, defs []string) error {
switch defs[0] {
2017-06-25 17:51:08 +02:00
case "anything":
2017-10-29 16:46:17 +01:00
return defineBootAnything(s, defs)
2017-06-25 17:51:08 +02:00
case "class":
2017-10-29 16:46:17 +01:00
return defineBootClass(s, defs)
2017-06-25 17:51:08 +02:00
case "chars":
2017-10-29 16:46:17 +01:00
return defineBootCharSequence(s, defs)
2017-06-25 17:51:08 +02:00
case "sequence":
2017-10-29 16:46:17 +01:00
return defineBootSequence(s, defs)
2017-11-05 03:28:36 +01:00
/*
never fails:
case "choice":
return defineBootChoice(s, defs)
default:
return errInvalidDefinition
*/
2017-06-25 17:51:08 +02:00
default:
2017-11-05 03:28:36 +01:00
return defineBootChoice(s, defs)
2017-06-25 17:51:08 +02:00
}
}
func defineAllBoot(s *Syntax, defs [][]string) error {
for _, d := range defs {
2017-11-05 03:28:36 +01:00
/*
never fails:
if err := defineBoot(s, d); err != nil {
return err
}
*/
defineBoot(s, d)
2017-06-25 17:51:08 +02:00
}
return nil
}
2017-10-27 17:25:20 +02:00
func createBoot() (*Syntax, error) {
2017-10-31 21:53:09 +01:00
s := &Syntax{}
2017-11-05 03:28:36 +01:00
/*
never fails:
if err := defineAllBoot(s, bootSyntaxDefs); err != nil {
return nil, err
}
*/
defineAllBoot(s, bootSyntaxDefs)
2017-06-25 17:51:08 +02:00
return s, s.Init()
}
2017-06-26 00:20:54 +02:00
func bootSyntax() (*Syntax, error) {
2017-11-05 03:28:36 +01:00
/*
never fails:
b, err := createBoot()
if err != nil {
return nil, err
}
2017-06-25 17:51:08 +02:00
2017-11-05 03:28:36 +01:00
f, err := os.Open("syntax.treerack")
if err != nil {
return nil, err
}
2017-06-25 17:51:08 +02:00
2017-11-05 03:28:36 +01:00
defer f.Close()
2017-06-25 17:51:08 +02:00
2017-11-05 03:28:36 +01:00
doc, err := b.Parse(f)
if err != nil {
return nil, err
}
*/
b, _ := createBoot()
f, _ := os.Open("syntax.treerack")
defer f.Close()
doc, _ := b.Parse(f)
2017-06-25 17:51:08 +02:00
2017-10-31 21:53:09 +01:00
s := &Syntax{}
2017-06-25 17:51:08 +02:00
return s, define(s, doc)
}