|
|
|
@ -12,13 +12,9 @@ import ( |
|
|
|
|
"golang.org/x/exp/slices" |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
func s(str string) fmt.Stringer { |
|
|
|
|
return Stringer{S: str} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
var ( |
|
|
|
|
notNewline = RuneFunc( |
|
|
|
|
s("not-newline"), func(r rune) bool { return r != '\n' }, |
|
|
|
|
"not-newline", func(r rune) bool { return r != '\n' }, |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
comment = Prefixed( |
|
|
|
@ -26,7 +22,7 @@ var ( |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
whitespace = ZeroOrMore(FirstOf( |
|
|
|
|
Discard(RuneFunc(s("whitespace"), unicode.IsSpace)), |
|
|
|
|
Discard(RuneFunc("whitespace", unicode.IsSpace)), |
|
|
|
|
Discard(comment), |
|
|
|
|
)) |
|
|
|
|
) |
|
|
|
@ -43,13 +39,12 @@ func trimmedRune(r rune) Symbol[Located[rune]] { |
|
|
|
|
|
|
|
|
|
var ( |
|
|
|
|
digit = RuneFunc( |
|
|
|
|
s("digit"), func(r rune) bool { return '0' <= r && r <= '9' }, |
|
|
|
|
"digit", func(r rune) bool { return '0' <= r && r <= '9' }, |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
positiveNumber = StringFromRunes(OneOrMore(digit)) |
|
|
|
|
|
|
|
|
|
negativeNumber = Reduction( |
|
|
|
|
s("negative-number"), |
|
|
|
|
Rune('-'), |
|
|
|
|
positiveNumber, |
|
|
|
|
func(neg Located[rune], posNum Located[string]) Located[string] { |
|
|
|
@ -57,23 +52,25 @@ var ( |
|
|
|
|
}, |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
number = Mapping( |
|
|
|
|
s("number"), |
|
|
|
|
FirstOf(negativeNumber, positiveNumber), |
|
|
|
|
func(str Located[string]) Located[Value] { |
|
|
|
|
i, err := strconv.ParseInt(str.Value, 10, 64) |
|
|
|
|
if err != nil { |
|
|
|
|
panic(fmt.Errorf("parsing %q as int: %w", str, err)) |
|
|
|
|
} |
|
|
|
|
number = Named( |
|
|
|
|
"number", |
|
|
|
|
Mapping( |
|
|
|
|
FirstOf(negativeNumber, positiveNumber), |
|
|
|
|
func(str Located[string]) Located[Value] { |
|
|
|
|
i, err := strconv.ParseInt(str.Value, 10, 64) |
|
|
|
|
if err != nil { |
|
|
|
|
panic(fmt.Errorf("parsing %q as int: %w", str, err)) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return Locate(str.Location, Number(i)) |
|
|
|
|
}, |
|
|
|
|
return Locate(str.Location, Number(i)) |
|
|
|
|
}, |
|
|
|
|
), |
|
|
|
|
) |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
var ( |
|
|
|
|
letter = RuneFunc( |
|
|
|
|
s("letter"), |
|
|
|
|
"letter", |
|
|
|
|
func(r rune) bool { |
|
|
|
|
return unicode.In(r, unicode.Letter, unicode.Mark) |
|
|
|
|
}, |
|
|
|
@ -81,18 +78,20 @@ var ( |
|
|
|
|
|
|
|
|
|
nameTail = ZeroOrMore(FirstOf(letter, digit)) |
|
|
|
|
|
|
|
|
|
name = Reduction( |
|
|
|
|
s("name"), |
|
|
|
|
letter, |
|
|
|
|
nameTail, |
|
|
|
|
func(head Located[rune], tail []Located[rune]) Located[Value] { |
|
|
|
|
name := make([]rune, 0, len(tail)+1) |
|
|
|
|
name = append(name, head.Value) |
|
|
|
|
for _, r := range tail { |
|
|
|
|
name = append(name, r.Value) |
|
|
|
|
} |
|
|
|
|
return Locate(head.Location, Name(string(name))) |
|
|
|
|
}, |
|
|
|
|
name = Named( |
|
|
|
|
"name", |
|
|
|
|
Reduction( |
|
|
|
|
letter, |
|
|
|
|
nameTail, |
|
|
|
|
func(head Located[rune], tail []Located[rune]) Located[Value] { |
|
|
|
|
name := make([]rune, 0, len(tail)+1) |
|
|
|
|
name = append(name, head.Value) |
|
|
|
|
for _, r := range tail { |
|
|
|
|
name = append(name, r.Value) |
|
|
|
|
} |
|
|
|
|
return Locate(head.Location, Name(string(name))) |
|
|
|
|
}, |
|
|
|
|
), |
|
|
|
|
) |
|
|
|
|
) |
|
|
|
|
|
|
|
|
@ -122,10 +121,8 @@ var graphSym, value = func() ( |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
var ( |
|
|
|
|
rightParen = trimmedRune(')') |
|
|
|
|
tupleEnd = Mapping( |
|
|
|
|
rightParen, |
|
|
|
|
rightParen, |
|
|
|
|
tupleEnd = Mapping( |
|
|
|
|
trimmedRune(')'), |
|
|
|
|
func(Located[rune]) tupleState { |
|
|
|
|
// if ')', then map that to an empty state. This acts as a
|
|
|
|
|
// sentinel value to indicate "end of tuple".
|
|
|
|
@ -133,10 +130,8 @@ var graphSym, value = func() ( |
|
|
|
|
}, |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
rightCurlyBrace = trimmedRune('}') |
|
|
|
|
graphEnd = Mapping( |
|
|
|
|
rightCurlyBrace, |
|
|
|
|
rightCurlyBrace, |
|
|
|
|
graphEnd = Mapping( |
|
|
|
|
trimmedRune('}'), |
|
|
|
|
func(Located[rune]) graphState { |
|
|
|
|
// if '}', then map that to an empty state. This acts as a
|
|
|
|
|
// sentinel value to indicate "end of graph".
|
|
|
|
@ -163,20 +158,21 @@ var graphSym, value = func() ( |
|
|
|
|
graphOpenEdgeValueTail = new(SymbolPtr[graphState]) |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
tuple.Symbol = Reduction[Located[rune], tupleState, *OpenEdge]( |
|
|
|
|
s("tuple"), |
|
|
|
|
trimmedRune('('), |
|
|
|
|
tupleTail, |
|
|
|
|
func(_ Located[rune], ts tupleState) *OpenEdge { |
|
|
|
|
slices.Reverse(ts.ins) |
|
|
|
|
return graph.TupleOut(None, ts.ins...) |
|
|
|
|
}, |
|
|
|
|
tuple.Symbol = Named( |
|
|
|
|
"tuple", |
|
|
|
|
Reduction[Located[rune], tupleState, *OpenEdge]( |
|
|
|
|
trimmedRune('('), |
|
|
|
|
tupleTail, |
|
|
|
|
func(_ Located[rune], ts tupleState) *OpenEdge { |
|
|
|
|
slices.Reverse(ts.ins) |
|
|
|
|
return graph.TupleOut(None, ts.ins...) |
|
|
|
|
}, |
|
|
|
|
), |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
tupleTail.Symbol = FirstOf( |
|
|
|
|
tupleEnd, |
|
|
|
|
Mapping[tupleState, tupleState]( |
|
|
|
|
tupleOpenEdge, |
|
|
|
|
tupleOpenEdge, |
|
|
|
|
func(ts tupleState) tupleState { |
|
|
|
|
ts.ins = append(ts.ins, ts.oe) |
|
|
|
@ -188,7 +184,6 @@ var graphSym, value = func() ( |
|
|
|
|
|
|
|
|
|
tupleOpenEdge.Symbol = FirstOf( |
|
|
|
|
Reduction[Located[Value], tupleState, tupleState]( |
|
|
|
|
value, |
|
|
|
|
value, |
|
|
|
|
tupleOpenEdgeValueTail, |
|
|
|
|
func(val Located[Value], ts tupleState) tupleState { |
|
|
|
@ -197,7 +192,6 @@ var graphSym, value = func() ( |
|
|
|
|
}, |
|
|
|
|
), |
|
|
|
|
Reduction[*OpenEdge, tupleState, tupleState]( |
|
|
|
|
tuple, |
|
|
|
|
tuple, |
|
|
|
|
tupleOpenEdgeTail, |
|
|
|
|
func(oe *OpenEdge, ts tupleState) tupleState { |
|
|
|
@ -217,23 +211,24 @@ var graphSym, value = func() ( |
|
|
|
|
Prefixed[Located[rune], tupleState](trimmedRune('<'), tupleOpenEdge), |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
graphSym.Symbol = Reduction[Located[rune], graphState, Located[Value]]( |
|
|
|
|
s("graph"), |
|
|
|
|
trimmedRune('{'), |
|
|
|
|
graphTail, |
|
|
|
|
func(r Located[rune], gs graphState) Located[Value] { |
|
|
|
|
if gs.g == nil { |
|
|
|
|
gs.g = new(Graph) |
|
|
|
|
} |
|
|
|
|
graphSym.Symbol = Named( |
|
|
|
|
"graph", |
|
|
|
|
Reduction[Located[rune], graphState, Located[Value]]( |
|
|
|
|
trimmedRune('{'), |
|
|
|
|
graphTail, |
|
|
|
|
func(r Located[rune], gs graphState) Located[Value] { |
|
|
|
|
if gs.g == nil { |
|
|
|
|
gs.g = new(Graph) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return Locate(r.Location, Value{Graph: gs.g}) |
|
|
|
|
}, |
|
|
|
|
return Locate(r.Location, Value{Graph: gs.g}) |
|
|
|
|
}, |
|
|
|
|
), |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
graphTail.Symbol = FirstOf( |
|
|
|
|
graphEnd, |
|
|
|
|
Reduction( |
|
|
|
|
name, |
|
|
|
|
name, |
|
|
|
|
Prefixed[Located[rune], graphState]( |
|
|
|
|
trimmedRune('='), graphOpenEdge, |
|
|
|
@ -253,7 +248,6 @@ var graphSym, value = func() ( |
|
|
|
|
|
|
|
|
|
graphOpenEdge.Symbol = FirstOf( |
|
|
|
|
Reduction[Located[Value], graphState, graphState]( |
|
|
|
|
value, |
|
|
|
|
value, |
|
|
|
|
graphOpenEdgeValueTail, |
|
|
|
|
func(val Located[Value], gs graphState) graphState { |
|
|
|
@ -262,7 +256,6 @@ var graphSym, value = func() ( |
|
|
|
|
}, |
|
|
|
|
), |
|
|
|
|
Reduction[*OpenEdge, graphState, graphState]( |
|
|
|
|
tuple, |
|
|
|
|
tuple, |
|
|
|
|
graphOpenEdgeTail, |
|
|
|
|
func(oe *OpenEdge, gs graphState) graphState { |
|
|
|
|