diff --git a/gradle.properties b/gradle.properties index 13efff07a..07537229c 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ # Warning, "version" should be the same in gradle.properties and Version.java # Any idea anyone how to magically synchronize those :-) ? -version = 1.2023.14beta1 +version = 1.2023.14beta2 org.gradle.workers.max = 3 \ No newline at end of file diff --git a/src/net/sourceforge/plantuml/activitydiagram3/InstructionRepeat.java b/src/net/sourceforge/plantuml/activitydiagram3/InstructionRepeat.java index 287b84a21..1680f463f 100644 --- a/src/net/sourceforge/plantuml/activitydiagram3/InstructionRepeat.java +++ b/src/net/sourceforge/plantuml/activitydiagram3/InstructionRepeat.java @@ -59,6 +59,7 @@ import net.sourceforge.plantuml.sequencediagram.NotePosition; import net.sourceforge.plantuml.sequencediagram.NoteType; import net.sourceforge.plantuml.stereo.Stereotype; import net.sourceforge.plantuml.style.ISkinParam; +import net.sourceforge.plantuml.style.StyleBuilder; public class InstructionRepeat extends AbstractInstruction implements Instruction { @@ -87,6 +88,7 @@ public class InstructionRepeat extends AbstractInstruction implements Instructio private LinkRendering endRepeatLinkRendering = LinkRendering.none(); private final Colors colors; + private final StyleBuilder currentStyleBuilder; public boolean containsBreak() { return repeatList.containsBreak(); @@ -94,6 +96,7 @@ public class InstructionRepeat extends AbstractInstruction implements Instructio public InstructionRepeat(Swimlanes swimlanes, Instruction parent, LinkRendering nextLinkRenderer, HColor color, Display startLabel, BoxStyle boxStyleIn, Colors colors) { + this.currentStyleBuilder = swimlanes.getCurrentStyleBuilder(); this.swimlanes = swimlanes; this.swimlane = swimlanes.getCurrentSwimlane(); this.repeatList = new InstructionList(this.swimlane); @@ -158,7 +161,7 @@ public class InstructionRepeat extends AbstractInstruction implements Instructio if (this.testCalled == false && incoming1.isNone()) incoming1 = swimlanes.nextLinkRenderer(); final Ftile result = factory.repeat(boxStyleIn, swimlane, swimlaneOut, startLabel, decorateOut, test, yes, out, - colors, back, isLastOfTheParent(), incoming1, incoming2); + colors, back, isLastOfTheParent(), incoming1, incoming2, currentStyleBuilder); if (killed) return new FtileKilled(result); diff --git a/src/net/sourceforge/plantuml/activitydiagram3/InstructionWhile.java b/src/net/sourceforge/plantuml/activitydiagram3/InstructionWhile.java index 554510da7..8ec637324 100644 --- a/src/net/sourceforge/plantuml/activitydiagram3/InstructionWhile.java +++ b/src/net/sourceforge/plantuml/activitydiagram3/InstructionWhile.java @@ -56,6 +56,7 @@ import net.sourceforge.plantuml.klimt.geom.VerticalAlignment; import net.sourceforge.plantuml.sequencediagram.NotePosition; import net.sourceforge.plantuml.sequencediagram.NoteType; import net.sourceforge.plantuml.style.ISkinParam; +import net.sourceforge.plantuml.style.StyleBuilder; public class InstructionWhile extends WithNote implements Instruction, InstructionCollection { @@ -82,6 +83,7 @@ public class InstructionWhile extends WithNote implements Instruction, Instructi private LinkRendering incoming1 = LinkRendering.none(); private LinkRendering incoming2 = LinkRendering.none(); private boolean backwardCalled; + private final StyleBuilder currentStyleBuilder; public void overwriteYes(Display yes) { this.yes = yes; @@ -94,6 +96,7 @@ public class InstructionWhile extends WithNote implements Instruction, Instructi this.nextLinkRenderer = Objects.requireNonNull(nextLinkRenderer); this.yes = Objects.requireNonNull(yes); this.swimlane = swimlane; + this.currentStyleBuilder = skinParam.getCurrentStyleBuilder(); this.color = color; this.skinParam = skinParam; } @@ -118,7 +121,7 @@ public class InstructionWhile extends WithNote implements Instruction, Instructi final Ftile back = Display.isNull(backward) ? null : factory.activity(backward, swimlane, boxStyle, Colors.empty(), null); Ftile tmp = repeatList.createFtile(factory); - tmp = factory.createWhile(outColor, swimlane, tmp, test, yes, color, specialOut, back, incoming1, incoming2); + tmp = factory.createWhile(outColor, swimlane, tmp, test, yes, color, specialOut, back, incoming1, incoming2, currentStyleBuilder); if (getPositionedNotes().size() > 0) tmp = FtileWithNoteOpale.create(tmp, getPositionedNotes(), false, VerticalAlignment.CENTER); diff --git a/src/net/sourceforge/plantuml/activitydiagram3/ftile/FtileFactory.java b/src/net/sourceforge/plantuml/activitydiagram3/ftile/FtileFactory.java index 7b4f9a4bf..f7cabc662 100644 --- a/src/net/sourceforge/plantuml/activitydiagram3/ftile/FtileFactory.java +++ b/src/net/sourceforge/plantuml/activitydiagram3/ftile/FtileFactory.java @@ -84,10 +84,11 @@ public interface FtileFactory { public Ftile repeat(BoxStyle boxStyleIn, Swimlane swimlane, Swimlane swimlaneOut, Display startLabel, Ftile repeat, Display test, Display yes, Display out, Colors colors, Ftile backward, boolean noOut, - LinkRendering incoming1, LinkRendering incoming2); + LinkRendering incoming1, LinkRendering incoming2, StyleBuilder currentStyleBuilder); public Ftile createWhile(LinkRendering outColor, Swimlane swimlane, Ftile whileBlock, Display test, Display yes, - HColor color, Instruction specialOut, Ftile backward, LinkRendering incoming1, LinkRendering incoming2); + HColor color, Instruction specialOut, Ftile backward, LinkRendering incoming1, LinkRendering incoming2, + StyleBuilder currentStyleBuilder); public Ftile createIf(Swimlane swimlane, List thens, Branch elseBranch, LinkRendering outColor, LinkRendering topInlinkRendering, Url url, Collection notes, Stereotype stereotype, diff --git a/src/net/sourceforge/plantuml/activitydiagram3/ftile/FtileFactoryDelegator.java b/src/net/sourceforge/plantuml/activitydiagram3/ftile/FtileFactoryDelegator.java index 4738d0725..b39f1ad2e 100644 --- a/src/net/sourceforge/plantuml/activitydiagram3/ftile/FtileFactoryDelegator.java +++ b/src/net/sourceforge/plantuml/activitydiagram3/ftile/FtileFactoryDelegator.java @@ -175,16 +175,17 @@ public class FtileFactoryDelegator implements FtileFactory { @Override public Ftile repeat(BoxStyle boxStyleIn, Swimlane swimlane, Swimlane swimlaneOut, Display startLabel, Ftile repeat, Display test, Display yes, Display out, Colors colors, Ftile backward, boolean noOut, - LinkRendering incoming1, LinkRendering incoming2) { + LinkRendering incoming1, LinkRendering incoming2, StyleBuilder currentStyleBuilder) { return factory.repeat(boxStyleIn, swimlane, swimlaneOut, startLabel, repeat, test, yes, out, colors, backward, - noOut, incoming1, incoming2); + noOut, incoming1, incoming2, currentStyleBuilder); } @Override public Ftile createWhile(LinkRendering outColor, Swimlane swimlane, Ftile whileBlock, Display test, Display yes, - HColor color, Instruction specialOut, Ftile back, LinkRendering incoming1, LinkRendering incoming2) { + HColor color, Instruction specialOut, Ftile back, LinkRendering incoming1, LinkRendering incoming2, + StyleBuilder styleBuilder) { return factory.createWhile(outColor, swimlane, whileBlock, test, yes, color, specialOut, back, incoming1, - incoming2); + incoming2, styleBuilder); } @Override diff --git a/src/net/sourceforge/plantuml/activitydiagram3/ftile/Swimlanes.java b/src/net/sourceforge/plantuml/activitydiagram3/ftile/Swimlanes.java index 1d5bebdd7..0df019d31 100644 --- a/src/net/sourceforge/plantuml/activitydiagram3/ftile/Swimlanes.java +++ b/src/net/sourceforge/plantuml/activitydiagram3/ftile/Swimlanes.java @@ -82,6 +82,7 @@ import net.sourceforge.plantuml.style.ISkinParam; import net.sourceforge.plantuml.style.PName; import net.sourceforge.plantuml.style.SName; import net.sourceforge.plantuml.style.Style; +import net.sourceforge.plantuml.style.StyleBuilder; import net.sourceforge.plantuml.style.StyleSignatureBasic; import net.sourceforge.plantuml.style.Styleable; import net.sourceforge.plantuml.svek.UGraphicForSnake; @@ -127,9 +128,9 @@ public class Swimlanes extends AbstractTextBlock implements TextBlock, Styleable } protected Style getStyle() { - if (style == null) { + if (style == null) this.style = getStyleSignature().getMergedStyle(skinParam.getCurrentStyleBuilder()); - } + return style; } @@ -455,4 +456,8 @@ public class Swimlanes extends AbstractTextBlock implements TextBlock, Styleable return cachedMinMax; } + public StyleBuilder getCurrentStyleBuilder() { + return skinParam.getCurrentStyleBuilder(); + } + } diff --git a/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/FtileFactoryDelegatorRepeat.java b/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/FtileFactoryDelegatorRepeat.java index a289a153d..140845b0a 100644 --- a/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/FtileFactoryDelegatorRepeat.java +++ b/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/FtileFactoryDelegatorRepeat.java @@ -62,6 +62,7 @@ import net.sourceforge.plantuml.klimt.font.FontConfiguration; import net.sourceforge.plantuml.klimt.geom.XDimension2D; import net.sourceforge.plantuml.style.PName; import net.sourceforge.plantuml.style.Style; +import net.sourceforge.plantuml.style.StyleBuilder; import net.sourceforge.plantuml.svek.ConditionStyle; public class FtileFactoryDelegatorRepeat extends FtileFactoryDelegator { @@ -73,13 +74,12 @@ public class FtileFactoryDelegatorRepeat extends FtileFactoryDelegator { @Override public Ftile repeat(BoxStyle boxStyleIn, Swimlane swimlane, Swimlane swimlaneOut, Display startLabel, final Ftile repeat, Display test, Display yes, Display out, Colors colors, Ftile backward, boolean noOut, - LinkRendering incoming1, LinkRendering incoming2) { + LinkRendering incoming1, LinkRendering incoming2, StyleBuilder currentStyleBuilder) { final ConditionStyle conditionStyle = skinParam().getConditionStyle(); - final Style styleArrow = getDefaultStyleDefinitionArrow().getMergedStyle(skinParam().getCurrentStyleBuilder()); - final Style styleDiamond = getDefaultStyleDefinitionDiamond() - .getMergedStyle(skinParam().getCurrentStyleBuilder()); + final Style styleArrow = getDefaultStyleDefinitionArrow().getMergedStyle(currentStyleBuilder); + final Style styleDiamond = getDefaultStyleDefinitionDiamond().getMergedStyle(currentStyleBuilder); final HColor borderColor = styleDiamond.value(PName.LineColor).asColor(skinParam().getIHtmlColorSet()); final HColor diamondColor = styleDiamond.value(PName.BackGroundColor).asColor(skinParam().getIHtmlColorSet()); final Rainbow arrowColor = Rainbow.build(styleArrow, skinParam().getIHtmlColorSet()); diff --git a/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/FtileFactoryDelegatorWhile.java b/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/FtileFactoryDelegatorWhile.java index 510a8df34..09e28adbc 100644 --- a/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/FtileFactoryDelegatorWhile.java +++ b/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/FtileFactoryDelegatorWhile.java @@ -58,6 +58,7 @@ import net.sourceforge.plantuml.klimt.drawing.UGraphic; import net.sourceforge.plantuml.klimt.font.FontConfiguration; import net.sourceforge.plantuml.style.PName; import net.sourceforge.plantuml.style.Style; +import net.sourceforge.plantuml.style.StyleBuilder; import net.sourceforge.plantuml.svek.ConditionStyle; public class FtileFactoryDelegatorWhile extends FtileFactoryDelegator { @@ -68,13 +69,13 @@ public class FtileFactoryDelegatorWhile extends FtileFactoryDelegator { @Override public Ftile createWhile(LinkRendering outColor, Swimlane swimlane, Ftile whileBlock, Display test, Display yes, - HColor color, Instruction specialOut, Ftile backward, LinkRendering incoming1, LinkRendering incoming2) { + HColor color, Instruction specialOut, Ftile backward, LinkRendering incoming1, LinkRendering incoming2, + StyleBuilder currentStyleBuilder) { final ConditionStyle conditionStyle = skinParam().getConditionStyle(); - final Style styleArrow = getDefaultStyleDefinitionArrow().getMergedStyle(skinParam().getCurrentStyleBuilder()); - final Style styleDiamond = getDefaultStyleDefinitionDiamond() - .getMergedStyle(skinParam().getCurrentStyleBuilder()); + final Style styleArrow = getDefaultStyleDefinitionArrow().getMergedStyle(currentStyleBuilder); + final Style styleDiamond = getDefaultStyleDefinitionDiamond().getMergedStyle(currentStyleBuilder); final HColor borderColor = styleDiamond.value(PName.LineColor).asColor(skinParam().getIHtmlColorSet()); final HColor backColor = styleDiamond.value(PName.BackGroundColor).asColor(skinParam().getIHtmlColorSet()); final Rainbow arrowColor = Rainbow.build(styleArrow, skinParam().getIHtmlColorSet()); diff --git a/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/VCompactFactory.java b/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/VCompactFactory.java index 340ed7a57..743936057 100644 --- a/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/VCompactFactory.java +++ b/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/VCompactFactory.java @@ -156,14 +156,14 @@ public class VCompactFactory implements FtileFactory { @Override public Ftile repeat(BoxStyle boxStyleIn, Swimlane swimlane, Swimlane swimlaneOut, Display startLabel, Ftile repeat, Display test, Display yes, Display out, Colors colors, Ftile backward, boolean noOut, - LinkRendering incoming1, LinkRendering incoming2) { + LinkRendering incoming1, LinkRendering incoming2, StyleBuilder currentStyleBuilder) { return repeat; } @Override public Ftile createWhile(LinkRendering afterEndwhile, Swimlane swimlane, Ftile whileBlock, Display test, Display yes, HColor color, Instruction specialOut, Ftile back, LinkRendering incoming1, - LinkRendering incoming2) { + LinkRendering incoming2, StyleBuilder styleBuilder) { return whileBlock; } diff --git a/src/net/sourceforge/plantuml/ebnf/ETileLookAheadOrBehind.java b/src/net/sourceforge/plantuml/ebnf/ETileLookAheadOrBehind.java new file mode 100644 index 000000000..23a046faf --- /dev/null +++ b/src/net/sourceforge/plantuml/ebnf/ETileLookAheadOrBehind.java @@ -0,0 +1,110 @@ +/* ======================================================================== + * PlantUML : a free UML diagram generator + * ======================================================================== + * + * (C) Copyright 2009-2020, Arnaud Roques + * + * Project Info: https://plantuml.com + * + * If you like this project or if you find it useful, you can support us at: + * + * https://plantuml.com/patreon (only 1$ per month!) + * https://plantuml.com/paypal + * + * This file is part of PlantUML. + * + * PlantUML is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * PlantUML distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + * + * + * Original Author: Arnaud Roques + * + * + */ +package net.sourceforge.plantuml.ebnf; + +import net.sourceforge.plantuml.klimt.UStroke; +import net.sourceforge.plantuml.klimt.UTranslate; +import net.sourceforge.plantuml.klimt.color.HColor; +import net.sourceforge.plantuml.klimt.color.HColorSet; +import net.sourceforge.plantuml.klimt.drawing.UGraphic; +import net.sourceforge.plantuml.klimt.font.FontConfiguration; +import net.sourceforge.plantuml.klimt.font.StringBounder; +import net.sourceforge.plantuml.klimt.geom.XDimension2D; +import net.sourceforge.plantuml.klimt.shape.URectangle; +import net.sourceforge.plantuml.klimt.shape.UText; +import net.sourceforge.plantuml.style.PName; +import net.sourceforge.plantuml.style.Style; + +public class ETileLookAheadOrBehind extends ETile { + + private final ETile orig; + private final HColorSet colorSet; + private final double deltax1 = 4; + private final double deltax2 = 8; + private final double deltay = 6; + private final Style style; + private final UText supText; + + private final FontConfiguration fc; + + public ETileLookAheadOrBehind(ETile orig, FontConfiguration fc, Style style, HColorSet colorSet, String type) { + this.style = style; + this.orig = orig; + this.fc = fc; + this.colorSet = colorSet; + this.supText = UText.build(type, fc); + + } + + @Override + public double getH1(StringBounder stringBounder) { + return deltay + orig.getH1(stringBounder); + } + + @Override + public double getH2(StringBounder stringBounder) { + return orig.getH2(stringBounder) + deltay; + } + + @Override + public double getWidth(StringBounder stringBounder) { + return orig.getWidth(stringBounder) + deltax1 + deltax2 + supText.calculateDimension(stringBounder).getWidth(); + } + + @Override + public void drawU(UGraphic ug) { + final StringBounder stringBounder = ug.getStringBounder(); + final XDimension2D dim = calculateDimension(stringBounder); + + final HColor lineColor = style.value(PName.LineColor).asColor(colorSet); + + final URectangle rect = URectangle.build(dim).rounded(30); + + ug.apply(lineColor).apply(new UStroke(2, 3, 1)).draw(rect); + final double posText = getH1(stringBounder) + supText.getDescent(stringBounder); + + ug.apply(new UTranslate(4, 2 + posText)).draw(supText); + + orig.drawU(ug.apply(new UTranslate(deltax1 + supText.calculateDimension(stringBounder).getWidth(), deltay))); + + } + + @Override + public void push(ETile tile) { + throw new UnsupportedOperationException(); + } + +} diff --git a/src/net/sourceforge/plantuml/klimt/shape/UText.java b/src/net/sourceforge/plantuml/klimt/shape/UText.java index 938007efb..6968ba1ed 100644 --- a/src/net/sourceforge/plantuml/klimt/shape/UText.java +++ b/src/net/sourceforge/plantuml/klimt/shape/UText.java @@ -38,6 +38,7 @@ package net.sourceforge.plantuml.klimt.shape; import net.sourceforge.plantuml.klimt.UShape; import net.sourceforge.plantuml.klimt.font.FontConfiguration; import net.sourceforge.plantuml.klimt.font.StringBounder; +import net.sourceforge.plantuml.klimt.geom.XDimension2D; public class UText implements UShape { @@ -83,4 +84,8 @@ public class UText implements UShape { return orientation; } + public XDimension2D calculateDimension(StringBounder stringBounder) { + return stringBounder.calculateDimension(font.getFont(), text); + } + } diff --git a/src/net/sourceforge/plantuml/regexdiagram/PSystemRegex.java b/src/net/sourceforge/plantuml/regexdiagram/PSystemRegex.java index 03e171ef1..4a1e610f0 100644 --- a/src/net/sourceforge/plantuml/regexdiagram/PSystemRegex.java +++ b/src/net/sourceforge/plantuml/regexdiagram/PSystemRegex.java @@ -52,6 +52,7 @@ import net.sourceforge.plantuml.ebnf.ETile; import net.sourceforge.plantuml.ebnf.ETileAlternation; import net.sourceforge.plantuml.ebnf.ETileBox; import net.sourceforge.plantuml.ebnf.ETileConcatenation; +import net.sourceforge.plantuml.ebnf.ETileLookAheadOrBehind; import net.sourceforge.plantuml.ebnf.ETileNamedGroup; import net.sourceforge.plantuml.ebnf.ETileOneOrMore; import net.sourceforge.plantuml.ebnf.ETileOptional; @@ -162,6 +163,10 @@ public class PSystemRegex extends TitledDiagram { push(token, Symbol.TERMINAL_STRING1); else if (token.getType() == ReTokenType.GROUP) push(token, Symbol.SPECIAL_SEQUENCE); + else if (token.getType() == ReTokenType.LOOK_AHEAD) + lookAheadOrBehind(token.getData()); + else if (token.getType() == ReTokenType.LOOK_BEHIND) + lookAheadOrBehind(token.getData()); else if (token.getType() == ReTokenType.NAMED_GROUP) namedGroup(token.getData()); else if (token.getType() == ReTokenType.CLASS) @@ -205,6 +210,11 @@ public class PSystemRegex extends TitledDiagram { stack.addFirst(new ETileBox(element.getData(), type, fontConfiguration, style, colorSet, getSkinParam())); } + private void lookAheadOrBehind(String name) { + final ETile arg1 = stack.removeFirst(); + stack.addFirst(new ETileLookAheadOrBehind(arg1, fontConfiguration, style, colorSet, name)); + } + private void namedGroup(String name) { final ETile arg1 = stack.removeFirst(); stack.addFirst(new ETileNamedGroup(arg1, fontConfiguration, colorSet, getSkinParam(), name)); diff --git a/src/net/sourceforge/plantuml/regexdiagram/ReTokenType.java b/src/net/sourceforge/plantuml/regexdiagram/ReTokenType.java index 11d68ff88..5941488ea 100644 --- a/src/net/sourceforge/plantuml/regexdiagram/ReTokenType.java +++ b/src/net/sourceforge/plantuml/regexdiagram/ReTokenType.java @@ -44,13 +44,19 @@ public enum ReTokenType { ANCHOR, // GROUP, // NAMED_GROUP, // + LOOK_AHEAD, // + LOOK_BEHIND, // ALTERNATIVE, // PARENTHESIS_OPEN, // PARENTHESIS_CLOSE, // CONCATENATION_IMPLICIT; + public boolean isNamedGroupOrLookAheadOrLookBehind() { + return this == NAMED_GROUP || this == LOOK_AHEAD || this == LOOK_BEHIND; + } + static public boolean needImplicitConcatenation(ReTokenType token1, ReTokenType token2) { - if (token1 == NAMED_GROUP) + if (token1.isNamedGroupOrLookAheadOrLookBehind()) return false; if (token1 == ALTERNATIVE) return false; diff --git a/src/net/sourceforge/plantuml/regexdiagram/RegexExpression.java b/src/net/sourceforge/plantuml/regexdiagram/RegexExpression.java index 01bd39abd..50a3003e3 100644 --- a/src/net/sourceforge/plantuml/regexdiagram/RegexExpression.java +++ b/src/net/sourceforge/plantuml/regexdiagram/RegexExpression.java @@ -60,11 +60,22 @@ public class RegexExpression { } else if (current == '|') { result.add(new ReToken(ReTokenType.ALTERNATIVE, "|")); it.jump(); + } else if (isStartPosixGroup(it)) { + final String s = readGroupPosix(it); + result.add(new ReToken(ReTokenType.CLASS, s)); } else if (current == '[') { final String s = readGroup(it); result.add(new ReToken(ReTokenType.GROUP, s)); } else if (isStartComment(it)) { skipComment(it); + } else if (isStartLookAhead(it)) { + final ReToken token = readLookAhead(it); + result.add(token); + result.add(new ReToken(ReTokenType.PARENTHESIS_OPEN, "(")); + } else if (isStartLookBehind(it)) { + final ReToken token = readLookBehind(it); + result.add(token); + result.add(new ReToken(ReTokenType.PARENTHESIS_OPEN, "(")); } else if (isStartNamedCapturingGroup(it)) { final ReToken token = readNamedGroup(it); result.add(token); @@ -102,6 +113,20 @@ public class RegexExpression { } + private static boolean isStartLookAhead(CharInspector it) { + final char current0 = it.peek(0); + if (current0 == '(' && it.peek(1) == '?' && (it.peek(2) == '=' || it.peek(2) == '!')) + return true; + return false; + } + + private static boolean isStartLookBehind(CharInspector it) { + final char current0 = it.peek(0); + if (current0 == '(' && it.peek(1) == '?' && it.peek(2) == '<' && (it.peek(3) == '=' || it.peek(3) == '!')) + return true; + return false; + } + private static boolean isStartOpenParenthesis(CharInspector it) { final char current0 = it.peek(0); if (current0 == '(') @@ -109,10 +134,28 @@ public class RegexExpression { return false; } + private static boolean isStartPosixGroup(CharInspector it) { + final char current0 = it.peek(0); + if (current0 == '[' && it.peek(1) == '[' && it.peek(2) == ':') + return true; + return false; + } + private static boolean isStartNamedCapturingGroup(CharInspector it) { final char current0 = it.peek(0); - if (current0 == '(' && it.peek(1) == '?' && it.peek(2) == '<') - return true; + if (current0 == '(' && it.peek(1) == '?' && it.peek(2) == '<') { + int i = 3; + while (it.peek(i) != 0) { + if (it.peek(i) == '>' && i == 3) + return false; + if (it.peek(i) == '>') + return true; + if (Character.isLetter(it.peek(i)) == false) + return false; + i++; + } + + } return false; } @@ -140,6 +183,23 @@ public class RegexExpression { } } + private static ReToken readLookAhead(CharInspector it) throws RegexParsingException { + it.jump(); + it.jump(); + final char ch = it.peek(0); + it.jump(); + return new ReToken(ReTokenType.LOOK_AHEAD, "?" + ch); + } + + private static ReToken readLookBehind(CharInspector it) throws RegexParsingException { + it.jump(); + it.jump(); + it.jump(); + final char ch = it.peek(0); + it.jump(); + return new ReToken(ReTokenType.LOOK_BEHIND, "?<" + ch); + } + private static ReToken readNamedGroup(CharInspector it) throws RegexParsingException { it.jump(); it.jump(); @@ -218,6 +278,23 @@ public class RegexExpression { return false; } + private static String readGroupPosix(CharInspector it) { + it.jump(); + it.jump(); + it.jump(); + final StringBuilder result = new StringBuilder(":"); + while (it.peek(0) != 0) { + char ch = it.peek(0); + it.jump(); + result.append(ch); + if (ch == ':') + break; + } + it.jump(); + it.jump(); + return result.toString(); + } + private static String readGroup(CharInspector it) { final char current0 = it.peek(0); if (current0 != '[') diff --git a/src/net/sourceforge/plantuml/regexdiagram/ShuntingYard.java b/src/net/sourceforge/plantuml/regexdiagram/ShuntingYard.java index 8b45b6274..3749d771e 100644 --- a/src/net/sourceforge/plantuml/regexdiagram/ShuntingYard.java +++ b/src/net/sourceforge/plantuml/regexdiagram/ShuntingYard.java @@ -59,7 +59,7 @@ public class ShuntingYard { ouputQueue.add(token); } else if (token.getType() == ReTokenType.GROUP) { ouputQueue.add(token); - } else if (token.getType() == ReTokenType.NAMED_GROUP) { + } else if (token.getType().isNamedGroupOrLookAheadOrLookBehind()) { operatorStack.addFirst(token); } else if (token.getType() == ReTokenType.CLASS) { ouputQueue.add(token); @@ -82,10 +82,8 @@ public class ShuntingYard { && operatorStack.peekFirst().getType() != ReTokenType.PARENTHESIS_OPEN) ouputQueue.add(operatorStack.removeFirst()); final ReToken first = operatorStack.removeFirst(); - if (operatorStack.peekFirst() != null - && operatorStack.peekFirst().getType() == ReTokenType.NAMED_GROUP) + if (operatorStack.peekFirst() != null && operatorStack.peekFirst().getType().isNamedGroupOrLookAheadOrLookBehind()) ouputQueue.add(operatorStack.removeFirst()); - } else { throw new UnsupportedOperationException(token.toString()); diff --git a/src/net/sourceforge/plantuml/version/Version.java b/src/net/sourceforge/plantuml/version/Version.java index 05f088d68..fa4a80d68 100644 --- a/src/net/sourceforge/plantuml/version/Version.java +++ b/src/net/sourceforge/plantuml/version/Version.java @@ -46,7 +46,7 @@ public class Version { // Warning, "version" should be the same in gradle.properties and Version.java // Any idea anyone how to magically synchronize those :-) ? - private static final String version = "1.2023.14beta1"; + private static final String version = "1.2023.14beta2"; public static String versionString() { return version;