mirror of
https://github.com/octoleo/plantuml.git
synced 2024-12-22 10:59:01 +00:00
version 1.2020.2
This commit is contained in:
parent
3a156f1ff4
commit
7a5b515bf6
2
pom.xml
2
pom.xml
@ -35,7 +35,7 @@
|
||||
|
||||
<groupId>net.sourceforge.plantuml</groupId>
|
||||
<artifactId>plantuml</artifactId>
|
||||
<version>1.2020.2-SNAPSHOT</version>
|
||||
<version>1.2020.3-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>PlantUML</name>
|
||||
|
@ -36,6 +36,7 @@
|
||||
package net.sourceforge.plantuml;
|
||||
|
||||
import net.sourceforge.plantuml.command.regex.FoxSignature;
|
||||
import net.sourceforge.plantuml.tim.TLineType;
|
||||
|
||||
final public class StringLocated {
|
||||
|
||||
@ -43,6 +44,10 @@ final public class StringLocated {
|
||||
private final LineLocation location;
|
||||
private final String preprocessorError;
|
||||
|
||||
private StringLocated trimmed;
|
||||
private long fox = -1;
|
||||
private TLineType type;
|
||||
|
||||
public StringLocated(String s, LineLocation location) {
|
||||
this(s, location, null);
|
||||
}
|
||||
@ -76,12 +81,14 @@ final public class StringLocated {
|
||||
return new StringLocated(s, location, preprocessorError);
|
||||
}
|
||||
|
||||
public StringLocated sub(int start, int end) {
|
||||
public StringLocated substring(int start, int end) {
|
||||
return new StringLocated(this.getString().substring(start, end), this.getLocation(),
|
||||
this.getPreprocessorError());
|
||||
}
|
||||
|
||||
private StringLocated trimmed;
|
||||
public StringLocated substring(int start) {
|
||||
return new StringLocated(this.getString().substring(start), this.getLocation(), this.getPreprocessorError());
|
||||
}
|
||||
|
||||
public StringLocated getTrimmed() {
|
||||
if (trimmed == null) {
|
||||
@ -134,8 +141,6 @@ final public class StringLocated {
|
||||
return preprocessorError;
|
||||
}
|
||||
|
||||
private long fox = -1;
|
||||
|
||||
public long getFoxSignature() {
|
||||
if (fox == -1) {
|
||||
fox = FoxSignature.getFoxSignature(getString());
|
||||
@ -143,4 +148,11 @@ final public class StringLocated {
|
||||
return fox;
|
||||
}
|
||||
|
||||
public TLineType getType() {
|
||||
if (type == null) {
|
||||
type = TLineType.getFromLineInternal(s);
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -334,6 +334,9 @@ public class StringUtils {
|
||||
if (uml.startsWith("@startuml\nauthor\n")) {
|
||||
return false;
|
||||
}
|
||||
if (uml.startsWith("@startuml\ndonors\n")) {
|
||||
return false;
|
||||
}
|
||||
if (uml.startsWith("@startuml\ncheckversion")) {
|
||||
return false;
|
||||
}
|
||||
@ -343,6 +346,9 @@ public class StringUtils {
|
||||
if (uml.startsWith("@startuml\nsudoku\n")) {
|
||||
return false;
|
||||
}
|
||||
if (uml.startsWith("@startuml\nstdlib\n")) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -38,8 +38,9 @@ package net.sourceforge.plantuml;
|
||||
import java.util.Comparator;
|
||||
|
||||
import net.sourceforge.plantuml.cucadiagram.dot.DotMaker2;
|
||||
import net.sourceforge.plantuml.project.lang.Complement;
|
||||
|
||||
public class Url implements EnsureVisible {
|
||||
public class Url implements EnsureVisible, Complement {
|
||||
|
||||
private final String url;
|
||||
private final String tooltip;
|
||||
|
@ -194,7 +194,7 @@ public class BlocLines implements Iterable<StringLocated> {
|
||||
for (int i = 0; i < copy.size(); i++) {
|
||||
final StringLocated s = copy.get(i);
|
||||
if (s.getString().length() > 0) {
|
||||
copy.set(i, s.sub(1, s.getString().length()));
|
||||
copy.set(i, s.substring(1, s.getString().length()));
|
||||
}
|
||||
}
|
||||
} while (firstColumnRemovable(copy));
|
||||
@ -229,7 +229,7 @@ public class BlocLines implements Iterable<StringLocated> {
|
||||
copy.set(0, new StringLocated(data, null));
|
||||
final int n = copy.size() - 1;
|
||||
final StringLocated s = copy.get(n);
|
||||
copy.set(n, s.sub(0, s.getString().length() - 1));
|
||||
copy.set(n, s.substring(0, s.getString().length() - 1));
|
||||
return new BlocLines(copy);
|
||||
}
|
||||
|
||||
@ -278,7 +278,7 @@ public class BlocLines implements Iterable<StringLocated> {
|
||||
if (i == 0) {
|
||||
return arg;
|
||||
}
|
||||
return arg.sub(i, arg.getString().length());
|
||||
return arg.substring(i, arg.getString().length());
|
||||
}
|
||||
|
||||
public BlocLines subExtract(int margeStart, int margeEnd) {
|
||||
|
@ -71,6 +71,7 @@ import net.sourceforge.plantuml.graphic.TextBlockUtils;
|
||||
import net.sourceforge.plantuml.graphic.VerticalAlignment;
|
||||
import net.sourceforge.plantuml.sequencediagram.MessageNumber;
|
||||
import net.sourceforge.plantuml.skin.VisibilityModifier;
|
||||
import net.sourceforge.plantuml.style.PName;
|
||||
import net.sourceforge.plantuml.style.Style;
|
||||
import net.sourceforge.plantuml.ugraphic.UFont;
|
||||
import net.sourceforge.plantuml.ugraphic.UStroke;
|
||||
@ -84,7 +85,11 @@ public class Display implements Iterable<CharSequence> {
|
||||
|
||||
public final static Display NULL = new Display(null, null, true, CreoleMode.FULL);
|
||||
|
||||
public Display withoutStereotype(Style usedStyle) {
|
||||
public Display withoutStereotypeIfNeeded(Style usedStyle) {
|
||||
final boolean showStereotype = usedStyle.value(PName.ShowStereotype).asBoolean();
|
||||
if (showStereotype) {
|
||||
return this;
|
||||
}
|
||||
final List<CharSequence> copy = new ArrayList<CharSequence>(displayData);
|
||||
final Display result = new Display(naturalHorizontalAlignment, isNull, defaultCreoleMode);
|
||||
for (Iterator<CharSequence> it = copy.iterator(); it.hasNext();) {
|
||||
@ -441,8 +446,8 @@ public class Display implements Iterable<CharSequence> {
|
||||
|
||||
public TextBlock create(FontConfiguration fontConfiguration, HorizontalAlignment horizontalAlignment,
|
||||
ISkinSimple spriteContainer, CreoleMode creoleMode) {
|
||||
return create(fontConfiguration, horizontalAlignment, spriteContainer, LineBreakStrategy.NONE, creoleMode,
|
||||
null, null);
|
||||
return create(fontConfiguration, horizontalAlignment, spriteContainer, LineBreakStrategy.NONE, creoleMode, null,
|
||||
null);
|
||||
}
|
||||
|
||||
public TextBlock create(FontConfiguration fontConfiguration, HorizontalAlignment horizontalAlignment,
|
||||
@ -513,15 +518,15 @@ public class Display implements Iterable<CharSequence> {
|
||||
FontConfiguration stereotypeConfiguration) {
|
||||
final Sheet sheet = new CreoleParser(fontConfiguration, horizontalAlignment, spriteContainer, creoleMode,
|
||||
stereotypeConfiguration).createSheet(this);
|
||||
final SheetBlock1 sheetBlock1 = new SheetBlock1(sheet, maxMessageSize, spriteContainer == null ? 0
|
||||
: spriteContainer.getPadding());
|
||||
final SheetBlock1 sheetBlock1 = new SheetBlock1(sheet, maxMessageSize,
|
||||
spriteContainer == null ? 0 : spriteContainer.getPadding());
|
||||
return new SheetBlock2(sheetBlock1, sheetBlock1, new UStroke(1.5));
|
||||
}
|
||||
|
||||
private TextBlock createMessageNumber(FontConfiguration fontConfiguration, HorizontalAlignment horizontalAlignment,
|
||||
ISkinSimple spriteContainer, LineBreakStrategy maxMessageSize, FontConfiguration stereotypeConfiguration) {
|
||||
TextBlock tb1 = subList(0, 1).getCreole(fontConfiguration, horizontalAlignment, spriteContainer,
|
||||
maxMessageSize, CreoleMode.FULL, stereotypeConfiguration);
|
||||
TextBlock tb1 = subList(0, 1).getCreole(fontConfiguration, horizontalAlignment, spriteContainer, maxMessageSize,
|
||||
CreoleMode.FULL, stereotypeConfiguration);
|
||||
tb1 = TextBlockUtils.withMargin(tb1, 0, 4, 0, 0);
|
||||
final TextBlock tb2 = subList(1, size()).getCreole(fontConfiguration, horizontalAlignment, spriteContainer,
|
||||
maxMessageSize, CreoleMode.FULL, stereotypeConfiguration);
|
||||
|
@ -71,24 +71,24 @@ public class PSystemDonors extends AbstractPSystem {
|
||||
private static final int COLS = 6;
|
||||
private static final int FREE_LINES = 6;
|
||||
|
||||
public static final String DONORS = "6qOA02mFU3XMJbc44wzsfuUeUc2VR6qyRpkVqESmi8ZJNK3y1jWxFUutqbz4LxhtJJEYBLjJd6SKnOAW"
|
||||
+ "nzlacc6RUtiWLXFpLN9dtkWNveKX2Mr8WEjmHyIdof0IVEycQbqbNzfRkOJbCk0By7OGIqNtNoPkJxUE"
|
||||
+ "2t6mGuLG3YdksVytfxRkNbM58LrMhTFH5Ih0gi0ZOdS_QdDfrCPtKvlUX09qAd45DrMLy7hZfYBDuAxZ"
|
||||
+ "N3gqw1GZpI8bNZUE43SwC_JKfF1ByaH6vZ_g1RJfNAufaJEXF4Q9HDTjVqVs7PG_BNb1H48ks2ImW4gE"
|
||||
+ "m0cANXinFY8oQEZgIMDihcRC4oyCAUZ4lloZKTIufsHw6bfyH5s1ahYlSG3Iatgqu6nXDA2i9rkCQ9Ag"
|
||||
+ "C_CbtByEorDwpJJS3nPHbhG9hYd8cz0JFk6hBfcSuwMeuIy_JVB8rmGQBbi6t9iEVOjhaqIvdMsQkVDf"
|
||||
+ "KssUqjdgQkD_DeVSDMNLyfjHH2D7SEzl2obON5e0FmAzD2SgoPzb7rd8Xd1jfHVITQvUkHeHBjcGgM9T"
|
||||
+ "_eWjh-d_wE9ocn7Bus2HpvwlCqt9G4jTYLo6lj3AvhRE5qfAK-FpoAEbupFXcgpPlUFqFihcDF-_RYip"
|
||||
+ "un80dPbY5dJze1YifjNmP0CHc1QwFUGcG5v0TPZSoiFg4R_E1mHlAYCHXGrAB-Hzi-MGYnGciBmxIdG0"
|
||||
+ "9ayfxU4Zve48HUs2daQLUgGiGh_TfATjsPYuJ_fWVzPW3FAOpjOu2Nyi18umpAf5ixvR-m8z1LUvNEPL"
|
||||
+ "Ty_Fgm3M5juBBbBz90DwfGKZ8hL6DFQzx99mQA0mYxFahI6-PrXZvQ7x1vpMeatCQ3CVCWsI6ybgfRSO"
|
||||
+ "tZKP_kOXgzcnMkGvi4V4PaWpenMyFveyKejBV4Hqi9mWMm0Ivk8LU_72dIjLkPoSRAvJcEgnMWiLyhla"
|
||||
+ "4rYgmCBJWxNo7i0piaUnSpZlbJKVZTUGuda1bNAOe2wTA7Ea56NQMY33rghrRBGEjf_gM31lurivAmw5"
|
||||
+ "jqrqrhX1mHGsdHAuqOYHA2SQ5NhPay80V_twbNfoKmSPl_QooJYriY6MGgMSByiNfw3nTWoj-rlqVzks"
|
||||
+ "lQsSF_zUDvkSUkFjAmNGSv0S_nxAhAEBajNzDFWRR9WCSC1AAjeuuSf3Isy5aXRinpk3gFFjZEQTd2ot"
|
||||
+ "f1QzSlvGsT_zoIm7LtF3YejwYdBu4gTiUsi45M_x_ZS6MpaC_4LKcPFXwgzUBICAnFOsuZoDVOzIt5cL"
|
||||
+ "11BCZii4pdxrqscQXupPHoYp7Yu2-Vc8T3c4XnRKqhGuJWHMnHdUUwTroOJ_9JU9kEgdh2tLGq_ZL6vg"
|
||||
+ "5sZuTYMA6qQ1uI9cny3uTfEJ5RZvfeTwgBOVwVGN4oSkAeRTtdDs0W00";
|
||||
public static final String DONORS = "6taA0AmEU9ELAujmujswMQFg3ojH8OBbUK9n65Z4qzs0-0FSEptkDz9VH5UwzqqpeYr_pV7pZA4O27ey"
|
||||
+ "VrqDs_nl3nxxgV8W-Ev2KDA92uXiAx7-a7f_TK3C5DrlcT3URXqNwk24ckSZ-BYouVtDS9vl6X-zz0nO"
|
||||
+ "GjLFqNtj_qrTPLrULOLPkblL-UWAbR5LkrbpkljHu8ues7Seq23Kc4vTN8T3LOUvTgAlJemGOEAT4tpR"
|
||||
+ "jPWLenuY9LKtjY0b1YDqjqdhb-GN6RN_g1VGfhrSKo9dGddC4ecksqg7znrqFolvvOW7Nx19O06L7E4J"
|
||||
+ "5Brjn934UT3GEPlHsCAHBKy2C6IWZNtuHr4SAPwIcMreaIIaG4dAjt40CYfrQn6pvSs0yfxHObYJXCxt"
|
||||
+ "Xt3VE4och3feU0Wi4Yof3Qefo9lG4pxLLrqoEET3KSLVVflairaCD2XR0kJDZBw5HvD4-Py-aFdyRbBR"
|
||||
+ "FAMnrNNC_puSYg8fiuRVz3PgEO9xVrb8mU920SeHwAK-KKb-Vyg-iH23S6sb5z8njrr9emYNR4YhM9UV"
|
||||
+ "Oearwz-wnCQcnRBSMBIF_nTyKpBG4YkHPEXjMlbaxNoXf6bglB_arT3vRc9Dtapl6Ar7wPpc_tV3Iise"
|
||||
+ "X85ETp7AT4EWs8o6QgXPc0XC2zqS2XCW3w3sDBdbJwilyMkV8FEc4ed8RRZqWB_-JAvouS9KhEds9cO0"
|
||||
+ "auUKUf8aBOXGrY7eIQ1K8sKH-XacBTEMZedxf0qUfysCWH_LCSL9-6aXS7N3l9etMxkspp5RS8FlPJvr"
|
||||
+ "7zAuYkTqS-zv5wdv6mpeBIte4QanejZtial2LGCbihXB7XhYkuSTN3nqtu8pMRI16MsEGsP2vLeoQkaj"
|
||||
+ "HXcQTBubapNjrLPK6X1U7EFWZenEy7WZUQGMbqZYPZ2325i0qlhY4xiauSw4gbjkTZRN5gODNxq8BS7l"
|
||||
+ "Kfd0KeKNdYxiwEv-SKPZ5DadvhqoUsayfXGV2wYIKmLLQQFqcLBaQMiP6JBMe6Uz3R3BgMuB-3O_rR1E"
|
||||
+ "ABojejCM6tIRGeQhX6yqYYTg5UqQkDYaC82lUNaAdZRMGSPtUbb7722RIq885Lfp-0UdfR7w22rblKN_"
|
||||
+ "jstRoyhvy-zrP0MdddZcLGNG8qZpVpzble15h-jx6_fMvLCUs06pnP0UR2rM7b1w9v3KO1-biugwDCs8"
|
||||
+ "htX7kKLjqSgF3vN_wNIFM4m7tx3yefeYdxx4QRQzD9nAqdtV5ukJ73R-AQhCokIgrAg94Tt4Te_YF8sT"
|
||||
+ "Podkkde54lIEImNkdhhUJjDyIf_p1QM7uOeXFn-H8PlghWMra9RZjC0sSTRtPhOXcUf_IGy-2RLrdDN3"
|
||||
+ "qC7sRt8NQFRjJMxS40K6HVo1WNtsc9CJ5CSR0kt6r1rfkPYoSz4ztIuMhB7Vz8_8ieG_B6kLYJ3NowrO" + "B0lnh6sq0m00";
|
||||
|
||||
/*
|
||||
* Special thanks to our sponsors and donors:
|
||||
|
@ -221,11 +221,11 @@ public abstract class PSystemError extends AbstractPSystem {
|
||||
}
|
||||
final int min = (int) (System.currentTimeMillis() / 60000L) % 60;
|
||||
// udrawable = addMessageAdopt(udrawable);
|
||||
if (min == 1 || min == 8) {
|
||||
if (min == 1 || min == 8 || min == 13 || min == 55) {
|
||||
udrawable = addMessagePatreon(udrawable);
|
||||
} else if (min == 15) {
|
||||
udrawable = addMessageLiberapay(udrawable);
|
||||
} else if (min == 30) {
|
||||
} else if (min == 30 || min == 39 || min == 48) {
|
||||
udrawable = addMessageDedication(udrawable);
|
||||
} else if (getSource().containsIgnoreCase("arecibo")) {
|
||||
udrawable = addMessageArecibo(udrawable);
|
||||
|
@ -244,7 +244,10 @@ public class QuoteUtils {
|
||||
"Obhagl Uhagvat vf n pbzcyvpngrq cebsrffvba.",
|
||||
"Znahsnpghere'f cebgbpby qvpgngrf V pna abg or pncgherq. V zhfg frys-qrfgehpg.", "Snvyher vf abg na bcgvba",
|
||||
"Rirelguvat snvyf nyy gur gvzr", "Gur orfg jnl gb nibvq snvyher vf gb snvy pbafgnagyl",
|
||||
"Cerzngher bcgvzvmngvba vf gur ebbg bs nyy rivy", "Chgnva, w'ra nv zneer q'nibve gbhwbhef envfba");
|
||||
"Cerzngher bcgvzvmngvba vf gur ebbg bs nyy rivy", "Chgnva, w'ra nv zneer q'nibve gbhwbhef envfba",
|
||||
"Guvf vf gur jnl", "Cngvrapr lbh zhfg unir zl lbhat cnqnjna", "V gubhtug lbh jrer ba zl fvqr",
|
||||
"Qba'g cnavp. Abar bs lbh cnavp. Nofbyhgryl ab ernfba gb cnavp.",
|
||||
"Gung jnf hacyrnfnag. V'z fbeel lbh unq gb frr gung.", "Gur neg bs fvzcyvpvgl vf n chmmyr bs pbzcyrkvgl.");
|
||||
|
||||
private QuoteUtils() {
|
||||
}
|
||||
|
@ -42,7 +42,6 @@ import java.util.regex.Pattern;
|
||||
|
||||
import net.sourceforge.plantuml.AParentFolder;
|
||||
import net.sourceforge.plantuml.BackSlash;
|
||||
import net.sourceforge.plantuml.tim.TVariable;
|
||||
import net.sourceforge.plantuml.tim.expression.TValue;
|
||||
|
||||
public class Define {
|
||||
@ -124,7 +123,7 @@ public class Define {
|
||||
return signature.getFonctionName();
|
||||
}
|
||||
|
||||
public TVariable asTVariable() {
|
||||
return new TVariable(TValue.fromString(definition));
|
||||
public TValue asTVariable() {
|
||||
return TValue.fromString(definition);
|
||||
}
|
||||
}
|
||||
|
@ -46,11 +46,13 @@ import net.sourceforge.plantuml.tim.EaterStartsub;
|
||||
import net.sourceforge.plantuml.tim.TContext;
|
||||
import net.sourceforge.plantuml.tim.TLineType;
|
||||
import net.sourceforge.plantuml.tim.TMemory;
|
||||
import net.sourceforge.plantuml.tim.iterator.CodeIteratorImpl;
|
||||
|
||||
public class Sub {
|
||||
|
||||
private final String name;
|
||||
private final List<StringLocated> lines = new ArrayList<StringLocated>();
|
||||
// private boolean indentationDone = false;
|
||||
|
||||
public Sub(String name) {
|
||||
this.name = name;
|
||||
@ -62,37 +64,47 @@ public class Sub {
|
||||
}
|
||||
|
||||
public void add(StringLocated s) {
|
||||
// if (indentationDone) {
|
||||
// throw new IllegalStateException();
|
||||
// }
|
||||
this.lines.add(s);
|
||||
}
|
||||
|
||||
public final List<StringLocated> lines() {
|
||||
// if (indentationDone == false) {
|
||||
// CodeIteratorImpl.indentNow(lines);
|
||||
// indentationDone = true;
|
||||
// }
|
||||
return Collections.unmodifiableList(lines);
|
||||
}
|
||||
|
||||
public static Sub fromFile(ReadLine reader, String blocname, TContext context, TMemory memory) throws IOException,
|
||||
EaterException {
|
||||
public static Sub fromFile(ReadLine reader, String blocname, TContext context, TMemory memory)
|
||||
throws IOException, EaterException {
|
||||
Sub result = null;
|
||||
StringLocated s = null;
|
||||
boolean skip = false;
|
||||
while ((s = reader.readLine()) != null) {
|
||||
final TLineType type = TLineType.getFromLine(s.getTrimmed().getString());
|
||||
final TLineType type = s.getTrimmed().getType();
|
||||
if (type == TLineType.STARTSUB) {
|
||||
final EaterStartsub eater = new EaterStartsub(s.getTrimmed().getString());
|
||||
eater.execute(context, memory);
|
||||
final EaterStartsub eater = new EaterStartsub(s.getTrimmed());
|
||||
eater.analyze(context, memory);
|
||||
if (eater.getSubname().equals(blocname)) {
|
||||
result = new Sub(blocname);
|
||||
skip = false;
|
||||
if (result == null) {
|
||||
result = new Sub(blocname);
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (type == TLineType.ENDSUB && result != null) {
|
||||
reader.close();
|
||||
return result;
|
||||
skip = true;
|
||||
}
|
||||
if (result != null) {
|
||||
if (result != null && skip == false) {
|
||||
result.add(s);
|
||||
}
|
||||
}
|
||||
reader.close();
|
||||
return null;
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
@ -76,7 +76,7 @@ public class UncommentReadLine implements ReadLine {
|
||||
return new StringLocated("", result.getLocation());
|
||||
}
|
||||
if (headerToRemove != null && result.getString().startsWith(headerToRemove)) {
|
||||
return result.sub(headerToRemove.length(), result.getString().length());
|
||||
return result.substring(headerToRemove.length(), result.getString().length());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -128,7 +128,7 @@ public class PreprocessorUtils {
|
||||
return ReadLineReader.create(new InputStreamReader(is, charset), url.toString(), s.getLocation());
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
throw new EaterException("Cannot open URL");
|
||||
throw EaterException.located("Cannot open URL", s);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -35,6 +35,7 @@
|
||||
*/
|
||||
package net.sourceforge.plantuml.project.core;
|
||||
|
||||
import net.sourceforge.plantuml.Url;
|
||||
import net.sourceforge.plantuml.project.Load;
|
||||
import net.sourceforge.plantuml.project.draw.TaskDraw;
|
||||
import net.sourceforge.plantuml.project.lang.ComplementColors;
|
||||
@ -70,5 +71,7 @@ public interface Task extends Subject, Moment {
|
||||
|
||||
public void setCompletion(int completion);
|
||||
|
||||
public void setUrl(Url url);
|
||||
|
||||
|
||||
}
|
||||
|
@ -39,6 +39,7 @@ import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import net.sourceforge.plantuml.Url;
|
||||
import net.sourceforge.plantuml.project.Load;
|
||||
import net.sourceforge.plantuml.project.LoadPlanable;
|
||||
import net.sourceforge.plantuml.project.PlanUtils;
|
||||
@ -53,6 +54,14 @@ public class TaskImpl implements Task, LoadPlanable {
|
||||
private final Map<Resource, Integer> resources2 = new LinkedHashMap<Resource, Integer>();
|
||||
private final LoadPlanable defaultPlan;
|
||||
private boolean diamond;
|
||||
|
||||
private Url url;
|
||||
private TaskDraw taskDraw;
|
||||
private ComplementColors colors;
|
||||
|
||||
public void setUrl(Url url) {
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
public TaskImpl(TaskCode code, LoadPlanable defaultPlan) {
|
||||
this.code = code;
|
||||
@ -72,7 +81,8 @@ public class TaskImpl implements Task, LoadPlanable {
|
||||
}
|
||||
|
||||
public int loadForResource(Resource res, Wink instant) {
|
||||
if (resources2.keySet().contains(res) && instant.compareTo(getStart()) >= 0 && instant.compareTo(getEnd()) <= 0) {
|
||||
if (resources2.keySet().contains(res) && instant.compareTo(getStart()) >= 0
|
||||
&& instant.compareTo(getEnd()) <= 0) {
|
||||
if (res.isClosedAt(instant)) {
|
||||
return 0;
|
||||
}
|
||||
@ -172,11 +182,9 @@ public class TaskImpl implements Task, LoadPlanable {
|
||||
solver.setData(TaskAttribute.END, end);
|
||||
}
|
||||
|
||||
private TaskDraw taskDraw;
|
||||
private ComplementColors colors;
|
||||
|
||||
public void setTaskDraw(TaskDraw taskDraw) {
|
||||
taskDraw.setColorsAndCompletion(colors, completion);
|
||||
taskDraw.setColorsAndCompletion(colors, completion, url);
|
||||
this.taskDraw = taskDraw;
|
||||
}
|
||||
|
||||
@ -199,7 +207,7 @@ public class TaskImpl implements Task, LoadPlanable {
|
||||
public boolean isDiamond() {
|
||||
return this.diamond;
|
||||
}
|
||||
|
||||
|
||||
private int completion = 100;
|
||||
|
||||
public void setCompletion(int completion) {
|
||||
|
@ -35,6 +35,7 @@
|
||||
*/
|
||||
package net.sourceforge.plantuml.project.core;
|
||||
|
||||
import net.sourceforge.plantuml.Url;
|
||||
import net.sourceforge.plantuml.project.Load;
|
||||
import net.sourceforge.plantuml.project.draw.TaskDraw;
|
||||
import net.sourceforge.plantuml.project.lang.ComplementColors;
|
||||
@ -112,4 +113,8 @@ public class TaskSeparator implements Task {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public void setUrl(Url url) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -36,13 +36,14 @@
|
||||
package net.sourceforge.plantuml.project.draw;
|
||||
|
||||
import net.sourceforge.plantuml.Direction;
|
||||
import net.sourceforge.plantuml.Url;
|
||||
import net.sourceforge.plantuml.graphic.UDrawable;
|
||||
import net.sourceforge.plantuml.project.lang.ComplementColors;
|
||||
import net.sourceforge.plantuml.ugraphic.UGraphic;
|
||||
|
||||
public interface TaskDraw extends UDrawable {
|
||||
|
||||
public void setColorsAndCompletion(ComplementColors colors, int completion);
|
||||
public void setColorsAndCompletion(ComplementColors colors, int completion, Url url);
|
||||
|
||||
public double getY();
|
||||
|
||||
|
@ -37,6 +37,7 @@ package net.sourceforge.plantuml.project.draw;
|
||||
|
||||
import net.sourceforge.plantuml.Direction;
|
||||
import net.sourceforge.plantuml.SpriteContainerEmpty;
|
||||
import net.sourceforge.plantuml.Url;
|
||||
import net.sourceforge.plantuml.cucadiagram.Display;
|
||||
import net.sourceforge.plantuml.graphic.FontConfiguration;
|
||||
import net.sourceforge.plantuml.graphic.HorizontalAlignment;
|
||||
@ -66,6 +67,7 @@ public class TaskDrawRegular implements TaskDraw {
|
||||
private final double y;
|
||||
private ComplementColors colors;
|
||||
private int completion = 100;
|
||||
private Url url;
|
||||
|
||||
private final double margin = 2;
|
||||
|
||||
@ -125,22 +127,29 @@ public class TaskDrawRegular implements TaskDraw {
|
||||
if (fullLength < 10) {
|
||||
return;
|
||||
}
|
||||
if (url != null) {
|
||||
ug.startUrl(url);
|
||||
}
|
||||
final URectangle full = new URectangle(fullLength, getShapeHeight(), 8, 8);
|
||||
if (completion == 100) {
|
||||
ug.draw(full);
|
||||
return;
|
||||
} else {
|
||||
final double partialLength = fullLength * completion / 100.;
|
||||
ug.apply(new UChangeColor(HtmlColorUtils.WHITE)).apply(new UChangeBackColor(HtmlColorUtils.WHITE))
|
||||
.draw(full);
|
||||
if (partialLength > 2) {
|
||||
final URectangle partial = new URectangle(partialLength, getShapeHeight(), 8, 8);
|
||||
ug.apply(new UChangeColor(null)).draw(partial);
|
||||
}
|
||||
if (partialLength > 10 && partialLength < fullLength - 10) {
|
||||
final URectangle patch = new URectangle(8, getShapeHeight());
|
||||
ug.apply(new UChangeColor(null)).apply(new UTranslate(partialLength - 8, 0)).draw(patch);
|
||||
}
|
||||
ug.apply(new UChangeBackColor(null)).draw(full);
|
||||
}
|
||||
final double partialLength = fullLength * completion / 100.;
|
||||
ug.apply(new UChangeColor(HtmlColorUtils.WHITE)).apply(new UChangeBackColor(HtmlColorUtils.WHITE)).draw(full);
|
||||
if (partialLength > 2) {
|
||||
final URectangle partial = new URectangle(partialLength, getShapeHeight(), 8, 8);
|
||||
ug.apply(new UChangeColor(null)).draw(partial);
|
||||
if (url != null) {
|
||||
ug.closeAction();
|
||||
}
|
||||
if (partialLength > 10 && partialLength < fullLength - 10) {
|
||||
final URectangle patch = new URectangle(8, getShapeHeight());
|
||||
ug.apply(new UChangeColor(null)).apply(new UTranslate(partialLength - 8, 0)).draw(patch);
|
||||
}
|
||||
ug.apply(new UChangeBackColor(null)).draw(full);
|
||||
|
||||
}
|
||||
|
||||
@ -185,8 +194,9 @@ public class TaskDrawRegular implements TaskDraw {
|
||||
return y + getHeight() / 2;
|
||||
}
|
||||
|
||||
public void setColorsAndCompletion(ComplementColors colors, int completion) {
|
||||
public void setColorsAndCompletion(ComplementColors colors, int completion, Url url) {
|
||||
this.colors = colors;
|
||||
this.completion = completion;
|
||||
this.url = url;
|
||||
}
|
||||
}
|
||||
|
@ -37,6 +37,7 @@ package net.sourceforge.plantuml.project.draw;
|
||||
|
||||
import net.sourceforge.plantuml.Direction;
|
||||
import net.sourceforge.plantuml.SpriteContainerEmpty;
|
||||
import net.sourceforge.plantuml.Url;
|
||||
import net.sourceforge.plantuml.cucadiagram.Display;
|
||||
import net.sourceforge.plantuml.graphic.FontConfiguration;
|
||||
import net.sourceforge.plantuml.graphic.HorizontalAlignment;
|
||||
@ -126,7 +127,7 @@ public class TaskDrawSeparator implements TaskDraw {
|
||||
return y + getHeight() / 2;
|
||||
}
|
||||
|
||||
public void setColorsAndCompletion(ComplementColors colors, int completion) {
|
||||
public void setColorsAndCompletion(ComplementColors colors, int completion, Url url) {
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -48,7 +48,7 @@ public class ComplementBeforeOrAfterOrAtTaskStartOrEnd implements ComplementPatt
|
||||
|
||||
public IRegex toRegex(String suffix) {
|
||||
return new RegexLeaf("COMPLEMENT" + suffix,
|
||||
"(?:at|(\\d+)[%s]+days?[%s]+(before|after))[%s]+\\[([^\\[\\]]+?)\\].?s[%s]+(start|end)");
|
||||
"(?:at|with|after|(\\d+)[%s]+days?[%s]+(before|after))[%s]+\\[([^\\[\\]]+?)\\].?s[%s]+(start|end)");
|
||||
}
|
||||
|
||||
public Failable<Complement> getComplement(GanttDiagram system, RegexResult arg, String suffix) {
|
||||
|
62
src/net/sourceforge/plantuml/project/lang/ComplementUrl.java
Normal file
62
src/net/sourceforge/plantuml/project/lang/ComplementUrl.java
Normal file
@ -0,0 +1,62 @@
|
||||
/* ========================================================================
|
||||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* (C) Copyright 2009-2020, Arnaud Roques
|
||||
*
|
||||
* Project Info: http://plantuml.com
|
||||
*
|
||||
* If you like this project or if you find it useful, you can support us at:
|
||||
*
|
||||
* http://plantuml.com/patreon (only 1$ per month!)
|
||||
* http://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.project.lang;
|
||||
|
||||
import net.sourceforge.plantuml.Url;
|
||||
import net.sourceforge.plantuml.UrlBuilder;
|
||||
import net.sourceforge.plantuml.UrlBuilder.ModeUrl;
|
||||
import net.sourceforge.plantuml.command.regex.IRegex;
|
||||
import net.sourceforge.plantuml.command.regex.RegexConcat;
|
||||
import net.sourceforge.plantuml.command.regex.RegexLeaf;
|
||||
import net.sourceforge.plantuml.command.regex.RegexResult;
|
||||
import net.sourceforge.plantuml.project.Failable;
|
||||
import net.sourceforge.plantuml.project.GanttDiagram;
|
||||
|
||||
public class ComplementUrl implements ComplementPattern {
|
||||
|
||||
public IRegex toRegex(String suffix) {
|
||||
return new RegexConcat( //
|
||||
new RegexLeaf("COMPLEMENT" + suffix, "(" + UrlBuilder.getRegexp() + ")")); //
|
||||
}
|
||||
|
||||
public Failable<Complement> getComplement(GanttDiagram diagram, RegexResult arg, String suffix) {
|
||||
final String urlString = arg.get("COMPLEMENT" + suffix, 0);
|
||||
final UrlBuilder urlBuilder = new UrlBuilder("", ModeUrl.STRICT);
|
||||
final Url url = urlBuilder.getUrl(urlString);
|
||||
return Failable.<Complement>ok(url);
|
||||
}
|
||||
|
||||
}
|
@ -50,10 +50,9 @@ import net.sourceforge.plantuml.project.core.Task;
|
||||
public class SubjectTask implements SubjectPattern {
|
||||
|
||||
public Collection<VerbPattern> getVerbs() {
|
||||
return Arrays
|
||||
.<VerbPattern> asList(new VerbLasts(), new VerbTaskStarts(), new VerbTaskStartsAbsolute(),
|
||||
new VerbHappens(), new VerbEnds(), new VerbTaskEndsAbsolute(), new VerbIsColored(),
|
||||
new VerbIsDeleted(), new VerbIsForTask());
|
||||
return Arrays.<VerbPattern>asList(new VerbLasts(), new VerbTaskStarts(), new VerbTaskStartsAbsolute(),
|
||||
new VerbHappens(), new VerbEnds(), new VerbTaskEndsAbsolute(), new VerbIsColored(), new VerbIsDeleted(),
|
||||
new VerbIsForTask(), new VerbLinksTo());
|
||||
}
|
||||
|
||||
public IRegex toRegex() {
|
||||
|
70
src/net/sourceforge/plantuml/project/lang/VerbLinksTo.java
Normal file
70
src/net/sourceforge/plantuml/project/lang/VerbLinksTo.java
Normal file
@ -0,0 +1,70 @@
|
||||
/* ========================================================================
|
||||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* (C) Copyright 2009-2020, Arnaud Roques
|
||||
*
|
||||
* Project Info: http://plantuml.com
|
||||
*
|
||||
* If you like this project or if you find it useful, you can support us at:
|
||||
*
|
||||
* http://plantuml.com/patreon (only 1$ per month!)
|
||||
* http://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.project.lang;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
|
||||
import net.sourceforge.plantuml.Url;
|
||||
import net.sourceforge.plantuml.command.CommandExecutionResult;
|
||||
import net.sourceforge.plantuml.command.regex.IRegex;
|
||||
import net.sourceforge.plantuml.command.regex.RegexLeaf;
|
||||
import net.sourceforge.plantuml.command.regex.RegexResult;
|
||||
import net.sourceforge.plantuml.project.GanttDiagram;
|
||||
import net.sourceforge.plantuml.project.core.Task;
|
||||
|
||||
public class VerbLinksTo implements VerbPattern {
|
||||
|
||||
public Collection<ComplementPattern> getComplements() {
|
||||
return Arrays.<ComplementPattern>asList(new ComplementUrl());
|
||||
}
|
||||
|
||||
public IRegex toRegex() {
|
||||
return new RegexLeaf("links to");
|
||||
}
|
||||
|
||||
public Verb getVerb(GanttDiagram project, RegexResult arg) {
|
||||
return new Verb() {
|
||||
public CommandExecutionResult execute(Subject subject, Complement complement) {
|
||||
final Task task = (Task) subject;
|
||||
final Url url = (Url) complement;
|
||||
task.setUrl(url);
|
||||
return CommandExecutionResult.ok();
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
}
|
@ -67,8 +67,8 @@ abstract class CommandExoArrowAny extends SingleLineCommand2<SequenceDiagram> {
|
||||
final protected CommandExecutionResult executeArg(SequenceDiagram diagram, LineLocation location, RegexResult arg) {
|
||||
final String body = arg.getLazzy("ARROW_BODYA", 0) + arg.getLazzy("ARROW_BODYB", 0);
|
||||
final String dressing = arg.getLazzy("ARROW_DRESSING", 0);
|
||||
final Participant p = diagram.getOrCreateParticipant(StringUtils
|
||||
.eventuallyRemoveStartingAndEndingDoubleQuote(arg.get("PARTICIPANT", 0)));
|
||||
final Participant p = diagram.getOrCreateParticipant(
|
||||
StringUtils.eventuallyRemoveStartingAndEndingDoubleQuote(arg.get("PARTICIPANT", 0)));
|
||||
|
||||
final boolean sync = dressing.length() == 2;
|
||||
final boolean dotted = body.contains("--");
|
||||
@ -82,25 +82,25 @@ abstract class CommandExoArrowAny extends SingleLineCommand2<SequenceDiagram> {
|
||||
|
||||
final boolean bothDirection = arg.get("ARROW_BOTHDRESSING", 0) != null;
|
||||
|
||||
ArrowConfiguration config = bothDirection ? ArrowConfiguration.withDirectionBoth() : ArrowConfiguration
|
||||
.withDirectionNormal();
|
||||
ArrowConfiguration config = bothDirection ? ArrowConfiguration.withDirectionBoth()
|
||||
: ArrowConfiguration.withDirectionNormal();
|
||||
if (dotted) {
|
||||
config = config.withBody(ArrowBody.DOTTED);
|
||||
}
|
||||
if (sync) {
|
||||
config = config.withHead(ArrowHead.ASYNC);
|
||||
}
|
||||
config = config.withPart(getArrowPart(dressing));
|
||||
final MessageExoType messageExoType = getMessageExoType(arg);
|
||||
|
||||
config = config.withPart(getArrowPart(dressing, messageExoType));
|
||||
config = CommandArrow.applyStyle(arg.getLazzy("ARROW_STYLE", 0), config);
|
||||
|
||||
|
||||
final String activationSpec = arg.get("ACTIVATION", 0);
|
||||
|
||||
if (activationSpec != null && activationSpec.charAt(0) == '*') {
|
||||
diagram.activate(p, LifeEventType.CREATE, null);
|
||||
}
|
||||
|
||||
final MessageExoType messageExoType = getMessageExoType(arg);
|
||||
|
||||
if (messageExoType == MessageExoType.TO_RIGHT || messageExoType == MessageExoType.TO_LEFT) {
|
||||
if (containsSymbolExterior(arg, "o")) {
|
||||
config = config.withDecoration2(ArrowDecoration.CIRCLE);
|
||||
@ -178,12 +178,18 @@ abstract class CommandExoArrowAny extends SingleLineCommand2<SequenceDiagram> {
|
||||
return CommandExecutionResult.ok();
|
||||
}
|
||||
|
||||
private ArrowPart getArrowPart(String dressing) {
|
||||
private ArrowPart getArrowPart(String dressing, MessageExoType messageExoType) {
|
||||
if (dressing.contains("/")) {
|
||||
return ArrowPart.BOTTOM_PART;
|
||||
if (messageExoType.getDirection() == 1) {
|
||||
return ArrowPart.BOTTOM_PART;
|
||||
}
|
||||
return ArrowPart.TOP_PART;
|
||||
}
|
||||
if (dressing.contains("\\")) {
|
||||
return ArrowPart.TOP_PART;
|
||||
if (messageExoType.getDirection() == 1) {
|
||||
return ArrowPart.TOP_PART;
|
||||
}
|
||||
return ArrowPart.BOTTOM_PART;
|
||||
}
|
||||
return ArrowPart.FULL;
|
||||
}
|
||||
|
@ -118,7 +118,9 @@ public class PlayingSpace implements Bordered {
|
||||
for (LinkAnchor linkAnchor : linkAnchors) {
|
||||
final YPositionedTile tile1 = getFromAnchor(positionedTiles, linkAnchor.getAnchor1());
|
||||
final YPositionedTile tile2 = getFromAnchor(positionedTiles, linkAnchor.getAnchor2());
|
||||
linkAnchor.drawAnchor(ug, tile1, tile2, skinParam);
|
||||
if (tile1 != null && tile2 != null) {
|
||||
linkAnchor.drawAnchor(ug, tile1, tile2, skinParam);
|
||||
}
|
||||
}
|
||||
// System.err.println("MainTile::drawUInternal finalY=" + y);
|
||||
return y;
|
||||
|
@ -97,7 +97,7 @@ public abstract class AbstractTextualComponent extends AbstractComponent {
|
||||
horizontalAlignment = style.getHorizontalAlignment();
|
||||
fontForStereotype = stereo.getUFont();
|
||||
htmlColorForStereotype = stereo.value(PName.FontColor).asColor(getIHtmlColorSet());
|
||||
this.display = display.withoutStereotype(style);
|
||||
this.display = display.withoutStereotypeIfNeeded(style);
|
||||
} else {
|
||||
this.font = fc.getFont();
|
||||
this.fontColor = fc.getColor();
|
||||
|
@ -55,6 +55,7 @@ public enum PName {
|
||||
ExportedName, //
|
||||
Image, //
|
||||
HorizontalAlignment, //
|
||||
ShowStereotype, //
|
||||
ImagePosition;
|
||||
|
||||
public static PName getFromName(String name) {
|
||||
|
@ -49,6 +49,8 @@ public interface Value {
|
||||
|
||||
public double asDouble();
|
||||
|
||||
public boolean asBoolean();
|
||||
|
||||
public int asFontStyle();
|
||||
|
||||
public HorizontalAlignment asHorizontalAlignment();
|
||||
|
@ -57,6 +57,10 @@ public abstract class ValueAbstract implements Value {
|
||||
throw new UnsupportedOperationException("Class=" + getClass());
|
||||
}
|
||||
|
||||
public boolean asBoolean() {
|
||||
throw new UnsupportedOperationException("Class=" + getClass());
|
||||
}
|
||||
|
||||
public int asFontStyle() {
|
||||
throw new UnsupportedOperationException("Class=" + getClass());
|
||||
}
|
||||
|
@ -67,6 +67,10 @@ public class ValueImpl implements Value {
|
||||
return set.getColorIfValid(value);
|
||||
}
|
||||
|
||||
public boolean asBoolean() {
|
||||
return "true".equalsIgnoreCase(value);
|
||||
}
|
||||
|
||||
public int asInt() {
|
||||
return Integer.parseInt(value);
|
||||
}
|
||||
|
@ -59,6 +59,11 @@ public class ValueNull extends ValueAbstract implements Value {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean asBoolean() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String asString() {
|
||||
return "";
|
||||
|
@ -50,12 +50,28 @@ public abstract class Eater {
|
||||
|
||||
private int i = 0;
|
||||
private final String s;
|
||||
private final StringLocated sl;
|
||||
|
||||
public Eater(String s) {
|
||||
this.s = s;
|
||||
public Eater(StringLocated sl) {
|
||||
this.s = sl.getString();
|
||||
this.sl = sl;
|
||||
}
|
||||
|
||||
public abstract void execute(TContext context, TMemory memory) throws EaterException;
|
||||
public final StringLocated getStringLocated() {
|
||||
if (sl == null) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
return sl;
|
||||
}
|
||||
|
||||
public final LineLocation getLineLocation() {
|
||||
if (sl == null) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
return sl.getLocation();
|
||||
}
|
||||
|
||||
public abstract void analyze(TContext context, TMemory memory) throws EaterException, EaterExceptionLocated;
|
||||
|
||||
public int getCurrentPosition() {
|
||||
return i;
|
||||
@ -67,26 +83,31 @@ public abstract class Eater {
|
||||
return result;
|
||||
}
|
||||
|
||||
final protected TValue eatExpression(TContext context, TMemory memory) throws EaterException {
|
||||
final protected TValue eatExpression(TContext context, TMemory memory) throws EaterException, EaterExceptionLocated {
|
||||
if (peekChar() == '{') {
|
||||
String data = eatAllToEnd();
|
||||
System.err.println("data=" + data);
|
||||
JsonValue json = Json.parse(data);
|
||||
System.err.println("json=" + json);
|
||||
// System.err.println("data=" + data);
|
||||
final JsonValue json = Json.parse(data);
|
||||
// System.err.println("json=" + json);
|
||||
return TValue.fromJson(json);
|
||||
}
|
||||
final TokenStack tokenStack = eatTokenStack();
|
||||
return tokenStack.getResult(getLineLocation(), context, memory);
|
||||
}
|
||||
|
||||
final protected TokenStack eatTokenStack() throws EaterException {
|
||||
final TokenStack tokenStack = new TokenStack();
|
||||
addIntoTokenStack(tokenStack, false);
|
||||
if (tokenStack.size() == 0) {
|
||||
throw new EaterException("Missing expression");
|
||||
throw EaterException.located("Missing expression", getStringLocated());
|
||||
}
|
||||
return tokenStack.getResult(context, memory);
|
||||
return tokenStack;
|
||||
}
|
||||
|
||||
final protected TValue eatExpressionStopAtColon(TContext context, TMemory memory) throws EaterException {
|
||||
final protected TValue eatExpressionStopAtColon(TContext context, TMemory memory) throws EaterException, EaterExceptionLocated {
|
||||
final TokenStack tokenStack = new TokenStack();
|
||||
addIntoTokenStack(tokenStack, true);
|
||||
return tokenStack.getResult(context, memory);
|
||||
return tokenStack.getResult(getLineLocation(), context, memory);
|
||||
}
|
||||
|
||||
final protected void addIntoTokenStack(TokenStack tokenStack, boolean stopAtColon) throws EaterException {
|
||||
@ -103,7 +124,7 @@ public abstract class Eater {
|
||||
final public String eatAndGetQuotedString() throws EaterException {
|
||||
final char separator = peekChar();
|
||||
if (TLineType.isQuote(separator) == false) {
|
||||
throw new EaterException("quote10");
|
||||
throw EaterException.located("quote10", getStringLocated());
|
||||
}
|
||||
checkAndEatChar(separator);
|
||||
final StringBuilder value = new StringBuilder();
|
||||
@ -124,7 +145,7 @@ public abstract class Eater {
|
||||
while (true) {
|
||||
char ch = peekChar();
|
||||
if (ch == 0) {
|
||||
throw new EaterException("until001");
|
||||
throw EaterException.located("until001", getStringLocated());
|
||||
}
|
||||
if (level == 0 && (ch == ',' || ch == ')')) {
|
||||
return value.toString().trim();
|
||||
@ -167,7 +188,7 @@ public abstract class Eater {
|
||||
final protected String eatAndGetVarname() throws EaterException {
|
||||
final StringBuilder varname = new StringBuilder("" + eatOneChar());
|
||||
if (TLineType.isLetterOrUnderscoreOrDollar(varname.charAt(0)) == false) {
|
||||
throw new EaterException("a002");
|
||||
throw EaterException.located("a002", getStringLocated());
|
||||
}
|
||||
addUpToLastLetterOrUnderscoreOrDigit(varname);
|
||||
return varname.toString();
|
||||
@ -176,7 +197,7 @@ public abstract class Eater {
|
||||
final protected String eatAndGetFunctionName() throws EaterException {
|
||||
final StringBuilder varname = new StringBuilder("" + eatOneChar());
|
||||
if (TLineType.isLetterOrUnderscoreOrDollar(varname.charAt(0)) == false) {
|
||||
throw new EaterException("a003");
|
||||
throw EaterException.located("a003", getStringLocated());
|
||||
}
|
||||
addUpToLastLetterOrUnderscoreOrDigit(varname);
|
||||
return varname.toString();
|
||||
@ -220,7 +241,7 @@ public abstract class Eater {
|
||||
|
||||
final protected void checkAndEatChar(char ch) throws EaterException {
|
||||
if (i >= s.length() || s.charAt(i) != ch) {
|
||||
throw new EaterException("a001");
|
||||
throw EaterException.located("a001", getStringLocated());
|
||||
}
|
||||
i++;
|
||||
}
|
||||
@ -269,7 +290,8 @@ public abstract class Eater {
|
||||
}
|
||||
}
|
||||
|
||||
// final protected void addUpToUnused(char separator1, char separator2, StringBuilder sb) {
|
||||
// final protected void addUpToUnused(char separator1, char separator2,
|
||||
// StringBuilder sb) {
|
||||
// while (i < s.length()) {
|
||||
// final char ch = peekChar();
|
||||
// if (ch == separator1 || ch == separator2) {
|
||||
@ -281,7 +303,7 @@ public abstract class Eater {
|
||||
// }
|
||||
|
||||
final protected TFunctionImpl eatDeclareFunction(TContext context, TMemory memory, boolean unquoted,
|
||||
LineLocation location, boolean allowNoParenthesis) throws EaterException {
|
||||
LineLocation location, boolean allowNoParenthesis) throws EaterException, EaterExceptionLocated {
|
||||
final List<TFunctionArgument> args = new ArrayList<TFunctionArgument>();
|
||||
final String functionName = eatAndGetFunctionName();
|
||||
skipSpaces();
|
||||
@ -289,7 +311,7 @@ public abstract class Eater {
|
||||
if (allowNoParenthesis) {
|
||||
return new TFunctionImpl(functionName, args, unquoted);
|
||||
}
|
||||
throw new EaterException("Missing opening parenthesis");
|
||||
throw EaterException.located("Missing opening parenthesis", getStringLocated());
|
||||
}
|
||||
while (true) {
|
||||
skipSpaces();
|
||||
@ -302,7 +324,7 @@ public abstract class Eater {
|
||||
eatOneChar();
|
||||
final TokenStack def = TokenStack.eatUntilCloseParenthesisOrComma(this);
|
||||
def.guessFunctions();
|
||||
defValue = def.getResult(context, memory);
|
||||
defValue = def.getResult(getLineLocation(), context, memory);
|
||||
// System.err.println("result=" + defValue);
|
||||
} else {
|
||||
defValue = null;
|
||||
@ -314,7 +336,7 @@ public abstract class Eater {
|
||||
checkAndEatChar(")");
|
||||
break;
|
||||
} else {
|
||||
throw new EaterException("Error in function definition");
|
||||
throw EaterException.located("Error in function definition", getStringLocated());
|
||||
}
|
||||
}
|
||||
skipSpaces();
|
||||
@ -322,7 +344,7 @@ public abstract class Eater {
|
||||
}
|
||||
|
||||
final protected TFunctionImpl eatDeclareFunctionWithOptionalReturn(TContext context, TMemory memory,
|
||||
boolean unquoted, LineLocation location) throws EaterException {
|
||||
boolean unquoted, LineLocation location) throws EaterException, EaterExceptionLocated {
|
||||
final TFunctionImpl result = eatDeclareFunction(context, memory, unquoted, location, false);
|
||||
if (peekChar() == 'r') {
|
||||
checkAndEatChar("return");
|
||||
|
@ -34,16 +34,17 @@
|
||||
*/
|
||||
package net.sourceforge.plantuml.tim;
|
||||
|
||||
import net.sourceforge.plantuml.StringLocated;
|
||||
import net.sourceforge.plantuml.tim.expression.TValue;
|
||||
|
||||
public class EaterAffectation extends Eater {
|
||||
|
||||
public EaterAffectation(String s) {
|
||||
super(s);
|
||||
public EaterAffectation(StringLocated sl) {
|
||||
super(sl.getTrimmed());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(TContext context, TMemory memory) throws EaterException {
|
||||
public void analyze(TContext context, TMemory memory) throws EaterException, EaterExceptionLocated {
|
||||
skipSpaces();
|
||||
checkAndEatChar("!");
|
||||
skipSpaces();
|
||||
@ -58,7 +59,7 @@ public class EaterAffectation extends Eater {
|
||||
checkAndEatChar('=');
|
||||
skipSpaces();
|
||||
final TValue value = eatExpression(context, memory);
|
||||
memory.putVariable(varname, new TVariable(value), scope);
|
||||
memory.putVariable(varname, value, scope);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -34,28 +34,29 @@
|
||||
*/
|
||||
package net.sourceforge.plantuml.tim;
|
||||
|
||||
import net.sourceforge.plantuml.StringLocated;
|
||||
import net.sourceforge.plantuml.tim.expression.TValue;
|
||||
|
||||
public class EaterAffectationDefine extends Eater {
|
||||
|
||||
public EaterAffectationDefine(String s) {
|
||||
super(s);
|
||||
public EaterAffectationDefine(StringLocated s) {
|
||||
super(s.getTrimmed());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(TContext context, TMemory memory) throws EaterException {
|
||||
public void analyze(TContext context, TMemory memory) throws EaterException, EaterExceptionLocated {
|
||||
skipSpaces();
|
||||
checkAndEatChar("!define");
|
||||
skipSpaces();
|
||||
final String varname = eatAndGetVarname();
|
||||
skipSpaces();
|
||||
final String tmp = eatAllToEnd();
|
||||
final String tmp2 = context.applyFunctionsAndVariables(memory, tmp);
|
||||
final String tmp2 = context.applyFunctionsAndVariables(memory, getLineLocation(), tmp);
|
||||
final TValue value = TValue.fromString(tmp2);
|
||||
// if (memory instanceof TMemoryLocal) {
|
||||
// memory = ((TMemoryLocal) memory).getGlobalForInternalUseOnly();
|
||||
// }
|
||||
memory.putVariable(varname, new TVariable(value), TVariableScope.GLOBAL);
|
||||
memory.putVariable(varname, value, TVariableScope.GLOBAL);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -34,16 +34,17 @@
|
||||
*/
|
||||
package net.sourceforge.plantuml.tim;
|
||||
|
||||
import net.sourceforge.plantuml.StringLocated;
|
||||
import net.sourceforge.plantuml.tim.expression.TValue;
|
||||
|
||||
public class EaterAssert extends Eater {
|
||||
|
||||
public EaterAssert(String s) {
|
||||
public EaterAssert(StringLocated s) {
|
||||
super(s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(TContext context, TMemory memory) throws EaterException {
|
||||
public void analyze(TContext context, TMemory memory) throws EaterException, EaterExceptionLocated {
|
||||
skipSpaces();
|
||||
checkAndEatChar("!assert");
|
||||
skipSpaces();
|
||||
@ -54,9 +55,9 @@ public class EaterAssert extends Eater {
|
||||
if (ch == ':') {
|
||||
checkAndEatChar(':');
|
||||
final TValue message = eatExpression(context, memory);
|
||||
throw new EaterException("Assertion error : " + message.toString());
|
||||
throw EaterException.located("Assertion error : " + message.toString(), getStringLocated());
|
||||
}
|
||||
throw new EaterException("Assertion error");
|
||||
throw EaterException.located("Assertion error", getStringLocated());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -44,12 +44,12 @@ public class EaterDeclareFunction extends Eater {
|
||||
private boolean finalFlag;
|
||||
|
||||
public EaterDeclareFunction(StringLocated s) {
|
||||
super(s.getTrimmed().getString());
|
||||
super(s.getTrimmed());
|
||||
this.location = s.getLocation();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(TContext context, TMemory memory) throws EaterException {
|
||||
public void analyze(TContext context, TMemory memory) throws EaterException, EaterExceptionLocated {
|
||||
skipSpaces();
|
||||
checkAndEatChar("!");
|
||||
boolean unquoted = false;
|
||||
|
@ -34,14 +34,16 @@
|
||||
*/
|
||||
package net.sourceforge.plantuml.tim;
|
||||
|
||||
import net.sourceforge.plantuml.StringLocated;
|
||||
|
||||
public class EaterDumpMemory extends Eater {
|
||||
|
||||
public EaterDumpMemory(String s) {
|
||||
public EaterDumpMemory(StringLocated s) {
|
||||
super(s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(TContext context, TMemory memory) throws EaterException {
|
||||
public void analyze(TContext context, TMemory memory) throws EaterException {
|
||||
skipSpaces();
|
||||
checkAndEatChar("!dump_memory");
|
||||
skipSpaces();
|
||||
|
@ -34,18 +34,19 @@
|
||||
*/
|
||||
package net.sourceforge.plantuml.tim;
|
||||
|
||||
import net.sourceforge.plantuml.StringLocated;
|
||||
import net.sourceforge.plantuml.tim.expression.TValue;
|
||||
|
||||
public class EaterElseIf extends Eater {
|
||||
|
||||
private boolean booleanValue;
|
||||
|
||||
public EaterElseIf(String s) {
|
||||
public EaterElseIf(StringLocated s) {
|
||||
super(s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(TContext context, TMemory memory) throws EaterException {
|
||||
public void analyze(TContext context, TMemory memory) throws EaterException, EaterExceptionLocated {
|
||||
skipSpaces();
|
||||
checkAndEatChar("!elseif");
|
||||
skipSpaces();
|
||||
|
@ -39,23 +39,25 @@ import net.sourceforge.plantuml.StringLocated;
|
||||
public class EaterException extends Exception {
|
||||
|
||||
private final String message;
|
||||
private final StringLocated location;
|
||||
|
||||
public EaterException(String message, StringLocated location) {
|
||||
private EaterException(String message) {
|
||||
this.message = message;
|
||||
this.location = location;
|
||||
}
|
||||
|
||||
public EaterException(String message) {
|
||||
this(message, null);
|
||||
public static EaterException unlocated(String message) {
|
||||
return new EaterException(message);
|
||||
}
|
||||
|
||||
public static EaterException located(String message, StringLocated unused) {
|
||||
return new EaterException(message);
|
||||
}
|
||||
|
||||
public final String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public final StringLocated getLocation() {
|
||||
return location;
|
||||
public EaterExceptionLocated withLocation(StringLocated sl) {
|
||||
return EaterExceptionLocated.located(message, sl);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -34,32 +34,31 @@
|
||||
*/
|
||||
package net.sourceforge.plantuml.tim;
|
||||
|
||||
import java.util.Deque;
|
||||
import java.util.LinkedList;
|
||||
import net.sourceforge.plantuml.StringLocated;
|
||||
|
||||
public abstract class ConditionalContexts {
|
||||
public class EaterExceptionLocated extends Exception {
|
||||
|
||||
private final Deque<ConditionalContext> allIfs = new LinkedList<ConditionalContext>();
|
||||
private final String message;
|
||||
private final StringLocated location;
|
||||
|
||||
public ConditionalContext peekConditionalContext() {
|
||||
return allIfs.peekLast();
|
||||
private EaterExceptionLocated(String message, StringLocated location) {
|
||||
this.message = message;
|
||||
this.location = location;
|
||||
}
|
||||
|
||||
public void addConditionalContext(ConditionalContext fromValue) {
|
||||
allIfs.addLast(fromValue);
|
||||
}
|
||||
|
||||
public ConditionalContext pollConditionalContext() {
|
||||
return allIfs.pollLast();
|
||||
}
|
||||
|
||||
public boolean areAllIfOk() {
|
||||
for (ConditionalContext conditionalContext : allIfs) {
|
||||
if (conditionalContext.conditionIsOkHere() == false) {
|
||||
return false;
|
||||
}
|
||||
public static EaterExceptionLocated located(String message, StringLocated location) {
|
||||
if (location == null) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
return true;
|
||||
return new EaterExceptionLocated(message, location);
|
||||
}
|
||||
|
||||
public final String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public final StringLocated getLocation() {
|
||||
return location;
|
||||
}
|
||||
|
||||
}
|
78
src/net/sourceforge/plantuml/tim/EaterForeach.java
Normal file
78
src/net/sourceforge/plantuml/tim/EaterForeach.java
Normal file
@ -0,0 +1,78 @@
|
||||
/* ========================================================================
|
||||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* (C) Copyright 2009-2020, Arnaud Roques
|
||||
*
|
||||
* Project Info: http://plantuml.com
|
||||
*
|
||||
* If you like this project or if you find it useful, you can support us at:
|
||||
*
|
||||
* http://plantuml.com/patreon (only 1$ per month!)
|
||||
* http://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.tim;
|
||||
|
||||
import net.sourceforge.plantuml.StringLocated;
|
||||
import net.sourceforge.plantuml.json.JsonArray;
|
||||
import net.sourceforge.plantuml.tim.expression.TValue;
|
||||
|
||||
public class EaterForeach extends Eater {
|
||||
|
||||
private String varname;
|
||||
private JsonArray jsonArray;
|
||||
|
||||
public EaterForeach(StringLocated s) {
|
||||
super(s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void analyze(TContext context, TMemory memory) throws EaterException, EaterExceptionLocated {
|
||||
skipSpaces();
|
||||
checkAndEatChar("!foreach");
|
||||
skipSpaces();
|
||||
this.varname = eatAndGetVarname();
|
||||
skipSpaces();
|
||||
checkAndEatChar("in");
|
||||
skipSpaces();
|
||||
final TValue value = eatExpression(context, memory);
|
||||
this.jsonArray = (JsonArray) value.toJson();
|
||||
}
|
||||
|
||||
public boolean isSkip() {
|
||||
if (this.jsonArray == null) {
|
||||
return true;
|
||||
}
|
||||
return this.jsonArray.size() == 0;
|
||||
}
|
||||
|
||||
public final String getVarname() {
|
||||
return varname;
|
||||
}
|
||||
|
||||
public final JsonArray getJsonArray() {
|
||||
return jsonArray;
|
||||
}
|
||||
|
||||
}
|
@ -38,6 +38,7 @@ import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import net.sourceforge.plantuml.StringLocated;
|
||||
import net.sourceforge.plantuml.tim.expression.TValue;
|
||||
import net.sourceforge.plantuml.tim.expression.TokenStack;
|
||||
|
||||
@ -47,14 +48,14 @@ public class EaterFunctionCall extends Eater {
|
||||
private final boolean isLegacyDefine;
|
||||
private final boolean unquoted;
|
||||
|
||||
public EaterFunctionCall(String s, boolean isLegacyDefine, boolean unquoted) {
|
||||
public EaterFunctionCall(StringLocated s, boolean isLegacyDefine, boolean unquoted) {
|
||||
super(s);
|
||||
this.isLegacyDefine = isLegacyDefine;
|
||||
this.unquoted = unquoted;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(TContext context, TMemory memory) throws EaterException {
|
||||
public void analyze(TContext context, TMemory memory) throws EaterException, EaterExceptionLocated {
|
||||
skipUntilChar('(');
|
||||
checkAndEatChar('(');
|
||||
skipSpaces();
|
||||
@ -66,7 +67,7 @@ public class EaterFunctionCall extends Eater {
|
||||
skipSpaces();
|
||||
if (isLegacyDefine || unquoted) {
|
||||
final String tmp = eatAndGetOptionalQuotedString();
|
||||
final String tmp2 = context.applyFunctionsAndVariables(memory, tmp);
|
||||
final String tmp2 = context.applyFunctionsAndVariables(memory, getLineLocation(), tmp);
|
||||
// final TVariable var = memory.getVariable(tmp);
|
||||
// final TValue result = var == null ? TValue.fromString(tmp) : var.getValue2();
|
||||
final TValue result = TValue.fromString(tmp2);
|
||||
@ -74,7 +75,7 @@ public class EaterFunctionCall extends Eater {
|
||||
} else {
|
||||
final TokenStack tokens = TokenStack.eatUntilCloseParenthesisOrComma(this).withoutSpace();
|
||||
tokens.guessFunctions();
|
||||
final TValue result = tokens.getResult(context, memory);
|
||||
final TValue result = tokens.getResult(getLineLocation(), context, memory);
|
||||
values.add(result);
|
||||
}
|
||||
skipSpaces();
|
||||
@ -85,7 +86,7 @@ public class EaterFunctionCall extends Eater {
|
||||
if (ch == ')') {
|
||||
break;
|
||||
}
|
||||
throw new EaterException("call001");
|
||||
throw EaterException.located("call001", getStringLocated());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -34,18 +34,19 @@
|
||||
*/
|
||||
package net.sourceforge.plantuml.tim;
|
||||
|
||||
import net.sourceforge.plantuml.StringLocated;
|
||||
import net.sourceforge.plantuml.tim.expression.TValue;
|
||||
|
||||
public class EaterIf extends Eater {
|
||||
|
||||
private boolean booleanValue;
|
||||
|
||||
public EaterIf(String s) {
|
||||
public EaterIf(StringLocated s) {
|
||||
super(s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(TContext context, TMemory memory) throws EaterException {
|
||||
public void analyze(TContext context, TMemory memory) throws EaterException, EaterExceptionLocated {
|
||||
skipSpaces();
|
||||
checkAndEatChar("!if");
|
||||
skipSpaces();
|
||||
|
@ -34,19 +34,21 @@
|
||||
*/
|
||||
package net.sourceforge.plantuml.tim;
|
||||
|
||||
import net.sourceforge.plantuml.StringLocated;
|
||||
import net.sourceforge.plantuml.preproc.EvalBoolean;
|
||||
import net.sourceforge.plantuml.preproc.Truth;
|
||||
import net.sourceforge.plantuml.tim.expression.TValue;
|
||||
|
||||
public class EaterIfdef extends Eater {
|
||||
|
||||
private String expression;
|
||||
|
||||
public EaterIfdef(String s) {
|
||||
public EaterIfdef(StringLocated s) {
|
||||
super(s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(TContext context, TMemory memory) throws EaterException {
|
||||
public void analyze(TContext context, TMemory memory) throws EaterException {
|
||||
skipSpaces();
|
||||
checkAndEatChar("!ifdef");
|
||||
skipSpaces();
|
||||
@ -57,7 +59,7 @@ public class EaterIfdef extends Eater {
|
||||
final EvalBoolean eval = new EvalBoolean(expression, new Truth() {
|
||||
|
||||
public boolean isTrue(String varname) {
|
||||
final TVariable currentValue = memory.getVariable(varname);
|
||||
final TValue currentValue = memory.getVariable(varname);
|
||||
return currentValue != null || context.doesFunctionExist(varname);
|
||||
}
|
||||
});
|
||||
|
@ -34,16 +34,19 @@
|
||||
*/
|
||||
package net.sourceforge.plantuml.tim;
|
||||
|
||||
import net.sourceforge.plantuml.StringLocated;
|
||||
import net.sourceforge.plantuml.tim.expression.TValue;
|
||||
|
||||
public class EaterIfndef extends Eater {
|
||||
|
||||
private String varname;
|
||||
|
||||
public EaterIfndef(String s) {
|
||||
public EaterIfndef(StringLocated s) {
|
||||
super(s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(TContext context, TMemory memory) throws EaterException {
|
||||
public void analyze(TContext context, TMemory memory) throws EaterException {
|
||||
skipSpaces();
|
||||
checkAndEatChar("!ifndef");
|
||||
skipSpaces();
|
||||
@ -51,7 +54,7 @@ public class EaterIfndef extends Eater {
|
||||
}
|
||||
|
||||
public boolean isTrue(TContext context, TMemory memory) {
|
||||
final TVariable currentValue = memory.getVariable(varname);
|
||||
final TValue currentValue = memory.getVariable(varname);
|
||||
return currentValue == null && context.doesFunctionExist(varname) == false;
|
||||
}
|
||||
|
||||
|
@ -34,20 +34,22 @@
|
||||
*/
|
||||
package net.sourceforge.plantuml.tim;
|
||||
|
||||
import net.sourceforge.plantuml.StringLocated;
|
||||
|
||||
public class EaterImport extends Eater {
|
||||
|
||||
private String location;
|
||||
|
||||
public EaterImport(String s) {
|
||||
public EaterImport(StringLocated s) {
|
||||
super(s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(TContext context, TMemory memory) throws EaterException {
|
||||
public void analyze(TContext context, TMemory memory) throws EaterException, EaterExceptionLocated {
|
||||
skipSpaces();
|
||||
checkAndEatChar("!import");
|
||||
skipSpaces();
|
||||
this.location = context.applyFunctionsAndVariables(memory, this.eatAllToEnd());
|
||||
this.location = context.applyFunctionsAndVariables(memory, getLineLocation(), this.eatAllToEnd());
|
||||
|
||||
}
|
||||
|
||||
|
@ -34,6 +34,7 @@
|
||||
*/
|
||||
package net.sourceforge.plantuml.tim;
|
||||
|
||||
import net.sourceforge.plantuml.StringLocated;
|
||||
import net.sourceforge.plantuml.preproc2.PreprocessorIncludeStrategy;
|
||||
|
||||
public class EaterInclude extends Eater {
|
||||
@ -41,12 +42,12 @@ public class EaterInclude extends Eater {
|
||||
private String location;
|
||||
private PreprocessorIncludeStrategy strategy = PreprocessorIncludeStrategy.DEFAULT;
|
||||
|
||||
public EaterInclude(String s) {
|
||||
public EaterInclude(StringLocated s) {
|
||||
super(s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(TContext context, TMemory memory) throws EaterException {
|
||||
public void analyze(TContext context, TMemory memory) throws EaterException, EaterExceptionLocated {
|
||||
skipSpaces();
|
||||
checkAndEatChar("!include");
|
||||
final char peekChar = peekChar();
|
||||
@ -64,7 +65,7 @@ public class EaterInclude extends Eater {
|
||||
}
|
||||
}
|
||||
skipSpaces();
|
||||
this.location = context.applyFunctionsAndVariables(memory, this.eatAllToEnd());
|
||||
this.location = context.applyFunctionsAndVariables(memory, getLineLocation(), this.eatAllToEnd());
|
||||
|
||||
}
|
||||
|
||||
|
@ -34,21 +34,22 @@
|
||||
*/
|
||||
package net.sourceforge.plantuml.tim;
|
||||
|
||||
import net.sourceforge.plantuml.StringLocated;
|
||||
|
||||
public class EaterIncludeDef extends Eater {
|
||||
|
||||
private String location;
|
||||
|
||||
public EaterIncludeDef(String s) {
|
||||
public EaterIncludeDef(StringLocated s) {
|
||||
super(s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(TContext context, TMemory memory) throws EaterException {
|
||||
public void analyze(TContext context, TMemory memory) throws EaterException, EaterExceptionLocated {
|
||||
skipSpaces();
|
||||
checkAndEatChar("!includedef");
|
||||
skipSpaces();
|
||||
this.location = context.applyFunctionsAndVariables(memory, this.eatAllToEnd());
|
||||
this.location = context.applyFunctionsAndVariables(memory, getLineLocation(), this.eatAllToEnd());
|
||||
|
||||
}
|
||||
|
||||
|
@ -34,20 +34,22 @@
|
||||
*/
|
||||
package net.sourceforge.plantuml.tim;
|
||||
|
||||
import net.sourceforge.plantuml.StringLocated;
|
||||
|
||||
public class EaterIncludesub extends Eater {
|
||||
|
||||
private String location;
|
||||
|
||||
public EaterIncludesub(String s) {
|
||||
public EaterIncludesub(StringLocated s) {
|
||||
super(s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(TContext context, TMemory memory) throws EaterException {
|
||||
public void analyze(TContext context, TMemory memory) throws EaterException, EaterExceptionLocated {
|
||||
skipSpaces();
|
||||
checkAndEatChar("!includesub");
|
||||
skipSpaces();
|
||||
this.location = context.applyFunctionsAndVariables(memory, this.eatAllToEnd());
|
||||
this.location = context.applyFunctionsAndVariables(memory, getLineLocation(), this.eatAllToEnd());
|
||||
|
||||
}
|
||||
|
||||
|
@ -34,25 +34,22 @@
|
||||
*/
|
||||
package net.sourceforge.plantuml.tim;
|
||||
|
||||
import net.sourceforge.plantuml.LineLocation;
|
||||
import net.sourceforge.plantuml.StringLocated;
|
||||
|
||||
public class EaterLegacyDefine extends Eater {
|
||||
|
||||
private TFunctionImpl function;
|
||||
private final LineLocation location;
|
||||
|
||||
public EaterLegacyDefine(StringLocated s) {
|
||||
super(s.getTrimmed().getString());
|
||||
this.location = s.getLocation();
|
||||
super(s.getTrimmed());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(TContext context, TMemory memory) throws EaterException {
|
||||
public void analyze(TContext context, TMemory memory) throws EaterException, EaterExceptionLocated {
|
||||
skipSpaces();
|
||||
checkAndEatChar("!define");
|
||||
skipSpaces();
|
||||
function = eatDeclareFunction(context, memory, true, location, false);
|
||||
function = eatDeclareFunction(context, memory, true, getLineLocation(), false);
|
||||
final String def = this.eatAllToEnd();
|
||||
function.setFunctionType(TFunctionType.LEGACY_DEFINE);
|
||||
function.setLegacyDefinition(def);
|
||||
|
@ -34,25 +34,22 @@
|
||||
*/
|
||||
package net.sourceforge.plantuml.tim;
|
||||
|
||||
import net.sourceforge.plantuml.LineLocation;
|
||||
import net.sourceforge.plantuml.StringLocated;
|
||||
|
||||
public class EaterLegacyDefineLong extends Eater {
|
||||
|
||||
private TFunctionImpl function;
|
||||
private final LineLocation location;
|
||||
|
||||
public EaterLegacyDefineLong(StringLocated s) {
|
||||
super(s.getTrimmed().getString());
|
||||
this.location = s.getLocation();
|
||||
super(s.getTrimmed());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(TContext context, TMemory memory) throws EaterException {
|
||||
public void analyze(TContext context, TMemory memory) throws EaterException, EaterExceptionLocated {
|
||||
skipSpaces();
|
||||
checkAndEatChar("!definelong");
|
||||
skipSpaces();
|
||||
function = eatDeclareFunction(context, memory, true, location, true);
|
||||
function = eatDeclareFunction(context, memory, true, getLineLocation(), true);
|
||||
function.setFunctionType(TFunctionType.LEGACY_DEFINELONG);
|
||||
}
|
||||
|
||||
|
@ -35,19 +35,20 @@
|
||||
package net.sourceforge.plantuml.tim;
|
||||
|
||||
import net.sourceforge.plantuml.Log;
|
||||
import net.sourceforge.plantuml.StringLocated;
|
||||
|
||||
public class EaterLog extends Eater {
|
||||
|
||||
public EaterLog(String s) {
|
||||
public EaterLog(StringLocated s) {
|
||||
super(s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(TContext context, TMemory memory) throws EaterException {
|
||||
public void analyze(TContext context, TMemory memory) throws EaterException, EaterExceptionLocated {
|
||||
skipSpaces();
|
||||
checkAndEatChar("!log");
|
||||
skipSpaces();
|
||||
final String logData = context.applyFunctionsAndVariables(memory, this.eatAllToEnd());
|
||||
final String logData = context.applyFunctionsAndVariables(memory, getLineLocation(), this.eatAllToEnd());
|
||||
Log.error("[Log] " + logData);
|
||||
}
|
||||
|
||||
|
@ -34,18 +34,19 @@
|
||||
*/
|
||||
package net.sourceforge.plantuml.tim;
|
||||
|
||||
import net.sourceforge.plantuml.StringLocated;
|
||||
import net.sourceforge.plantuml.tim.expression.TValue;
|
||||
|
||||
public class EaterReturn extends Eater {
|
||||
|
||||
private TValue value;
|
||||
|
||||
public EaterReturn(String s) {
|
||||
public EaterReturn(StringLocated s) {
|
||||
super(s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(TContext context, TMemory memory) throws EaterException {
|
||||
public void analyze(TContext context, TMemory memory) throws EaterException, EaterExceptionLocated {
|
||||
skipSpaces();
|
||||
checkAndEatChar("!return");
|
||||
skipSpaces();
|
||||
|
@ -34,22 +34,24 @@
|
||||
*/
|
||||
package net.sourceforge.plantuml.tim;
|
||||
|
||||
import net.sourceforge.plantuml.StringLocated;
|
||||
|
||||
public class EaterStartsub extends Eater {
|
||||
|
||||
private String subname;
|
||||
|
||||
public EaterStartsub(String s) {
|
||||
public EaterStartsub(StringLocated s) {
|
||||
super(s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(TContext context, TMemory memory) throws EaterException {
|
||||
public void analyze(TContext context, TMemory memory) throws EaterException {
|
||||
skipSpaces();
|
||||
checkAndEatChar("!startsub");
|
||||
skipSpaces();
|
||||
this.subname = eatAllToEnd();
|
||||
if (this.subname.matches("\\w+") == false) {
|
||||
throw new EaterException("Bad sub name");
|
||||
throw EaterException.located("Bad sub name", getStringLocated());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -39,11 +39,11 @@ import net.sourceforge.plantuml.StringLocated;
|
||||
public class EaterUndef extends Eater {
|
||||
|
||||
public EaterUndef(StringLocated s) {
|
||||
super(s.getTrimmed().getString());
|
||||
super(s.getTrimmed());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(TContext context, TMemory memory) throws EaterException {
|
||||
public void analyze(TContext context, TMemory memory) throws EaterException {
|
||||
skipSpaces();
|
||||
checkAndEatChar("!undef");
|
||||
skipSpaces();
|
||||
|
59
src/net/sourceforge/plantuml/tim/EaterWhile.java
Normal file
59
src/net/sourceforge/plantuml/tim/EaterWhile.java
Normal file
@ -0,0 +1,59 @@
|
||||
/* ========================================================================
|
||||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* (C) Copyright 2009-2020, Arnaud Roques
|
||||
*
|
||||
* Project Info: http://plantuml.com
|
||||
*
|
||||
* If you like this project or if you find it useful, you can support us at:
|
||||
*
|
||||
* http://plantuml.com/patreon (only 1$ per month!)
|
||||
* http://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.tim;
|
||||
|
||||
import net.sourceforge.plantuml.StringLocated;
|
||||
import net.sourceforge.plantuml.tim.expression.TokenStack;
|
||||
|
||||
public class EaterWhile extends Eater {
|
||||
|
||||
private TokenStack expression;
|
||||
|
||||
public EaterWhile(StringLocated s) {
|
||||
super(s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void analyze(TContext context, TMemory memory) throws EaterException {
|
||||
skipSpaces();
|
||||
checkAndEatChar("!while");
|
||||
skipSpaces();
|
||||
this.expression = eatTokenStack();
|
||||
}
|
||||
|
||||
public final TokenStack getWhileExpression() {
|
||||
return expression;
|
||||
}
|
||||
}
|
@ -0,0 +1,89 @@
|
||||
/* ========================================================================
|
||||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* (C) Copyright 2009-2020, Arnaud Roques
|
||||
*
|
||||
* Project Info: http://plantuml.com
|
||||
*
|
||||
* If you like this project or if you find it useful, you can support us at:
|
||||
*
|
||||
* http://plantuml.com/patreon (only 1$ per month!)
|
||||
* http://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.tim;
|
||||
|
||||
import net.sourceforge.plantuml.json.JsonArray;
|
||||
import net.sourceforge.plantuml.tim.iterator.CodePosition;
|
||||
|
||||
public class ExecutionContextForeach {
|
||||
|
||||
private final String varname;
|
||||
private final JsonArray jsonArray;
|
||||
private final CodePosition codePosition;
|
||||
private boolean skipMe;
|
||||
private int currentIndex;
|
||||
|
||||
private ExecutionContextForeach(String varname, JsonArray jsonArray, CodePosition codePosition) {
|
||||
this.varname = varname;
|
||||
this.jsonArray = jsonArray;
|
||||
this.codePosition = codePosition;
|
||||
}
|
||||
|
||||
public static ExecutionContextForeach fromValue(String varname, JsonArray jsonArray, CodePosition codePosition) {
|
||||
return new ExecutionContextForeach(varname, jsonArray, codePosition);
|
||||
}
|
||||
|
||||
public void skipMeNow() {
|
||||
skipMe = true;
|
||||
}
|
||||
|
||||
public final boolean isSkipMe() {
|
||||
return skipMe;
|
||||
}
|
||||
|
||||
public CodePosition getStartForeach() {
|
||||
return codePosition;
|
||||
}
|
||||
|
||||
public final int currentIndex() {
|
||||
return currentIndex;
|
||||
}
|
||||
|
||||
public final void inc() {
|
||||
this.currentIndex++;
|
||||
if (currentIndex >= jsonArray.size()) {
|
||||
this.skipMe = true;
|
||||
}
|
||||
}
|
||||
|
||||
public final String getVarname() {
|
||||
return varname;
|
||||
}
|
||||
|
||||
public final JsonArray getJsonArray() {
|
||||
return jsonArray;
|
||||
}
|
||||
|
||||
}
|
@ -34,20 +34,20 @@
|
||||
*/
|
||||
package net.sourceforge.plantuml.tim;
|
||||
|
||||
public class ConditionalContext {
|
||||
public class ExecutionContextIf {
|
||||
|
||||
private boolean isTrue;
|
||||
private boolean hasBeenBurn;
|
||||
|
||||
private ConditionalContext(boolean isTrue) {
|
||||
private ExecutionContextIf(boolean isTrue) {
|
||||
this.isTrue = isTrue;
|
||||
if (this.isTrue) {
|
||||
hasBeenBurn = true;
|
||||
}
|
||||
}
|
||||
|
||||
public static ConditionalContext fromValue(boolean isTrue) {
|
||||
return new ConditionalContext(isTrue);
|
||||
public static ExecutionContextIf fromValue(boolean isTrue) {
|
||||
return new ExecutionContextIf(isTrue);
|
||||
}
|
||||
|
||||
public boolean conditionIsOkHere() {
|
78
src/net/sourceforge/plantuml/tim/ExecutionContextWhile.java
Normal file
78
src/net/sourceforge/plantuml/tim/ExecutionContextWhile.java
Normal file
@ -0,0 +1,78 @@
|
||||
/* ========================================================================
|
||||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* (C) Copyright 2009-2020, Arnaud Roques
|
||||
*
|
||||
* Project Info: http://plantuml.com
|
||||
*
|
||||
* If you like this project or if you find it useful, you can support us at:
|
||||
*
|
||||
* http://plantuml.com/patreon (only 1$ per month!)
|
||||
* http://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.tim;
|
||||
|
||||
import net.sourceforge.plantuml.LineLocation;
|
||||
import net.sourceforge.plantuml.tim.expression.TValue;
|
||||
import net.sourceforge.plantuml.tim.expression.TokenStack;
|
||||
import net.sourceforge.plantuml.tim.iterator.CodePosition;
|
||||
|
||||
public class ExecutionContextWhile {
|
||||
|
||||
private final TokenStack whileExpression;
|
||||
private final CodePosition codePosition;
|
||||
private boolean skipMe;
|
||||
|
||||
private ExecutionContextWhile(TokenStack whileExpression, CodePosition codePosition) {
|
||||
this.whileExpression = whileExpression;
|
||||
this.codePosition = codePosition;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return whileExpression.toString() + " " + codePosition;
|
||||
}
|
||||
|
||||
public static ExecutionContextWhile fromValue(TokenStack whileExpression, CodePosition codePosition) {
|
||||
return new ExecutionContextWhile(whileExpression, codePosition);
|
||||
}
|
||||
|
||||
public TValue conditionValue(LineLocation location, TContext context, TMemory memory) throws EaterException, EaterExceptionLocated {
|
||||
return whileExpression.getResult(location, context, memory);
|
||||
}
|
||||
|
||||
public void skipMe() {
|
||||
skipMe = true;
|
||||
}
|
||||
|
||||
public final boolean isSkipMe() {
|
||||
return skipMe;
|
||||
}
|
||||
|
||||
public CodePosition getStartWhile() {
|
||||
return codePosition;
|
||||
}
|
||||
|
||||
}
|
91
src/net/sourceforge/plantuml/tim/ExecutionContexts.java
Normal file
91
src/net/sourceforge/plantuml/tim/ExecutionContexts.java
Normal file
@ -0,0 +1,91 @@
|
||||
/* ========================================================================
|
||||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* (C) Copyright 2009-2020, Arnaud Roques
|
||||
*
|
||||
* Project Info: http://plantuml.com
|
||||
*
|
||||
* If you like this project or if you find it useful, you can support us at:
|
||||
*
|
||||
* http://plantuml.com/patreon (only 1$ per month!)
|
||||
* http://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.tim;
|
||||
|
||||
import java.util.Deque;
|
||||
import java.util.LinkedList;
|
||||
|
||||
public abstract class ExecutionContexts {
|
||||
|
||||
private final Deque<ExecutionContextIf> allIfs = new LinkedList<ExecutionContextIf>();
|
||||
private final Deque<ExecutionContextWhile> allWhiles = new LinkedList<ExecutionContextWhile>();
|
||||
private final Deque<ExecutionContextForeach> allForeachs = new LinkedList<ExecutionContextForeach>();
|
||||
|
||||
public void addIf(ExecutionContextIf value) {
|
||||
allIfs.addLast(value);
|
||||
}
|
||||
|
||||
public void addWhile(ExecutionContextWhile value) {
|
||||
allWhiles.addLast(value);
|
||||
}
|
||||
|
||||
public void addForeach(ExecutionContextForeach value) {
|
||||
allForeachs.addLast(value);
|
||||
}
|
||||
|
||||
public ExecutionContextIf peekIf() {
|
||||
return allIfs.peekLast();
|
||||
}
|
||||
|
||||
public ExecutionContextWhile peekWhile() {
|
||||
return allWhiles.peekLast();
|
||||
}
|
||||
|
||||
public ExecutionContextForeach peekForeach() {
|
||||
return allForeachs.peekLast();
|
||||
}
|
||||
|
||||
public ExecutionContextIf pollIf() {
|
||||
return allIfs.pollLast();
|
||||
}
|
||||
|
||||
public ExecutionContextWhile pollWhile() {
|
||||
return allWhiles.pollLast();
|
||||
}
|
||||
|
||||
public ExecutionContextForeach pollForeach() {
|
||||
return allForeachs.pollLast();
|
||||
}
|
||||
|
||||
public boolean areAllIfOk(TContext context, TMemory memory) throws EaterException {
|
||||
for (ExecutionContextIf conditionalContext : allIfs) {
|
||||
if (conditionalContext.conditionIsOkHere() == false) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
139
src/net/sourceforge/plantuml/tim/FunctionsSet.java
Normal file
139
src/net/sourceforge/plantuml/tim/FunctionsSet.java
Normal file
@ -0,0 +1,139 @@
|
||||
/* ========================================================================
|
||||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* (C) Copyright 2009-2020, Arnaud Roques
|
||||
*
|
||||
* Project Info: http://plantuml.com
|
||||
*
|
||||
* If you like this project or if you find it useful, you can support us at:
|
||||
*
|
||||
* http://plantuml.com/patreon (only 1$ per month!)
|
||||
* http://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.tim;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import net.sourceforge.plantuml.StringLocated;
|
||||
|
||||
public class FunctionsSet {
|
||||
|
||||
private final Map<TFunctionSignature, TFunction> functions = new HashMap<TFunctionSignature, TFunction>();
|
||||
private final Set<TFunctionSignature> functionsFinal = new HashSet<TFunctionSignature>();
|
||||
private final Trie functions3 = new TrieImpl();
|
||||
private TFunctionImpl pendingFunction;
|
||||
|
||||
public TFunction getFunctionSmart(TFunctionSignature searched) {
|
||||
final TFunction func = this.functions.get(searched);
|
||||
if (func != null) {
|
||||
return func;
|
||||
}
|
||||
for (TFunction candidate : this.functions.values()) {
|
||||
if (candidate.getSignature().sameNameAs(searched) == false) {
|
||||
continue;
|
||||
}
|
||||
if (candidate.canCover(searched.getNbArg())) {
|
||||
return candidate;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return functions().size();
|
||||
}
|
||||
|
||||
public Map<TFunctionSignature, TFunction> functions() {
|
||||
return Collections.unmodifiableMap(functions);
|
||||
}
|
||||
|
||||
public String getLonguestMatchStartingIn(String s) {
|
||||
return functions3.getLonguestMatchStartingIn(s);
|
||||
}
|
||||
|
||||
public TFunctionImpl pendingFunction() {
|
||||
return pendingFunction;
|
||||
}
|
||||
|
||||
public void addFunction(TFunction func) {
|
||||
if (func.getFunctionType() == TFunctionType.LEGACY_DEFINELONG) {
|
||||
((TFunctionImpl) func).finalizeEnddefinelong();
|
||||
}
|
||||
this.functions.put(func.getSignature(), func);
|
||||
this.functions3.add(func.getSignature().getFunctionName() + "(");
|
||||
}
|
||||
|
||||
public void executeEndfunction() {
|
||||
this.addFunction(this.pendingFunction);
|
||||
this.pendingFunction = null;
|
||||
}
|
||||
|
||||
public void executeLegacyDefine(TContext context, TMemory memory, StringLocated s) throws EaterException, EaterExceptionLocated {
|
||||
if (this.pendingFunction != null) {
|
||||
throw EaterException.located("already0048", s);
|
||||
}
|
||||
final EaterLegacyDefine legacyDefine = new EaterLegacyDefine(s);
|
||||
legacyDefine.analyze(context, memory);
|
||||
final TFunction function = legacyDefine.getFunction();
|
||||
this.functions.put(function.getSignature(), function);
|
||||
this.functions3.add(function.getSignature().getFunctionName() + "(");
|
||||
}
|
||||
|
||||
public void executeLegacyDefineLong(TContext context, TMemory memory, StringLocated s) throws EaterException, EaterExceptionLocated {
|
||||
if (this.pendingFunction != null) {
|
||||
throw EaterException.located("already0068", s);
|
||||
}
|
||||
final EaterLegacyDefineLong legacyDefineLong = new EaterLegacyDefineLong(s);
|
||||
legacyDefineLong.analyze(context, memory);
|
||||
this.pendingFunction = legacyDefineLong.getFunction();
|
||||
}
|
||||
|
||||
public void executeDeclareFunction(TContext context, TMemory memory, StringLocated s) throws EaterException, EaterExceptionLocated {
|
||||
if (this.pendingFunction != null) {
|
||||
throw EaterException.located("already0068", s);
|
||||
}
|
||||
final EaterDeclareFunction declareFunction = new EaterDeclareFunction(s);
|
||||
declareFunction.analyze(context, memory);
|
||||
final boolean finalFlag = declareFunction.getFinalFlag();
|
||||
final TFunctionSignature declaredSignature = declareFunction.getFunction().getSignature();
|
||||
final TFunction previous = this.functions.get(declaredSignature);
|
||||
if (previous != null && (finalFlag || this.functionsFinal.contains(declaredSignature))) {
|
||||
throw EaterException.located("This function is already defined", s);
|
||||
}
|
||||
if (finalFlag) {
|
||||
this.functionsFinal.add(declaredSignature);
|
||||
}
|
||||
if (declareFunction.getFunction().hasBody()) {
|
||||
this.addFunction(declareFunction.getFunction());
|
||||
} else {
|
||||
this.pendingFunction = declareFunction.getFunction();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -47,6 +47,7 @@ import java.util.Set;
|
||||
|
||||
import net.sourceforge.plantuml.DefinitionsContainer;
|
||||
import net.sourceforge.plantuml.FileSystem;
|
||||
import net.sourceforge.plantuml.LineLocation;
|
||||
import net.sourceforge.plantuml.StringLocated;
|
||||
import net.sourceforge.plantuml.command.CommandExecutionResult;
|
||||
import net.sourceforge.plantuml.json.JsonObject;
|
||||
@ -64,6 +65,18 @@ import net.sourceforge.plantuml.preproc2.PreprocessorIncludeStrategy;
|
||||
import net.sourceforge.plantuml.preproc2.PreprocessorUtils;
|
||||
import net.sourceforge.plantuml.tim.expression.Knowledge;
|
||||
import net.sourceforge.plantuml.tim.expression.TValue;
|
||||
import net.sourceforge.plantuml.tim.iterator.CodeIterator;
|
||||
import net.sourceforge.plantuml.tim.iterator.CodeIteratorAffectation;
|
||||
import net.sourceforge.plantuml.tim.iterator.CodeIteratorForeach;
|
||||
import net.sourceforge.plantuml.tim.iterator.CodeIteratorFunction;
|
||||
import net.sourceforge.plantuml.tim.iterator.CodeIteratorIf;
|
||||
import net.sourceforge.plantuml.tim.iterator.CodeIteratorImpl;
|
||||
import net.sourceforge.plantuml.tim.iterator.CodeIteratorInnerComment;
|
||||
import net.sourceforge.plantuml.tim.iterator.CodeIteratorLegacyDefine;
|
||||
import net.sourceforge.plantuml.tim.iterator.CodeIteratorLongComment;
|
||||
import net.sourceforge.plantuml.tim.iterator.CodeIteratorShortComment;
|
||||
import net.sourceforge.plantuml.tim.iterator.CodeIteratorSub;
|
||||
import net.sourceforge.plantuml.tim.iterator.CodeIteratorWhile;
|
||||
import net.sourceforge.plantuml.tim.stdlib.AlwaysFalse;
|
||||
import net.sourceforge.plantuml.tim.stdlib.AlwaysTrue;
|
||||
import net.sourceforge.plantuml.tim.stdlib.CallUserFunction;
|
||||
@ -91,15 +104,12 @@ public class TContext {
|
||||
|
||||
private final List<StringLocated> resultList = new ArrayList<StringLocated>();
|
||||
private final List<StringLocated> debug = new ArrayList<StringLocated>();
|
||||
private final Map<TFunctionSignature, TFunction> functions2 = new HashMap<TFunctionSignature, TFunction>();
|
||||
private final Set<TFunctionSignature> functionsFinal = new HashSet<TFunctionSignature>();
|
||||
private final Trie functions3 = new TrieImpl();
|
||||
|
||||
public final FunctionsSet functionsSet = new FunctionsSet();
|
||||
|
||||
private ImportedFiles importedFiles;
|
||||
private final String charset;
|
||||
|
||||
private TFunctionImpl pendingFunction;
|
||||
private Sub pendingSub;
|
||||
private boolean inLongComment;
|
||||
private final Map<String, Sub> subs = new HashMap<String, Sub>();
|
||||
private final DefinitionsContainer definitionsContainer;
|
||||
|
||||
@ -107,28 +117,28 @@ public class TContext {
|
||||
private final Set<FileWithSuffix> filesUsedCurrent = new HashSet<FileWithSuffix>();
|
||||
|
||||
private void addStandardFunctions(Defines defines) {
|
||||
addFunction(new Strlen());
|
||||
addFunction(new Substr());
|
||||
addFunction(new FileExists());
|
||||
addFunction(new Getenv());
|
||||
addFunction(new Dirpath(defines));
|
||||
addFunction(new Filename(defines));
|
||||
addFunction(new DateFunction());
|
||||
addFunction(new Strpos());
|
||||
addFunction(new InvokeVoidFunction());
|
||||
addFunction(new AlwaysFalse());
|
||||
addFunction(new AlwaysTrue());
|
||||
addFunction(new LogicalNot());
|
||||
addFunction(new FunctionExists());
|
||||
addFunction(new VariableExists());
|
||||
addFunction(new CallUserFunction());
|
||||
addFunction(new RetrieveVoidFunction());
|
||||
addFunction(new SetVariableValue());
|
||||
addFunction(new GetVariableValue());
|
||||
addFunction(new IntVal());
|
||||
addFunction(new GetVersion());
|
||||
addFunction(new Upper());
|
||||
addFunction(new Lower());
|
||||
functionsSet.addFunction(new Strlen());
|
||||
functionsSet.addFunction(new Substr());
|
||||
functionsSet.addFunction(new FileExists());
|
||||
functionsSet.addFunction(new Getenv());
|
||||
functionsSet.addFunction(new Dirpath(defines));
|
||||
functionsSet.addFunction(new Filename(defines));
|
||||
functionsSet.addFunction(new DateFunction());
|
||||
functionsSet.addFunction(new Strpos());
|
||||
functionsSet.addFunction(new InvokeVoidFunction());
|
||||
functionsSet.addFunction(new AlwaysFalse());
|
||||
functionsSet.addFunction(new AlwaysTrue());
|
||||
functionsSet.addFunction(new LogicalNot());
|
||||
functionsSet.addFunction(new FunctionExists());
|
||||
functionsSet.addFunction(new VariableExists());
|
||||
functionsSet.addFunction(new CallUserFunction());
|
||||
functionsSet.addFunction(new RetrieveVoidFunction());
|
||||
functionsSet.addFunction(new SetVariableValue());
|
||||
functionsSet.addFunction(new GetVariableValue());
|
||||
functionsSet.addFunction(new IntVal());
|
||||
functionsSet.addFunction(new GetVersion());
|
||||
functionsSet.addFunction(new Upper());
|
||||
functionsSet.addFunction(new Lower());
|
||||
// !exit
|
||||
// !log
|
||||
// %min
|
||||
@ -151,155 +161,101 @@ public class TContext {
|
||||
public Knowledge asKnowledge(final TMemory memory) {
|
||||
return new Knowledge() {
|
||||
|
||||
public TVariable getVariable(String name) {
|
||||
public TValue getVariable(String name) {
|
||||
if (name.contains(".")) {
|
||||
return fromJson(memory, name);
|
||||
}
|
||||
return memory.getVariable(name);
|
||||
}
|
||||
|
||||
public TFunction getFunction(TFunctionSignature name) {
|
||||
return getFunctionSmart(name);
|
||||
return functionsSet.getFunctionSmart(name);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public TFunction getFunctionSmart(TFunctionSignature searched) {
|
||||
final TFunction func = functions2.get(searched);
|
||||
if (func != null) {
|
||||
return func;
|
||||
private TValue fromJson(TMemory memory, String name) {
|
||||
final int x = name.indexOf('.');
|
||||
final TValue data = memory.getVariable(name.substring(0, x));
|
||||
if (data == null) {
|
||||
return null;
|
||||
}
|
||||
for (TFunction candidate : functions2.values()) {
|
||||
if (candidate.getSignature().sameNameAs(searched) == false) {
|
||||
continue;
|
||||
}
|
||||
if (candidate.canCover(searched.getNbArg())) {
|
||||
return candidate;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
final JsonObject json = (JsonObject) data.toJson();
|
||||
// System.err.println("json=" + json);
|
||||
// System.err.println("json=" + json.getClass());
|
||||
// System.err.println("json2=" + name.substring(x + 1));
|
||||
final JsonValue result = json.get(name.substring(x + 1));
|
||||
// System.err.println("result=" + result);
|
||||
return TValue.fromJson(result);
|
||||
}
|
||||
|
||||
public void executeOneLine(TMemory memory, TLineType type, StringLocated s, TFunctionType fromType)
|
||||
throws EaterException {
|
||||
private CodeIterator buildCodeIterator(TMemory memory, List<StringLocated> body) {
|
||||
final CodeIterator it10 = new CodeIteratorImpl(body);
|
||||
final CodeIterator it20 = new CodeIteratorLongComment(it10, debug);
|
||||
final CodeIterator it30 = new CodeIteratorShortComment(it20, debug);
|
||||
final CodeIterator it40 = new CodeIteratorInnerComment(it30);
|
||||
final CodeIterator it50 = new CodeIteratorSub(it40, subs, this, memory);
|
||||
final CodeIterator it60 = new CodeIteratorFunction(it50, this, memory, functionsSet, debug);
|
||||
final CodeIterator it70 = new CodeIteratorIf(it60, this, memory, debug);
|
||||
final CodeIterator it80 = new CodeIteratorLegacyDefine(it70, this, memory, functionsSet, debug);
|
||||
final CodeIterator it90 = new CodeIteratorWhile(it80, this, memory, debug);
|
||||
final CodeIterator it100 = new CodeIteratorForeach(it90, this, memory, debug);
|
||||
final CodeIterator it110 = new CodeIteratorAffectation(it100, this, memory, debug);
|
||||
|
||||
this.debug.add(s);
|
||||
assert type == TLineType.getFromLine(s.getString());
|
||||
final CodeIterator it = it110;
|
||||
return it;
|
||||
}
|
||||
|
||||
if (this.inLongComment == false && type == TLineType.STARTSUB) {
|
||||
if (pendingSub != null) {
|
||||
throw new EaterException("Cannot nest sub");
|
||||
public void executeLines(TMemory memory, List<StringLocated> body, TFunctionType ftype)
|
||||
throws EaterExceptionLocated {
|
||||
final CodeIterator it = buildCodeIterator(memory, body);
|
||||
|
||||
StringLocated s = null;
|
||||
try {
|
||||
while ((s = it.peek()) != null) {
|
||||
executeOneLineSafe(memory, s, ftype);
|
||||
it.next();
|
||||
}
|
||||
final EaterStartsub eater = new EaterStartsub(s.getTrimmed().getString());
|
||||
eater.execute(this, memory);
|
||||
this.pendingSub = new Sub(eater.getSubname());
|
||||
this.subs.put(eater.getSubname(), this.pendingSub);
|
||||
return;
|
||||
}
|
||||
if (this.inLongComment == false && type == TLineType.ENDSUB) {
|
||||
if (pendingSub == null) {
|
||||
throw new EaterException("No corresponding !startsub");
|
||||
}
|
||||
final Sub newly = this.pendingSub;
|
||||
this.pendingSub = null;
|
||||
this.runSub(memory, newly);
|
||||
return;
|
||||
}
|
||||
// if (this.inLongComment == false && type == TLineType.INCLUDESUB) {
|
||||
// this.executeIncludesub(memory, s);
|
||||
// return;
|
||||
// }
|
||||
|
||||
if (pendingSub != null) {
|
||||
pendingSub.add(s);
|
||||
return;
|
||||
} catch (EaterException e) {
|
||||
throw e.withLocation(s);
|
||||
}
|
||||
|
||||
if (this.getPendingFunction() != null) {
|
||||
if (this.inLongComment == false && type == TLineType.END_FUNCTION) {
|
||||
this.executeEndfunction();
|
||||
} else {
|
||||
this.getPendingFunction().addBody(s);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
private void executeLinesInternal(TMemory memory, List<StringLocated> body, TFunctionType ftype)
|
||||
throws EaterExceptionLocated, EaterException {
|
||||
final CodeIterator it = buildCodeIterator(memory, body);
|
||||
|
||||
StringLocated s = null;
|
||||
while ((s = it.peek()) != null) {
|
||||
executeOneLineSafe(memory, s, ftype);
|
||||
it.next();
|
||||
}
|
||||
|
||||
if (this.inLongComment && s.getTrimmed().getString().endsWith("'/")) {
|
||||
this.inLongComment = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (type == TLineType.COMMENT_LONG_START) {
|
||||
this.inLongComment = true;
|
||||
return;
|
||||
private void executeOneLineSafe(TMemory memory, StringLocated s, TFunctionType ftype)
|
||||
throws EaterException, EaterExceptionLocated {
|
||||
try {
|
||||
this.debug.add(s);
|
||||
executeOneLineNotSafe(memory, s, ftype);
|
||||
} catch (Exception e) {
|
||||
if (e instanceof EaterException)
|
||||
throw (EaterException) e;
|
||||
if (e instanceof EaterExceptionLocated)
|
||||
throw (EaterExceptionLocated) e;
|
||||
e.printStackTrace();
|
||||
throw EaterException.located("Fatal parsing error", s);
|
||||
}
|
||||
if (this.inLongComment) {
|
||||
return;
|
||||
}
|
||||
if (type == TLineType.COMMENT_SIMPLE) {
|
||||
return;
|
||||
}
|
||||
s = s.removeInnerComment();
|
||||
}
|
||||
|
||||
if (type == TLineType.IF) {
|
||||
this.executeIf(memory, s.getTrimmed().getString());
|
||||
return;
|
||||
} else if (type == TLineType.IFDEF) {
|
||||
this.executeIfdef(memory, s.getTrimmed().getString());
|
||||
return;
|
||||
} else if (type == TLineType.IFNDEF) {
|
||||
this.executeIfndef(memory, s.getTrimmed().getString());
|
||||
return;
|
||||
} else if (type == TLineType.ELSE) {
|
||||
this.executeElse(memory, s.getTrimmed().getString());
|
||||
return;
|
||||
} else if (type == TLineType.ELSEIF) {
|
||||
this.executeElseIf(memory, s.getTrimmed().getString());
|
||||
return;
|
||||
} else if (type == TLineType.ENDIF) {
|
||||
this.executeEndif(memory, s.getTrimmed().getString());
|
||||
return;
|
||||
}
|
||||
private void executeOneLineNotSafe(TMemory memory, StringLocated s, TFunctionType ftype)
|
||||
throws EaterException, EaterExceptionLocated {
|
||||
final TLineType type = s.getType();
|
||||
|
||||
final ConditionalContext conditionalContext = memory.peekConditionalContext();
|
||||
if (conditionalContext != null && memory.areAllIfOk() == false) {
|
||||
return;
|
||||
}
|
||||
if (this.inLongComment == false && type == TLineType.INCLUDESUB) {
|
||||
if (type == TLineType.INCLUDESUB) {
|
||||
this.executeIncludesub(memory, s);
|
||||
return;
|
||||
}
|
||||
|
||||
if (type == TLineType.DUMP_MEMORY) {
|
||||
this.executeDumpMemory(memory, s.getTrimmed().getString());
|
||||
return;
|
||||
} else if (type == TLineType.ASSERT) {
|
||||
this.executeAssert(memory, s.getTrimmed().getString());
|
||||
return;
|
||||
} else if (type == TLineType.UNDEF) {
|
||||
this.executeUndef(memory, s);
|
||||
return;
|
||||
} else if (fromType != TFunctionType.RETURN && type == TLineType.PLAIN) {
|
||||
this.addPlain(memory, s);
|
||||
return;
|
||||
} else if (fromType == TFunctionType.RETURN && type == TLineType.RETURN) {
|
||||
// Actually, ignore because we are in a if
|
||||
return;
|
||||
} else if (type == TLineType.LEGACY_DEFINE) {
|
||||
this.executeLegacyDefine(memory, s);
|
||||
return;
|
||||
} else if (type == TLineType.LEGACY_DEFINELONG) {
|
||||
this.executeLegacyDefineLong(memory, s);
|
||||
return;
|
||||
} else if (type == TLineType.AFFECTATION_DEFINE) {
|
||||
this.executeAffectationDefine(memory, s.getTrimmed().getString());
|
||||
return;
|
||||
} else if (type == TLineType.AFFECTATION) {
|
||||
this.executeAffectation(memory, s.getTrimmed().getString());
|
||||
return;
|
||||
} else if (fromType == null && type == TLineType.DECLARE_FUNCTION) {
|
||||
this.executeDeclareFunction(memory, s);
|
||||
return;
|
||||
} else if (fromType == null && type == TLineType.END_FUNCTION) {
|
||||
CommandExecutionResult.error("error endfunc");
|
||||
return;
|
||||
} else if (type == TLineType.INCLUDE) {
|
||||
this.executeInclude(memory, s);
|
||||
return;
|
||||
@ -309,18 +265,39 @@ public class TContext {
|
||||
} else if (type == TLineType.IMPORT) {
|
||||
this.executeImport(memory, s);
|
||||
return;
|
||||
}
|
||||
|
||||
if (type == TLineType.DUMP_MEMORY) {
|
||||
this.executeDumpMemory(memory, s.getTrimmed());
|
||||
return;
|
||||
} else if (type == TLineType.ASSERT) {
|
||||
this.executeAssert(memory, s.getTrimmed());
|
||||
return;
|
||||
} else if (type == TLineType.UNDEF) {
|
||||
this.executeUndef(memory, s);
|
||||
return;
|
||||
} else if (ftype != TFunctionType.RETURN && type == TLineType.PLAIN) {
|
||||
this.addPlain(memory, s);
|
||||
return;
|
||||
} else if (ftype == TFunctionType.RETURN && type == TLineType.RETURN) {
|
||||
// Actually, ignore because we are in a if
|
||||
return;
|
||||
} else if (type == TLineType.AFFECTATION_DEFINE) {
|
||||
this.executeAffectationDefine(memory, s);
|
||||
return;
|
||||
} else if (ftype == null && type == TLineType.END_FUNCTION) {
|
||||
CommandExecutionResult.error("error endfunc");
|
||||
return;
|
||||
} else if (type == TLineType.LOG) {
|
||||
this.executeLog(memory, s);
|
||||
return;
|
||||
} else {
|
||||
// Thread.dumpStack();
|
||||
throw new EaterException("Parsing Error");
|
||||
// throw new UnsupportedOperationException("type=" + type + " fromType=" + fromType);
|
||||
throw EaterException.located("Parsing Error", s);
|
||||
}
|
||||
}
|
||||
|
||||
private void addPlain(TMemory memory, StringLocated s) throws EaterException {
|
||||
StringLocated tmp = applyFunctionsAndVariables(memory, s);
|
||||
private void addPlain(TMemory memory, StringLocated s) throws EaterException, EaterExceptionLocated {
|
||||
StringLocated tmp = applyFunctionsAndVariablesInternal(memory, s);
|
||||
if (tmp != null) {
|
||||
if (pendingAdd != null) {
|
||||
tmp = new StringLocated(pendingAdd + tmp.getString(), tmp.getLocation());
|
||||
@ -330,136 +307,32 @@ public class TContext {
|
||||
}
|
||||
}
|
||||
|
||||
private void executeAffectationDefine(TMemory memory, String s) throws EaterException {
|
||||
new EaterAffectationDefine(s).execute(this, memory);
|
||||
private void executeAffectationDefine(TMemory memory, StringLocated s)
|
||||
throws EaterException, EaterExceptionLocated {
|
||||
new EaterAffectationDefine(s).analyze(this, memory);
|
||||
}
|
||||
|
||||
private void executeAffectation(TMemory memory, String s) throws EaterException {
|
||||
new EaterAffectation(s).execute(this, memory);
|
||||
}
|
||||
|
||||
private void executeIf(TMemory memory, String s) throws EaterException {
|
||||
final EaterIf condition = new EaterIf(s);
|
||||
condition.execute(this, memory);
|
||||
final boolean isTrue = condition.isTrue();
|
||||
memory.addConditionalContext(ConditionalContext.fromValue(isTrue));
|
||||
}
|
||||
|
||||
private void executeElseIf(TMemory memory, String s) throws EaterException {
|
||||
final ConditionalContext poll = memory.peekConditionalContext();
|
||||
if (poll == null) {
|
||||
throw new EaterException("No if related to this else");
|
||||
}
|
||||
|
||||
poll.enteringElseIf();
|
||||
if (poll.hasBeenBurn() == false) {
|
||||
final EaterElseIf condition = new EaterElseIf(s);
|
||||
condition.execute(this, memory);
|
||||
final boolean isTrue = condition.isTrue();
|
||||
if (isTrue) {
|
||||
poll.nowInSomeElseIf();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void executeDumpMemory(TMemory memory, String s) throws EaterException {
|
||||
private void executeDumpMemory(TMemory memory, StringLocated s) throws EaterException {
|
||||
final EaterDumpMemory condition = new EaterDumpMemory(s);
|
||||
condition.execute(this, memory);
|
||||
condition.analyze(this, memory);
|
||||
}
|
||||
|
||||
private void executeAssert(TMemory memory, String s) throws EaterException {
|
||||
private void executeAssert(TMemory memory, StringLocated s) throws EaterException, EaterExceptionLocated {
|
||||
final EaterAssert condition = new EaterAssert(s);
|
||||
condition.execute(this, memory);
|
||||
}
|
||||
|
||||
private void executeIfdef(TMemory memory, String s) throws EaterException {
|
||||
final EaterIfdef condition = new EaterIfdef(s);
|
||||
condition.execute(this, memory);
|
||||
final boolean isTrue = condition.isTrue(this, memory);
|
||||
memory.addConditionalContext(ConditionalContext.fromValue(isTrue));
|
||||
}
|
||||
|
||||
private void executeIfndef(TMemory memory, String s) throws EaterException {
|
||||
final EaterIfndef condition = new EaterIfndef(s);
|
||||
condition.execute(this, memory);
|
||||
final boolean isTrue = condition.isTrue(this, memory);
|
||||
memory.addConditionalContext(ConditionalContext.fromValue(isTrue));
|
||||
}
|
||||
|
||||
private void executeElse(TMemory memory, String s) throws EaterException {
|
||||
final ConditionalContext poll = memory.peekConditionalContext();
|
||||
if (poll == null) {
|
||||
throw new EaterException("No if related to this else");
|
||||
}
|
||||
poll.nowInElse();
|
||||
}
|
||||
|
||||
private void executeEndif(TMemory memory, String s) throws EaterException {
|
||||
final ConditionalContext poll = memory.pollConditionalContext();
|
||||
if (poll == null) {
|
||||
throw new EaterException("No if related to this endif");
|
||||
}
|
||||
}
|
||||
|
||||
private void executeDeclareFunction(TMemory memory, StringLocated s) throws EaterException {
|
||||
if (this.pendingFunction != null) {
|
||||
throw new EaterException("already0068");
|
||||
}
|
||||
final EaterDeclareFunction declareFunction = new EaterDeclareFunction(s);
|
||||
declareFunction.execute(this, memory);
|
||||
final boolean finalFlag = declareFunction.getFinalFlag();
|
||||
final TFunctionSignature declaredSignature = declareFunction.getFunction().getSignature();
|
||||
final TFunction previous = functions2.get(declaredSignature);
|
||||
if (previous != null && (finalFlag || functionsFinal.contains(declaredSignature))) {
|
||||
throw new EaterException("This function is already defined");
|
||||
}
|
||||
if (finalFlag) {
|
||||
functionsFinal.add(declaredSignature);
|
||||
}
|
||||
if (declareFunction.getFunction().hasBody()) {
|
||||
addFunction(declareFunction.getFunction());
|
||||
} else {
|
||||
this.pendingFunction = declareFunction.getFunction();
|
||||
}
|
||||
condition.analyze(this, memory);
|
||||
}
|
||||
|
||||
private void executeUndef(TMemory memory, StringLocated s) throws EaterException {
|
||||
final EaterUndef undef = new EaterUndef(s);
|
||||
undef.execute(this, memory);
|
||||
undef.analyze(this, memory);
|
||||
}
|
||||
|
||||
private void executeLegacyDefine(TMemory memory, StringLocated s) throws EaterException {
|
||||
if (this.pendingFunction != null) {
|
||||
throw new EaterException("already0048");
|
||||
}
|
||||
final EaterLegacyDefine legacyDefine = new EaterLegacyDefine(s);
|
||||
legacyDefine.execute(this, memory);
|
||||
final TFunction function = legacyDefine.getFunction();
|
||||
// if (functions2.containsKey(function.getSignature())) {
|
||||
// throw new EaterException("already0047");
|
||||
// }
|
||||
this.functions2.put(function.getSignature(), function);
|
||||
this.functions3.add(function.getSignature().getFunctionName() + "(");
|
||||
}
|
||||
|
||||
private void executeLegacyDefineLong(TMemory memory, StringLocated s) throws EaterException {
|
||||
if (this.pendingFunction != null) {
|
||||
throw new EaterException("already0068");
|
||||
}
|
||||
final EaterLegacyDefineLong legacyDefineLong = new EaterLegacyDefineLong(s);
|
||||
legacyDefineLong.execute(this, memory);
|
||||
// if (functions2.containsKey(legacyDefineLong.getFunction().getSignature())) {
|
||||
// throw new EaterException("already0066");
|
||||
// }
|
||||
this.pendingFunction = legacyDefineLong.getFunction();
|
||||
}
|
||||
|
||||
private StringLocated applyFunctionsAndVariables(TMemory memory, StringLocated located) throws EaterException {
|
||||
if (memory.isEmpty() && functions2.size() == 0) {
|
||||
private StringLocated applyFunctionsAndVariablesInternal(TMemory memory, StringLocated located)
|
||||
throws EaterException, EaterExceptionLocated {
|
||||
if (memory.isEmpty() && functionsSet.size() == 0) {
|
||||
return located;
|
||||
}
|
||||
final String s = located.getString();
|
||||
final String result = applyFunctionsAndVariables(memory, s);
|
||||
final String result = applyFunctionsAndVariables(memory, located.getLocation(), located.getString());
|
||||
if (result == null) {
|
||||
return null;
|
||||
}
|
||||
@ -468,127 +341,89 @@ public class TContext {
|
||||
|
||||
private String pendingAdd = null;
|
||||
|
||||
public String applyFunctionsAndVariables(TMemory memory, String s) throws EaterException {
|
||||
public String applyFunctionsAndVariables(TMemory memory, LineLocation location, String str)
|
||||
throws EaterException, EaterExceptionLocated {
|
||||
// https://en.wikipedia.org/wiki/Boyer%E2%80%93Moore%E2%80%93Horspool_algorithm
|
||||
// https://stackoverflow.com/questions/1326682/java-replacing-multiple-different-substring-in-a-string-at-once-or-in-the-most
|
||||
// https://en.wikipedia.org/wiki/String-searching_algorithm
|
||||
// https://www.quora.com/What-is-the-most-efficient-algorithm-to-replace-all-occurrences-of-a-pattern-P-in-a-string-with-a-pattern-P
|
||||
// https://en.wikipedia.org/wiki/Trie
|
||||
if (memory.isEmpty() && functions2.size() == 0) {
|
||||
return s;
|
||||
if (memory.isEmpty() && functionsSet.size() == 0) {
|
||||
return str;
|
||||
}
|
||||
final StringBuilder result = new StringBuilder();
|
||||
for (int i = 0; i < s.length(); i++) {
|
||||
final char c = s.charAt(i);
|
||||
final String presentFunction = getFunctionNameAt(s, i);
|
||||
for (int i = 0; i < str.length(); i++) {
|
||||
final char c = str.charAt(i);
|
||||
final String presentFunction = getFunctionNameAt(str, i);
|
||||
if (presentFunction != null) {
|
||||
final String sub = s.substring(i);
|
||||
final EaterFunctionCall call = new EaterFunctionCall(sub, isLegacyDefine(presentFunction),
|
||||
isUnquoted(presentFunction));
|
||||
call.execute(this, memory);
|
||||
final TFunction function = getFunctionSmart(new TFunctionSignature(presentFunction, call.getValues()
|
||||
.size()));
|
||||
final String sub = str.substring(i);
|
||||
final EaterFunctionCall call = new EaterFunctionCall(new StringLocated(sub, location),
|
||||
isLegacyDefine(presentFunction), isUnquoted(presentFunction));
|
||||
call.analyze(this, memory);
|
||||
final TFunction function = functionsSet
|
||||
.getFunctionSmart(new TFunctionSignature(presentFunction, call.getValues().size()));
|
||||
if (function == null) {
|
||||
throw new EaterException("Function not found " + presentFunction);
|
||||
throw EaterException.located("Function not found " + presentFunction,
|
||||
new StringLocated(str, location));
|
||||
}
|
||||
if (function.getFunctionType() == TFunctionType.VOID) {
|
||||
this.pendingAdd = result.toString();
|
||||
executeVoid3(memory, sub, function);
|
||||
executeVoid3(location, memory, sub, function);
|
||||
return null;
|
||||
}
|
||||
if (function.getFunctionType() == TFunctionType.LEGACY_DEFINELONG) {
|
||||
this.pendingAdd = s.substring(0, i);
|
||||
executeVoid3(memory, sub, function);
|
||||
this.pendingAdd = str.substring(0, i);
|
||||
executeVoid3(location, memory, sub, function);
|
||||
return null;
|
||||
}
|
||||
assert function.getFunctionType() == TFunctionType.RETURN
|
||||
|| function.getFunctionType() == TFunctionType.LEGACY_DEFINE;
|
||||
final TValue functionReturn = function.executeReturn(this, memory, call.getValues());
|
||||
final TValue functionReturn = function.executeReturn(this, memory, location, call.getValues());
|
||||
result.append(functionReturn.toString());
|
||||
i += call.getCurrentPosition() - 1;
|
||||
continue;
|
||||
} else if (new VariableManager(this, memory, location).getVarnameAt(str, i) != null) {
|
||||
i = new VariableManager(this, memory, location).replaceVariables(str, i, result);
|
||||
} else {
|
||||
result.append(c);
|
||||
}
|
||||
final String presentVariable = getVarnameAt(memory, s, i);
|
||||
if (presentVariable != null) {
|
||||
if (result.toString().endsWith("##")) {
|
||||
result.setLength(result.length() - 2);
|
||||
}
|
||||
final TValue value = memory.getVariable(presentVariable).getValue();
|
||||
i += presentVariable.length() - 1;
|
||||
if (value.isJson()) {
|
||||
JsonValue jsonValue = (JsonObject) value.toJson();
|
||||
// System.err.println("jsonValue1=" + jsonValue);
|
||||
i++;
|
||||
while (true) {
|
||||
final char n = s.charAt(i);
|
||||
// System.err.println("n=" + n);
|
||||
if (n != '.') {
|
||||
if (jsonValue.isString()) {
|
||||
result.append(jsonValue.asString());
|
||||
} else {
|
||||
result.append(jsonValue.toString());
|
||||
}
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
final StringBuilder fieldName = new StringBuilder();
|
||||
while (true) {
|
||||
if (Character.isJavaIdentifierPart(s.charAt(i)) == false) {
|
||||
break;
|
||||
}
|
||||
fieldName.append(s.charAt(i));
|
||||
i++;
|
||||
}
|
||||
// System.err.println("fieldName=" + fieldName);
|
||||
jsonValue = ((JsonObject) jsonValue).get(fieldName.toString());
|
||||
// System.err.println("jsonValue2=" + jsonValue);
|
||||
}
|
||||
} else {
|
||||
result.append(value.toString());
|
||||
}
|
||||
if (i + 2 < s.length() && s.charAt(i + 1) == '#' && s.charAt(i + 2) == '#') {
|
||||
i += 2;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
result.append(c);
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
private void executeVoid3(TMemory memory, String s, TFunction function) throws EaterException {
|
||||
function.executeVoid(this, memory, s);
|
||||
private void executeVoid3(LineLocation location, TMemory memory, String s, TFunction function)
|
||||
throws EaterException, EaterExceptionLocated {
|
||||
function.executeVoid(this, memory, location, s);
|
||||
}
|
||||
|
||||
private void executeImport(TMemory memory, StringLocated s) throws EaterException {
|
||||
final EaterImport _import = new EaterImport(s.getTrimmed().getString());
|
||||
_import.execute(this, memory);
|
||||
private void executeImport(TMemory memory, StringLocated s) throws EaterException, EaterExceptionLocated {
|
||||
final EaterImport _import = new EaterImport(s.getTrimmed());
|
||||
_import.analyze(this, memory);
|
||||
|
||||
try {
|
||||
final File file = FileSystem.getInstance().getFile(
|
||||
applyFunctionsAndVariables(memory, _import.getLocation()));
|
||||
final File file = FileSystem.getInstance()
|
||||
.getFile(applyFunctionsAndVariables(memory, s.getLocation(), _import.getLocation()));
|
||||
if (file.exists() && file.isDirectory() == false) {
|
||||
importedFiles.add(file);
|
||||
return;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
throw new EaterException("Cannot import " + e.getMessage());
|
||||
throw EaterException.located("Cannot import " + e.getMessage(), s);
|
||||
}
|
||||
|
||||
throw new EaterException("Cannot import");
|
||||
throw EaterException.located("Cannot import", s);
|
||||
}
|
||||
|
||||
private void executeLog(TMemory memory, StringLocated s) throws EaterException {
|
||||
final EaterLog log = new EaterLog(s.getTrimmed().getString());
|
||||
log.execute(this, memory);
|
||||
private void executeLog(TMemory memory, StringLocated s) throws EaterException, EaterExceptionLocated {
|
||||
final EaterLog log = new EaterLog(s.getTrimmed());
|
||||
log.analyze(this, memory);
|
||||
}
|
||||
|
||||
private void executeIncludesub(TMemory memory, StringLocated s) throws EaterException {
|
||||
private void executeIncludesub(TMemory memory, StringLocated s) throws EaterException, EaterExceptionLocated {
|
||||
ImportedFiles saveImportedFiles = null;
|
||||
try {
|
||||
final EaterIncludesub include = new EaterIncludesub(s.getTrimmed().getString());
|
||||
include.execute(this, memory);
|
||||
final EaterIncludesub include = new EaterIncludesub(s.getTrimmed());
|
||||
include.analyze(this, memory);
|
||||
final String location = include.getLocation();
|
||||
final int idx = location.indexOf('!');
|
||||
Sub sub = null;
|
||||
@ -603,21 +438,20 @@ public class TContext {
|
||||
final Reader reader = f2.getReader(charset);
|
||||
ReadLine readerline = ReadLineReader.create(reader, location, s.getLocation());
|
||||
readerline = new UncommentReadLine(readerline);
|
||||
// readerline = new ReadLineQuoteComment(true).applyFilter(readerline);
|
||||
sub = Sub.fromFile(readerline, blocname, this, memory);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
throw new EaterException("cannot include " + e);
|
||||
throw EaterException.located("cannot include " + e, s);
|
||||
}
|
||||
}
|
||||
if (sub == null) {
|
||||
sub = subs.get(location);
|
||||
}
|
||||
if (sub == null) {
|
||||
throw new EaterException("cannot include " + location);
|
||||
throw EaterException.located("cannot include " + location, s);
|
||||
}
|
||||
runSub(memory, sub);
|
||||
executeLinesInternal(memory, sub.lines(), null);
|
||||
} finally {
|
||||
if (saveImportedFiles != null) {
|
||||
this.importedFiles = saveImportedFiles;
|
||||
@ -625,37 +459,32 @@ public class TContext {
|
||||
}
|
||||
}
|
||||
|
||||
private void runSub(TMemory memory, final Sub sub) throws EaterException {
|
||||
for (StringLocated sl : sub.lines()) {
|
||||
executeOneLine(memory, TLineType.getFromLine(sl.getString()), sl, null);
|
||||
}
|
||||
}
|
||||
|
||||
private void executeIncludeDef(TMemory memory, StringLocated s) throws EaterException {
|
||||
final EaterIncludeDef include = new EaterIncludeDef(s.getTrimmed().getString());
|
||||
include.execute(this, memory);
|
||||
private void executeIncludeDef(TMemory memory, StringLocated s) throws EaterException, EaterExceptionLocated {
|
||||
final EaterIncludeDef include = new EaterIncludeDef(s.getTrimmed());
|
||||
include.analyze(this, memory);
|
||||
final String definitionName = include.getLocation();
|
||||
final List<String> definition = definitionsContainer.getDefinition(definitionName);
|
||||
ReadLine reader2 = new ReadLineList(definition, s.getLocation());
|
||||
|
||||
try {
|
||||
// reader2 = new ReadLineQuoteComment(true).applyFilter(reader2);
|
||||
final List<StringLocated> body = new ArrayList<StringLocated>();
|
||||
do {
|
||||
final StringLocated sl = reader2.readLine();
|
||||
if (sl == null) {
|
||||
executeLinesInternal(memory, body, null);
|
||||
return;
|
||||
}
|
||||
executeOneLine(memory, TLineType.getFromLine(sl.getString()), sl, null);
|
||||
body.add(sl);
|
||||
} while (true);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
throw new EaterException("" + e);
|
||||
throw EaterException.located("" + e, s);
|
||||
}
|
||||
}
|
||||
|
||||
private void executeInclude(TMemory memory, StringLocated s) throws EaterException {
|
||||
final EaterInclude include = new EaterInclude(s.getTrimmed().getString());
|
||||
include.execute(this, memory);
|
||||
private void executeInclude(TMemory memory, StringLocated s) throws EaterException, EaterExceptionLocated {
|
||||
final EaterInclude include = new EaterInclude(s.getTrimmed());
|
||||
include.analyze(this, memory);
|
||||
String location = include.getLocation();
|
||||
final PreprocessorIncludeStrategy strategy = include.getPreprocessorIncludeStrategy();
|
||||
final int idx = location.lastIndexOf('!');
|
||||
@ -682,7 +511,7 @@ public class TContext {
|
||||
return;
|
||||
}
|
||||
if (strategy == PreprocessorIncludeStrategy.ONCE && filesUsedCurrent.contains(f2)) {
|
||||
throw new EaterException("This file has already been included");
|
||||
throw EaterException.located("This file has already been included", s);
|
||||
}
|
||||
|
||||
if (StartDiagramExtractReader.containsStartDiagram(f2, s, charset)) {
|
||||
@ -690,7 +519,7 @@ public class TContext {
|
||||
} else {
|
||||
final Reader reader = f2.getReader(charset);
|
||||
if (reader == null) {
|
||||
throw new EaterException("Cannot include file");
|
||||
throw EaterException.located("Cannot include file", s);
|
||||
}
|
||||
reader2 = ReadLineReader.create(reader, location, s.getLocation());
|
||||
}
|
||||
@ -698,18 +527,18 @@ public class TContext {
|
||||
this.importedFiles = this.importedFiles.withCurrentDir(f2.getParentFile());
|
||||
assert reader2 != null;
|
||||
filesUsedCurrent.add(f2);
|
||||
// filesUsedGlobal.add(f2);
|
||||
}
|
||||
}
|
||||
if (reader2 != null) {
|
||||
// reader2 = new ReadLineQuoteComment(true).applyFilter(reader2);
|
||||
try {
|
||||
final List<StringLocated> body = new ArrayList<StringLocated>();
|
||||
do {
|
||||
final StringLocated sl = reader2.readLine();
|
||||
if (sl == null) {
|
||||
executeLines(memory, body, null);
|
||||
return;
|
||||
}
|
||||
executeOneLine(memory, TLineType.getFromLine(sl.getString()), sl, null);
|
||||
body.add(sl);
|
||||
} while (true);
|
||||
} finally {
|
||||
if (saveImportedFiles != null) {
|
||||
@ -719,14 +548,14 @@ public class TContext {
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
throw new EaterException("cannot include " + e);
|
||||
throw EaterException.located("cannot include " + e, s);
|
||||
}
|
||||
|
||||
throw new EaterException("cannot include " + location);
|
||||
throw EaterException.located("cannot include " + location, s);
|
||||
}
|
||||
|
||||
public boolean isLegacyDefine(String functionName) {
|
||||
for (Map.Entry<TFunctionSignature, TFunction> ent : functions2.entrySet()) {
|
||||
for (Map.Entry<TFunctionSignature, TFunction> ent : functionsSet.functions().entrySet()) {
|
||||
if (ent.getKey().getFunctionName().equals(functionName) && ent.getValue().getFunctionType().isLegacy()) {
|
||||
return true;
|
||||
}
|
||||
@ -735,7 +564,7 @@ public class TContext {
|
||||
}
|
||||
|
||||
public boolean isUnquoted(String functionName) {
|
||||
for (Map.Entry<TFunctionSignature, TFunction> ent : functions2.entrySet()) {
|
||||
for (Map.Entry<TFunctionSignature, TFunction> ent : functionsSet.functions().entrySet()) {
|
||||
if (ent.getKey().getFunctionName().equals(functionName) && ent.getValue().isUnquoted()) {
|
||||
return true;
|
||||
}
|
||||
@ -744,7 +573,7 @@ public class TContext {
|
||||
}
|
||||
|
||||
public boolean doesFunctionExist(String functionName) {
|
||||
for (Map.Entry<TFunctionSignature, TFunction> ent : functions2.entrySet()) {
|
||||
for (Map.Entry<TFunctionSignature, TFunction> ent : functionsSet.functions().entrySet()) {
|
||||
if (ent.getKey().getFunctionName().equals(functionName)) {
|
||||
return true;
|
||||
}
|
||||
@ -752,30 +581,12 @@ public class TContext {
|
||||
return false;
|
||||
}
|
||||
|
||||
private static String getVarnameAt(TMemory memory, String s, int pos) {
|
||||
if (pos > 0 && TLineType.isLetterOrUnderscoreOrDigit(s.charAt(pos - 1)) && justAfterBackslashN(s, pos) == false) {
|
||||
return null;
|
||||
}
|
||||
final String varname = memory.variablesNames3().getLonguestMatchStartingIn(s.substring(pos));
|
||||
if (varname.length() == 0) {
|
||||
return null;
|
||||
}
|
||||
if (pos + varname.length() == s.length()
|
||||
|| TLineType.isLetterOrUnderscoreOrDigit(s.charAt(pos + varname.length())) == false) {
|
||||
return varname;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static boolean justAfterBackslashN(String s, int pos) {
|
||||
return pos > 1 && s.charAt(pos - 2) == '\\' && s.charAt(pos - 1) == 'n';
|
||||
}
|
||||
|
||||
private String getFunctionNameAt(String s, int pos) {
|
||||
if (pos > 0 && TLineType.isLetterOrUnderscoreOrDigit(s.charAt(pos - 1)) && justAfterBackslashN(s, pos) == false) {
|
||||
if (pos > 0 && TLineType.isLetterOrUnderscoreOrDigit(s.charAt(pos - 1))
|
||||
&& VariableManager.justAfterBackslashN(s, pos) == false) {
|
||||
return null;
|
||||
}
|
||||
final String fname = functions3.getLonguestMatchStartingIn(s.substring(pos));
|
||||
final String fname = functionsSet.getLonguestMatchStartingIn(s.substring(pos));
|
||||
if (fname.length() == 0) {
|
||||
return null;
|
||||
}
|
||||
@ -790,23 +601,6 @@ public class TContext {
|
||||
return debug;
|
||||
}
|
||||
|
||||
public final TFunctionImpl getPendingFunction() {
|
||||
return pendingFunction;
|
||||
}
|
||||
|
||||
private void addFunction(TFunction func) {
|
||||
if (func.getFunctionType() == TFunctionType.LEGACY_DEFINELONG) {
|
||||
((TFunctionImpl) func).finalizeEnddefinelong();
|
||||
}
|
||||
this.functions2.put(func.getSignature(), func);
|
||||
this.functions3.add(func.getSignature().getFunctionName() + "(");
|
||||
}
|
||||
|
||||
public void executeEndfunction() {
|
||||
addFunction(pendingFunction);
|
||||
pendingFunction = null;
|
||||
}
|
||||
|
||||
public String extractFromResultList(int n1) {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
while (resultList.size() > n1) {
|
||||
@ -828,4 +622,8 @@ public class TContext {
|
||||
}
|
||||
}
|
||||
|
||||
public TFunction getFunctionSmart(TFunctionSignature signature) {
|
||||
return functionsSet.getFunctionSmart(signature);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -36,6 +36,7 @@ package net.sourceforge.plantuml.tim;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import net.sourceforge.plantuml.LineLocation;
|
||||
import net.sourceforge.plantuml.tim.expression.TValue;
|
||||
|
||||
public interface TFunction {
|
||||
@ -46,11 +47,11 @@ public interface TFunction {
|
||||
|
||||
public TFunctionType getFunctionType();
|
||||
|
||||
public void executeVoid(TContext context, TMemory memory, String s) throws EaterException;
|
||||
public void executeVoid(TContext context, TMemory memory, LineLocation location, String s) throws EaterException, EaterExceptionLocated;
|
||||
|
||||
public TValue executeReturn(TContext context, TMemory memory, List<TValue> args) throws EaterException;
|
||||
public TValue executeReturn(TContext context, TMemory memory, LineLocation location, List<TValue> args) throws EaterException, EaterExceptionLocated;
|
||||
|
||||
public void executeVoidInternal(TContext context, TMemory memory, List<TValue> args) throws EaterException;
|
||||
public void executeVoidInternal(TContext context, TMemory memory, List<TValue> args) throws EaterException, EaterExceptionLocated;
|
||||
|
||||
public boolean isUnquoted();
|
||||
|
||||
|
@ -35,10 +35,12 @@
|
||||
package net.sourceforge.plantuml.tim;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import net.sourceforge.plantuml.LineLocation;
|
||||
import net.sourceforge.plantuml.StringLocated;
|
||||
import net.sourceforge.plantuml.tim.expression.TValue;
|
||||
|
||||
@ -76,72 +78,75 @@ public class TFunctionImpl implements TFunction {
|
||||
|
||||
public void addBody(StringLocated s) {
|
||||
body.add(s);
|
||||
if (TLineType.getFromLine(s.getString()) == TLineType.RETURN) {
|
||||
if (s.getType() == TLineType.RETURN) {
|
||||
this.functionType = TFunctionType.RETURN;
|
||||
}
|
||||
}
|
||||
|
||||
public void executeVoid(TContext context, TMemory memory, String s) throws EaterException {
|
||||
final EaterFunctionCall call = new EaterFunctionCall(s, context.isLegacyDefine(signature.getFunctionName()),
|
||||
unquoted);
|
||||
call.execute(context, memory);
|
||||
public void executeVoid(TContext context, TMemory memory, LineLocation location, String s)
|
||||
throws EaterException, EaterExceptionLocated {
|
||||
final EaterFunctionCall call = new EaterFunctionCall(new StringLocated(s, location),
|
||||
context.isLegacyDefine(signature.getFunctionName()), unquoted);
|
||||
call.analyze(context, memory);
|
||||
final String endOfLine = call.getEndOfLine();
|
||||
final List<TValue> args = call.getValues();
|
||||
executeVoidInternal(context, memory, args);
|
||||
context.appendEndOfLine(endOfLine);
|
||||
}
|
||||
|
||||
public void executeVoidInternal(TContext context, TMemory memory, List<TValue> args) throws EaterException {
|
||||
public void executeVoidInternal(TContext context, TMemory memory, List<TValue> args)
|
||||
throws EaterException, EaterExceptionLocated {
|
||||
if (functionType != TFunctionType.VOID && functionType != TFunctionType.LEGACY_DEFINELONG) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
final TMemory copy = getNewMemory(memory, args);
|
||||
for (StringLocated sl : body) {
|
||||
context.executeOneLine(copy, TLineType.getFromLine(sl.getString()), sl, TFunctionType.VOID);
|
||||
}
|
||||
context.executeLines(copy, body, TFunctionType.VOID);
|
||||
}
|
||||
|
||||
private TMemory getNewMemory(TMemory memory, List<TValue> values) {
|
||||
final Map<String, TVariable> foo = new HashMap<String, TVariable>();
|
||||
final Map<String, TValue> foo = new HashMap<String, TValue>();
|
||||
for (int i = 0; i < args.size(); i++) {
|
||||
final TValue tmp = i < values.size() ? values.get(i) : args.get(i).getOptionalDefaultValue();
|
||||
foo.put(args.get(i).getName(), new TVariable(tmp));
|
||||
foo.put(args.get(i).getName(), tmp);
|
||||
}
|
||||
final TMemory copy = memory.forkFromGlobal(foo);
|
||||
return copy;
|
||||
}
|
||||
|
||||
public TValue executeReturn(TContext context, TMemory memory, List<TValue> args) throws EaterException {
|
||||
public TValue executeReturn(TContext context, TMemory memory, LineLocation location, List<TValue> args)
|
||||
throws EaterException, EaterExceptionLocated {
|
||||
if (functionType == TFunctionType.LEGACY_DEFINE) {
|
||||
return executeReturnLegacyDefine(context, memory, args);
|
||||
return executeReturnLegacyDefine(location, context, memory, args);
|
||||
}
|
||||
if (functionType != TFunctionType.RETURN) {
|
||||
throw new EaterException("Illegal call here");
|
||||
throw EaterException.unlocated("Illegal call here");
|
||||
}
|
||||
final TMemory copy = getNewMemory(memory, args);
|
||||
|
||||
for (StringLocated sl : body) {
|
||||
final TLineType lineType = TLineType.getFromLine(sl.getString());
|
||||
final ConditionalContext conditionalContext = copy.peekConditionalContext();
|
||||
if ((conditionalContext == null || conditionalContext.conditionIsOkHere()) && lineType == TLineType.RETURN) {
|
||||
final TLineType lineType = sl.getType();
|
||||
final ExecutionContextIf conditionalContext = copy.peekIf();
|
||||
if ((conditionalContext == null || ((ExecutionContextIf) conditionalContext).conditionIsOkHere())
|
||||
&& lineType == TLineType.RETURN) {
|
||||
// System.err.println("s2=" + sl.getString());
|
||||
final EaterReturn eaterReturn = new EaterReturn(sl.getString());
|
||||
eaterReturn.execute(context, copy);
|
||||
final EaterReturn eaterReturn = new EaterReturn(sl);
|
||||
eaterReturn.analyze(context, copy);
|
||||
// System.err.println("s3=" + eaterReturn.getValue2());
|
||||
return eaterReturn.getValue2();
|
||||
}
|
||||
context.executeOneLine(copy, lineType, sl, TFunctionType.RETURN);
|
||||
context.executeLines(copy, Arrays.asList(sl), TFunctionType.RETURN);
|
||||
}
|
||||
throw new EaterException("no return");
|
||||
throw EaterException.unlocated("no return");
|
||||
// return TValue.fromString("(NONE)");
|
||||
}
|
||||
|
||||
private TValue executeReturnLegacyDefine(TContext context, TMemory memory, List<TValue> args) throws EaterException {
|
||||
private TValue executeReturnLegacyDefine(LineLocation location, TContext context, TMemory memory, List<TValue> args)
|
||||
throws EaterException, EaterExceptionLocated {
|
||||
if (legacyDefinition == null) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
final TMemory copy = getNewMemory(memory, args);
|
||||
final String tmp = context.applyFunctionsAndVariables(copy, legacyDefinition);
|
||||
final String tmp = context.applyFunctionsAndVariables(copy, location, legacyDefinition);
|
||||
if (tmp == null) {
|
||||
return TValue.fromString("");
|
||||
}
|
||||
|
@ -36,9 +36,23 @@ package net.sourceforge.plantuml.tim;
|
||||
|
||||
public enum TLineType {
|
||||
|
||||
PLAIN, AFFECTATION_DEFINE, AFFECTATION, ASSERT, IF, IFDEF, UNDEF, IFNDEF, ELSE, ELSEIF, ENDIF, DECLARE_FUNCTION, END_FUNCTION, RETURN, LEGACY_DEFINE, LEGACY_DEFINELONG, INCLUDE, INCLUDE_DEF, IMPORT, STARTSUB, ENDSUB, INCLUDESUB, LOG, DUMP_MEMORY, COMMENT_SIMPLE, COMMENT_LONG_START;
|
||||
PLAIN, AFFECTATION_DEFINE, AFFECTATION, ASSERT, IF, IFDEF, UNDEF, IFNDEF, ELSE, ELSEIF, ENDIF, WHILE, ENDWHILE,
|
||||
FOREACH, ENDFOREACH, DECLARE_FUNCTION, END_FUNCTION, RETURN, LEGACY_DEFINE, LEGACY_DEFINELONG, INCLUDE, INCLUDE_DEF,
|
||||
IMPORT, STARTSUB, ENDSUB, INCLUDESUB, LOG, DUMP_MEMORY, COMMENT_SIMPLE, COMMENT_LONG_START;
|
||||
|
||||
public static TLineType getFromLine(String s) {
|
||||
// private boolean elseLike() {
|
||||
// return this == ELSE || this == ELSEIF;
|
||||
// }
|
||||
//
|
||||
// public boolean incIndentAfter() {
|
||||
// return this == IF || this == IFDEF || this == IFNDEF || elseLike();
|
||||
// }
|
||||
//
|
||||
// public boolean decIndentBefore() {
|
||||
// return this == ENDIF || elseLike();
|
||||
// }
|
||||
|
||||
public static TLineType getFromLineInternal(String s) {
|
||||
if (s.matches("^\\s*!define\\s+[\\p{L}_][\\p{L}_0-9]*\\(.*")) {
|
||||
return LEGACY_DEFINE;
|
||||
}
|
||||
@ -87,6 +101,18 @@ public enum TLineType {
|
||||
if (s.matches("^\\s*!endif\\b.*")) {
|
||||
return ENDIF;
|
||||
}
|
||||
if (s.matches("^\\s*!while\\s+.*")) {
|
||||
return WHILE;
|
||||
}
|
||||
if (s.matches("^\\s*!endwhile\\b.*")) {
|
||||
return ENDWHILE;
|
||||
}
|
||||
if (s.matches("^\\s*!foreach\\s+.*")) {
|
||||
return FOREACH;
|
||||
}
|
||||
if (s.matches("^\\s*!endfor\\b.*")) {
|
||||
return ENDFOREACH;
|
||||
}
|
||||
if (s.matches("^\\s*!(endfunction|enddefinelong)\\b.*")) {
|
||||
return END_FUNCTION;
|
||||
}
|
||||
|
@ -37,11 +37,13 @@ package net.sourceforge.plantuml.tim;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import net.sourceforge.plantuml.tim.expression.TValue;
|
||||
|
||||
public interface TMemory {
|
||||
|
||||
public TVariable getVariable(String varname);
|
||||
public TValue getVariable(String varname);
|
||||
|
||||
public void putVariable(String varname, TVariable value, TVariableScope scope) throws EaterException;
|
||||
public void putVariable(String varname, TValue value, TVariableScope scope) throws EaterException;
|
||||
|
||||
public void removeVariable(String varname);
|
||||
|
||||
@ -51,15 +53,28 @@ public interface TMemory {
|
||||
|
||||
public Trie variablesNames3();
|
||||
|
||||
public TMemory forkFromGlobal(Map<String, TVariable> input);
|
||||
public TMemory forkFromGlobal(Map<String, TValue> input);
|
||||
|
||||
public ConditionalContext peekConditionalContext();
|
||||
public ExecutionContextIf peekIf();
|
||||
|
||||
public boolean areAllIfOk();
|
||||
public boolean areAllIfOk(TContext context, TMemory memory) throws EaterException;
|
||||
|
||||
public void addConditionalContext(ConditionalContext context);
|
||||
public void addIf(ExecutionContextIf context);
|
||||
|
||||
public ConditionalContext pollConditionalContext();
|
||||
public void addWhile(ExecutionContextWhile value);
|
||||
|
||||
public void addForeach(ExecutionContextForeach value);
|
||||
|
||||
public ExecutionContextIf pollIf();
|
||||
|
||||
public ExecutionContextWhile pollWhile();
|
||||
|
||||
public ExecutionContextWhile peekWhile();
|
||||
|
||||
public ExecutionContextForeach pollForeach();
|
||||
|
||||
public ExecutionContextForeach peekForeach();
|
||||
|
||||
public void dumpDebug(String message);
|
||||
|
||||
}
|
||||
|
@ -44,12 +44,12 @@ import java.util.TreeMap;
|
||||
import net.sourceforge.plantuml.Log;
|
||||
import net.sourceforge.plantuml.tim.expression.TValue;
|
||||
|
||||
public class TMemoryGlobal extends ConditionalContexts implements TMemory {
|
||||
public class TMemoryGlobal extends ExecutionContexts implements TMemory {
|
||||
|
||||
private final Map<String, TVariable> globalVariables = new HashMap<String, TVariable>();
|
||||
private final Map<String, TValue> globalVariables = new HashMap<String, TValue>();
|
||||
private final TrieImpl variables = new TrieImpl();
|
||||
|
||||
public TVariable getVariable(String varname) {
|
||||
public TValue getVariable(String varname) {
|
||||
return this.globalVariables.get(varname);
|
||||
}
|
||||
|
||||
@ -61,17 +61,17 @@ public class TMemoryGlobal extends ConditionalContexts implements TMemory {
|
||||
|
||||
void dumpMemoryInternal() {
|
||||
Log.error("[MemGlobal] Number of variable(s) : " + globalVariables.size());
|
||||
for (Entry<String, TVariable> ent : new TreeMap<String, TVariable>(globalVariables).entrySet()) {
|
||||
for (Entry<String, TValue> ent : new TreeMap<String, TValue>(globalVariables).entrySet()) {
|
||||
final String name = ent.getKey();
|
||||
final TValue value = ent.getValue().getValue();
|
||||
final TValue value = ent.getValue();
|
||||
Log.error("[MemGlobal] " + name + " = " + value);
|
||||
}
|
||||
}
|
||||
|
||||
public void putVariable(String varname, TVariable value, TVariableScope scope) throws EaterException {
|
||||
public void putVariable(String varname, TValue value, TVariableScope scope) throws EaterException {
|
||||
Log.info("[MemGlobal] Setting " + varname);
|
||||
if (scope == TVariableScope.LOCAL) {
|
||||
throw new EaterException("Cannot use local variable here");
|
||||
throw EaterException.unlocated("Cannot use local variable here");
|
||||
}
|
||||
this.globalVariables.put(varname, value);
|
||||
this.variables.add(varname);
|
||||
@ -94,7 +94,7 @@ public class TMemoryGlobal extends ConditionalContexts implements TMemory {
|
||||
return variables;
|
||||
}
|
||||
|
||||
public TMemory forkFromGlobal(Map<String, TVariable> input) {
|
||||
public TMemory forkFromGlobal(Map<String, TValue> input) {
|
||||
return new TMemoryLocal(this, input);
|
||||
}
|
||||
|
||||
|
@ -43,15 +43,15 @@ import java.util.TreeMap;
|
||||
import net.sourceforge.plantuml.Log;
|
||||
import net.sourceforge.plantuml.tim.expression.TValue;
|
||||
|
||||
public class TMemoryLocal extends ConditionalContexts implements TMemory {
|
||||
public class TMemoryLocal extends ExecutionContexts implements TMemory {
|
||||
|
||||
private final TMemoryGlobal memoryGlobal;
|
||||
private TrieImpl overridenVariables00;
|
||||
private final Map<String, TVariable> overridenVariables01 = new HashMap<String, TVariable>();
|
||||
private final Map<String, TValue> overridenVariables01 = new HashMap<String, TValue>();
|
||||
private final TrieImpl localVariables00 = new TrieImpl();
|
||||
private final Map<String, TVariable> localVariables01 = new HashMap<String, TVariable>();
|
||||
private final Map<String, TValue> localVariables01 = new HashMap<String, TValue>();
|
||||
|
||||
public TMemoryLocal(TMemoryGlobal global, Map<String, TVariable> input) {
|
||||
public TMemoryLocal(TMemoryGlobal global, Map<String, TValue> input) {
|
||||
this.memoryGlobal = global;
|
||||
this.overridenVariables01.putAll(input);
|
||||
}
|
||||
@ -59,24 +59,24 @@ public class TMemoryLocal extends ConditionalContexts implements TMemory {
|
||||
public void dumpDebug(String message) {
|
||||
Log.error("[MemLocal] Start of memory_dump " + message);
|
||||
memoryGlobal.dumpMemoryInternal();
|
||||
final TreeMap<String, TVariable> over = new TreeMap<String, TVariable>(overridenVariables01);
|
||||
final TreeMap<String, TValue> over = new TreeMap<String, TValue>(overridenVariables01);
|
||||
Log.error("[MemLocal] Number of overriden variable(s) : " + over.size());
|
||||
for (Entry<String, TVariable> ent : over.entrySet()) {
|
||||
for (Entry<String, TValue> ent : over.entrySet()) {
|
||||
final String name = ent.getKey();
|
||||
final TValue value = ent.getValue().getValue();
|
||||
final TValue value = ent.getValue();
|
||||
Log.error("[MemLocal] " + name + " = " + value);
|
||||
}
|
||||
final TreeMap<String, TVariable> local = new TreeMap<String, TVariable>(localVariables01);
|
||||
final TreeMap<String, TValue> local = new TreeMap<String, TValue>(localVariables01);
|
||||
Log.error("[MemLocal] Number of local variable(s) : " + local.size());
|
||||
for (Entry<String, TVariable> ent : local.entrySet()) {
|
||||
for (Entry<String, TValue> ent : local.entrySet()) {
|
||||
final String name = ent.getKey();
|
||||
final TValue value = ent.getValue().getValue();
|
||||
final TValue value = ent.getValue();
|
||||
Log.error("[MemLocal] " + name + " = " + value);
|
||||
}
|
||||
Log.error("[MemGlobal] End of memory_dump");
|
||||
}
|
||||
|
||||
public void putVariable(String varname, TVariable value, TVariableScope scope) throws EaterException {
|
||||
public void putVariable(String varname, TValue value, TVariableScope scope) throws EaterException {
|
||||
if (scope == TVariableScope.GLOBAL) {
|
||||
memoryGlobal.putVariable(varname, value, scope);
|
||||
return;
|
||||
@ -110,8 +110,8 @@ public class TMemoryLocal extends ConditionalContexts implements TMemory {
|
||||
}
|
||||
}
|
||||
|
||||
public TVariable getVariable(String varname) {
|
||||
TVariable result = overridenVariables01.get(varname);
|
||||
public TValue getVariable(String varname) {
|
||||
TValue result = overridenVariables01.get(varname);
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
@ -170,7 +170,7 @@ public class TMemoryLocal extends ConditionalContexts implements TMemory {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public TMemory forkFromGlobal(Map<String, TVariable> input) {
|
||||
public TMemory forkFromGlobal(Map<String, TValue> input) {
|
||||
return new TMemoryLocal(memoryGlobal, input);
|
||||
}
|
||||
|
||||
|
@ -58,18 +58,14 @@ public class TimLoader {
|
||||
}
|
||||
}
|
||||
|
||||
public void load(List<StringLocated> input) {
|
||||
for (StringLocated s : input) {
|
||||
final TLineType type = TLineType.getFromLine(s.getTrimmed().getString());
|
||||
try {
|
||||
context.executeOneLine(global, type, s, null);
|
||||
} catch (EaterException e) {
|
||||
context.getResultList().add(s.withErrorPreprocessor(e.getMessage()));
|
||||
this.resultList = context.getResultList();
|
||||
changeLastLine(context.getDebug(), e.getMessage());
|
||||
this.preprocessorError = true;
|
||||
return;
|
||||
}
|
||||
public void load(List<StringLocated> list) {
|
||||
// CodeIteratorImpl.indentNow(list);
|
||||
try {
|
||||
context.executeLines(global, list, null);
|
||||
} catch (EaterExceptionLocated e) {
|
||||
context.getResultList().add(e.getLocation().withErrorPreprocessor(e.getMessage()));
|
||||
changeLastLine(context.getDebug(), e.getMessage());
|
||||
this.preprocessorError = true;
|
||||
}
|
||||
this.resultList = context.getResultList();
|
||||
}
|
||||
|
143
src/net/sourceforge/plantuml/tim/VariableManager.java
Normal file
143
src/net/sourceforge/plantuml/tim/VariableManager.java
Normal file
@ -0,0 +1,143 @@
|
||||
/* ========================================================================
|
||||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* (C) Copyright 2009-2020, Arnaud Roques
|
||||
*
|
||||
* Project Info: http://plantuml.com
|
||||
*
|
||||
* If you like this project or if you find it useful, you can support us at:
|
||||
*
|
||||
* http://plantuml.com/patreon (only 1$ per month!)
|
||||
* http://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.tim;
|
||||
|
||||
import net.sourceforge.plantuml.LineLocation;
|
||||
import net.sourceforge.plantuml.json.JsonArray;
|
||||
import net.sourceforge.plantuml.json.JsonObject;
|
||||
import net.sourceforge.plantuml.json.JsonValue;
|
||||
import net.sourceforge.plantuml.tim.expression.TValue;
|
||||
|
||||
public class VariableManager {
|
||||
|
||||
private final TMemory memory;
|
||||
private final TContext context;
|
||||
private final LineLocation location;
|
||||
|
||||
public VariableManager(TContext context, TMemory memory, LineLocation location) {
|
||||
this.memory = memory;
|
||||
this.context = context;
|
||||
this.location = location;
|
||||
}
|
||||
|
||||
public int replaceVariables(String str, int i, StringBuilder result) throws EaterException, EaterExceptionLocated {
|
||||
final String presentVariable = getVarnameAt(str, i);
|
||||
if (result.toString().endsWith("##")) {
|
||||
result.setLength(result.length() - 2);
|
||||
}
|
||||
final TValue value = memory.getVariable(presentVariable);
|
||||
i += presentVariable.length() - 1;
|
||||
if (value.isJson()) {
|
||||
if (value.toJson().isString()) {
|
||||
result.append(value.toJson().asString());
|
||||
} else {
|
||||
JsonValue jsonValue = (JsonObject) value.toJson();
|
||||
i++;
|
||||
i = replaceJson(jsonValue, str, i, result) - 1;
|
||||
}
|
||||
} else {
|
||||
result.append(value.toString());
|
||||
}
|
||||
if (i + 2 < str.length() && str.charAt(i + 1) == '#' && str.charAt(i + 2) == '#') {
|
||||
i += 2;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
private int replaceJson(JsonValue jsonValue, String str, int i, StringBuilder result)
|
||||
throws EaterException, EaterExceptionLocated {
|
||||
while (true) {
|
||||
final char n = str.charAt(i);
|
||||
if (n == '.') {
|
||||
i++;
|
||||
final StringBuilder fieldName = new StringBuilder();
|
||||
while (true) {
|
||||
if (i >= str.length()) {
|
||||
throw EaterException.unlocated("Parsing error");
|
||||
}
|
||||
if (Character.isJavaIdentifierPart(str.charAt(i)) == false) {
|
||||
break;
|
||||
}
|
||||
fieldName.append(str.charAt(i));
|
||||
i++;
|
||||
}
|
||||
jsonValue = ((JsonObject) jsonValue).get(fieldName.toString());
|
||||
} else if (n == '[') {
|
||||
i++;
|
||||
final StringBuilder inBracket = new StringBuilder();
|
||||
while (true) {
|
||||
if (str.charAt(i) == ']') {
|
||||
break;
|
||||
}
|
||||
inBracket.append(str.charAt(i));
|
||||
i++;
|
||||
}
|
||||
final String nbString = context.applyFunctionsAndVariables(memory, location, inBracket.toString());
|
||||
final int nb = Integer.parseInt(nbString);
|
||||
jsonValue = ((JsonArray) jsonValue).get(nb);
|
||||
i++;
|
||||
} else {
|
||||
if (jsonValue.isString()) {
|
||||
result.append(jsonValue.asString());
|
||||
} else {
|
||||
result.append(jsonValue.toString());
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
public String getVarnameAt(String s, int pos) {
|
||||
if (pos > 0 && TLineType.isLetterOrUnderscoreOrDigit(s.charAt(pos - 1))
|
||||
&& justAfterBackslashN(s, pos) == false) {
|
||||
return null;
|
||||
}
|
||||
final String varname = memory.variablesNames3().getLonguestMatchStartingIn(s.substring(pos));
|
||||
if (varname.length() == 0) {
|
||||
return null;
|
||||
}
|
||||
if (pos + varname.length() == s.length()
|
||||
|| TLineType.isLetterOrUnderscoreOrDigit(s.charAt(pos + varname.length())) == false) {
|
||||
return varname;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static boolean justAfterBackslashN(String s, int pos) {
|
||||
return pos > 1 && s.charAt(pos - 2) == '\\' && s.charAt(pos - 1) == 'n';
|
||||
}
|
||||
|
||||
}
|
@ -36,11 +36,10 @@ package net.sourceforge.plantuml.tim.expression;
|
||||
|
||||
import net.sourceforge.plantuml.tim.TFunction;
|
||||
import net.sourceforge.plantuml.tim.TFunctionSignature;
|
||||
import net.sourceforge.plantuml.tim.TVariable;
|
||||
|
||||
public interface Knowledge {
|
||||
|
||||
public TVariable getVariable(String name);
|
||||
public TValue getVariable(String name);
|
||||
|
||||
public TFunction getFunction(TFunctionSignature signature);
|
||||
|
||||
|
@ -39,6 +39,8 @@ import java.util.ArrayList;
|
||||
import java.util.Deque;
|
||||
import java.util.List;
|
||||
|
||||
import net.sourceforge.plantuml.LineLocation;
|
||||
import net.sourceforge.plantuml.tim.EaterExceptionLocated;
|
||||
import net.sourceforge.plantuml.tim.EaterException;
|
||||
import net.sourceforge.plantuml.tim.TContext;
|
||||
import net.sourceforge.plantuml.tim.TFunction;
|
||||
@ -51,7 +53,12 @@ public class ReversePolishInterpretor {
|
||||
private boolean trace = false;
|
||||
|
||||
public ReversePolishInterpretor(TokenStack queue, Knowledge knowledge, TMemory memory, TContext context)
|
||||
throws EaterException {
|
||||
throws EaterException, EaterExceptionLocated {
|
||||
this(null, queue, knowledge, memory, context);
|
||||
}
|
||||
|
||||
public ReversePolishInterpretor(LineLocation location, TokenStack queue, Knowledge knowledge, TMemory memory,
|
||||
TContext context) throws EaterException, EaterExceptionLocated {
|
||||
|
||||
final Deque<TValue> stack = new ArrayDeque<TValue>();
|
||||
if (trace)
|
||||
@ -64,12 +71,14 @@ public class ReversePolishInterpretor {
|
||||
stack.addFirst(TValue.fromNumber(token));
|
||||
} else if (token.getTokenType() == TokenType.QUOTED_STRING) {
|
||||
stack.addFirst(TValue.fromString(token));
|
||||
} else if (token.getTokenType() == TokenType.JSON_DATA) {
|
||||
stack.addFirst(TValue.fromJson(token.getJson()));
|
||||
} else if (token.getTokenType() == TokenType.OPERATOR) {
|
||||
final TValue v2 = stack.removeFirst();
|
||||
final TValue v1 = stack.removeFirst();
|
||||
final TokenOperator op = token.getTokenOperator();
|
||||
if (op == null) {
|
||||
throw new EaterException("bad op");
|
||||
throw EaterException.unlocated("bad op");
|
||||
}
|
||||
final TValue tmp = op.operate(v1, v2);
|
||||
stack.addFirst(tmp);
|
||||
@ -77,7 +86,7 @@ public class ReversePolishInterpretor {
|
||||
final int nb = Integer.parseInt(token.getSurface());
|
||||
final Token token2 = it.nextToken();
|
||||
if (token2.getTokenType() != TokenType.FUNCTION_NAME) {
|
||||
throw new EaterException("rpn43");
|
||||
throw EaterException.unlocated("rpn43");
|
||||
}
|
||||
if (trace)
|
||||
System.err.println("token2=" + token2);
|
||||
@ -85,10 +94,11 @@ public class ReversePolishInterpretor {
|
||||
if (trace)
|
||||
System.err.println("function=" + function);
|
||||
if (function == null) {
|
||||
throw new EaterException("Unknow built-in function " + token2.getSurface());
|
||||
throw EaterException.unlocated("Unknow built-in function " + token2.getSurface());
|
||||
}
|
||||
if (function.canCover(nb) == false) {
|
||||
throw new EaterException("Bad number of arguments for " + function.getSignature().getFunctionName());
|
||||
throw EaterException
|
||||
.unlocated("Bad number of arguments for " + function.getSignature().getFunctionName());
|
||||
}
|
||||
final List<TValue> args = new ArrayList<TValue>();
|
||||
for (int i = 0; i < nb; i++) {
|
||||
@ -96,12 +106,15 @@ public class ReversePolishInterpretor {
|
||||
}
|
||||
if (trace)
|
||||
System.err.println("args=" + args);
|
||||
final TValue r = function.executeReturn(context, memory, args);
|
||||
if (location == null) {
|
||||
throw EaterException.unlocated("rpn44");
|
||||
}
|
||||
final TValue r = function.executeReturn(context, memory, location, args);
|
||||
if (trace)
|
||||
System.err.println("r=" + r);
|
||||
stack.addFirst(r);
|
||||
} else {
|
||||
throw new EaterException("rpn41");
|
||||
throw EaterException.unlocated("rpn41");
|
||||
}
|
||||
}
|
||||
result = stack.removeFirst();
|
||||
|
@ -37,9 +37,6 @@ package net.sourceforge.plantuml.tim.expression;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Deque;
|
||||
|
||||
import net.sourceforge.plantuml.tim.EaterException;
|
||||
import net.sourceforge.plantuml.tim.TVariable;
|
||||
|
||||
// https://en.wikipedia.org/wiki/Shunting-yard_algorithm
|
||||
// https://en.cppreference.com/w/c/language/operator_precedence
|
||||
public class ShuntingYard {
|
||||
@ -58,7 +55,7 @@ public class ShuntingYard {
|
||||
System.err.println("");
|
||||
}
|
||||
|
||||
public ShuntingYard(TokenIterator it, Knowledge knowledge) throws EaterException {
|
||||
public ShuntingYard(TokenIterator it, Knowledge knowledge) {
|
||||
|
||||
while (it.hasMoreTokens()) {
|
||||
final Token token = it.nextToken();
|
||||
@ -71,15 +68,16 @@ public class ShuntingYard {
|
||||
operatorStack.addFirst(token);
|
||||
} else if (token.getTokenType() == TokenType.PLAIN_TEXT) {
|
||||
final String name = token.getSurface();
|
||||
final TVariable variable = knowledge.getVariable(name);
|
||||
final TValue variable = knowledge.getVariable(name);
|
||||
if (variable == null) {
|
||||
throw new EaterException("Unknown variable " + name);
|
||||
ouputQueue.add(new Token("undefined", TokenType.QUOTED_STRING, null));
|
||||
} else {
|
||||
ouputQueue.add(variable.toToken());
|
||||
}
|
||||
ouputQueue.add(variable.getValue().toToken());
|
||||
} else if (token.getTokenType() == TokenType.OPERATOR) {
|
||||
while ((thereIsAFunctionAtTheTopOfTheOperatorStack(token) //
|
||||
|| thereIsAnOperatorAtTheTopOfTheOperatorStackWithGreaterPrecedence(token) //
|
||||
|| theOperatorAtTheTopOfTheOperatorStackHasEqualPrecedenceAndIsLeftAssociative(token)) //
|
||||
|| theOperatorAtTheTopOfTheOperatorStackHasEqualPrecedenceAndIsLeftAssociative(token)) //
|
||||
&& theOperatorAtTheTopOfTheOperatorStackIsNotALeftParenthesis(token)) {
|
||||
ouputQueue.add(operatorStack.removeFirst());
|
||||
}
|
||||
|
@ -142,9 +142,12 @@ public class TValue {
|
||||
|
||||
public Token toToken() {
|
||||
if (isNumber()) {
|
||||
return new Token(toString(), TokenType.NUMBER);
|
||||
return new Token(toString(), TokenType.NUMBER, null);
|
||||
}
|
||||
return new Token(toString(), TokenType.QUOTED_STRING);
|
||||
if (isJson()) {
|
||||
return new Token(toString(), TokenType.JSON_DATA, jsonValue);
|
||||
}
|
||||
return new Token(toString(), TokenType.QUOTED_STRING, null);
|
||||
}
|
||||
|
||||
public TValue greaterThanOrEquals(TValue v2) {
|
||||
|
@ -34,9 +34,12 @@
|
||||
*/
|
||||
package net.sourceforge.plantuml.tim.expression;
|
||||
|
||||
import net.sourceforge.plantuml.json.JsonValue;
|
||||
|
||||
public class Token {
|
||||
|
||||
private final String surface;
|
||||
private final JsonValue json;
|
||||
private final TokenType tokenType;
|
||||
|
||||
@Override
|
||||
@ -44,13 +47,14 @@ public class Token {
|
||||
return tokenType + "{" + surface + "}";
|
||||
}
|
||||
|
||||
public Token(char surface, TokenType tokenType) {
|
||||
this("" + surface, tokenType);
|
||||
public Token(char surface, TokenType tokenType, JsonValue json) {
|
||||
this("" + surface, tokenType, json);
|
||||
}
|
||||
|
||||
public Token(String surface, TokenType tokenType) {
|
||||
public Token(String surface, TokenType tokenType, JsonValue json) {
|
||||
this.surface = surface;
|
||||
this.tokenType = tokenType;
|
||||
this.json = json;
|
||||
}
|
||||
|
||||
public TokenOperator getTokenOperator() {
|
||||
@ -73,7 +77,14 @@ public class Token {
|
||||
if (this.tokenType != TokenType.PLAIN_TEXT) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
return new Token(surface, TokenType.FUNCTION_NAME);
|
||||
return new Token(surface, TokenType.FUNCTION_NAME, null);
|
||||
}
|
||||
|
||||
public JsonValue getJson() {
|
||||
if (this.tokenType != TokenType.JSON_DATA) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
return json;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -42,7 +42,9 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import net.sourceforge.plantuml.LineLocation;
|
||||
import net.sourceforge.plantuml.tim.Eater;
|
||||
import net.sourceforge.plantuml.tim.EaterExceptionLocated;
|
||||
import net.sourceforge.plantuml.tim.EaterException;
|
||||
import net.sourceforge.plantuml.tim.TContext;
|
||||
import net.sourceforge.plantuml.tim.TMemory;
|
||||
@ -93,7 +95,7 @@ public class TokenStack {
|
||||
eater.skipSpaces();
|
||||
final char ch = eater.peekChar();
|
||||
if (ch == 0) {
|
||||
throw new EaterException("until001");
|
||||
throw EaterException.unlocated("until001");
|
||||
}
|
||||
if (level == 0 && (ch == ',' || ch == ')')) {
|
||||
return result;
|
||||
@ -114,7 +116,7 @@ public class TokenStack {
|
||||
while (true) {
|
||||
final Token ch = it.peekToken();
|
||||
if (ch == null) {
|
||||
throw new EaterException("until002");
|
||||
throw EaterException.unlocated("until002");
|
||||
}
|
||||
final TokenType typech = ch.getTokenType();
|
||||
if (level == 0 && (typech == TokenType.COMMA || typech == TokenType.CLOSE_PAREN_MATH)
|
||||
@ -147,10 +149,10 @@ public class TokenStack {
|
||||
} else if (type == TokenType.COMMA) {
|
||||
result++;
|
||||
} else {
|
||||
throw new EaterException("count13");
|
||||
throw EaterException.unlocated("count13");
|
||||
}
|
||||
}
|
||||
throw new EaterException("count12");
|
||||
throw EaterException.unlocated("count12");
|
||||
}
|
||||
|
||||
public void guessFunctions() throws EaterException {
|
||||
@ -172,10 +174,10 @@ public class TokenStack {
|
||||
assert tokens.get(iopen).getTokenType() == TokenType.OPEN_PAREN_MATH;
|
||||
assert tokens.get(iclose).getTokenType() == TokenType.CLOSE_PAREN_MATH;
|
||||
if (iopen > 0 && tokens.get(iopen - 1).getTokenType() == TokenType.PLAIN_TEXT) {
|
||||
tokens.set(iopen - 1, new Token(tokens.get(iopen - 1).getSurface(), TokenType.FUNCTION_NAME));
|
||||
tokens.set(iopen - 1, new Token(tokens.get(iopen - 1).getSurface(), TokenType.FUNCTION_NAME, null));
|
||||
final int nbArg = countFunctionArg(subTokenStack(iopen + 1).tokenIterator());
|
||||
tokens.set(iopen, new Token("" + nbArg, TokenType.OPEN_PAREN_FUNC));
|
||||
tokens.set(iclose, new Token(")", TokenType.CLOSE_PAREN_FUNC));
|
||||
tokens.set(iopen, new Token("" + nbArg, TokenType.OPEN_PAREN_FUNC, null));
|
||||
tokens.set(iclose, new Token(")", TokenType.CLOSE_PAREN_FUNC, null));
|
||||
}
|
||||
}
|
||||
// System.err.println("after=" + toString());
|
||||
@ -206,14 +208,14 @@ public class TokenStack {
|
||||
return new InternalIterator();
|
||||
}
|
||||
|
||||
public TValue getResult(TContext context, TMemory memory) throws EaterException {
|
||||
public TValue getResult(LineLocation location, TContext context, TMemory memory) throws EaterException, EaterExceptionLocated {
|
||||
final Knowledge knowledge = context.asKnowledge(memory);
|
||||
final TokenStack tmp = withoutSpace();
|
||||
tmp.guessFunctions();
|
||||
final TokenIterator it = tmp.tokenIterator();
|
||||
final ShuntingYard shuntingYard = new ShuntingYard(it, knowledge);
|
||||
final ReversePolishInterpretor rpn = new ReversePolishInterpretor(shuntingYard.getQueue(), knowledge, memory,
|
||||
context);
|
||||
final ReversePolishInterpretor rpn = new ReversePolishInterpretor(location, shuntingYard.getQueue(), knowledge,
|
||||
memory, context);
|
||||
return rpn.getResult();
|
||||
|
||||
}
|
||||
|
@ -39,7 +39,7 @@ import net.sourceforge.plantuml.tim.EaterException;
|
||||
import net.sourceforge.plantuml.tim.TLineType;
|
||||
|
||||
public enum TokenType {
|
||||
QUOTED_STRING, OPERATOR, OPEN_PAREN_MATH, COMMA, CLOSE_PAREN_MATH, NUMBER, PLAIN_TEXT, SPACES, FUNCTION_NAME, OPEN_PAREN_FUNC, CLOSE_PAREN_FUNC;
|
||||
QUOTED_STRING, JSON_DATA, OPERATOR, OPEN_PAREN_MATH, COMMA, CLOSE_PAREN_MATH, NUMBER, PLAIN_TEXT, SPACES, FUNCTION_NAME, OPEN_PAREN_FUNC, CLOSE_PAREN_FUNC;
|
||||
|
||||
private boolean isSingleChar1() {
|
||||
return this == OPEN_PAREN_MATH || this == COMMA || this == CLOSE_PAREN_MATH;
|
||||
@ -83,24 +83,24 @@ public enum TokenType {
|
||||
}
|
||||
final TokenOperator tokenOperator = TokenOperator.getTokenOperator(ch, eater.peekCharN2());
|
||||
if (TLineType.isQuote(ch)) {
|
||||
return new Token(eater.eatAndGetQuotedString(), TokenType.QUOTED_STRING);
|
||||
return new Token(eater.eatAndGetQuotedString(), TokenType.QUOTED_STRING, null);
|
||||
} else if (tokenOperator != null) {
|
||||
if (tokenOperator.getDisplay().length() == 1) {
|
||||
return new Token(eater.eatOneChar(), TokenType.OPERATOR);
|
||||
return new Token(eater.eatOneChar(), TokenType.OPERATOR, null);
|
||||
}
|
||||
return new Token("" + eater.eatOneChar() + eater.eatOneChar(), TokenType.OPERATOR);
|
||||
return new Token("" + eater.eatOneChar() + eater.eatOneChar(), TokenType.OPERATOR, null);
|
||||
} else if (ch == '(') {
|
||||
return new Token(eater.eatOneChar(), TokenType.OPEN_PAREN_MATH);
|
||||
return new Token(eater.eatOneChar(), TokenType.OPEN_PAREN_MATH, null);
|
||||
} else if (ch == ')') {
|
||||
return new Token(eater.eatOneChar(), TokenType.CLOSE_PAREN_MATH);
|
||||
return new Token(eater.eatOneChar(), TokenType.CLOSE_PAREN_MATH, null);
|
||||
} else if (ch == ',') {
|
||||
return new Token(eater.eatOneChar(), TokenType.COMMA);
|
||||
return new Token(eater.eatOneChar(), TokenType.COMMA, null);
|
||||
} else if (TLineType.isLatinDigit(ch)) {
|
||||
return new Token(eater.eatAndGetNumber(), TokenType.NUMBER);
|
||||
return new Token(eater.eatAndGetNumber(), TokenType.NUMBER, null);
|
||||
} else if (TLineType.isSpaceChar(ch)) {
|
||||
return new Token(eater.eatAndGetSpaces(), TokenType.SPACES);
|
||||
return new Token(eater.eatAndGetSpaces(), TokenType.SPACES, null);
|
||||
}
|
||||
return new Token(eatAndGetTokenPlainText(eater), TokenType.PLAIN_TEXT);
|
||||
return new Token(eatAndGetTokenPlainText(eater), TokenType.PLAIN_TEXT, null);
|
||||
}
|
||||
|
||||
static private String eatAndGetTokenPlainText(Eater eater) throws EaterException {
|
||||
|
@ -0,0 +1,61 @@
|
||||
/* ========================================================================
|
||||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* (C) Copyright 2009-2020, Arnaud Roques
|
||||
*
|
||||
* Project Info: http://plantuml.com
|
||||
*
|
||||
* If you like this project or if you find it useful, you can support us at:
|
||||
*
|
||||
* http://plantuml.com/patreon (only 1$ per month!)
|
||||
* http://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.tim.iterator;
|
||||
|
||||
import net.sourceforge.plantuml.tim.EaterExceptionLocated;
|
||||
import net.sourceforge.plantuml.tim.EaterException;
|
||||
|
||||
public abstract class AbstractCodeIterator implements CodeIterator {
|
||||
|
||||
protected final CodeIterator source;
|
||||
|
||||
public AbstractCodeIterator(CodeIterator source) {
|
||||
this.source = source;
|
||||
}
|
||||
|
||||
public void next() throws EaterException, EaterExceptionLocated {
|
||||
source.next();
|
||||
}
|
||||
|
||||
final public CodePosition getCodePosition() {
|
||||
return source.getCodePosition();
|
||||
}
|
||||
|
||||
final public void jumpToCodePosition(CodePosition newPosition) throws EaterException {
|
||||
source.jumpToCodePosition(newPosition);
|
||||
}
|
||||
|
||||
|
||||
}
|
51
src/net/sourceforge/plantuml/tim/iterator/CodeIterator.java
Normal file
51
src/net/sourceforge/plantuml/tim/iterator/CodeIterator.java
Normal file
@ -0,0 +1,51 @@
|
||||
/* ========================================================================
|
||||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* (C) Copyright 2009-2020, Arnaud Roques
|
||||
*
|
||||
* Project Info: http://plantuml.com
|
||||
*
|
||||
* If you like this project or if you find it useful, you can support us at:
|
||||
*
|
||||
* http://plantuml.com/patreon (only 1$ per month!)
|
||||
* http://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.tim.iterator;
|
||||
|
||||
import net.sourceforge.plantuml.StringLocated;
|
||||
import net.sourceforge.plantuml.tim.EaterExceptionLocated;
|
||||
import net.sourceforge.plantuml.tim.EaterException;
|
||||
|
||||
public interface CodeIterator {
|
||||
|
||||
public StringLocated peek() throws EaterException, EaterExceptionLocated;
|
||||
|
||||
public void next() throws EaterException, EaterExceptionLocated;
|
||||
|
||||
public CodePosition getCodePosition();
|
||||
|
||||
public void jumpToCodePosition(CodePosition newPosition) throws EaterException;
|
||||
|
||||
}
|
@ -0,0 +1,98 @@
|
||||
/* ========================================================================
|
||||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* (C) Copyright 2009-2020, Arnaud Roques
|
||||
*
|
||||
* Project Info: http://plantuml.com
|
||||
*
|
||||
* If you like this project or if you find it useful, you can support us at:
|
||||
*
|
||||
* http://plantuml.com/patreon (only 1$ per month!)
|
||||
* http://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.tim.iterator;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import net.sourceforge.plantuml.StringLocated;
|
||||
import net.sourceforge.plantuml.json.ParseException;
|
||||
import net.sourceforge.plantuml.tim.EaterAffectation;
|
||||
import net.sourceforge.plantuml.tim.EaterExceptionLocated;
|
||||
import net.sourceforge.plantuml.tim.EaterException;
|
||||
import net.sourceforge.plantuml.tim.TContext;
|
||||
import net.sourceforge.plantuml.tim.TLineType;
|
||||
import net.sourceforge.plantuml.tim.TMemory;
|
||||
|
||||
public class CodeIteratorAffectation extends AbstractCodeIterator {
|
||||
|
||||
private final TContext context;
|
||||
private final TMemory memory;
|
||||
private final List<StringLocated> logs;
|
||||
|
||||
public CodeIteratorAffectation(CodeIterator source, TContext context, TMemory memory, List<StringLocated> log) {
|
||||
super(source);
|
||||
this.context = context;
|
||||
this.memory = memory;
|
||||
this.logs = log;
|
||||
}
|
||||
|
||||
public StringLocated peek() throws EaterException, EaterExceptionLocated {
|
||||
while (true) {
|
||||
final StringLocated result = source.peek();
|
||||
if (result == null) {
|
||||
return null;
|
||||
}
|
||||
if (result.getType() == TLineType.AFFECTATION) {
|
||||
logs.add(result);
|
||||
doAffectation(result);
|
||||
next();
|
||||
continue;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
private void doAffectation(StringLocated result) throws EaterException, EaterExceptionLocated {
|
||||
int lastLocation = -1;
|
||||
for (int i = 0; i < 100; i++)
|
||||
try {
|
||||
this.executeAffectation(context, memory, result);
|
||||
return;
|
||||
} catch (ParseException e) {
|
||||
if (e.getColumn() <= lastLocation) {
|
||||
throw EaterException.located("Error in JSON format", result);
|
||||
}
|
||||
lastLocation = e.getColumn();
|
||||
next();
|
||||
final StringLocated forward = source.peek();
|
||||
result = result.append(forward.getString());
|
||||
}
|
||||
}
|
||||
|
||||
private void executeAffectation(TContext context, TMemory memory, StringLocated s) throws EaterException, EaterExceptionLocated {
|
||||
new EaterAffectation(s).analyze(context, memory);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,131 @@
|
||||
/* ========================================================================
|
||||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* (C) Copyright 2009-2020, Arnaud Roques
|
||||
*
|
||||
* Project Info: http://plantuml.com
|
||||
*
|
||||
* If you like this project or if you find it useful, you can support us at:
|
||||
*
|
||||
* http://plantuml.com/patreon (only 1$ per month!)
|
||||
* http://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.tim.iterator;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import net.sourceforge.plantuml.StringLocated;
|
||||
import net.sourceforge.plantuml.json.JsonValue;
|
||||
import net.sourceforge.plantuml.tim.EaterExceptionLocated;
|
||||
import net.sourceforge.plantuml.tim.EaterException;
|
||||
import net.sourceforge.plantuml.tim.EaterForeach;
|
||||
import net.sourceforge.plantuml.tim.ExecutionContextForeach;
|
||||
import net.sourceforge.plantuml.tim.TContext;
|
||||
import net.sourceforge.plantuml.tim.TLineType;
|
||||
import net.sourceforge.plantuml.tim.TMemory;
|
||||
import net.sourceforge.plantuml.tim.TVariableScope;
|
||||
import net.sourceforge.plantuml.tim.expression.TValue;
|
||||
|
||||
public class CodeIteratorForeach extends AbstractCodeIterator {
|
||||
|
||||
private final TContext context;
|
||||
private final TMemory memory;
|
||||
private final List<StringLocated> logs;
|
||||
|
||||
public CodeIteratorForeach(CodeIterator source, TContext context, TMemory memory, List<StringLocated> logs) {
|
||||
super(source);
|
||||
this.context = context;
|
||||
this.memory = memory;
|
||||
this.logs = logs;
|
||||
}
|
||||
|
||||
public StringLocated peek() throws EaterException, EaterExceptionLocated {
|
||||
int level = 0;
|
||||
while (true) {
|
||||
final StringLocated result = source.peek();
|
||||
if (result == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final ExecutionContextForeach foreach = memory.peekForeach();
|
||||
if (foreach != null && foreach.isSkipMe()) {
|
||||
if (result.getType() == TLineType.FOREACH) {
|
||||
level++;
|
||||
} else if (result.getType() == TLineType.ENDFOREACH) {
|
||||
level--;
|
||||
if (level == -1) {
|
||||
memory.pollForeach();
|
||||
level = 0;
|
||||
}
|
||||
}
|
||||
next();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (result.getType() == TLineType.FOREACH) {
|
||||
logs.add(result);
|
||||
executeForeach(memory, result.getTrimmed());
|
||||
next();
|
||||
continue;
|
||||
} else if (result.getType() == TLineType.ENDFOREACH) {
|
||||
logs.add(result);
|
||||
if (foreach == null) {
|
||||
throw EaterException.located("No foreach related to this endforeach", result);
|
||||
}
|
||||
foreach.inc();
|
||||
if (foreach.isSkipMe()) {
|
||||
memory.pollForeach();
|
||||
} else {
|
||||
setLoopVariable(memory, foreach, result);
|
||||
source.jumpToCodePosition(foreach.getStartForeach());
|
||||
}
|
||||
next();
|
||||
continue;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
private void executeForeach(TMemory memory, StringLocated s) throws EaterException, EaterExceptionLocated {
|
||||
final EaterForeach condition = new EaterForeach(s);
|
||||
condition.analyze(context, memory);
|
||||
final ExecutionContextForeach foreach = ExecutionContextForeach.fromValue(condition.getVarname(),
|
||||
condition.getJsonArray(), source.getCodePosition());
|
||||
if (condition.isSkip()) {
|
||||
foreach.skipMeNow();
|
||||
} else {
|
||||
setLoopVariable(memory, foreach, s);
|
||||
}
|
||||
memory.addForeach(foreach);
|
||||
}
|
||||
|
||||
private void setLoopVariable(TMemory memory, ExecutionContextForeach foreach, StringLocated position)
|
||||
throws EaterException {
|
||||
final JsonValue first = foreach.getJsonArray().get(foreach.currentIndex());
|
||||
memory.putVariable(foreach.getVarname(), TValue.fromJson(first), TVariableScope.GLOBAL);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,93 @@
|
||||
/* ========================================================================
|
||||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* (C) Copyright 2009-2020, Arnaud Roques
|
||||
*
|
||||
* Project Info: http://plantuml.com
|
||||
*
|
||||
* If you like this project or if you find it useful, you can support us at:
|
||||
*
|
||||
* http://plantuml.com/patreon (only 1$ per month!)
|
||||
* http://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.tim.iterator;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import net.sourceforge.plantuml.StringLocated;
|
||||
import net.sourceforge.plantuml.tim.EaterExceptionLocated;
|
||||
import net.sourceforge.plantuml.tim.EaterException;
|
||||
import net.sourceforge.plantuml.tim.FunctionsSet;
|
||||
import net.sourceforge.plantuml.tim.TContext;
|
||||
import net.sourceforge.plantuml.tim.TLineType;
|
||||
import net.sourceforge.plantuml.tim.TMemory;
|
||||
|
||||
public class CodeIteratorFunction extends AbstractCodeIterator {
|
||||
|
||||
private final FunctionsSet functionsSet;
|
||||
|
||||
private final TContext context;
|
||||
private final TMemory memory;
|
||||
private final List<StringLocated> logs;
|
||||
|
||||
public CodeIteratorFunction(CodeIterator source, TContext context, TMemory memory, FunctionsSet functionsSet,
|
||||
List<StringLocated> logs) {
|
||||
super(source);
|
||||
this.context = context;
|
||||
this.functionsSet = functionsSet;
|
||||
this.logs = logs;
|
||||
this.memory = memory;
|
||||
}
|
||||
|
||||
public StringLocated peek() throws EaterException, EaterExceptionLocated {
|
||||
while (true) {
|
||||
final StringLocated result = source.peek();
|
||||
if (result == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (functionsSet.pendingFunction() != null) {
|
||||
logs.add(result);
|
||||
if (result.getType() == TLineType.END_FUNCTION) {
|
||||
functionsSet.executeEndfunction();
|
||||
} else {
|
||||
functionsSet.pendingFunction().addBody(result);
|
||||
}
|
||||
next();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (result.getType() == TLineType.DECLARE_FUNCTION) {
|
||||
logs.add(result);
|
||||
functionsSet.executeDeclareFunction(context, memory, result);
|
||||
next();
|
||||
continue;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
163
src/net/sourceforge/plantuml/tim/iterator/CodeIteratorIf.java
Normal file
163
src/net/sourceforge/plantuml/tim/iterator/CodeIteratorIf.java
Normal file
@ -0,0 +1,163 @@
|
||||
/* ========================================================================
|
||||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* (C) Copyright 2009-2020, Arnaud Roques
|
||||
*
|
||||
* Project Info: http://plantuml.com
|
||||
*
|
||||
* If you like this project or if you find it useful, you can support us at:
|
||||
*
|
||||
* http://plantuml.com/patreon (only 1$ per month!)
|
||||
* http://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.tim.iterator;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import net.sourceforge.plantuml.StringLocated;
|
||||
import net.sourceforge.plantuml.tim.EaterElseIf;
|
||||
import net.sourceforge.plantuml.tim.EaterExceptionLocated;
|
||||
import net.sourceforge.plantuml.tim.EaterException;
|
||||
import net.sourceforge.plantuml.tim.EaterIf;
|
||||
import net.sourceforge.plantuml.tim.EaterIfdef;
|
||||
import net.sourceforge.plantuml.tim.EaterIfndef;
|
||||
import net.sourceforge.plantuml.tim.ExecutionContextIf;
|
||||
import net.sourceforge.plantuml.tim.TContext;
|
||||
import net.sourceforge.plantuml.tim.TLineType;
|
||||
import net.sourceforge.plantuml.tim.TMemory;
|
||||
|
||||
public class CodeIteratorIf extends AbstractCodeIterator {
|
||||
|
||||
private final TContext context;
|
||||
private final TMemory memory;
|
||||
private final List<StringLocated> logs;
|
||||
|
||||
public CodeIteratorIf(CodeIterator source, TContext context, TMemory memory, List<StringLocated> logs) {
|
||||
super(source);
|
||||
this.context = context;
|
||||
this.memory = memory;
|
||||
this.logs = logs;
|
||||
}
|
||||
|
||||
public StringLocated peek() throws EaterException, EaterExceptionLocated {
|
||||
while (true) {
|
||||
final StringLocated result = source.peek();
|
||||
if (result == null) {
|
||||
return null;
|
||||
}
|
||||
if (result.getType() == TLineType.IF) {
|
||||
logs.add(result);
|
||||
executeIf(context, memory, result.getTrimmed());
|
||||
next();
|
||||
continue;
|
||||
} else if (result.getType() == TLineType.IFDEF) {
|
||||
logs.add(result);
|
||||
executeIfdef(context, memory, result.getTrimmed());
|
||||
next();
|
||||
continue;
|
||||
} else if (result.getType() == TLineType.IFNDEF) {
|
||||
logs.add(result);
|
||||
executeIfndef(context, memory, result.getTrimmed());
|
||||
next();
|
||||
continue;
|
||||
} else if (result.getType() == TLineType.ELSE) {
|
||||
logs.add(result);
|
||||
executeElse(context, memory, result.getTrimmed());
|
||||
next();
|
||||
continue;
|
||||
} else if (result.getType() == TLineType.ELSEIF) {
|
||||
logs.add(result);
|
||||
executeElseIf(context, memory, result.getTrimmed());
|
||||
next();
|
||||
continue;
|
||||
} else if (result.getType() == TLineType.ENDIF) {
|
||||
logs.add(result);
|
||||
executeEndif(context, memory, result.getTrimmed());
|
||||
next();
|
||||
continue;
|
||||
} else if (memory.peekIf() != null && (memory.areAllIfOk(context, memory) == false)) {
|
||||
logs.add(result);
|
||||
next();
|
||||
continue;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
private void executeIf(TContext context, TMemory memory, StringLocated s) throws EaterException, EaterExceptionLocated {
|
||||
final EaterIf condition = new EaterIf(s);
|
||||
condition.analyze(context, memory);
|
||||
final boolean isTrue = condition.isTrue();
|
||||
memory.addIf(ExecutionContextIf.fromValue(isTrue));
|
||||
}
|
||||
|
||||
private void executeElseIf(TContext context, TMemory memory, StringLocated s) throws EaterException, EaterExceptionLocated {
|
||||
final ExecutionContextIf poll = (ExecutionContextIf) memory.peekIf();
|
||||
if (poll == null) {
|
||||
throw EaterException.located("No if related to this else", s);
|
||||
}
|
||||
|
||||
poll.enteringElseIf();
|
||||
if (poll.hasBeenBurn() == false) {
|
||||
final EaterElseIf condition = new EaterElseIf(s);
|
||||
condition.analyze(context, memory);
|
||||
final boolean isTrue = condition.isTrue();
|
||||
if (isTrue) {
|
||||
poll.nowInSomeElseIf();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void executeIfdef(TContext context, TMemory memory, StringLocated s) throws EaterException {
|
||||
final EaterIfdef condition = new EaterIfdef(s);
|
||||
condition.analyze(context, memory);
|
||||
final boolean isTrue = condition.isTrue(context, memory);
|
||||
memory.addIf(ExecutionContextIf.fromValue(isTrue));
|
||||
}
|
||||
|
||||
private void executeIfndef(TContext context, TMemory memory, StringLocated s) throws EaterException {
|
||||
final EaterIfndef condition = new EaterIfndef(s);
|
||||
condition.analyze(context, memory);
|
||||
final boolean isTrue = condition.isTrue(context, memory);
|
||||
memory.addIf(ExecutionContextIf.fromValue(isTrue));
|
||||
}
|
||||
|
||||
private void executeElse(TContext context, TMemory memory, StringLocated s) throws EaterException {
|
||||
final ExecutionContextIf poll = (ExecutionContextIf) memory.peekIf();
|
||||
if (poll == null) {
|
||||
throw EaterException.located("No if related to this else", s);
|
||||
}
|
||||
poll.nowInElse();
|
||||
}
|
||||
|
||||
private void executeEndif(TContext context, TMemory memory, StringLocated s) throws EaterException {
|
||||
final ExecutionContextIf poll = (ExecutionContextIf) memory.pollIf();
|
||||
if (poll == null) {
|
||||
throw EaterException.located("No if related to this endif", s);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,98 @@
|
||||
/* ========================================================================
|
||||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* (C) Copyright 2009-2020, Arnaud Roques
|
||||
*
|
||||
* Project Info: http://plantuml.com
|
||||
*
|
||||
* If you like this project or if you find it useful, you can support us at:
|
||||
*
|
||||
* http://plantuml.com/patreon (only 1$ per month!)
|
||||
* http://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.tim.iterator;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import net.sourceforge.plantuml.StringLocated;
|
||||
import net.sourceforge.plantuml.tim.EaterException;
|
||||
|
||||
public class CodeIteratorImpl implements CodeIterator {
|
||||
|
||||
private final List<StringLocated> list;
|
||||
private int current = 0;
|
||||
private int countJump = 0;
|
||||
|
||||
static class Position implements CodePosition {
|
||||
final int pos;
|
||||
|
||||
Position(int pos) {
|
||||
this.pos = pos;
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public String toString() {
|
||||
// return "-->" + list.get(pos);
|
||||
// }
|
||||
}
|
||||
|
||||
public CodeIteratorImpl(List<StringLocated> list) {
|
||||
this.list = list;
|
||||
}
|
||||
|
||||
public StringLocated peek() {
|
||||
if (current == list.size()) {
|
||||
return null;
|
||||
}
|
||||
if (current > list.size()) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
return list.get(current);
|
||||
}
|
||||
|
||||
public void next() {
|
||||
if (current >= list.size()) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
assert current < list.size();
|
||||
current++;
|
||||
assert current <= list.size();
|
||||
}
|
||||
|
||||
public CodePosition getCodePosition() {
|
||||
return new Position(current);
|
||||
}
|
||||
|
||||
public void jumpToCodePosition(CodePosition newPosition) throws EaterException {
|
||||
this.countJump++;
|
||||
if (this.countJump > 999) {
|
||||
throw EaterException.unlocated("Infinite loop?");
|
||||
}
|
||||
final Position pos = (Position) newPosition;
|
||||
this.current = pos.pos;
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
/* ========================================================================
|
||||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* (C) Copyright 2009-2020, Arnaud Roques
|
||||
*
|
||||
* Project Info: http://plantuml.com
|
||||
*
|
||||
* If you like this project or if you find it useful, you can support us at:
|
||||
*
|
||||
* http://plantuml.com/patreon (only 1$ per month!)
|
||||
* http://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.tim.iterator;
|
||||
|
||||
import net.sourceforge.plantuml.StringLocated;
|
||||
import net.sourceforge.plantuml.tim.EaterExceptionLocated;
|
||||
import net.sourceforge.plantuml.tim.EaterException;
|
||||
|
||||
public class CodeIteratorInnerComment extends AbstractCodeIterator {
|
||||
|
||||
public CodeIteratorInnerComment(CodeIterator source) {
|
||||
super(source);
|
||||
}
|
||||
|
||||
public StringLocated peek() throws EaterException, EaterExceptionLocated {
|
||||
final StringLocated result = source.peek();
|
||||
if (result == null) {
|
||||
return null;
|
||||
}
|
||||
return result.removeInnerComment();
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,85 @@
|
||||
/* ========================================================================
|
||||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* (C) Copyright 2009-2020, Arnaud Roques
|
||||
*
|
||||
* Project Info: http://plantuml.com
|
||||
*
|
||||
* If you like this project or if you find it useful, you can support us at:
|
||||
*
|
||||
* http://plantuml.com/patreon (only 1$ per month!)
|
||||
* http://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.tim.iterator;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import net.sourceforge.plantuml.StringLocated;
|
||||
import net.sourceforge.plantuml.tim.EaterExceptionLocated;
|
||||
import net.sourceforge.plantuml.tim.EaterException;
|
||||
import net.sourceforge.plantuml.tim.FunctionsSet;
|
||||
import net.sourceforge.plantuml.tim.TContext;
|
||||
import net.sourceforge.plantuml.tim.TLineType;
|
||||
import net.sourceforge.plantuml.tim.TMemory;
|
||||
|
||||
public class CodeIteratorLegacyDefine extends AbstractCodeIterator {
|
||||
|
||||
private final FunctionsSet functionsSet;
|
||||
|
||||
private final TContext context;
|
||||
private final TMemory memory;
|
||||
private final List<StringLocated> logs;
|
||||
|
||||
public CodeIteratorLegacyDefine(CodeIterator source, TContext context, TMemory memory, FunctionsSet functionsSet,
|
||||
List<StringLocated> logs) {
|
||||
super(source);
|
||||
this.context = context;
|
||||
this.functionsSet = functionsSet;
|
||||
this.logs = logs;
|
||||
this.memory = memory;
|
||||
}
|
||||
|
||||
public StringLocated peek() throws EaterException, EaterExceptionLocated {
|
||||
while (true) {
|
||||
final StringLocated result = source.peek();
|
||||
if (result == null) {
|
||||
return null;
|
||||
}
|
||||
if (result.getType() == TLineType.LEGACY_DEFINE) {
|
||||
logs.add(result);
|
||||
functionsSet.executeLegacyDefine(context, memory, result);
|
||||
next();
|
||||
continue;
|
||||
} else if (result.getType() == TLineType.LEGACY_DEFINELONG) {
|
||||
logs.add(result);
|
||||
functionsSet.executeLegacyDefineLong(context, memory, result);
|
||||
next();
|
||||
continue;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,75 @@
|
||||
/* ========================================================================
|
||||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* (C) Copyright 2009-2020, Arnaud Roques
|
||||
*
|
||||
* Project Info: http://plantuml.com
|
||||
*
|
||||
* If you like this project or if you find it useful, you can support us at:
|
||||
*
|
||||
* http://plantuml.com/patreon (only 1$ per month!)
|
||||
* http://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.tim.iterator;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import net.sourceforge.plantuml.StringLocated;
|
||||
import net.sourceforge.plantuml.tim.EaterExceptionLocated;
|
||||
import net.sourceforge.plantuml.tim.EaterException;
|
||||
import net.sourceforge.plantuml.tim.TLineType;
|
||||
|
||||
public class CodeIteratorLongComment extends AbstractCodeIterator {
|
||||
|
||||
private final List<StringLocated> logs;
|
||||
|
||||
public CodeIteratorLongComment(CodeIterator source, List<StringLocated> logs) {
|
||||
super(source);
|
||||
this.logs = logs;
|
||||
}
|
||||
|
||||
public StringLocated peek() throws EaterException, EaterExceptionLocated {
|
||||
while (true) {
|
||||
if (source.peek() == null) {
|
||||
return null;
|
||||
}
|
||||
if (source.peek().getType() != TLineType.COMMENT_LONG_START) {
|
||||
return source.peek();
|
||||
}
|
||||
StringLocated s = null;
|
||||
while ((s = source.peek()) != null && s.getTrimmed().getString().endsWith("'/") == false) {
|
||||
logs.add(s);
|
||||
source.next();
|
||||
}
|
||||
assert source.peek() == null || s.getTrimmed().getString().endsWith("'/");
|
||||
if (source.peek() != null) {
|
||||
assert s.getTrimmed().getString().endsWith("'/");
|
||||
logs.add(source.peek());
|
||||
source.next();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
/* ========================================================================
|
||||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* (C) Copyright 2009-2020, Arnaud Roques
|
||||
*
|
||||
* Project Info: http://plantuml.com
|
||||
*
|
||||
* If you like this project or if you find it useful, you can support us at:
|
||||
*
|
||||
* http://plantuml.com/patreon (only 1$ per month!)
|
||||
* http://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.tim.iterator;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import net.sourceforge.plantuml.StringLocated;
|
||||
import net.sourceforge.plantuml.tim.EaterExceptionLocated;
|
||||
import net.sourceforge.plantuml.tim.EaterException;
|
||||
import net.sourceforge.plantuml.tim.TLineType;
|
||||
|
||||
public class CodeIteratorShortComment extends AbstractCodeIterator {
|
||||
|
||||
private final List<StringLocated> logs;
|
||||
|
||||
public CodeIteratorShortComment(CodeIterator source, List<StringLocated> logs) {
|
||||
super(source);
|
||||
this.logs = logs;
|
||||
}
|
||||
|
||||
public StringLocated peek() throws EaterException, EaterExceptionLocated {
|
||||
while (true) {
|
||||
final StringLocated result = source.peek();
|
||||
if (result == null) {
|
||||
return null;
|
||||
}
|
||||
if (result.getType() == TLineType.COMMENT_SIMPLE) {
|
||||
logs.add(result);
|
||||
next();
|
||||
continue;
|
||||
}
|
||||
assert result != null && result.getType() != TLineType.COMMENT_SIMPLE;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
112
src/net/sourceforge/plantuml/tim/iterator/CodeIteratorSub.java
Normal file
112
src/net/sourceforge/plantuml/tim/iterator/CodeIteratorSub.java
Normal file
@ -0,0 +1,112 @@
|
||||
/* ========================================================================
|
||||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* (C) Copyright 2009-2020, Arnaud Roques
|
||||
*
|
||||
* Project Info: http://plantuml.com
|
||||
*
|
||||
* If you like this project or if you find it useful, you can support us at:
|
||||
*
|
||||
* http://plantuml.com/patreon (only 1$ per month!)
|
||||
* http://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.tim.iterator;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
import net.sourceforge.plantuml.StringLocated;
|
||||
import net.sourceforge.plantuml.preproc.Sub;
|
||||
import net.sourceforge.plantuml.tim.EaterExceptionLocated;
|
||||
import net.sourceforge.plantuml.tim.EaterException;
|
||||
import net.sourceforge.plantuml.tim.EaterStartsub;
|
||||
import net.sourceforge.plantuml.tim.TContext;
|
||||
import net.sourceforge.plantuml.tim.TLineType;
|
||||
import net.sourceforge.plantuml.tim.TMemory;
|
||||
|
||||
public class CodeIteratorSub extends AbstractCodeIterator {
|
||||
|
||||
private final Map<String, Sub> subs;
|
||||
|
||||
private CodeIterator readingInProgress;
|
||||
|
||||
private final TMemory memory;
|
||||
private final TContext context;
|
||||
|
||||
public CodeIteratorSub(CodeIterator source, Map<String, Sub> subs, TContext context, TMemory memory) {
|
||||
super(source);
|
||||
this.context = context;
|
||||
this.memory = memory;
|
||||
this.subs = subs;
|
||||
}
|
||||
|
||||
public Map<String, Sub> getSubs() {
|
||||
return Collections.unmodifiableMap(subs);
|
||||
}
|
||||
|
||||
public StringLocated peek() throws EaterException, EaterExceptionLocated {
|
||||
StringLocated result = source.peek();
|
||||
if (result == null) {
|
||||
return null;
|
||||
}
|
||||
if (result.getType() == TLineType.STARTSUB) {
|
||||
final EaterStartsub eater = new EaterStartsub(result.getTrimmed());
|
||||
eater.analyze(context, memory);
|
||||
final Sub created = new Sub(eater.getSubname());
|
||||
this.subs.put(eater.getSubname(), created);
|
||||
source.next();
|
||||
StringLocated s = null;
|
||||
while ((s = source.peek()) != null) {
|
||||
if (s.getType() == TLineType.STARTSUB) {
|
||||
throw EaterException.located("Cannot nest sub", s);
|
||||
} else if (s.getType() == TLineType.ENDSUB) {
|
||||
source.next();
|
||||
readingInProgress = new CodeIteratorImpl(created.lines());
|
||||
break;
|
||||
} else {
|
||||
created.add(s);
|
||||
source.next();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (readingInProgress != null) {
|
||||
return readingInProgress.peek();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void next() throws EaterException, EaterExceptionLocated {
|
||||
if (readingInProgress == null) {
|
||||
source.next();
|
||||
return;
|
||||
}
|
||||
readingInProgress.next();
|
||||
if (readingInProgress.peek() == null) {
|
||||
readingInProgress = null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
123
src/net/sourceforge/plantuml/tim/iterator/CodeIteratorWhile.java
Normal file
123
src/net/sourceforge/plantuml/tim/iterator/CodeIteratorWhile.java
Normal file
@ -0,0 +1,123 @@
|
||||
/* ========================================================================
|
||||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* (C) Copyright 2009-2020, Arnaud Roques
|
||||
*
|
||||
* Project Info: http://plantuml.com
|
||||
*
|
||||
* If you like this project or if you find it useful, you can support us at:
|
||||
*
|
||||
* http://plantuml.com/patreon (only 1$ per month!)
|
||||
* http://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.tim.iterator;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import net.sourceforge.plantuml.StringLocated;
|
||||
import net.sourceforge.plantuml.tim.EaterExceptionLocated;
|
||||
import net.sourceforge.plantuml.tim.EaterException;
|
||||
import net.sourceforge.plantuml.tim.EaterWhile;
|
||||
import net.sourceforge.plantuml.tim.ExecutionContextWhile;
|
||||
import net.sourceforge.plantuml.tim.TContext;
|
||||
import net.sourceforge.plantuml.tim.TLineType;
|
||||
import net.sourceforge.plantuml.tim.TMemory;
|
||||
import net.sourceforge.plantuml.tim.expression.TValue;
|
||||
import net.sourceforge.plantuml.tim.expression.TokenStack;
|
||||
|
||||
public class CodeIteratorWhile extends AbstractCodeIterator {
|
||||
|
||||
private final TContext context;
|
||||
private final TMemory memory;
|
||||
private final List<StringLocated> logs;
|
||||
|
||||
public CodeIteratorWhile(CodeIterator source, TContext context, TMemory memory, List<StringLocated> logs) {
|
||||
super(source);
|
||||
this.context = context;
|
||||
this.memory = memory;
|
||||
this.logs = logs;
|
||||
}
|
||||
|
||||
public StringLocated peek() throws EaterException, EaterExceptionLocated {
|
||||
int level = 0;
|
||||
while (true) {
|
||||
final StringLocated result = source.peek();
|
||||
if (result == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final ExecutionContextWhile currentWhile = memory.peekWhile();
|
||||
if (currentWhile != null && currentWhile.isSkipMe()) {
|
||||
if (result.getType() == TLineType.WHILE) {
|
||||
level++;
|
||||
} else if (result.getType() == TLineType.ENDWHILE) {
|
||||
level--;
|
||||
if (level == -1) {
|
||||
memory.pollWhile();
|
||||
level = 0;
|
||||
}
|
||||
}
|
||||
next();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (result.getType() == TLineType.WHILE) {
|
||||
logs.add(result);
|
||||
executeWhile(memory, result.getTrimmed());
|
||||
next();
|
||||
continue;
|
||||
} else if (result.getType() == TLineType.ENDWHILE) {
|
||||
logs.add(result);
|
||||
if (currentWhile == null) {
|
||||
throw EaterException.located("No while related to this endwhile", result);
|
||||
}
|
||||
final TValue value = currentWhile.conditionValue(result.getLocation(), context, memory);
|
||||
if (value.toBoolean()) {
|
||||
source.jumpToCodePosition(currentWhile.getStartWhile());
|
||||
} else {
|
||||
memory.pollWhile();
|
||||
}
|
||||
next();
|
||||
continue;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
private void executeWhile(TMemory memory, StringLocated s) throws EaterException, EaterExceptionLocated {
|
||||
final EaterWhile condition = new EaterWhile(s);
|
||||
condition.analyze(context, memory);
|
||||
final TokenStack whileExpression = condition.getWhileExpression();
|
||||
final ExecutionContextWhile theWhile = ExecutionContextWhile.fromValue(whileExpression,
|
||||
source.getCodePosition());
|
||||
final TValue value = theWhile.conditionValue(s.getLocation(), context, memory);
|
||||
if (value.toBoolean() == false) {
|
||||
theWhile.skipMe();
|
||||
}
|
||||
memory.addWhile(theWhile);
|
||||
}
|
||||
|
||||
}
|
@ -32,28 +32,8 @@
|
||||
* Original Author: Arnaud Roques
|
||||
*
|
||||
*/
|
||||
package net.sourceforge.plantuml.tim;
|
||||
package net.sourceforge.plantuml.tim.iterator;
|
||||
|
||||
import net.sourceforge.plantuml.tim.expression.TValue;
|
||||
|
||||
public class TVariable {
|
||||
|
||||
private final TValue value;
|
||||
|
||||
public TVariable(TValue value) {
|
||||
if (value == null) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return super.toString() + " " + value.toString();
|
||||
}
|
||||
|
||||
public TValue getValue() {
|
||||
return value;
|
||||
}
|
||||
public interface CodePosition {
|
||||
|
||||
}
|
@ -36,6 +36,7 @@ package net.sourceforge.plantuml.tim.stdlib;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import net.sourceforge.plantuml.LineLocation;
|
||||
import net.sourceforge.plantuml.tim.EaterException;
|
||||
import net.sourceforge.plantuml.tim.TContext;
|
||||
import net.sourceforge.plantuml.tim.TFunctionSignature;
|
||||
@ -52,7 +53,7 @@ public class AlwaysFalse extends SimpleReturnFunction {
|
||||
return nbArg == 0;
|
||||
}
|
||||
|
||||
public TValue executeReturn(TContext context, TMemory memory, List<TValue> args) throws EaterException {
|
||||
public TValue executeReturn(TContext context, TMemory memory, LineLocation location, List<TValue> args) throws EaterException {
|
||||
return TValue.fromBoolean(false);
|
||||
}
|
||||
}
|
||||
|
@ -36,6 +36,7 @@ package net.sourceforge.plantuml.tim.stdlib;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import net.sourceforge.plantuml.LineLocation;
|
||||
import net.sourceforge.plantuml.tim.EaterException;
|
||||
import net.sourceforge.plantuml.tim.TContext;
|
||||
import net.sourceforge.plantuml.tim.TFunctionSignature;
|
||||
@ -52,7 +53,7 @@ public class AlwaysTrue extends SimpleReturnFunction {
|
||||
return nbArg == 0;
|
||||
}
|
||||
|
||||
public TValue executeReturn(TContext context, TMemory memory, List<TValue> args) throws EaterException {
|
||||
public TValue executeReturn(TContext context, TMemory memory, LineLocation location, List<TValue> args) throws EaterException {
|
||||
return TValue.fromBoolean(true);
|
||||
}
|
||||
}
|
||||
|
@ -36,6 +36,8 @@ package net.sourceforge.plantuml.tim.stdlib;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import net.sourceforge.plantuml.LineLocation;
|
||||
import net.sourceforge.plantuml.tim.EaterExceptionLocated;
|
||||
import net.sourceforge.plantuml.tim.EaterException;
|
||||
import net.sourceforge.plantuml.tim.TContext;
|
||||
import net.sourceforge.plantuml.tim.TFunction;
|
||||
@ -53,15 +55,15 @@ public class CallUserFunction extends SimpleReturnFunction {
|
||||
return nbArg > 0;
|
||||
}
|
||||
|
||||
public TValue executeReturn(TContext context, TMemory memory, List<TValue> values) throws EaterException {
|
||||
public TValue executeReturn(TContext context, TMemory memory, LineLocation location, List<TValue> values) throws EaterException, EaterExceptionLocated {
|
||||
final String fname = values.get(0).toString();
|
||||
final List<TValue> args = values.subList(1, values.size());
|
||||
final TFunctionSignature signature = new TFunctionSignature(fname, args.size());
|
||||
final TFunction func = context.getFunctionSmart(signature);
|
||||
if (func == null) {
|
||||
throw new EaterException("Cannot find void function " + fname);
|
||||
throw EaterException.unlocated("Cannot find void function " + fname);
|
||||
}
|
||||
return func.executeReturn(context, memory, args);
|
||||
return func.executeReturn(context, memory, location, args);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -38,6 +38,7 @@ import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import net.sourceforge.plantuml.LineLocation;
|
||||
import net.sourceforge.plantuml.tim.EaterException;
|
||||
import net.sourceforge.plantuml.tim.TContext;
|
||||
import net.sourceforge.plantuml.tim.TFunctionSignature;
|
||||
@ -54,7 +55,7 @@ public class DateFunction extends SimpleReturnFunction {
|
||||
return nbArg == 0 || nbArg == 1;
|
||||
}
|
||||
|
||||
public TValue executeReturn(TContext context, TMemory memory, List<TValue> args) throws EaterException {
|
||||
public TValue executeReturn(TContext context, TMemory memory, LineLocation location, List<TValue> args) throws EaterException {
|
||||
if (args.size() == 0) {
|
||||
return TValue.fromString(new Date().toString());
|
||||
}
|
||||
@ -62,7 +63,7 @@ public class DateFunction extends SimpleReturnFunction {
|
||||
try {
|
||||
return TValue.fromString(new SimpleDateFormat(format).format(new Date()));
|
||||
} catch (Exception e) {
|
||||
throw new EaterException("Bad date pattern");
|
||||
throw EaterException.unlocated("Bad date pattern");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -36,6 +36,7 @@ package net.sourceforge.plantuml.tim.stdlib;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import net.sourceforge.plantuml.LineLocation;
|
||||
import net.sourceforge.plantuml.preproc.Defines;
|
||||
import net.sourceforge.plantuml.tim.EaterException;
|
||||
import net.sourceforge.plantuml.tim.TContext;
|
||||
@ -59,7 +60,7 @@ public class Dirpath extends SimpleReturnFunction {
|
||||
return nbArg == 0;
|
||||
}
|
||||
|
||||
public TValue executeReturn(TContext context, TMemory memory, List<TValue> args) throws EaterException {
|
||||
public TValue executeReturn(TContext context, TMemory memory, LineLocation location, List<TValue> args) throws EaterException {
|
||||
if (value == null) {
|
||||
return TValue.fromString("");
|
||||
}
|
||||
|
@ -37,6 +37,7 @@ package net.sourceforge.plantuml.tim.stdlib;
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
|
||||
import net.sourceforge.plantuml.LineLocation;
|
||||
import net.sourceforge.plantuml.OptionFlags;
|
||||
import net.sourceforge.plantuml.tim.EaterException;
|
||||
import net.sourceforge.plantuml.tim.TContext;
|
||||
@ -54,7 +55,7 @@ public class FileExists extends SimpleReturnFunction {
|
||||
return nbArg == 1;
|
||||
}
|
||||
|
||||
public TValue executeReturn(TContext context, TMemory memory, List<TValue> args) throws EaterException {
|
||||
public TValue executeReturn(TContext context, TMemory memory, LineLocation location, List<TValue> args) throws EaterException {
|
||||
if (OptionFlags.ALLOW_INCLUDE == false) {
|
||||
return TValue.fromBoolean(false);
|
||||
}
|
||||
|
@ -36,6 +36,7 @@ package net.sourceforge.plantuml.tim.stdlib;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import net.sourceforge.plantuml.LineLocation;
|
||||
import net.sourceforge.plantuml.preproc.Defines;
|
||||
import net.sourceforge.plantuml.tim.EaterException;
|
||||
import net.sourceforge.plantuml.tim.TContext;
|
||||
@ -59,7 +60,7 @@ public class Filename extends SimpleReturnFunction {
|
||||
return nbArg == 0;
|
||||
}
|
||||
|
||||
public TValue executeReturn(TContext context, TMemory memory, List<TValue> args) throws EaterException {
|
||||
public TValue executeReturn(TContext context, TMemory memory, LineLocation location, List<TValue> args) throws EaterException {
|
||||
if (value == null) {
|
||||
return TValue.fromString("");
|
||||
}
|
||||
|
@ -36,6 +36,7 @@ package net.sourceforge.plantuml.tim.stdlib;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import net.sourceforge.plantuml.LineLocation;
|
||||
import net.sourceforge.plantuml.tim.EaterException;
|
||||
import net.sourceforge.plantuml.tim.TContext;
|
||||
import net.sourceforge.plantuml.tim.TFunctionSignature;
|
||||
@ -52,7 +53,7 @@ public class FunctionExists extends SimpleReturnFunction {
|
||||
return nbArg == 1;
|
||||
}
|
||||
|
||||
public TValue executeReturn(TContext context, TMemory memory, List<TValue> args) throws EaterException {
|
||||
public TValue executeReturn(TContext context, TMemory memory, LineLocation location, List<TValue> args) throws EaterException {
|
||||
final String name = args.get(0).toString();
|
||||
return TValue.fromBoolean(context.doesFunctionExist(name));
|
||||
}
|
||||
|
@ -36,11 +36,11 @@ package net.sourceforge.plantuml.tim.stdlib;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import net.sourceforge.plantuml.LineLocation;
|
||||
import net.sourceforge.plantuml.tim.EaterException;
|
||||
import net.sourceforge.plantuml.tim.TContext;
|
||||
import net.sourceforge.plantuml.tim.TFunctionSignature;
|
||||
import net.sourceforge.plantuml.tim.TMemory;
|
||||
import net.sourceforge.plantuml.tim.TVariable;
|
||||
import net.sourceforge.plantuml.tim.expression.TValue;
|
||||
|
||||
public class GetVariableValue extends SimpleReturnFunction {
|
||||
@ -53,13 +53,13 @@ public class GetVariableValue extends SimpleReturnFunction {
|
||||
return nbArg == 1;
|
||||
}
|
||||
|
||||
public TValue executeReturn(TContext context, TMemory memory, List<TValue> args) throws EaterException {
|
||||
public TValue executeReturn(TContext context, TMemory memory, LineLocation location, List<TValue> args) throws EaterException {
|
||||
final String name = args.get(0).toString();
|
||||
final TVariable variable = memory.getVariable(name);
|
||||
final TValue variable = memory.getVariable(name);
|
||||
if (variable == null) {
|
||||
return TValue.fromString("");
|
||||
}
|
||||
return variable.getValue();
|
||||
return variable;
|
||||
}
|
||||
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user