diff options
Diffstat (limited to 'subex/parse.go')
-rw-r--r-- | subex/parse.go | 154 |
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} } |