diff options
author | Charlie Stanton <charlie@shtanton.xyz> | 2022-12-24 10:04:42 +0000 |
---|---|---|
committer | Charlie Stanton <charlie@shtanton.xyz> | 2022-12-24 10:04:42 +0000 |
commit | b2d1d965dee8cc2c1e063067d53a3c8e28a46d6c (patch) | |
tree | 1319884f055b2c64cf1787936c1b4b580d40dcff /main/parse.go | |
parent | ce2db2bc333ed938ec93d5ad0838f8cb720c4865 (diff) | |
download | subex-main.tar |
Ranges of characters can be mapped with []
For example, capitalisation of a letter: [a-z=A-Z]
Caesar cipher shift of 1: [a-zA-Z=b-zaB-ZA]
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 |