cleanup boot
This commit is contained in:
parent
278a4952b9
commit
f0288e26b4
125
boot.go
125
boot.go
@ -32,12 +32,7 @@ func checkBootDefinitionLength(d []string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch d[0] {
|
switch d[0] {
|
||||||
case "chars", "class":
|
case "chars", "class", "sequence", "choice":
|
||||||
if len(d) < 4 {
|
|
||||||
return errInvalidDefinition
|
|
||||||
}
|
|
||||||
|
|
||||||
case "sequence", "choice":
|
|
||||||
if len(d) < 4 {
|
if len(d) < 4 {
|
||||||
return errInvalidDefinition
|
return errInvalidDefinition
|
||||||
}
|
}
|
||||||
@ -46,19 +41,19 @@ func checkBootDefinitionLength(d []string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseClass(c []rune) (not bool, chars []rune, ranges [][]rune, err error) {
|
func parseClass(class []rune) (not bool, chars []rune, ranges [][]rune, err error) {
|
||||||
if c[0] == '^' {
|
if class[0] == '^' {
|
||||||
not = true
|
not = true
|
||||||
c = c[1:]
|
class = class[1:]
|
||||||
}
|
}
|
||||||
|
|
||||||
for {
|
for {
|
||||||
if len(c) == 0 {
|
if len(class) == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var c0 rune
|
var c0 rune
|
||||||
c0, c = c[0], c[1:]
|
c0, class = class[0], class[1:]
|
||||||
switch c0 {
|
switch c0 {
|
||||||
case '[', ']', '^', '-':
|
case '[', ']', '^', '-':
|
||||||
err = errInvalidDefinition
|
err = errInvalidDefinition
|
||||||
@ -66,28 +61,34 @@ func parseClass(c []rune) (not bool, chars []rune, ranges [][]rune, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if c0 == '\\' {
|
if c0 == '\\' {
|
||||||
if len(c) == 0 {
|
if len(class) == 0 {
|
||||||
err = errInvalidDefinition
|
err = errInvalidDefinition
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c0, c = unescapeChar(c[0]), c[1:]
|
c0, class = unescapeChar(class[0]), class[1:]
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(c) < 2 || c[0] != '-' {
|
if len(class) < 2 || class[0] != '-' {
|
||||||
chars = append(chars, c0)
|
chars = append(chars, c0)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
var c1 rune
|
var c1 rune
|
||||||
c1, c = c[1], c[2:]
|
c1, class = class[1], class[2:]
|
||||||
if c1 == '\\' {
|
switch c1 {
|
||||||
if len(c) == 0 {
|
case '[', ']', '^', '-':
|
||||||
err = errInvalidDefinition
|
err = errInvalidDefinition
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c1, c = unescapeChar(c[0]), c[1:]
|
if c1 == '\\' {
|
||||||
|
if len(class) == 0 {
|
||||||
|
err = errInvalidDefinition
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c1, class = unescapeChar(class[0]), class[1:]
|
||||||
}
|
}
|
||||||
|
|
||||||
ranges = append(ranges, []rune{c0, c1})
|
ranges = append(ranges, []rune{c0, c1})
|
||||||
@ -100,6 +101,7 @@ func defineBootAnything(s *Syntax, d []string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func defineBootClass(s *Syntax, d []string) error {
|
func defineBootClass(s *Syntax, d []string) error {
|
||||||
|
name := d[1]
|
||||||
ct := stringToCommitType(d[2])
|
ct := stringToCommitType(d[2])
|
||||||
|
|
||||||
not, chars, ranges, err := parseClass([]rune(d[3]))
|
not, chars, ranges, err := parseClass([]rune(d[3]))
|
||||||
@ -107,75 +109,78 @@ func defineBootClass(s *Syntax, d []string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return s.Class(d[1], ct, not, chars, ranges)
|
return s.Class(name, ct, not, chars, ranges)
|
||||||
}
|
}
|
||||||
|
|
||||||
func defineBootCharSequence(s *Syntax, d []string) error {
|
func defineBootCharSequence(s *Syntax, d []string) error {
|
||||||
|
name := d[1]
|
||||||
ct := stringToCommitType(d[2])
|
ct := stringToCommitType(d[2])
|
||||||
|
|
||||||
chars, err := unescape('\\', []rune{'"', '\\'}, []rune(d[3]))
|
chars, err := unescapeCharSequence(d[3])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return s.CharSequence(d[1], ct, chars)
|
return s.CharSequence(name, ct, chars)
|
||||||
}
|
}
|
||||||
|
|
||||||
func namesToSequenceItemsQuantify(n []string, quantify bool) []SequenceItem {
|
func splitQuantifiedSymbol(s string) (string, int, int) {
|
||||||
|
ssplit := strings.Split(s, ":")
|
||||||
|
if len(ssplit) != 3 {
|
||||||
|
return s, 0, 0
|
||||||
|
}
|
||||||
|
|
||||||
|
name := ssplit[0]
|
||||||
|
|
||||||
|
min, err := strconv.Atoi(ssplit[1])
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
max, err := strconv.Atoi(ssplit[2])
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return name, min, max
|
||||||
|
}
|
||||||
|
|
||||||
|
func namesToSequenceItemsQuantify(n []string) []SequenceItem {
|
||||||
si := make([]SequenceItem, len(n))
|
si := make([]SequenceItem, len(n))
|
||||||
for i, ni := range n {
|
for i, ni := range n {
|
||||||
var min, max int
|
name, min, max := splitQuantifiedSymbol(ni)
|
||||||
if quantify {
|
si[i] = SequenceItem{Name: name, Min: min, Max: max}
|
||||||
nis := strings.Split(ni, ":")
|
|
||||||
if len(nis) == 3 {
|
|
||||||
ni = nis[0]
|
|
||||||
|
|
||||||
var err error
|
|
||||||
|
|
||||||
min, err = strconv.Atoi(nis[1])
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
max, err = strconv.Atoi(nis[2])
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
si[i] = SequenceItem{Name: ni, Min: min, Max: max}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return si
|
return si
|
||||||
}
|
}
|
||||||
|
|
||||||
func namesToSequenceItems(n []string) []SequenceItem {
|
func defineBootSequence(s *Syntax, defs []string) error {
|
||||||
return namesToSequenceItemsQuantify(n, false)
|
name := defs[1]
|
||||||
|
ct := stringToCommitType(defs[2])
|
||||||
|
items := namesToSequenceItemsQuantify(defs[3:])
|
||||||
|
return s.Sequence(name, ct, items...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func defineBootSequence(s *Syntax, d []string) error {
|
func defineBootChoice(s *Syntax, defs []string) error {
|
||||||
ct := stringToCommitType(d[2])
|
name := defs[1]
|
||||||
return s.Sequence(d[1], ct, namesToSequenceItemsQuantify(d[3:], true)...)
|
ct := stringToCommitType(defs[2])
|
||||||
|
items := defs[3:]
|
||||||
|
return s.Choice(name, ct, items...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func defineBootChoice(s *Syntax, d []string) error {
|
func defineBoot(s *Syntax, defs []string) error {
|
||||||
ct := stringToCommitType(d[2])
|
switch defs[0] {
|
||||||
return s.Choice(d[1], ct, d[3:]...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func defineBoot(s *Syntax, d []string) error {
|
|
||||||
switch d[0] {
|
|
||||||
case "anything":
|
case "anything":
|
||||||
return defineBootAnything(s, d)
|
return defineBootAnything(s, defs)
|
||||||
case "class":
|
case "class":
|
||||||
return defineBootClass(s, d)
|
return defineBootClass(s, defs)
|
||||||
case "chars":
|
case "chars":
|
||||||
return defineBootCharSequence(s, d)
|
return defineBootCharSequence(s, defs)
|
||||||
case "sequence":
|
case "sequence":
|
||||||
return defineBootSequence(s, d)
|
return defineBootSequence(s, defs)
|
||||||
case "choice":
|
case "choice":
|
||||||
return defineBootChoice(s, d)
|
return defineBootChoice(s, defs)
|
||||||
default:
|
default:
|
||||||
return errInvalidDefinition
|
return errInvalidDefinition
|
||||||
}
|
}
|
||||||
|
59
define.go
59
define.go
@ -2,65 +2,6 @@ package treerack
|
|||||||
|
|
||||||
import "strconv"
|
import "strconv"
|
||||||
|
|
||||||
func runesContain(rs []rune, r rune) bool {
|
|
||||||
for _, ri := range rs {
|
|
||||||
if ri == r {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func unescapeChar(c rune) rune {
|
|
||||||
switch c {
|
|
||||||
case 'n':
|
|
||||||
return '\n'
|
|
||||||
case 't':
|
|
||||||
return '\t'
|
|
||||||
case 'b':
|
|
||||||
return '\b'
|
|
||||||
case 'f':
|
|
||||||
return '\f'
|
|
||||||
case 'r':
|
|
||||||
return '\r'
|
|
||||||
case 'v':
|
|
||||||
return '\v'
|
|
||||||
default:
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func unescape(escape rune, banned []rune, chars []rune) ([]rune, error) {
|
|
||||||
var (
|
|
||||||
unescaped []rune
|
|
||||||
escaped bool
|
|
||||||
)
|
|
||||||
|
|
||||||
for _, ci := range chars {
|
|
||||||
if escaped {
|
|
||||||
unescaped = append(unescaped, unescapeChar(ci))
|
|
||||||
escaped = false
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
switch {
|
|
||||||
case ci == escape:
|
|
||||||
escaped = true
|
|
||||||
case runesContain(banned, ci):
|
|
||||||
return nil, ErrInvalidEscapeCharacter
|
|
||||||
default:
|
|
||||||
unescaped = append(unescaped, ci)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if escaped {
|
|
||||||
return nil, ErrInvalidEscapeCharacter
|
|
||||||
}
|
|
||||||
|
|
||||||
return unescaped, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func dropComments(n *Node) *Node {
|
func dropComments(n *Node) *Node {
|
||||||
ncc := *n
|
ncc := *n
|
||||||
nc := &ncc
|
nc := &ncc
|
||||||
|
@ -108,6 +108,15 @@ func childName(name string, childIndex int) string {
|
|||||||
return fmt.Sprintf("%s:%d", name, childIndex)
|
return fmt.Sprintf("%s:%d", name, childIndex)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func namesToSequenceItems(n []string) []SequenceItem {
|
||||||
|
si := make([]SequenceItem, len(n))
|
||||||
|
for i := range n {
|
||||||
|
si[i] = SequenceItem{Name: n[i]}
|
||||||
|
}
|
||||||
|
|
||||||
|
return si
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Syntax) Class(name string, ct CommitType, not bool, chars []rune, ranges [][]rune) error {
|
func (s *Syntax) Class(name string, ct CommitType, not bool, chars []rune, ranges [][]rune) error {
|
||||||
cname := childName(name, 0)
|
cname := childName(name, 0)
|
||||||
if err := s.register(newChar(cname, not, chars, ranges)); err != nil {
|
if err := s.register(newChar(cname, not, chars, ranges)); err != nil {
|
||||||
|
Loading…
Reference in New Issue
Block a user