diff options
author | Charlie Stanton <charlie@shtanton.xyz> | 2022-09-23 14:55:58 +0100 |
---|---|---|
committer | Charlie Stanton <charlie@shtanton.xyz> | 2022-09-23 14:55:58 +0100 |
commit | f3911888915f6aa96e6b28bd2a98a662faf20f47 (patch) | |
tree | 55373234480b057e1615c0d51316be256b1d6d29 | |
parent | 0a8690993d572a50b95dd4f1c1903ed00ddb9c2b (diff) | |
download | subex-f3911888915f6aa96e6b28bd2a98a662faf20f47.tar |
Adds try, maybe and join operators with !, ? and ; respectively
-rw-r--r-- | main/parse.go | 29 | ||||
-rw-r--r-- | main/regexast.go | 20 | ||||
-rw-r--r-- | main/subexast.go | 36 |
3 files changed, 79 insertions, 6 deletions
diff --git a/main/parse.go b/main/parse.go index a9bd4b5..6cc20ea 100644 --- a/main/parse.go +++ b/main/parse.go @@ -27,7 +27,7 @@ func parseRegex(l *RuneReader, minPower int) RegexAST { switch r { case eof: return nil - case ')', '*', '-', '|': + case ')', '*', '-', '|', '?', '!': l.rewind() return nil case '(': @@ -54,6 +54,10 @@ func parseRegex(l *RuneReader, minPower int) RegexAST { lhs = RegexASTMaximise{lhs} case r == '-' && minPower <= 4: lhs = RegexASTMinimise{lhs} + case r == '!' && minPower <= 4: + lhs = RegexASTTry{lhs} + case r == '?' && minPower <= 4: + lhs = RegexASTMaybe{lhs} case r == '|' && minPower <= 2: rhs := parseRegex(l, 3) if rhs == nil { @@ -79,7 +83,7 @@ func parseSubex(l *RuneReader, minPower int) SubexAST { if !l.accept(")") { panic("Missing matching )") } - case ')', '*', '-', '|': + case ')', '*', '-', '|', '!', '?', ';': l.rewind() return nil case '$': @@ -113,16 +117,29 @@ func parseSubex(l *RuneReader, minPower int) SubexAST { } r := l.next() switch { - case r == '*' && minPower <= 4: + case r == '*' && minPower <= 8: lhs = SubexASTMaximise{lhs} - case r == '-' && minPower <= 4: + case r == '-' && minPower <= 8: lhs = SubexASTMinimise{lhs} - case r == '|' && minPower <= 2: - rhs := parseSubex(l, 3) + case r == '!' && minPower <= 8: + lhs = SubexASTTry{lhs} + case r == '?' && minPower <= 8: + lhs = SubexASTMaybe{lhs} + case r == '|' && minPower <= 4: + rhs := parseSubex(l, 5) if rhs == nil { panic("Missing subex after |") } lhs = SubexASTOr{lhs, rhs} + case r == ';' && minPower <= 2: + rhs := parseSubex(l, 3) + if rhs == nil { + panic("Missing subex after ;") + } + lhs = SubexASTJoin{ + content: lhs, + delimiter: rhs, + } default: l.rewind() break loop diff --git a/main/regexast.go b/main/regexast.go index 0aab053..a5a60c4 100644 --- a/main/regexast.go +++ b/main/regexast.go @@ -70,3 +70,23 @@ func (ast RegexASTMinimise) compileWith(next RegexState) RegexState { state.second = ast.content.compileWith(state) return state } + +type RegexASTTry struct { + content RegexAST +} +func (ast RegexASTTry) compileWith(next RegexState) RegexState { + return RegexGroupState{ + ast.content.compileWith(next), + next, + } +} + +type RegexASTMaybe struct { + content RegexAST +} +func (ast RegexASTMaybe) compileWith(next RegexState) RegexState { + return RegexGroupState { + next, + ast.content.compileWith(next), + } +} diff --git a/main/subexast.go b/main/subexast.go index 7e2f33c..54cc5fe 100644 --- a/main/subexast.go +++ b/main/subexast.go @@ -115,3 +115,39 @@ func (ast SubexASTOutput) compileWith(next SubexState) SubexState { next: next, } } + +type SubexASTTry struct { + content SubexAST +} +func (ast SubexASTTry) compileWith(next SubexState) SubexState { + return SubexGroupState { + ast.content.compileWith(next), + next, + } +} + +type SubexASTMaybe struct { + content SubexAST +} +func (ast SubexASTMaybe) compileWith(next SubexState) SubexState { + return SubexGroupState { + next, + ast.content.compileWith(next), + } +} + +type SubexASTJoin struct { + content, delimiter SubexAST +} +func (ast SubexASTJoin) compileWith(next SubexState) SubexState { + afterContentState := &SubexGroupState { + nil, + next, + } + manyContentsState := ast.content.compileWith(afterContentState) + afterContentState.first = ast.delimiter.compileWith(manyContentsState) + return SubexGroupState { + manyContentsState, + next, + } +} |