<- Back to shtanton's homepage
aboutsummaryrefslogtreecommitdiff
path: root/subex/parse.go
diff options
context:
space:
mode:
Diffstat (limited to 'subex/parse.go')
-rw-r--r--subex/parse.go154
1 files changed, 37 insertions, 117 deletions
diff --git a/subex/parse.go b/subex/parse.go
index db07567..59b784d 100644
--- a/subex/parse.go
+++ b/subex/parse.go
@@ -4,9 +4,33 @@ import (
"main/walk"
)
+func expectBracket(l *RuneReader, ifLeft walk.Datum, ifRight walk.Datum) walk.Datum {
+ switch l.next() {
+ case '(':
+ return ifLeft
+ case ')':
+ return ifRight
+ default:
+ panic("Expected ( or )")
+ }
+}
+
+// Having just read termType, read in a bracket and return the corresponding walk.Datum
+func parseTerminatorDatumLiteral(termType rune, l *RuneReader) walk.Datum {
+ switch termType {
+ case '@':
+ return expectBracket(l, walk.ArrayBegin, walk.ArrayEnd)
+ case '~':
+ return expectBracket(l, walk.StartString{}, walk.EndString{})
+ case '#':
+ return expectBracket(l, walk.MapBegin, walk.MapEnd)
+ default:
+ return nil
+ }
+}
+
func parseReplacement(l *RuneReader) (output []TransducerOutput) {
// TODO escaping
- // TODO refactor all the terminator stuff @, #, ~
loop: for {
r := l.next()
switch r {
@@ -20,33 +44,8 @@ func parseReplacement(l *RuneReader) (output []TransducerOutput) {
panic("Missing slot character")
}
output = append(output, TransducerReplacementLoad{datum: slot})
- case '@':
- terminal := l.next()
- if terminal == '(' {
- output = append(output, TransducerReplacementRune{datum: walk.ArrayBegin})
- } else if terminal == ')' {
- output = append(output, TransducerReplacementRune{datum: walk.ArrayEnd})
- } else {
- panic("Expected ( or ) after @")
- }
- case '~':
- terminal := l.next()
- if terminal == '(' {
- output = append(output, TransducerReplacementRune{datum: walk.StartString{}})
- } else if terminal == ')' {
- output = append(output, TransducerReplacementRune{datum: walk.EndString{}})
- } else {
- panic("Expected ( or ) after ~")
- }
- case '#':
- terminal := l.next()
- if terminal == '(' {
- output = append(output, TransducerReplacementRune{datum: walk.MapBegin})
- } else if terminal == ')' {
- output = append(output, TransducerReplacementRune{datum: walk.MapEnd})
- } else {
- panic("Expected ( or ) after #")
- }
+ case '@', '~', '#':
+ output = append(output, TransducerReplacementRune{datum: parseTerminatorDatumLiteral(r, l)})
default:
output = append(output, TransducerReplacementRune{datum: r})
}
@@ -68,38 +67,11 @@ func parseRangeSubex(l *RuneReader) map[walk.Datum]walk.Datum {
} else if fromsStart == '=' {
hasTo = true
break
- } else if fromsStart == '@' {
- terminal := l.next()
- if terminal == '(' {
- froms = append(froms, walk.ArrayBegin)
- continue
- } else if terminal == ')' {
- froms = append(froms, walk.ArrayEnd)
- continue
- } else {
- panic("Expected ( or ) after @")
- }
- } else if fromsStart == '#' {
- terminal := l.next()
- if terminal == '(' {
- froms = append(froms, walk.MapBegin)
- continue
- } else if terminal == ')' {
- froms = append(froms, walk.MapEnd)
- continue
- } else {
- panic("Expected ( or ) after #")
- }
- } else if fromsStart == '~' {
- terminal := l.next()
- if terminal == '(' {
- froms = append(froms, walk.StartString{})
- continue
- } else if terminal == ')' {
- froms = append(froms, walk.EndString{})
+ } else {
+ datum := parseTerminatorDatumLiteral(fromsStart, l)
+ if datum != nil {
+ froms = append(froms, datum)
continue
- } else {
- panic("Expected ( or ) after ~")
}
}
if l.accept("-") {
@@ -125,38 +97,11 @@ func parseRangeSubex(l *RuneReader) map[walk.Datum]walk.Datum {
tosStart := l.next()
if tosStart == ']' {
break
- } else if tosStart == '@' {
- terminal := l.next()
- if terminal == '(' {
- tos = append(tos, walk.ArrayBegin)
- continue
- } else if terminal == ')' {
- tos = append(tos, walk.ArrayEnd)
- continue
- } else {
- panic("Expected ( or ) after @")
- }
- } else if tosStart == '#' {
- terminal := l.next()
- if terminal == '(' {
- tos = append(tos, walk.MapBegin)
- continue
- } else if terminal == ')' {
- tos = append(tos, walk.MapEnd)
- continue
- } else {
- panic("Expected ( or ) after #")
- }
- } else if tosStart == '~' {
- terminal := l.next()
- if terminal == '(' {
- tos = append(tos, walk.StartString{})
- continue
- } else if terminal == ')' {
- tos = append(tos, walk.EndString{})
+ } else {
+ datum := parseTerminatorDatumLiteral(tosStart, l)
+ if datum != nil {
+ tos = append(tos, datum)
continue
- } else {
- panic("Expected ( or ) after ~")
}
}
if l.accept("-") {
@@ -220,33 +165,8 @@ func parseSubex(l *RuneReader, minPower int) SubexAST {
lhs = SubexASTOutput{replacement}
case '.':
lhs = SubexASTCopyAny{}
- case '@':
- terminal := l.next()
- if terminal == '(' {
- lhs = SubexASTCopyRune{datum: walk.ArrayBegin}
- } else if terminal == ')' {
- lhs = SubexASTCopyRune{datum: walk.ArrayEnd}
- } else {
- panic("Expected ( or ) after @")
- }
- case '~':
- terminal := l.next()
- if terminal == '(' {
- lhs = SubexASTCopyRune{datum: walk.StartString{}}
- } else if terminal == ')' {
- lhs = SubexASTCopyRune{datum: walk.EndString{}}
- } else {
- panic("Expected ( or ) after ~")
- }
- case '#':
- terminal := l.next()
- if terminal == '(' {
- lhs = SubexASTCopyRune{datum: walk.MapBegin}
- } else if terminal == ')' {
- lhs = SubexASTCopyRune{datum: walk.MapEnd}
- } else {
- panic("Expected ( or ) after #")
- }
+ case '@', '#', '~':
+ lhs = SubexASTCopyRune{datum: parseTerminatorDatumLiteral(r, l)}
default:
lhs = SubexASTCopyRune{datum: r}
}