diff options
Diffstat (limited to 'main/parse.go')
-rw-r--r-- | main/parse.go | 68 |
1 files changed, 68 insertions, 0 deletions
diff --git a/main/parse.go b/main/parse.go index 59104c1..f155453 100644 --- a/main/parse.go +++ b/main/parse.go @@ -21,6 +21,71 @@ func parseReplacement(l *RuneReader) (output []TransducerOutput) { return output } +func parseRangeSubex(l *RuneReader) map[rune]rune { + parts := make(map[rune]rune) + var froms []rune + var hasTo bool + for { + fromsStart := l.next() + if fromsStart == ']' { + hasTo = false + break + } else if fromsStart == '=' { + hasTo = true + break + } + var fromsEnd rune + if l.accept("-") { + fromsEnd = l.next() + if fromsEnd == ']' || fromsEnd == '=' { + l.rewind() + fromsEnd = fromsStart + } + } else { + fromsEnd = fromsStart + } + for i := fromsStart; i <= fromsEnd; i += 1 { + froms = append(froms, i) + } + } + if len(froms) == 0 { + panic("Missing from part of range expression") + } + + var tos []rune + if hasTo { + for { + tosStart := l.next() + if tosStart == ']' { + break + } + var tosEnd rune + if l.accept("-") { + tosEnd = l.next() + if tosEnd == ']' { + l.rewind() + tosEnd = tosStart + } + } else { + tosEnd = tosStart + } + for i := tosStart; i <= tosEnd; i += 1 { + tos = append(tos, i) + } + } + } else { + tos = froms + } + if len(tos) == 0 { + panic("Missing to part of range expression") + } + + for i, from := range froms { + parts[from] = tos[i % len(tos)] + } + return parts +} + func parseSubex(l *RuneReader, minPower int) SubexAST { var lhs SubexAST r := l.next() @@ -32,6 +97,9 @@ func parseSubex(l *RuneReader, minPower int) SubexAST { if !l.accept(")") { panic("Missing matching )") } + case '[': + rangeParts := parseRangeSubex(l) + lhs = SubexASTRange {rangeParts} case ')', '*', '-', '|', '!', '?', ';': l.rewind() return nil |