diff options
| author | Ben Culkin <scorpress@gmail.com> | 2022-09-16 18:58:48 -0400 |
|---|---|---|
| committer | Ben Culkin <scorpress@gmail.com> | 2022-09-16 18:58:48 -0400 |
| commit | a3d2728f84375566da3da560b3faad018d34005d (patch) | |
| tree | d50829207b8b4418c11d6385f49386259bb2cc8a /base/src/main/java/bjc/utils/parserutils/pattern/PatternPart.java | |
| parent | 6186f1d87c5e170fa89aa327001706b0692526fc (diff) | |
Cleanup
Diffstat (limited to 'base/src/main/java/bjc/utils/parserutils/pattern/PatternPart.java')
| -rw-r--r-- | base/src/main/java/bjc/utils/parserutils/pattern/PatternPart.java | 191 |
1 files changed, 143 insertions, 48 deletions
diff --git a/base/src/main/java/bjc/utils/parserutils/pattern/PatternPart.java b/base/src/main/java/bjc/utils/parserutils/pattern/PatternPart.java index 6661072..2fd59ca 100644 --- a/base/src/main/java/bjc/utils/parserutils/pattern/PatternPart.java +++ b/base/src/main/java/bjc/utils/parserutils/pattern/PatternPart.java @@ -1,12 +1,14 @@ package bjc.utils.parserutils.pattern; -import java.util.StringJoiner; import java.util.function.Supplier; import java.util.regex.*; /** * Builder interface for regex patterns. * + * Note that you may need to add explicit non-grouping to get things to work + * right, based on the precedence of your regex operators. + * * @author bjculkin * */ @@ -17,27 +19,37 @@ public interface PatternPart { * @return The regex this part represents. */ public String toRegex(); - + + /** + * Can this regex be optimized? + * + * @return Whether or not this regex can be optimized to a string + */ public boolean canOptimize(); - + + /** + * Create a new pattern part from component bits. + * + * @param canOptimize Whether this part can be optimized + * @param func The function that provides the regex text + * + * @return A pattern part w/ the given body + */ static PatternPart part(boolean canOptimize, Supplier<String> func) { - return new PatternPart() { - - @Override - public String toRegex() { - return func.get(); - } - - @Override - public boolean canOptimize() { - return canOptimize; - } - }; - } - + return new FunctionalPatternPart(func, canOptimize); + } + + /** + * Create a new variable pattern part. + * + * @param source The function which supplies the text. + * + * @return A part that retrieves its bits from the given source + */ static PatternPart var(Supplier<String> source) { return part(false, source); } + /** * Create a 'raw' pattern part, which just echoes the given string. * @@ -48,26 +60,20 @@ public interface PatternPart { static PatternPart raw(String str) { return part(true, () -> str); } - + + /** + * Create a pattern composed of other patterns, interspersed with the given + * string. + * + * @param joiner The string to use as a joiner. + * @param parts The composed pattern parts. + * + * @return The given patterns composed by the parts, joined by `joiner`. + */ static PatternPart joining(String joiner, PatternPart... parts) { - return new PatternPart() { - - @Override - public String toRegex() { - StringJoiner sj = new StringJoiner(joiner); - for (PatternPart part : parts) sj.add(part.toRegex()); - return sj.toString(); - } - - @Override - public boolean canOptimize() { - for (PatternPart part : parts) - if (!part.canOptimize()) return false; - - return true; - } - }; + return new JoinerPatternPart(parts, joiner); } + /** * Create a pattern part which matches the given string. * @@ -78,7 +84,7 @@ public interface PatternPart { static PatternPart literal(String str) { return part(true, () -> Pattern.quote(str)); } - + /** * Create a pattern part which matches a single digit. * @@ -87,60 +93,149 @@ public interface PatternPart { static PatternPart digit() { return raw("\\d"); } - + + /** + * Create a character class pattern + * + * @param chars The characters that make up the class. + * + * @return A pattern representing the character class. + */ static PatternPart cclass(char... chars) { return part(true, () -> { StringBuilder sb = new StringBuilder("["); - for (char ch : chars) sb.append(ch); + for (char ch : chars) + sb.append(ch); sb.append("]"); return sb.toString(); }); } - + + /** + * Represents an inverted character class. + * + * @param chars The characters for the class not to include. + * + * @return A pattern representing a class that doesn't match the characters. + */ static PatternPart notCClass(char... chars) { return part(true, () -> { StringBuilder sb = new StringBuilder("[^"); - for (char ch : chars) sb.append(ch); + for (char ch : chars) + sb.append(ch); sb.append("]"); return sb.toString(); }); } - + + /** + * Represents a pattern that matches any non-space character. + * + * @return A pattern that matches any non-space character. + */ static PatternPart nonspace() { return raw("\\S"); } - + + /** + * Concatenate a series of pattern parts with whitespace. + * + * @param parts The parts to join + * + * @return A pattern that matches each of the given parts, separated by + * whitespace. + */ static PatternPart concat(PatternPart... parts) { return joining(" ", parts); } - + + /** + * Create a pattern which matches one of the given patterns. + * + * @param parts The possible patterns to match. + * + * @return A pattern which matches one of the given patterns. + */ static PatternPart alternate(PatternPart... parts) { return joining("|", parts); } - + + /** + * Create a pattern which matches the given pattern zero or more times. + * + * @param part The pattern to repeat + * + * @return A pattern which matches the given one zero or more times. + */ static PatternPart repeat(PatternPart part) { return part(part.canOptimize(), () -> part.toRegex() + "*"); } - + + /** + * Create a pattern which matches the given one zero or more times. + * + * @param part The pattern to be optional. + * + * @return A pattern where the part is optional + */ static PatternPart optional(PatternPart part) { return part(part.canOptimize(), () -> part.toRegex() + "?"); } - + + /** + * Create a pattern which matches the given pattern one or more times. + * + * @param part The pattern to repeat. + * + * @return A pattern which matches the given one one or more times. + */ static PatternPart repeatAtLeastOnce(PatternPart part) { return part(part.canOptimize(), () -> part.toRegex() + "*"); } - + + /** + * Surround the given pattern with strings. + * + * @param lhs The left-hand side of the pattern. + * @param rhs The right-hand side of the pattern. + * @param part The pattern to match. + * + * @return A pattern surrounded by the given strings. + */ static PatternPart surround(String lhs, String rhs, PatternPart part) { return part(part.canOptimize(), () -> lhs + part.toRegex() + rhs); } + + /** + * Wrap the given pattern in a capturing group. + * + * @param part The pattern to wrap. + * + * @return The pattern, wrapped in a capturing group + */ static PatternPart group(PatternPart part) { return surround("(", ")", part); } + /** + * Wrap the given pattern in a named-capturing group. + * + * @param groupName The name of the group + * @param part The pattern to wrap. + * + * @return A pattern wrap in a named-capturing group. + */ static PatternPart namedGroup(String groupName, PatternPart part) { return surround("(<" + groupName + ">", ")", part); } - + + /** + * Wrap the given pattern in a non-capturing group. + * + * @param part The pattern to wrap. + * + * @return A pattern wrap in a non-capturing group. + */ static PatternPart nonCaptureGroup(PatternPart part) { return surround("(?:", ")", part); } |
