use hlib
This commit is contained in:
parent
43e83607c0
commit
03d9ddbf63
|
@ -12,7 +12,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/eaburns/peggy/peg"
|
"github.com/eaburns/peggy/peg"
|
||||||
"within.website/x/h"
|
"tulpa.dev/hlang/h"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
{
|
||||||
|
package h
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/eaburns/peggy/peg"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
sep <- space+h
|
||||||
|
space <- ' '
|
||||||
|
h <- 'h' / "'"
|
||||||
|
H <- h+sep+ / h
|
|
@ -0,0 +1,789 @@
|
||||||
|
package h
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/eaburns/peggy/peg"
|
||||||
|
)
|
||||||
|
|
||||||
|
type _Parser struct {
|
||||||
|
text string
|
||||||
|
deltaPos []_Rules
|
||||||
|
deltaErr []_Rules
|
||||||
|
node map[_key]*peg.Node
|
||||||
|
fail map[_key]*peg.Fail
|
||||||
|
lastFail int
|
||||||
|
data interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
type _key struct {
|
||||||
|
start int
|
||||||
|
name string
|
||||||
|
}
|
||||||
|
|
||||||
|
func _NewParser(text string) *_Parser {
|
||||||
|
return &_Parser{
|
||||||
|
text: text,
|
||||||
|
deltaPos: make([]_Rules, len(text)+1),
|
||||||
|
deltaErr: make([]_Rules, len(text)+1),
|
||||||
|
node: make(map[_key]*peg.Node),
|
||||||
|
fail: make(map[_key]*peg.Fail),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type _Rules struct {
|
||||||
|
sep int32
|
||||||
|
space int32
|
||||||
|
h int32
|
||||||
|
H int32
|
||||||
|
}
|
||||||
|
|
||||||
|
func _max(a, b int) int {
|
||||||
|
if a > b {
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
func _next(parser *_Parser, pos int) (rune, int) {
|
||||||
|
r, w := peg.DecodeRuneInString(parser.text[pos:])
|
||||||
|
return r, w
|
||||||
|
}
|
||||||
|
|
||||||
|
func _node(name string) *peg.Node {
|
||||||
|
return &peg.Node{Name: name}
|
||||||
|
}
|
||||||
|
|
||||||
|
func _sub(parser *_Parser, start, end int, kids []*peg.Node) *peg.Node {
|
||||||
|
node := &peg.Node{
|
||||||
|
Text: parser.text[start:end],
|
||||||
|
Kids: make([]*peg.Node, len(kids)),
|
||||||
|
}
|
||||||
|
copy(node.Kids, kids)
|
||||||
|
return node
|
||||||
|
}
|
||||||
|
|
||||||
|
func _leaf(parser *_Parser, start, end int) *peg.Node {
|
||||||
|
return &peg.Node{Text: parser.text[start:end]}
|
||||||
|
}
|
||||||
|
|
||||||
|
func _sepAccepts(parser *_Parser, start int) (deltaPos, deltaErr int) {
|
||||||
|
if dp := parser.deltaPos[start].sep; dp != 0 {
|
||||||
|
de := parser.deltaErr[start].sep - 1
|
||||||
|
if dp > 0 {
|
||||||
|
dp--
|
||||||
|
}
|
||||||
|
return int(dp), int(de)
|
||||||
|
}
|
||||||
|
pos, perr := start, -1
|
||||||
|
// space+ h
|
||||||
|
// space+
|
||||||
|
// space
|
||||||
|
if dp, de := _spaceAccepts(parser, pos); dp < 0 {
|
||||||
|
perr = _max(perr, pos+de)
|
||||||
|
goto fail
|
||||||
|
} else {
|
||||||
|
perr = _max(perr, pos+de)
|
||||||
|
pos += dp
|
||||||
|
}
|
||||||
|
for {
|
||||||
|
pos1 := pos
|
||||||
|
// space
|
||||||
|
if dp, de := _spaceAccepts(parser, pos); dp < 0 {
|
||||||
|
perr = _max(perr, pos+de)
|
||||||
|
goto fail2
|
||||||
|
} else {
|
||||||
|
perr = _max(perr, pos+de)
|
||||||
|
pos += dp
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
fail2:
|
||||||
|
pos = pos1
|
||||||
|
break
|
||||||
|
}
|
||||||
|
// h
|
||||||
|
if dp, de := _hAccepts(parser, pos); dp < 0 {
|
||||||
|
perr = _max(perr, pos+de)
|
||||||
|
goto fail
|
||||||
|
} else {
|
||||||
|
perr = _max(perr, pos+de)
|
||||||
|
pos += dp
|
||||||
|
}
|
||||||
|
parser.deltaPos[start].sep = int32(pos-start) + 1
|
||||||
|
parser.deltaErr[start].sep = int32(perr-start) + 1
|
||||||
|
parser.lastFail = perr
|
||||||
|
return pos - start, perr - start
|
||||||
|
fail:
|
||||||
|
parser.deltaPos[start].sep = -1
|
||||||
|
parser.deltaErr[start].sep = int32(perr-start) + 1
|
||||||
|
parser.lastFail = perr
|
||||||
|
return -1, perr - start
|
||||||
|
}
|
||||||
|
|
||||||
|
func _sepNode(parser *_Parser, start int) (int, *peg.Node) {
|
||||||
|
dp := parser.deltaPos[start].sep
|
||||||
|
if dp < 0 {
|
||||||
|
return -1, nil
|
||||||
|
}
|
||||||
|
key := _key{start: start, name: "sep"}
|
||||||
|
node := parser.node[key]
|
||||||
|
if node != nil {
|
||||||
|
return start + int(dp-1), node
|
||||||
|
}
|
||||||
|
pos := start
|
||||||
|
node = _node("sep")
|
||||||
|
// space+ h
|
||||||
|
// space+
|
||||||
|
// space
|
||||||
|
if p, kid := _spaceNode(parser, pos); kid == nil {
|
||||||
|
goto fail
|
||||||
|
} else {
|
||||||
|
node.Kids = append(node.Kids, kid)
|
||||||
|
pos = p
|
||||||
|
}
|
||||||
|
for {
|
||||||
|
nkids0 := len(node.Kids)
|
||||||
|
pos1 := pos
|
||||||
|
// space
|
||||||
|
if p, kid := _spaceNode(parser, pos); kid == nil {
|
||||||
|
goto fail2
|
||||||
|
} else {
|
||||||
|
node.Kids = append(node.Kids, kid)
|
||||||
|
pos = p
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
fail2:
|
||||||
|
node.Kids = node.Kids[:nkids0]
|
||||||
|
pos = pos1
|
||||||
|
break
|
||||||
|
}
|
||||||
|
// h
|
||||||
|
if p, kid := _hNode(parser, pos); kid == nil {
|
||||||
|
goto fail
|
||||||
|
} else {
|
||||||
|
node.Kids = append(node.Kids, kid)
|
||||||
|
pos = p
|
||||||
|
}
|
||||||
|
node.Text = parser.text[start:pos]
|
||||||
|
parser.node[key] = node
|
||||||
|
return pos, node
|
||||||
|
fail:
|
||||||
|
return -1, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func _sepFail(parser *_Parser, start, errPos int) (int, *peg.Fail) {
|
||||||
|
if start > parser.lastFail {
|
||||||
|
return -1, &peg.Fail{}
|
||||||
|
}
|
||||||
|
dp := parser.deltaPos[start].sep
|
||||||
|
de := parser.deltaErr[start].sep
|
||||||
|
if start+int(de-1) < errPos {
|
||||||
|
if dp > 0 {
|
||||||
|
return start + int(dp-1), &peg.Fail{}
|
||||||
|
}
|
||||||
|
return -1, &peg.Fail{}
|
||||||
|
}
|
||||||
|
key := _key{start: start, name: "sep"}
|
||||||
|
failure := parser.fail[key]
|
||||||
|
if dp < 0 && failure != nil {
|
||||||
|
return -1, failure
|
||||||
|
}
|
||||||
|
if dp > 0 && failure != nil {
|
||||||
|
return start + int(dp-1), failure
|
||||||
|
}
|
||||||
|
pos := start
|
||||||
|
failure = &peg.Fail{
|
||||||
|
Name: "sep",
|
||||||
|
Pos: int(start),
|
||||||
|
}
|
||||||
|
// space+ h
|
||||||
|
// space+
|
||||||
|
// space
|
||||||
|
{
|
||||||
|
p, kid := _spaceFail(parser, pos, errPos)
|
||||||
|
if kid.Want != "" || len(kid.Kids) > 0 {
|
||||||
|
failure.Kids = append(failure.Kids, kid)
|
||||||
|
}
|
||||||
|
if p < 0 {
|
||||||
|
goto fail
|
||||||
|
}
|
||||||
|
pos = p
|
||||||
|
}
|
||||||
|
for {
|
||||||
|
pos1 := pos
|
||||||
|
// space
|
||||||
|
{
|
||||||
|
p, kid := _spaceFail(parser, pos, errPos)
|
||||||
|
if kid.Want != "" || len(kid.Kids) > 0 {
|
||||||
|
failure.Kids = append(failure.Kids, kid)
|
||||||
|
}
|
||||||
|
if p < 0 {
|
||||||
|
goto fail2
|
||||||
|
}
|
||||||
|
pos = p
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
fail2:
|
||||||
|
pos = pos1
|
||||||
|
break
|
||||||
|
}
|
||||||
|
// h
|
||||||
|
{
|
||||||
|
p, kid := _hFail(parser, pos, errPos)
|
||||||
|
if kid.Want != "" || len(kid.Kids) > 0 {
|
||||||
|
failure.Kids = append(failure.Kids, kid)
|
||||||
|
}
|
||||||
|
if p < 0 {
|
||||||
|
goto fail
|
||||||
|
}
|
||||||
|
pos = p
|
||||||
|
}
|
||||||
|
parser.fail[key] = failure
|
||||||
|
return pos, failure
|
||||||
|
fail:
|
||||||
|
parser.fail[key] = failure
|
||||||
|
return -1, failure
|
||||||
|
}
|
||||||
|
|
||||||
|
func _spaceAccepts(parser *_Parser, start int) (deltaPos, deltaErr int) {
|
||||||
|
if dp := parser.deltaPos[start].space; dp != 0 {
|
||||||
|
de := parser.deltaErr[start].space - 1
|
||||||
|
if dp > 0 {
|
||||||
|
dp--
|
||||||
|
}
|
||||||
|
return int(dp), int(de)
|
||||||
|
}
|
||||||
|
pos, perr := start, -1
|
||||||
|
// " "
|
||||||
|
if len(parser.text[pos:]) < 1 || parser.text[pos:pos+1] != " " {
|
||||||
|
perr = _max(perr, pos)
|
||||||
|
goto fail
|
||||||
|
}
|
||||||
|
pos++
|
||||||
|
parser.deltaPos[start].space = int32(pos-start) + 1
|
||||||
|
parser.deltaErr[start].space = int32(perr-start) + 1
|
||||||
|
parser.lastFail = perr
|
||||||
|
return pos - start, perr - start
|
||||||
|
fail:
|
||||||
|
parser.deltaPos[start].space = -1
|
||||||
|
parser.deltaErr[start].space = int32(perr-start) + 1
|
||||||
|
parser.lastFail = perr
|
||||||
|
return -1, perr - start
|
||||||
|
}
|
||||||
|
|
||||||
|
func _spaceNode(parser *_Parser, start int) (int, *peg.Node) {
|
||||||
|
dp := parser.deltaPos[start].space
|
||||||
|
if dp < 0 {
|
||||||
|
return -1, nil
|
||||||
|
}
|
||||||
|
key := _key{start: start, name: "space"}
|
||||||
|
node := parser.node[key]
|
||||||
|
if node != nil {
|
||||||
|
return start + int(dp-1), node
|
||||||
|
}
|
||||||
|
pos := start
|
||||||
|
node = _node("space")
|
||||||
|
// " "
|
||||||
|
if len(parser.text[pos:]) < 1 || parser.text[pos:pos+1] != " " {
|
||||||
|
goto fail
|
||||||
|
}
|
||||||
|
node.Kids = append(node.Kids, _leaf(parser, pos, pos+1))
|
||||||
|
pos++
|
||||||
|
node.Text = parser.text[start:pos]
|
||||||
|
parser.node[key] = node
|
||||||
|
return pos, node
|
||||||
|
fail:
|
||||||
|
return -1, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func _spaceFail(parser *_Parser, start, errPos int) (int, *peg.Fail) {
|
||||||
|
if start > parser.lastFail {
|
||||||
|
return -1, &peg.Fail{}
|
||||||
|
}
|
||||||
|
dp := parser.deltaPos[start].space
|
||||||
|
de := parser.deltaErr[start].space
|
||||||
|
if start+int(de-1) < errPos {
|
||||||
|
if dp > 0 {
|
||||||
|
return start + int(dp-1), &peg.Fail{}
|
||||||
|
}
|
||||||
|
return -1, &peg.Fail{}
|
||||||
|
}
|
||||||
|
key := _key{start: start, name: "space"}
|
||||||
|
failure := parser.fail[key]
|
||||||
|
if dp < 0 && failure != nil {
|
||||||
|
return -1, failure
|
||||||
|
}
|
||||||
|
if dp > 0 && failure != nil {
|
||||||
|
return start + int(dp-1), failure
|
||||||
|
}
|
||||||
|
pos := start
|
||||||
|
failure = &peg.Fail{
|
||||||
|
Name: "space",
|
||||||
|
Pos: int(start),
|
||||||
|
}
|
||||||
|
// " "
|
||||||
|
if len(parser.text[pos:]) < 1 || parser.text[pos:pos+1] != " " {
|
||||||
|
if pos >= errPos {
|
||||||
|
failure.Kids = append(failure.Kids, &peg.Fail{
|
||||||
|
Pos: int(pos),
|
||||||
|
Want: "\" \"",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
goto fail
|
||||||
|
}
|
||||||
|
pos++
|
||||||
|
parser.fail[key] = failure
|
||||||
|
return pos, failure
|
||||||
|
fail:
|
||||||
|
parser.fail[key] = failure
|
||||||
|
return -1, failure
|
||||||
|
}
|
||||||
|
|
||||||
|
func _hAccepts(parser *_Parser, start int) (deltaPos, deltaErr int) {
|
||||||
|
if dp := parser.deltaPos[start].h; dp != 0 {
|
||||||
|
de := parser.deltaErr[start].h - 1
|
||||||
|
if dp > 0 {
|
||||||
|
dp--
|
||||||
|
}
|
||||||
|
return int(dp), int(de)
|
||||||
|
}
|
||||||
|
pos, perr := start, -1
|
||||||
|
// "h"/"'"
|
||||||
|
{
|
||||||
|
pos2 := pos
|
||||||
|
// "h"
|
||||||
|
if len(parser.text[pos:]) < 1 || parser.text[pos:pos+1] != "h" {
|
||||||
|
perr = _max(perr, pos)
|
||||||
|
goto fail3
|
||||||
|
}
|
||||||
|
pos++
|
||||||
|
goto ok0
|
||||||
|
fail3:
|
||||||
|
pos = pos2
|
||||||
|
// "'"
|
||||||
|
if len(parser.text[pos:]) < 1 || parser.text[pos:pos+1] != "'" {
|
||||||
|
perr = _max(perr, pos)
|
||||||
|
goto fail4
|
||||||
|
}
|
||||||
|
pos++
|
||||||
|
goto ok0
|
||||||
|
fail4:
|
||||||
|
pos = pos2
|
||||||
|
goto fail
|
||||||
|
ok0:
|
||||||
|
}
|
||||||
|
parser.deltaPos[start].h = int32(pos-start) + 1
|
||||||
|
parser.deltaErr[start].h = int32(perr-start) + 1
|
||||||
|
parser.lastFail = perr
|
||||||
|
return pos - start, perr - start
|
||||||
|
fail:
|
||||||
|
parser.deltaPos[start].h = -1
|
||||||
|
parser.deltaErr[start].h = int32(perr-start) + 1
|
||||||
|
parser.lastFail = perr
|
||||||
|
return -1, perr - start
|
||||||
|
}
|
||||||
|
|
||||||
|
func _hNode(parser *_Parser, start int) (int, *peg.Node) {
|
||||||
|
dp := parser.deltaPos[start].h
|
||||||
|
if dp < 0 {
|
||||||
|
return -1, nil
|
||||||
|
}
|
||||||
|
key := _key{start: start, name: "h"}
|
||||||
|
node := parser.node[key]
|
||||||
|
if node != nil {
|
||||||
|
return start + int(dp-1), node
|
||||||
|
}
|
||||||
|
pos := start
|
||||||
|
node = _node("h")
|
||||||
|
// "h"/"'"
|
||||||
|
{
|
||||||
|
pos2 := pos
|
||||||
|
nkids1 := len(node.Kids)
|
||||||
|
// "h"
|
||||||
|
if len(parser.text[pos:]) < 1 || parser.text[pos:pos+1] != "h" {
|
||||||
|
goto fail3
|
||||||
|
}
|
||||||
|
node.Kids = append(node.Kids, _leaf(parser, pos, pos+1))
|
||||||
|
pos++
|
||||||
|
goto ok0
|
||||||
|
fail3:
|
||||||
|
node.Kids = node.Kids[:nkids1]
|
||||||
|
pos = pos2
|
||||||
|
// "'"
|
||||||
|
if len(parser.text[pos:]) < 1 || parser.text[pos:pos+1] != "'" {
|
||||||
|
goto fail4
|
||||||
|
}
|
||||||
|
node.Kids = append(node.Kids, _leaf(parser, pos, pos+1))
|
||||||
|
pos++
|
||||||
|
goto ok0
|
||||||
|
fail4:
|
||||||
|
node.Kids = node.Kids[:nkids1]
|
||||||
|
pos = pos2
|
||||||
|
goto fail
|
||||||
|
ok0:
|
||||||
|
}
|
||||||
|
node.Text = parser.text[start:pos]
|
||||||
|
parser.node[key] = node
|
||||||
|
return pos, node
|
||||||
|
fail:
|
||||||
|
return -1, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func _hFail(parser *_Parser, start, errPos int) (int, *peg.Fail) {
|
||||||
|
if start > parser.lastFail {
|
||||||
|
return -1, &peg.Fail{}
|
||||||
|
}
|
||||||
|
dp := parser.deltaPos[start].h
|
||||||
|
de := parser.deltaErr[start].h
|
||||||
|
if start+int(de-1) < errPos {
|
||||||
|
if dp > 0 {
|
||||||
|
return start + int(dp-1), &peg.Fail{}
|
||||||
|
}
|
||||||
|
return -1, &peg.Fail{}
|
||||||
|
}
|
||||||
|
key := _key{start: start, name: "h"}
|
||||||
|
failure := parser.fail[key]
|
||||||
|
if dp < 0 && failure != nil {
|
||||||
|
return -1, failure
|
||||||
|
}
|
||||||
|
if dp > 0 && failure != nil {
|
||||||
|
return start + int(dp-1), failure
|
||||||
|
}
|
||||||
|
pos := start
|
||||||
|
failure = &peg.Fail{
|
||||||
|
Name: "h",
|
||||||
|
Pos: int(start),
|
||||||
|
}
|
||||||
|
// "h"/"'"
|
||||||
|
{
|
||||||
|
pos2 := pos
|
||||||
|
// "h"
|
||||||
|
if len(parser.text[pos:]) < 1 || parser.text[pos:pos+1] != "h" {
|
||||||
|
if pos >= errPos {
|
||||||
|
failure.Kids = append(failure.Kids, &peg.Fail{
|
||||||
|
Pos: int(pos),
|
||||||
|
Want: "\"h\"",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
goto fail3
|
||||||
|
}
|
||||||
|
pos++
|
||||||
|
goto ok0
|
||||||
|
fail3:
|
||||||
|
pos = pos2
|
||||||
|
// "'"
|
||||||
|
if len(parser.text[pos:]) < 1 || parser.text[pos:pos+1] != "'" {
|
||||||
|
if pos >= errPos {
|
||||||
|
failure.Kids = append(failure.Kids, &peg.Fail{
|
||||||
|
Pos: int(pos),
|
||||||
|
Want: "\"'\"",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
goto fail4
|
||||||
|
}
|
||||||
|
pos++
|
||||||
|
goto ok0
|
||||||
|
fail4:
|
||||||
|
pos = pos2
|
||||||
|
goto fail
|
||||||
|
ok0:
|
||||||
|
}
|
||||||
|
parser.fail[key] = failure
|
||||||
|
return pos, failure
|
||||||
|
fail:
|
||||||
|
parser.fail[key] = failure
|
||||||
|
return -1, failure
|
||||||
|
}
|
||||||
|
|
||||||
|
func _HAccepts(parser *_Parser, start int) (deltaPos, deltaErr int) {
|
||||||
|
if dp := parser.deltaPos[start].H; dp != 0 {
|
||||||
|
de := parser.deltaErr[start].H - 1
|
||||||
|
if dp > 0 {
|
||||||
|
dp--
|
||||||
|
}
|
||||||
|
return int(dp), int(de)
|
||||||
|
}
|
||||||
|
pos, perr := start, -1
|
||||||
|
// h+ sep+/h
|
||||||
|
{
|
||||||
|
pos2 := pos
|
||||||
|
// h+ sep+
|
||||||
|
// h+
|
||||||
|
// h
|
||||||
|
if dp, de := _hAccepts(parser, pos); dp < 0 {
|
||||||
|
perr = _max(perr, pos+de)
|
||||||
|
goto fail3
|
||||||
|
} else {
|
||||||
|
perr = _max(perr, pos+de)
|
||||||
|
pos += dp
|
||||||
|
}
|
||||||
|
for {
|
||||||
|
pos5 := pos
|
||||||
|
// h
|
||||||
|
if dp, de := _hAccepts(parser, pos); dp < 0 {
|
||||||
|
perr = _max(perr, pos+de)
|
||||||
|
goto fail6
|
||||||
|
} else {
|
||||||
|
perr = _max(perr, pos+de)
|
||||||
|
pos += dp
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
fail6:
|
||||||
|
pos = pos5
|
||||||
|
break
|
||||||
|
}
|
||||||
|
// sep+
|
||||||
|
// sep
|
||||||
|
if dp, de := _sepAccepts(parser, pos); dp < 0 {
|
||||||
|
perr = _max(perr, pos+de)
|
||||||
|
goto fail3
|
||||||
|
} else {
|
||||||
|
perr = _max(perr, pos+de)
|
||||||
|
pos += dp
|
||||||
|
}
|
||||||
|
for {
|
||||||
|
pos8 := pos
|
||||||
|
// sep
|
||||||
|
if dp, de := _sepAccepts(parser, pos); dp < 0 {
|
||||||
|
perr = _max(perr, pos+de)
|
||||||
|
goto fail9
|
||||||
|
} else {
|
||||||
|
perr = _max(perr, pos+de)
|
||||||
|
pos += dp
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
fail9:
|
||||||
|
pos = pos8
|
||||||
|
break
|
||||||
|
}
|
||||||
|
goto ok0
|
||||||
|
fail3:
|
||||||
|
pos = pos2
|
||||||
|
// h
|
||||||
|
if dp, de := _hAccepts(parser, pos); dp < 0 {
|
||||||
|
perr = _max(perr, pos+de)
|
||||||
|
goto fail10
|
||||||
|
} else {
|
||||||
|
perr = _max(perr, pos+de)
|
||||||
|
pos += dp
|
||||||
|
}
|
||||||
|
goto ok0
|
||||||
|
fail10:
|
||||||
|
pos = pos2
|
||||||
|
goto fail
|
||||||
|
ok0:
|
||||||
|
}
|
||||||
|
parser.deltaPos[start].H = int32(pos-start) + 1
|
||||||
|
parser.deltaErr[start].H = int32(perr-start) + 1
|
||||||
|
parser.lastFail = perr
|
||||||
|
return pos - start, perr - start
|
||||||
|
fail:
|
||||||
|
parser.deltaPos[start].H = -1
|
||||||
|
parser.deltaErr[start].H = int32(perr-start) + 1
|
||||||
|
parser.lastFail = perr
|
||||||
|
return -1, perr - start
|
||||||
|
}
|
||||||
|
|
||||||
|
func _HNode(parser *_Parser, start int) (int, *peg.Node) {
|
||||||
|
dp := parser.deltaPos[start].H
|
||||||
|
if dp < 0 {
|
||||||
|
return -1, nil
|
||||||
|
}
|
||||||
|
key := _key{start: start, name: "H"}
|
||||||
|
node := parser.node[key]
|
||||||
|
if node != nil {
|
||||||
|
return start + int(dp-1), node
|
||||||
|
}
|
||||||
|
pos := start
|
||||||
|
node = _node("H")
|
||||||
|
// h+ sep+/h
|
||||||
|
{
|
||||||
|
pos2 := pos
|
||||||
|
nkids1 := len(node.Kids)
|
||||||
|
// h+ sep+
|
||||||
|
// h+
|
||||||
|
// h
|
||||||
|
if p, kid := _hNode(parser, pos); kid == nil {
|
||||||
|
goto fail3
|
||||||
|
} else {
|
||||||
|
node.Kids = append(node.Kids, kid)
|
||||||
|
pos = p
|
||||||
|
}
|
||||||
|
for {
|
||||||
|
nkids4 := len(node.Kids)
|
||||||
|
pos5 := pos
|
||||||
|
// h
|
||||||
|
if p, kid := _hNode(parser, pos); kid == nil {
|
||||||
|
goto fail6
|
||||||
|
} else {
|
||||||
|
node.Kids = append(node.Kids, kid)
|
||||||
|
pos = p
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
fail6:
|
||||||
|
node.Kids = node.Kids[:nkids4]
|
||||||
|
pos = pos5
|
||||||
|
break
|
||||||
|
}
|
||||||
|
// sep+
|
||||||
|
// sep
|
||||||
|
if p, kid := _sepNode(parser, pos); kid == nil {
|
||||||
|
goto fail3
|
||||||
|
} else {
|
||||||
|
node.Kids = append(node.Kids, kid)
|
||||||
|
pos = p
|
||||||
|
}
|
||||||
|
for {
|
||||||
|
nkids7 := len(node.Kids)
|
||||||
|
pos8 := pos
|
||||||
|
// sep
|
||||||
|
if p, kid := _sepNode(parser, pos); kid == nil {
|
||||||
|
goto fail9
|
||||||
|
} else {
|
||||||
|
node.Kids = append(node.Kids, kid)
|
||||||
|
pos = p
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
fail9:
|
||||||
|
node.Kids = node.Kids[:nkids7]
|
||||||
|
pos = pos8
|
||||||
|
break
|
||||||
|
}
|
||||||
|
goto ok0
|
||||||
|
fail3:
|
||||||
|
node.Kids = node.Kids[:nkids1]
|
||||||
|
pos = pos2
|
||||||
|
// h
|
||||||
|
if p, kid := _hNode(parser, pos); kid == nil {
|
||||||
|
goto fail10
|
||||||
|
} else {
|
||||||
|
node.Kids = append(node.Kids, kid)
|
||||||
|
pos = p
|
||||||
|
}
|
||||||
|
goto ok0
|
||||||
|
fail10:
|
||||||
|
node.Kids = node.Kids[:nkids1]
|
||||||
|
pos = pos2
|
||||||
|
goto fail
|
||||||
|
ok0:
|
||||||
|
}
|
||||||
|
node.Text = parser.text[start:pos]
|
||||||
|
parser.node[key] = node
|
||||||
|
return pos, node
|
||||||
|
fail:
|
||||||
|
return -1, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func _HFail(parser *_Parser, start, errPos int) (int, *peg.Fail) {
|
||||||
|
if start > parser.lastFail {
|
||||||
|
return -1, &peg.Fail{}
|
||||||
|
}
|
||||||
|
dp := parser.deltaPos[start].H
|
||||||
|
de := parser.deltaErr[start].H
|
||||||
|
if start+int(de-1) < errPos {
|
||||||
|
if dp > 0 {
|
||||||
|
return start + int(dp-1), &peg.Fail{}
|
||||||
|
}
|
||||||
|
return -1, &peg.Fail{}
|
||||||
|
}
|
||||||
|
key := _key{start: start, name: "H"}
|
||||||
|
failure := parser.fail[key]
|
||||||
|
if dp < 0 && failure != nil {
|
||||||
|
return -1, failure
|
||||||
|
}
|
||||||
|
if dp > 0 && failure != nil {
|
||||||
|
return start + int(dp-1), failure
|
||||||
|
}
|
||||||
|
pos := start
|
||||||
|
failure = &peg.Fail{
|
||||||
|
Name: "H",
|
||||||
|
Pos: int(start),
|
||||||
|
}
|
||||||
|
// h+ sep+/h
|
||||||
|
{
|
||||||
|
pos2 := pos
|
||||||
|
// h+ sep+
|
||||||
|
// h+
|
||||||
|
// h
|
||||||
|
{
|
||||||
|
p, kid := _hFail(parser, pos, errPos)
|
||||||
|
if kid.Want != "" || len(kid.Kids) > 0 {
|
||||||
|
failure.Kids = append(failure.Kids, kid)
|
||||||
|
}
|
||||||
|
if p < 0 {
|
||||||
|
goto fail3
|
||||||
|
}
|
||||||
|
pos = p
|
||||||
|
}
|
||||||
|
for {
|
||||||
|
pos5 := pos
|
||||||
|
// h
|
||||||
|
{
|
||||||
|
p, kid := _hFail(parser, pos, errPos)
|
||||||
|
if kid.Want != "" || len(kid.Kids) > 0 {
|
||||||
|
failure.Kids = append(failure.Kids, kid)
|
||||||
|
}
|
||||||
|
if p < 0 {
|
||||||
|
goto fail6
|
||||||
|
}
|
||||||
|
pos = p
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
fail6:
|
||||||
|
pos = pos5
|
||||||
|
break
|
||||||
|
}
|
||||||
|
// sep+
|
||||||
|
// sep
|
||||||
|
{
|
||||||
|
p, kid := _sepFail(parser, pos, errPos)
|
||||||
|
if kid.Want != "" || len(kid.Kids) > 0 {
|
||||||
|
failure.Kids = append(failure.Kids, kid)
|
||||||
|
}
|
||||||
|
if p < 0 {
|
||||||
|
goto fail3
|
||||||
|
}
|
||||||
|
pos = p
|
||||||
|
}
|
||||||
|
for {
|
||||||
|
pos8 := pos
|
||||||
|
// sep
|
||||||
|
{
|
||||||
|
p, kid := _sepFail(parser, pos, errPos)
|
||||||
|
if kid.Want != "" || len(kid.Kids) > 0 {
|
||||||
|
failure.Kids = append(failure.Kids, kid)
|
||||||
|
}
|
||||||
|
if p < 0 {
|
||||||
|
goto fail9
|
||||||
|
}
|
||||||
|
pos = p
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
fail9:
|
||||||
|
pos = pos8
|
||||||
|
break
|
||||||
|
}
|
||||||
|
goto ok0
|
||||||
|
fail3:
|
||||||
|
pos = pos2
|
||||||
|
// h
|
||||||
|
{
|
||||||
|
p, kid := _hFail(parser, pos, errPos)
|
||||||
|
if kid.Want != "" || len(kid.Kids) > 0 {
|
||||||
|
failure.Kids = append(failure.Kids, kid)
|
||||||
|
}
|
||||||
|
if p < 0 {
|
||||||
|
goto fail10
|
||||||
|
}
|
||||||
|
pos = p
|
||||||
|
}
|
||||||
|
goto ok0
|
||||||
|
fail10:
|
||||||
|
pos = pos2
|
||||||
|
goto fail
|
||||||
|
ok0:
|
||||||
|
}
|
||||||
|
parser.fail[key] = failure
|
||||||
|
return pos, failure
|
||||||
|
fail:
|
||||||
|
parser.fail[key] = failure
|
||||||
|
return -1, failure
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
package h
|
||||||
|
|
||||||
|
//go:generate peggy -o h_gen.go h.peg
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/eaburns/peggy/peg"
|
||||||
|
"within.website/x/jbo/namcu"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (p *_Parser) Parse() (int, bool) {
|
||||||
|
pos, perr := _HAccepts(p, 0)
|
||||||
|
return perr, pos >= 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *_Parser) ErrorTree(minPos int) *peg.Fail {
|
||||||
|
p.fail = make(map[_key]*peg.Fail) // reset fail memo table
|
||||||
|
_, tree := _HFail(p, 0, minPos)
|
||||||
|
return tree
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *_Parser) ParseTree() *peg.Node {
|
||||||
|
_, tree := _HNode(p, 0)
|
||||||
|
return tree
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse parses h.
|
||||||
|
// On success, the parseTree is returned.
|
||||||
|
// On failure, both the word-level and the raw, morphological errors are returned.
|
||||||
|
func Parse(text string) (*peg.Node, error) {
|
||||||
|
p := _NewParser(text)
|
||||||
|
if perr, ok := p.Parse(); !ok {
|
||||||
|
return nil, fmt.Errorf("h: gentoldra fi'o zvati fe li %s", namcu.Lerfu(perr))
|
||||||
|
}
|
||||||
|
|
||||||
|
tree := p.ParseTree()
|
||||||
|
RemoveSpace(tree)
|
||||||
|
CollapseLists(tree)
|
||||||
|
|
||||||
|
return tree, nil
|
||||||
|
}
|
|
@ -0,0 +1,59 @@
|
||||||
|
package h
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/eaburns/peggy/peg"
|
||||||
|
)
|
||||||
|
|
||||||
|
// RemoveSpace removes whitespace-only nodes.
|
||||||
|
func RemoveSpace(n *peg.Node) { removeSpace(n) }
|
||||||
|
|
||||||
|
func removeSpace(n *peg.Node) bool {
|
||||||
|
if whitespace(n.Text) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if len(n.Kids) == 0 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
var kids []*peg.Node
|
||||||
|
for _, k := range n.Kids {
|
||||||
|
if removeSpace(k) {
|
||||||
|
kids = append(kids, k)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
n.Kids = kids
|
||||||
|
return len(n.Kids) > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// SpaceChars is the string of all whitespace characters.
|
||||||
|
const SpaceChars = "\x20"
|
||||||
|
|
||||||
|
func whitespace(s string) bool {
|
||||||
|
for _, r := range s {
|
||||||
|
if !strings.ContainsRune(SpaceChars, r) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// CollapseLists collapses chains of single-kid nodes.
|
||||||
|
func CollapseLists(n *peg.Node) {
|
||||||
|
if collapseLists(n) == 1 {
|
||||||
|
n.Kids = n.Kids[0].Kids
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func collapseLists(n *peg.Node) int {
|
||||||
|
var kids []*peg.Node
|
||||||
|
for _, k := range n.Kids {
|
||||||
|
if gk := collapseLists(k); gk == 1 {
|
||||||
|
kids = append(kids, k.Kids[0])
|
||||||
|
} else {
|
||||||
|
kids = append(kids, k)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
n.Kids = kids
|
||||||
|
return len(n.Kids)
|
||||||
|
}
|
Loading…
Reference in New Issue