mirror of
https://github.com/octoleo/plantuml.git
synced 2024-11-21 20:45:10 +00:00
refactor: prepare preprocessor error improvement (in progress)
https://github.com/plantuml/plantuml/pull/1668
This commit is contained in:
parent
436fb37f1a
commit
6329d9a8d5
@ -1,4 +1,4 @@
|
||||
# Warning, "version" should be the same in gradle.properties and Version.java
|
||||
# Any idea anyone how to magically synchronize those :-) ?
|
||||
version = 1.2024.4beta2
|
||||
version = 1.2024.4beta3
|
||||
org.gradle.workers.max = 3
|
@ -143,7 +143,7 @@ public class BlockUml {
|
||||
this.data = new ArrayList<>(strings);
|
||||
} else {
|
||||
final TimLoader timLoader = new TimLoader(mode.getImportedFiles(), defines, charset,
|
||||
(DefinitionsContainer) mode);
|
||||
(DefinitionsContainer) mode, strings.get(0));
|
||||
this.included.addAll(timLoader.load(strings));
|
||||
this.data = timLoader.getResultList();
|
||||
this.debug = timLoader.getDebug();
|
||||
|
@ -55,6 +55,7 @@ import net.sourceforge.plantuml.file.AParentFolder;
|
||||
import net.sourceforge.plantuml.security.SFile;
|
||||
import net.sourceforge.plantuml.security.SecurityProfile;
|
||||
import net.sourceforge.plantuml.security.SecurityUtils;
|
||||
import net.sourceforge.plantuml.text.StringLocated;
|
||||
import net.sourceforge.plantuml.tim.EaterException;
|
||||
import net.sourceforge.plantuml.tim.TMemory;
|
||||
import net.sourceforge.plantuml.tim.TVariableScope;
|
||||
@ -81,11 +82,11 @@ public class Defines implements Truth {
|
||||
return new Defines();
|
||||
}
|
||||
|
||||
public void copyTo(TMemory memory) throws EaterException {
|
||||
public void copyTo(TMemory memory, StringLocated location) throws EaterException {
|
||||
for (Entry<String, Define> ent : values.entrySet()) {
|
||||
final String name = ent.getKey();
|
||||
final Define def = ent.getValue();
|
||||
memory.putVariable(name, def.asTVariable(), TVariableScope.GLOBAL);
|
||||
memory.putVariable(name, def.asTVariable(), TVariableScope.GLOBAL, location);
|
||||
}
|
||||
|
||||
}
|
||||
@ -114,10 +115,10 @@ public class Defines implements Truth {
|
||||
final Defines result = createEmpty();
|
||||
result.overrideFilename(file.getName());
|
||||
result.environment.put("filedate", new Date(file.lastModified()).toString());
|
||||
if (SecurityUtils.getSecurityProfile() == SecurityProfile.UNSECURE) {
|
||||
if (SecurityUtils.getSecurityProfile() == SecurityProfile.UNSECURE)
|
||||
result.environment.put("dirpath",
|
||||
file.getAbsoluteFile().getParentFile().getAbsolutePath().replace('\\', '/'));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -126,10 +127,10 @@ public class Defines implements Truth {
|
||||
final Defines result = createEmpty();
|
||||
result.overrideFilename(file.getName());
|
||||
result.environment.put("filedate", new Date(file.lastModified()).toString());
|
||||
if (SecurityUtils.getSecurityProfile() == SecurityProfile.UNSECURE) {
|
||||
if (SecurityUtils.getSecurityProfile() == SecurityProfile.UNSECURE)
|
||||
result.environment.put("dirpath",
|
||||
file.getAbsoluteFile().getParentFile().getAbsolutePath().replace('\\', '/'));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -147,9 +148,9 @@ public class Defines implements Truth {
|
||||
|
||||
private static String nameNoExtension(String name) {
|
||||
final int x = name.lastIndexOf('.');
|
||||
if (x == -1) {
|
||||
if (x == -1)
|
||||
return name;
|
||||
}
|
||||
|
||||
return name.substring(0, x);
|
||||
}
|
||||
|
||||
@ -169,11 +170,10 @@ public class Defines implements Truth {
|
||||
}
|
||||
|
||||
public boolean isTrue(String name) {
|
||||
for (String key : values.keySet()) {
|
||||
if (key.equals(name) || key.startsWith(name + "(")) {
|
||||
for (String key : values.keySet())
|
||||
if (key.equals(name) || key.startsWith(name + "("))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -192,9 +192,9 @@ public class Defines implements Truth {
|
||||
}
|
||||
|
||||
private String method1(String line) {
|
||||
for (Define def : values.values()) {
|
||||
for (Define def : values.values())
|
||||
line = def.apply(line);
|
||||
}
|
||||
|
||||
return line;
|
||||
}
|
||||
|
||||
@ -215,18 +215,17 @@ public class Defines implements Truth {
|
||||
|
||||
private String method2(String line) {
|
||||
final Set<String> words = words(line);
|
||||
if (magic == null) {
|
||||
if (magic == null)
|
||||
magic = getAll();
|
||||
|
||||
}
|
||||
for (String w : words) {
|
||||
Collection<Define> tmp = magic.get(w);
|
||||
if (tmp == null) {
|
||||
if (tmp == null)
|
||||
continue;
|
||||
}
|
||||
for (Define def : tmp) {
|
||||
|
||||
for (Define def : tmp)
|
||||
line = def.apply(line);
|
||||
}
|
||||
|
||||
}
|
||||
return line;
|
||||
}
|
||||
@ -236,9 +235,9 @@ public class Defines implements Truth {
|
||||
Pattern p = Pattern.compile(ID);
|
||||
Matcher m = p.matcher(line);
|
||||
final Set<String> words = new HashSet<>();
|
||||
while (m.find()) {
|
||||
while (m.find())
|
||||
words.add(m.group(0));
|
||||
}
|
||||
|
||||
return words;
|
||||
}
|
||||
|
||||
|
@ -36,6 +36,7 @@
|
||||
package net.sourceforge.plantuml.preproc;
|
||||
|
||||
public interface Truth {
|
||||
|
||||
public boolean isTrue(String name);
|
||||
|
||||
}
|
||||
|
@ -139,21 +139,21 @@ public class PreprocessorUtils {
|
||||
if (StartDiagramExtractReader.containsStartDiagram(url, s, charset))
|
||||
return StartDiagramExtractReader.build(url, s, suf, charset);
|
||||
|
||||
return getReaderInclude(url, s.getLocation(), charset);
|
||||
return getReaderInclude(url, s, charset);
|
||||
} catch (IOException e) {
|
||||
Logme.error(e);
|
||||
throw EaterException.located("Cannot open URL " + e.getMessage());
|
||||
throw EaterException.located("Cannot open URL " + e.getMessage(), s);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static ReadLine getReaderInclude(SURL url, LineLocation lineLocation, Charset charset)
|
||||
public static ReadLine getReaderInclude(SURL url, StringLocated s, Charset charset)
|
||||
throws EaterException, UnsupportedEncodingException {
|
||||
final InputStream is = url.openStream();
|
||||
if (is == null)
|
||||
throw EaterException.located("Cannot open URL");
|
||||
throw EaterException.located("Cannot open URL", s);
|
||||
|
||||
return ReadLineReader.create(new InputStreamReader(is, charset), url.toString(), lineLocation);
|
||||
return ReadLineReader.create(new InputStreamReader(is, charset), url.toString(), s.getLocation());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -93,7 +93,7 @@ public abstract class Eater {
|
||||
final TokenStack tokenStack = new TokenStack();
|
||||
addIntoTokenStack(tokenStack, false);
|
||||
if (tokenStack.size() == 0)
|
||||
throw EaterException.located("Missing expression");
|
||||
throw EaterException.located("Missing expression", stringLocated);
|
||||
|
||||
return tokenStack;
|
||||
}
|
||||
@ -121,7 +121,7 @@ public abstract class Eater {
|
||||
final public String eatAndGetQuotedString() throws EaterException {
|
||||
final char separator = peekChar();
|
||||
if (TLineType.isQuote(separator) == false)
|
||||
throw EaterException.located("quote10");
|
||||
throw EaterException.located("quote10", stringLocated);
|
||||
|
||||
checkAndEatChar(separator);
|
||||
final StringBuilder value = new StringBuilder();
|
||||
@ -142,7 +142,7 @@ public abstract class Eater {
|
||||
while (true) {
|
||||
char ch = peekChar();
|
||||
if (ch == 0)
|
||||
throw EaterException.located("until001");
|
||||
throw EaterException.located("until001", stringLocated);
|
||||
|
||||
if (level == 0 && (ch == ',' || ch == ')'))
|
||||
return value.toString().trim();
|
||||
@ -190,7 +190,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 EaterException.located("a002");
|
||||
throw EaterException.located("a002", stringLocated);
|
||||
|
||||
addUpToLastLetterOrUnderscoreOrDigit(varname);
|
||||
return varname.toString();
|
||||
@ -199,7 +199,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 EaterException.located("a003");
|
||||
throw EaterException.located("a003", stringLocated);
|
||||
|
||||
addUpToLastLetterOrUnderscoreOrDigit(varname);
|
||||
return varname.toString();
|
||||
@ -249,7 +249,7 @@ public abstract class Eater {
|
||||
|
||||
final protected void checkAndEatChar(char ch) throws EaterException {
|
||||
if (i >= stringLocated.length() || stringLocated.charAt(i) != ch)
|
||||
throw EaterException.located("a001");
|
||||
throw EaterException.located("a001", stringLocated);
|
||||
|
||||
i++;
|
||||
}
|
||||
@ -299,7 +299,7 @@ public abstract class Eater {
|
||||
}
|
||||
|
||||
final protected TFunctionImpl eatDeclareFunction(TContext context, TMemory memory, boolean unquoted,
|
||||
LineLocation location, boolean allowNoParenthesis, TFunctionType type)
|
||||
StringLocated location, boolean allowNoParenthesis, TFunctionType type)
|
||||
throws EaterException, EaterExceptionLocated {
|
||||
final List<TFunctionArgument> args = new ArrayList<>();
|
||||
final String functionName = eatAndGetFunctionName();
|
||||
@ -308,7 +308,7 @@ public abstract class Eater {
|
||||
if (allowNoParenthesis)
|
||||
return new TFunctionImpl(functionName, args, unquoted, type);
|
||||
|
||||
throw EaterException.located("Missing opening parenthesis");
|
||||
throw EaterException.located("Missing opening parenthesis", stringLocated);
|
||||
}
|
||||
while (true) {
|
||||
skipSpaces();
|
||||
@ -320,7 +320,7 @@ public abstract class Eater {
|
||||
if (peekChar() == '=') {
|
||||
eatOneChar();
|
||||
final TokenStack def = TokenStack.eatUntilCloseParenthesisOrComma(this);
|
||||
def.guessFunctions();
|
||||
def.guessFunctions(location);
|
||||
defValue = def.getResult(getStringLocated(), context, memory);
|
||||
// System.err.println("result=" + defValue);
|
||||
} else {
|
||||
@ -333,7 +333,7 @@ public abstract class Eater {
|
||||
checkAndEatChar(")");
|
||||
break;
|
||||
} else {
|
||||
throw EaterException.located("Error in function definition");
|
||||
throw EaterException.located("Error in function definition", stringLocated);
|
||||
}
|
||||
}
|
||||
skipSpaces();
|
||||
@ -341,25 +341,25 @@ public abstract class Eater {
|
||||
}
|
||||
|
||||
final protected TFunctionImpl eatDeclareReturnFunctionWithOptionalReturn(TContext context, TMemory memory,
|
||||
boolean unquoted, LineLocation location) throws EaterException, EaterExceptionLocated {
|
||||
boolean unquoted, StringLocated location) throws EaterException, EaterExceptionLocated {
|
||||
final TFunctionImpl result = eatDeclareFunction(context, memory, unquoted, location, false,
|
||||
TFunctionType.RETURN_FUNCTION);
|
||||
if (peekChar() == 'r') {
|
||||
checkAndEatChar("return");
|
||||
skipSpaces();
|
||||
final String line = "!return " + eatAllToEnd();
|
||||
result.addBody(new StringLocated(line, location));
|
||||
result.addBody(new StringLocated(line, location.getLocation()));
|
||||
} else if (peekChar() == '!') {
|
||||
checkAndEatChar("!return");
|
||||
skipSpaces();
|
||||
final String line = "!return " + eatAllToEnd();
|
||||
result.addBody(new StringLocated(line, location));
|
||||
result.addBody(new StringLocated(line, location.getLocation()));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
final protected TFunctionImpl eatDeclareProcedure(TContext context, TMemory memory, boolean unquoted,
|
||||
LineLocation location) throws EaterException, EaterExceptionLocated {
|
||||
StringLocated location) throws EaterException, EaterExceptionLocated {
|
||||
final TFunctionImpl result = eatDeclareFunction(context, memory, unquoted, location, false,
|
||||
TFunctionType.PROCEDURE);
|
||||
return result;
|
||||
|
@ -53,7 +53,7 @@ public class EaterAffectation extends Eater {
|
||||
if (scope != null) {
|
||||
skipSpaces();
|
||||
if (peekChar() == '?' || peekChar() == '=') {
|
||||
// The variable itself is "local" or "glocal", which is not a good idea by the
|
||||
// The variable itself is "local" or "global", which is not a good idea by the
|
||||
// way
|
||||
scope = null;
|
||||
} else
|
||||
@ -72,7 +72,7 @@ public class EaterAffectation extends Eater {
|
||||
|
||||
skipSpaces();
|
||||
final TValue value = eatExpression(context, memory);
|
||||
memory.putVariable(varname, value, scope);
|
||||
memory.putVariable(varname, value, scope, getStringLocated());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -56,7 +56,7 @@ public class EaterAffectationDefine extends Eater {
|
||||
// if (memory instanceof TMemoryLocal) {
|
||||
// memory = ((TMemoryLocal) memory).getGlobalForInternalUseOnly();
|
||||
// }
|
||||
memory.putVariable(varname, value, TVariableScope.GLOBAL);
|
||||
memory.putVariable(varname, value, TVariableScope.GLOBAL, getStringLocated());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -55,9 +55,9 @@ public class EaterAssert extends Eater {
|
||||
if (ch == ':') {
|
||||
checkAndEatChar(':');
|
||||
final TValue message = eatExpression(context, memory);
|
||||
throw EaterException.located("Assertion error : " + message.toString());
|
||||
throw EaterException.located("Assertion error : " + message.toString(), getStringLocated());
|
||||
}
|
||||
throw EaterException.located("Assertion error");
|
||||
throw EaterException.located("Assertion error", getStringLocated());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -35,17 +35,16 @@
|
||||
package net.sourceforge.plantuml.tim;
|
||||
|
||||
import net.sourceforge.plantuml.text.StringLocated;
|
||||
import net.sourceforge.plantuml.utils.LineLocation;
|
||||
|
||||
public class EaterDeclareProcedure extends Eater {
|
||||
|
||||
private TFunctionImpl function;
|
||||
private final LineLocation location;
|
||||
private final StringLocated location;
|
||||
private boolean finalFlag;
|
||||
|
||||
public EaterDeclareProcedure(StringLocated s) {
|
||||
super(s.getTrimmed());
|
||||
this.location = s.getLocation();
|
||||
this.location = s;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -35,17 +35,16 @@
|
||||
package net.sourceforge.plantuml.tim;
|
||||
|
||||
import net.sourceforge.plantuml.text.StringLocated;
|
||||
import net.sourceforge.plantuml.utils.LineLocation;
|
||||
|
||||
public class EaterDeclareReturnFunction extends Eater {
|
||||
|
||||
private TFunctionImpl function;
|
||||
private final LineLocation location;
|
||||
private final StringLocated location;
|
||||
private boolean finalFlag;
|
||||
|
||||
public EaterDeclareReturnFunction(StringLocated s) {
|
||||
super(s.getTrimmed());
|
||||
this.location = s.getLocation();
|
||||
this.location = s;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -40,16 +40,16 @@ public class EaterException extends Exception {
|
||||
|
||||
private final String message;
|
||||
|
||||
private EaterException(String message) {
|
||||
private EaterException(String message, StringLocated location) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public static EaterException unlocated(String message) {
|
||||
return new EaterException(message);
|
||||
public static EaterException unlocated(String message, StringLocated location) {
|
||||
return new EaterException(message, location);
|
||||
}
|
||||
|
||||
public static EaterException located(String message) {
|
||||
return unlocated(message);
|
||||
public static EaterException located(String message, StringLocated location) {
|
||||
return unlocated(message, location);
|
||||
}
|
||||
|
||||
public final String getMessage() {
|
||||
|
@ -100,12 +100,12 @@ public class EaterFunctionCall extends Eater {
|
||||
checkAndEatChar('=');
|
||||
skipSpaces();
|
||||
final TokenStack tokens = TokenStack.eatUntilCloseParenthesisOrComma(this).withoutSpace();
|
||||
tokens.guessFunctions();
|
||||
tokens.guessFunctions(getStringLocated());
|
||||
final TValue result = tokens.getResult(getStringLocated(), context, memory);
|
||||
namedArguments.put(varname, result);
|
||||
} else {
|
||||
final TokenStack tokens = TokenStack.eatUntilCloseParenthesisOrComma(this).withoutSpace();
|
||||
tokens.guessFunctions();
|
||||
tokens.guessFunctions(getStringLocated());
|
||||
final TValue result = tokens.getResult(getStringLocated(), context, memory);
|
||||
values.add(result);
|
||||
}
|
||||
@ -119,9 +119,9 @@ public class EaterFunctionCall extends Eater {
|
||||
break;
|
||||
}
|
||||
if (unquoted) {
|
||||
throw EaterException.located("unquoted function/procedure cannot use expression.");
|
||||
throw EaterException.located("unquoted function/procedure cannot use expression.", getStringLocated());
|
||||
}
|
||||
throw EaterException.located("call001");
|
||||
throw EaterException.located("call001", getStringLocated());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -39,7 +39,7 @@ import net.sourceforge.plantuml.text.StringLocated;
|
||||
|
||||
public class EaterInclude extends Eater {
|
||||
|
||||
private String location;
|
||||
private String what;
|
||||
private PreprocessorIncludeStrategy strategy = PreprocessorIncludeStrategy.DEFAULT;
|
||||
|
||||
public EaterInclude(StringLocated s) {
|
||||
@ -65,15 +65,15 @@ public class EaterInclude extends Eater {
|
||||
}
|
||||
}
|
||||
skipSpaces();
|
||||
this.location = context.applyFunctionsAndVariables(memory,
|
||||
this.what = context.applyFunctionsAndVariables(memory,
|
||||
new StringLocated(this.eatAllToEnd(), getLineLocation()));
|
||||
// final TValue value = eatExpression(context, memory);
|
||||
// this.location = value.toString();
|
||||
|
||||
}
|
||||
|
||||
public final String getLocation() {
|
||||
return location;
|
||||
public final String getWhat() {
|
||||
return what;
|
||||
}
|
||||
|
||||
public final PreprocessorIncludeStrategy getPreprocessorIncludeStrategy() {
|
||||
|
@ -38,7 +38,7 @@ import net.sourceforge.plantuml.text.StringLocated;
|
||||
|
||||
public class EaterIncludesub extends Eater {
|
||||
|
||||
private String location;
|
||||
private String what;
|
||||
|
||||
public EaterIncludesub(StringLocated s) {
|
||||
super(s);
|
||||
@ -49,13 +49,13 @@ public class EaterIncludesub extends Eater {
|
||||
skipSpaces();
|
||||
checkAndEatChar("!includesub");
|
||||
skipSpaces();
|
||||
this.location = context.applyFunctionsAndVariables(memory,
|
||||
this.what = context.applyFunctionsAndVariables(memory,
|
||||
new StringLocated(this.eatAllToEnd(), getLineLocation()));
|
||||
|
||||
}
|
||||
|
||||
public final String getLocation() {
|
||||
return location;
|
||||
public final String getWhat() {
|
||||
return what;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ public class EaterLegacyDefine extends Eater {
|
||||
skipSpaces();
|
||||
checkAndEatChar("!define");
|
||||
skipSpaces();
|
||||
function = eatDeclareFunction(context, memory, true, getLineLocation(), false, TFunctionType.LEGACY_DEFINE);
|
||||
function = eatDeclareFunction(context, memory, true, getStringLocated(), false, TFunctionType.LEGACY_DEFINE);
|
||||
final String def = this.eatAllToEnd();
|
||||
// function.setFunctionType(TFunctionType.LEGACY_DEFINE);
|
||||
function.setLegacyDefinition(def);
|
||||
|
@ -49,7 +49,7 @@ public class EaterLegacyDefineLong extends Eater {
|
||||
skipSpaces();
|
||||
checkAndEatChar("!definelong");
|
||||
skipSpaces();
|
||||
function = eatDeclareFunction(context, memory, true, getLineLocation(), true, TFunctionType.LEGACY_DEFINELONG);
|
||||
function = eatDeclareFunction(context, memory, true, getStringLocated(), true, TFunctionType.LEGACY_DEFINELONG);
|
||||
// function.setFunctionType(TFunctionType.LEGACY_DEFINELONG);
|
||||
}
|
||||
|
||||
|
@ -50,9 +50,9 @@ public class EaterStartsub extends Eater {
|
||||
checkAndEatChar("!startsub");
|
||||
skipSpaces();
|
||||
this.subname = eatAllToEnd();
|
||||
if (this.subname.matches("\\w+") == false) {
|
||||
throw EaterException.located("Bad sub name");
|
||||
}
|
||||
if (this.subname.matches("\\w+") == false)
|
||||
throw EaterException.located("Bad sub name", getStringLocated());
|
||||
|
||||
}
|
||||
|
||||
public final String getSubname() {
|
||||
|
@ -101,24 +101,24 @@ public class EaterTheme extends Eater {
|
||||
} catch (IOException e) {
|
||||
Logme.error(e);
|
||||
}
|
||||
throw EaterException.located("Cannot load " + realName);
|
||||
throw EaterException.located("Cannot load " + realName, getStringLocated());
|
||||
}
|
||||
|
||||
if (from.startsWith("<") && from.endsWith(">")) {
|
||||
final ReadLine reader = ThemeUtils.getReaderTheme(realName, from);
|
||||
if (reader == null)
|
||||
throw EaterException.located("No such theme " + realName + " in " + from);
|
||||
throw EaterException.located("No such theme " + realName + " in " + from, getStringLocated());
|
||||
return reader;
|
||||
} else if (from.startsWith("http://") || from.startsWith("https://")) {
|
||||
final SURL url = SURL.create(ThemeUtils.getFullPath(from, realName));
|
||||
if (url == null)
|
||||
throw EaterException.located("Cannot open URL");
|
||||
throw EaterException.located("Cannot open URL", getStringLocated());
|
||||
|
||||
try {
|
||||
return PreprocessorUtils.getReaderInclude(url, getLineLocation(), UTF_8);
|
||||
return PreprocessorUtils.getReaderInclude(url, getStringLocated(), UTF_8);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
Logme.error(e);
|
||||
throw EaterException.located("Cannot decode charset");
|
||||
throw EaterException.located("Cannot decode charset", getStringLocated());
|
||||
}
|
||||
}
|
||||
|
||||
@ -126,12 +126,12 @@ public class EaterTheme extends Eater {
|
||||
final FileWithSuffix file = context.getFileWithSuffix(from, realName);
|
||||
final Reader tmp = file.getReader(UTF_8);
|
||||
if (tmp == null)
|
||||
throw EaterException.located("No such theme " + realName);
|
||||
throw EaterException.located("No such theme " + realName, getStringLocated());
|
||||
|
||||
return ReadLineReader.create(tmp, "theme " + realName);
|
||||
} catch (IOException e) {
|
||||
Logme.error(e);
|
||||
throw EaterException.located("Cannot load " + realName);
|
||||
throw EaterException.located("Cannot load " + realName, getStringLocated());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -51,16 +51,16 @@ public class FunctionsSet {
|
||||
|
||||
public TFunction getFunctionSmart(TFunctionSignature searched) {
|
||||
final TFunction func = this.functions.get(searched);
|
||||
if (func != null) {
|
||||
if (func != null)
|
||||
return func;
|
||||
}
|
||||
|
||||
for (TFunction candidate : this.functions.values()) {
|
||||
if (candidate.getSignature().sameFunctionNameAs(searched) == false) {
|
||||
if (candidate.getSignature().sameFunctionNameAs(searched) == false)
|
||||
continue;
|
||||
}
|
||||
if (candidate.canCover(searched.getNbArg(), searched.getNamedArguments())) {
|
||||
|
||||
if (candidate.canCover(searched.getNbArg(), searched.getNamedArguments()))
|
||||
return candidate;
|
||||
}
|
||||
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@ -82,9 +82,9 @@ public class FunctionsSet {
|
||||
}
|
||||
|
||||
public void addFunction(TFunction func) {
|
||||
if (func.getFunctionType() == TFunctionType.LEGACY_DEFINELONG) {
|
||||
if (func.getFunctionType() == TFunctionType.LEGACY_DEFINELONG)
|
||||
((TFunctionImpl) func).finalizeEnddefinelong();
|
||||
}
|
||||
|
||||
this.functions.put(func.getSignature(), func);
|
||||
this.functions3.add(func.getSignature().getFunctionName() + "(");
|
||||
}
|
||||
@ -96,9 +96,9 @@ public class FunctionsSet {
|
||||
|
||||
public void executeLegacyDefine(TContext context, TMemory memory, StringLocated s)
|
||||
throws EaterException, EaterExceptionLocated {
|
||||
if (this.pendingFunction != null) {
|
||||
throw EaterException.located("already0048");
|
||||
}
|
||||
if (this.pendingFunction != null)
|
||||
throw EaterException.located("already0048", s);
|
||||
|
||||
final EaterLegacyDefine legacyDefine = new EaterLegacyDefine(s);
|
||||
legacyDefine.analyze(context, memory);
|
||||
final TFunction function = legacyDefine.getFunction();
|
||||
@ -108,9 +108,9 @@ public class FunctionsSet {
|
||||
|
||||
public void executeLegacyDefineLong(TContext context, TMemory memory, StringLocated s)
|
||||
throws EaterException, EaterExceptionLocated {
|
||||
if (this.pendingFunction != null) {
|
||||
throw EaterException.located("already0068");
|
||||
}
|
||||
if (this.pendingFunction != null)
|
||||
throw EaterException.located("already0068", s);
|
||||
|
||||
final EaterLegacyDefineLong legacyDefineLong = new EaterLegacyDefineLong(s);
|
||||
legacyDefineLong.analyze(context, memory);
|
||||
this.pendingFunction = legacyDefineLong.getFunction();
|
||||
@ -118,48 +118,48 @@ public class FunctionsSet {
|
||||
|
||||
public void executeDeclareReturnFunction(TContext context, TMemory memory, StringLocated s)
|
||||
throws EaterException, EaterExceptionLocated {
|
||||
if (this.pendingFunction != null) {
|
||||
throw EaterException.located("already0068");
|
||||
}
|
||||
if (this.pendingFunction != null)
|
||||
throw EaterException.located("already0068", s);
|
||||
|
||||
final EaterDeclareReturnFunction declareFunction = new EaterDeclareReturnFunction(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");
|
||||
}
|
||||
if (finalFlag) {
|
||||
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()) {
|
||||
|
||||
if (declareFunction.getFunction().hasBody())
|
||||
this.addFunction(declareFunction.getFunction());
|
||||
} else {
|
||||
else
|
||||
this.pendingFunction = declareFunction.getFunction();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void executeDeclareProcedure(TContext context, TMemory memory, StringLocated s)
|
||||
throws EaterException, EaterExceptionLocated {
|
||||
if (this.pendingFunction != null) {
|
||||
throw EaterException.located("already0068");
|
||||
}
|
||||
if (this.pendingFunction != null)
|
||||
throw EaterException.located("already0068", s);
|
||||
|
||||
final EaterDeclareProcedure declareFunction = new EaterDeclareProcedure(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");
|
||||
}
|
||||
if (finalFlag) {
|
||||
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()) {
|
||||
|
||||
if (declareFunction.getFunction().hasBody())
|
||||
this.addFunction(declareFunction.getFunction());
|
||||
} else {
|
||||
else
|
||||
this.pendingFunction = declareFunction.getFunction();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -322,7 +322,7 @@ public class TContext {
|
||||
if (e instanceof EaterExceptionLocated)
|
||||
throw (EaterExceptionLocated) e;
|
||||
Logme.error(e);
|
||||
throw EaterException.located("Fatal parsing error");
|
||||
throw EaterException.located("Fatal parsing error", s);
|
||||
}
|
||||
}
|
||||
|
||||
@ -382,7 +382,7 @@ public class TContext {
|
||||
} else if (s.getString().matches("^\\s+$")) {
|
||||
return null;
|
||||
} else {
|
||||
throw EaterException.located("Compile Error " + ftype + " " + type);
|
||||
throw EaterException.located("Compile Error " + ftype + " " + type, s);
|
||||
}
|
||||
}
|
||||
|
||||
@ -465,7 +465,7 @@ public class TContext {
|
||||
call.getNamedArguments().keySet());
|
||||
final TFunction function = functionsSet.getFunctionSmart(signature);
|
||||
if (function == null)
|
||||
throw EaterException.located("Function not found " + presentFunction);
|
||||
throw EaterException.located("Function not found " + presentFunction, str);
|
||||
|
||||
if (function.getFunctionType() == TFunctionType.PROCEDURE) {
|
||||
this.pendingAdd = result.toString();
|
||||
@ -488,8 +488,8 @@ public class TContext {
|
||||
call.getNamedArguments());
|
||||
result.append(functionReturn.toString());
|
||||
i += call.getCurrentPosition() - 1;
|
||||
} else if (new VariableManager(this, memory, str.getLocation()).getVarnameAt(str.getString(), i) != null) {
|
||||
i = new VariableManager(this, memory, str.getLocation()).replaceVariables(str.getString(), i, result);
|
||||
} else if (new VariableManager(this, memory, str).getVarnameAt(str.getString(), i) != null) {
|
||||
i = new VariableManager(this, memory, str).replaceVariables(str.getString(), i, result);
|
||||
} else {
|
||||
result.append(c);
|
||||
}
|
||||
@ -512,18 +512,18 @@ public class TContext {
|
||||
_import.analyze(this, memory);
|
||||
|
||||
try {
|
||||
final SFile file = FileSystem.getInstance().getFile(
|
||||
applyFunctionsAndVariables(memory, new StringLocated(_import.getWhat(), s.getLocation())));
|
||||
final SFile file = FileSystem.getInstance()
|
||||
.getFile(applyFunctionsAndVariables(memory, new StringLocated(_import.getWhat(), s.getLocation())));
|
||||
if (file.exists() && file.isDirectory() == false) {
|
||||
importedFiles.add(file);
|
||||
return;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
Logme.error(e);
|
||||
throw EaterException.located("Cannot import " + e.getMessage());
|
||||
throw EaterException.located("Cannot import " + e.getMessage(), s);
|
||||
}
|
||||
|
||||
throw EaterException.located("Cannot import");
|
||||
throw EaterException.located("Cannot import", s);
|
||||
}
|
||||
|
||||
private void executeLog(TMemory memory, StringLocated s) throws EaterException, EaterExceptionLocated {
|
||||
@ -543,12 +543,12 @@ public class TContext {
|
||||
try {
|
||||
final EaterIncludesub include = new EaterIncludesub(s.getTrimmed());
|
||||
include.analyze(this, memory);
|
||||
final String location = include.getLocation();
|
||||
final int idx = location.indexOf('!');
|
||||
final String what = include.getWhat();
|
||||
final int idx = what.indexOf('!');
|
||||
Sub sub = null;
|
||||
if (idx != -1) {
|
||||
final String filename = location.substring(0, idx);
|
||||
final String blocname = location.substring(idx + 1);
|
||||
final String filename = what.substring(0, idx);
|
||||
final String blocname = what.substring(idx + 1);
|
||||
try {
|
||||
final FileWithSuffix f2 = importedFiles.getFile(filename, null);
|
||||
if (f2.fileOk()) {
|
||||
@ -556,10 +556,10 @@ public class TContext {
|
||||
this.importedFiles = this.importedFiles.withCurrentDir(f2.getParentFile());
|
||||
final Reader reader = f2.getReader(charset);
|
||||
if (reader == null)
|
||||
throw EaterException.located("cannot include " + location);
|
||||
throw EaterException.located("cannot include " + what, s);
|
||||
|
||||
try {
|
||||
ReadLine readerline = ReadLineReader.create(reader, location, s.getLocation());
|
||||
ReadLine readerline = ReadLineReader.create(reader, what, s.getLocation());
|
||||
readerline = new UncommentReadLine(readerline);
|
||||
sub = Sub.fromFile(readerline, blocname, this, memory);
|
||||
} finally {
|
||||
@ -568,14 +568,14 @@ public class TContext {
|
||||
}
|
||||
} catch (IOException e) {
|
||||
Logme.error(e);
|
||||
throw EaterException.located("cannot include " + location);
|
||||
throw EaterException.located("cannot include " + what, s);
|
||||
}
|
||||
}
|
||||
if (sub == null)
|
||||
sub = subs.get(location);
|
||||
sub = subs.get(what);
|
||||
|
||||
if (sub == null)
|
||||
throw EaterException.located("cannot include " + location);
|
||||
throw EaterException.located("cannot include " + what, s);
|
||||
|
||||
executeLinesInternal(memory, sub.lines(), null);
|
||||
} finally {
|
||||
@ -604,7 +604,7 @@ public class TContext {
|
||||
} while (true);
|
||||
} catch (IOException e) {
|
||||
Logme.error(e);
|
||||
throw EaterException.located("" + e);
|
||||
throw EaterException.located("" + e, s);
|
||||
} finally {
|
||||
try {
|
||||
reader2.close();
|
||||
@ -619,7 +619,7 @@ public class TContext {
|
||||
eater.analyze(this, memory);
|
||||
final ReadLine reader = eater.getTheme();
|
||||
if (reader == null)
|
||||
throw EaterException.located("No such theme " + eater.getName());
|
||||
throw EaterException.located("No such theme " + eater.getName(), s);
|
||||
|
||||
try {
|
||||
final List<StringLocated> body = new ArrayList<>();
|
||||
@ -633,7 +633,7 @@ public class TContext {
|
||||
} while (true);
|
||||
} catch (IOException e) {
|
||||
Logme.error(e);
|
||||
throw EaterException.located("Error reading theme " + e);
|
||||
throw EaterException.located("Error reading theme " + e, s);
|
||||
} finally {
|
||||
try {
|
||||
reader.close();
|
||||
@ -646,7 +646,7 @@ public class TContext {
|
||||
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();
|
||||
String location = include.getWhat();
|
||||
final PreprocessorIncludeStrategy strategy = include.getPreprocessorIncludeStrategy();
|
||||
final int idx = location.lastIndexOf('!');
|
||||
String suf = null;
|
||||
@ -661,7 +661,7 @@ public class TContext {
|
||||
if (location.startsWith("http://") || location.startsWith("https://")) {
|
||||
final SURL url = SURL.create(location);
|
||||
if (url == null)
|
||||
throw EaterException.located("Cannot open URL");
|
||||
throw EaterException.located("Cannot open URL", s);
|
||||
|
||||
reader = PreprocessorUtils.getReaderIncludeUrl(url, s, suf, charset);
|
||||
} else if (location.startsWith("<") && location.endsWith(">")) {
|
||||
@ -677,14 +677,14 @@ public class TContext {
|
||||
return;
|
||||
|
||||
if (strategy == PreprocessorIncludeStrategy.ONCE && filesUsedCurrent.contains(f2))
|
||||
throw EaterException.located("This file has already been included");
|
||||
throw EaterException.located("This file has already been included", s);
|
||||
|
||||
if (StartDiagramExtractReader.containsStartDiagram(f2, s, charset)) {
|
||||
reader = StartDiagramExtractReader.build(f2, s, charset);
|
||||
} else {
|
||||
final Reader tmp = f2.getReader(charset);
|
||||
if (tmp == null)
|
||||
throw EaterException.located("Cannot include file");
|
||||
throw EaterException.located("Cannot include file", s);
|
||||
|
||||
reader = ReadLineReader.create(tmp, location, s.getLocation());
|
||||
}
|
||||
@ -713,7 +713,7 @@ public class TContext {
|
||||
}
|
||||
} catch (IOException e) {
|
||||
Logme.error(e);
|
||||
throw EaterException.located("cannot include " + e);
|
||||
throw EaterException.located("cannot include " + e, s);
|
||||
} finally {
|
||||
if (reader != null) {
|
||||
try {
|
||||
@ -724,7 +724,7 @@ public class TContext {
|
||||
}
|
||||
}
|
||||
|
||||
throw EaterException.located("cannot include " + location);
|
||||
throw EaterException.located("cannot include " + location, s);
|
||||
}
|
||||
|
||||
public boolean isLegacyDefine(String functionName) {
|
||||
|
@ -148,12 +148,12 @@ public class TFunctionImpl implements TFunction {
|
||||
return executeReturnLegacyDefine(location.getLocation(), context, memory, args);
|
||||
|
||||
if (functionType != TFunctionType.RETURN_FUNCTION)
|
||||
throw EaterException.unlocated("Illegal call here. Is there a return directive in your function?");
|
||||
throw EaterException.unlocated("Illegal call here. Is there a return directive in your function?", location);
|
||||
|
||||
final TMemory copy = getNewMemory(memory, args, named);
|
||||
final TValue result = context.executeLines(copy, body, TFunctionType.RETURN_FUNCTION, true);
|
||||
if (result == null)
|
||||
throw EaterException.unlocated("No return directive found in your function");
|
||||
throw EaterException.unlocated("No return directive found in your function", location);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -37,13 +37,15 @@ package net.sourceforge.plantuml.tim;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import net.sourceforge.plantuml.text.StringLocated;
|
||||
import net.sourceforge.plantuml.tim.expression.TValue;
|
||||
|
||||
public interface TMemory {
|
||||
|
||||
public TValue getVariable(String varname);
|
||||
|
||||
public void putVariable(String varname, TValue value, TVariableScope scope) throws EaterException;
|
||||
public void putVariable(String varname, TValue value, TVariableScope scope, StringLocated location)
|
||||
throws EaterException;
|
||||
|
||||
public void removeVariable(String varname);
|
||||
|
||||
|
@ -41,6 +41,7 @@ import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import net.sourceforge.plantuml.text.StringLocated;
|
||||
import net.sourceforge.plantuml.tim.expression.TValue;
|
||||
import net.sourceforge.plantuml.utils.Log;
|
||||
|
||||
@ -49,10 +50,12 @@ public class TMemoryGlobal extends ExecutionContexts implements TMemory {
|
||||
private final Map<String, TValue> globalVariables = new HashMap<String, TValue>();
|
||||
private final TrieImpl variables = new TrieImpl();
|
||||
|
||||
@Override
|
||||
public TValue getVariable(String varname) {
|
||||
return this.globalVariables.get(varname);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dumpDebug(String message) {
|
||||
Log.error("[MemGlobal] Start of memory_dump " + message);
|
||||
dumpMemoryInternal();
|
||||
@ -68,32 +71,39 @@ public class TMemoryGlobal extends ExecutionContexts implements TMemory {
|
||||
}
|
||||
}
|
||||
|
||||
public void putVariable(String varname, TValue value, TVariableScope scope) throws EaterException {
|
||||
@Override
|
||||
public void putVariable(String varname, TValue value, TVariableScope scope, StringLocated location)
|
||||
throws EaterException {
|
||||
Log.info("[MemGlobal] Setting " + varname);
|
||||
if (scope == TVariableScope.LOCAL) {
|
||||
throw EaterException.unlocated("Cannot use local variable here");
|
||||
}
|
||||
if (scope == TVariableScope.LOCAL)
|
||||
throw EaterException.unlocated("Cannot use local variable here", location);
|
||||
|
||||
this.globalVariables.put(varname, value);
|
||||
this.variables.add(varname);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeVariable(String varname) {
|
||||
this.globalVariables.remove(varname);
|
||||
this.variables.remove(varname);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return globalVariables.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> variablesNames() {
|
||||
return Collections.unmodifiableSet(globalVariables.keySet());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Trie variablesNames3() {
|
||||
return variables;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TMemory forkFromGlobal(Map<String, TValue> input) {
|
||||
return new TMemoryLocal(this, input);
|
||||
}
|
||||
|
@ -40,6 +40,7 @@ import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import net.sourceforge.plantuml.text.StringLocated;
|
||||
import net.sourceforge.plantuml.tim.expression.TValue;
|
||||
import net.sourceforge.plantuml.utils.Log;
|
||||
|
||||
@ -76,19 +77,21 @@ public class TMemoryLocal extends ExecutionContexts implements TMemory {
|
||||
Log.error("[MemGlobal] End of memory_dump");
|
||||
}
|
||||
|
||||
public void putVariable(String varname, TValue value, TVariableScope scope) throws EaterException {
|
||||
@Override
|
||||
public void putVariable(String varname, TValue value, TVariableScope scope, StringLocated location)
|
||||
throws EaterException {
|
||||
if (scope == TVariableScope.GLOBAL) {
|
||||
memoryGlobal.putVariable(varname, value, scope);
|
||||
memoryGlobal.putVariable(varname, value, scope, location);
|
||||
return;
|
||||
}
|
||||
if (scope == TVariableScope.LOCAL || overridenVariables01.containsKey(varname)) {
|
||||
this.overridenVariables01.put(varname, value);
|
||||
if (this.overridenVariables00 != null) {
|
||||
if (this.overridenVariables00 != null)
|
||||
this.overridenVariables00.add(varname);
|
||||
}
|
||||
|
||||
Log.info("[MemLocal/overrriden] Setting " + varname);
|
||||
} else if (memoryGlobal.getVariable(varname) != null) {
|
||||
memoryGlobal.putVariable(varname, value, scope);
|
||||
memoryGlobal.putVariable(varname, value, scope, location);
|
||||
} else {
|
||||
this.localVariables01.put(varname, value);
|
||||
this.localVariables00.add(varname);
|
||||
@ -96,12 +99,13 @@ public class TMemoryLocal extends ExecutionContexts implements TMemory {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeVariable(String varname) {
|
||||
if (overridenVariables01.containsKey(varname)) {
|
||||
this.overridenVariables01.remove(varname);
|
||||
if (this.overridenVariables00 != null) {
|
||||
if (this.overridenVariables00 != null)
|
||||
this.overridenVariables00.remove(varname);
|
||||
}
|
||||
|
||||
} else if (memoryGlobal.getVariable(varname) != null) {
|
||||
memoryGlobal.removeVariable(varname);
|
||||
} else {
|
||||
@ -110,25 +114,27 @@ public class TMemoryLocal extends ExecutionContexts implements TMemory {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public TValue getVariable(String varname) {
|
||||
TValue result = overridenVariables01.get(varname);
|
||||
if (result != null) {
|
||||
if (result != null)
|
||||
return result;
|
||||
}
|
||||
|
||||
result = memoryGlobal.getVariable(varname);
|
||||
if (result != null) {
|
||||
if (result != null)
|
||||
return result;
|
||||
}
|
||||
|
||||
result = localVariables01.get(varname);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Trie variablesNames3() {
|
||||
if (overridenVariables00 == null) {
|
||||
overridenVariables00 = new TrieImpl();
|
||||
for (String name : overridenVariables01.keySet()) {
|
||||
for (String name : overridenVariables01.keySet())
|
||||
overridenVariables00.add(name);
|
||||
}
|
||||
|
||||
}
|
||||
return new Trie() {
|
||||
public void add(String s) {
|
||||
@ -140,12 +146,12 @@ public class TMemoryLocal extends ExecutionContexts implements TMemory {
|
||||
final String s2 = overridenVariables00.getLonguestMatchStartingIn(s);
|
||||
final String s3 = localVariables00.getLonguestMatchStartingIn(s);
|
||||
|
||||
if (s1.length() >= s2.length() && s1.length() >= s3.length()) {
|
||||
if (s1.length() >= s2.length() && s1.length() >= s3.length())
|
||||
return s1;
|
||||
}
|
||||
if (s2.length() >= s3.length() && s2.length() >= s1.length()) {
|
||||
|
||||
if (s2.length() >= s3.length() && s2.length() >= s1.length())
|
||||
return s2;
|
||||
}
|
||||
|
||||
return s3;
|
||||
}
|
||||
};
|
||||
@ -162,14 +168,17 @@ public class TMemoryLocal extends ExecutionContexts implements TMemory {
|
||||
// return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return memoryGlobal.isEmpty() && localVariables01.isEmpty() && overridenVariables01.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> variablesNames() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TMemory forkFromGlobal(Map<String, TValue> input) {
|
||||
return new TMemoryLocal(memoryGlobal, input);
|
||||
}
|
||||
|
@ -53,10 +53,10 @@ public class TimLoader {
|
||||
private List<StringLocated> resultList;
|
||||
|
||||
public TimLoader(ImportedFiles importedFiles, Defines defines, Charset charset,
|
||||
DefinitionsContainer definitionsContainer) {
|
||||
DefinitionsContainer definitionsContainer, StringLocated location) {
|
||||
this.context = new TContext(importedFiles, defines, charset, definitionsContainer);
|
||||
try {
|
||||
defines.copyTo(global);
|
||||
defines.copyTo(global, location);
|
||||
} catch (EaterException e) {
|
||||
Logme.error(e);
|
||||
}
|
||||
|
@ -46,9 +46,9 @@ public class VariableManager {
|
||||
|
||||
private final TMemory memory;
|
||||
private final TContext context;
|
||||
private final LineLocation location;
|
||||
private final StringLocated location;
|
||||
|
||||
public VariableManager(TContext context, TMemory memory, LineLocation location) {
|
||||
public VariableManager(TContext context, TMemory memory, StringLocated location) {
|
||||
this.memory = memory;
|
||||
this.context = context;
|
||||
this.location = location;
|
||||
@ -56,9 +56,9 @@ public class VariableManager {
|
||||
|
||||
public int replaceVariables(String str, int i, StringBuilder result) throws EaterException, EaterExceptionLocated {
|
||||
final String presentVariable = getVarnameAt(str, i);
|
||||
if (result.toString().endsWith("##")) {
|
||||
if (result.toString().endsWith("##"))
|
||||
result.setLength(result.length() - 2);
|
||||
}
|
||||
|
||||
final TValue value = memory.getVariable(presentVariable);
|
||||
i += presentVariable.length() - 1;
|
||||
if (value.isJson()) {
|
||||
@ -75,9 +75,9 @@ public class VariableManager {
|
||||
} else {
|
||||
result.append(value.toString());
|
||||
}
|
||||
if (i + 2 < str.length() && str.charAt(i + 1) == '#' && str.charAt(i + 2) == '#') {
|
||||
if (i + 2 < str.length() && str.charAt(i + 1) == '#' && str.charAt(i + 2) == '#')
|
||||
i += 2;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
@ -89,9 +89,9 @@ public class VariableManager {
|
||||
i++;
|
||||
final StringBuilder fieldName = new StringBuilder();
|
||||
while (i < str.length()) {
|
||||
if (Character.isJavaIdentifierPart(str.charAt(i)) == false) {
|
||||
if (Character.isJavaIdentifierPart(str.charAt(i)) == false)
|
||||
break;
|
||||
}
|
||||
|
||||
fieldName.append(str.charAt(i));
|
||||
i++;
|
||||
}
|
||||
@ -101,9 +101,9 @@ public class VariableManager {
|
||||
final StringBuilder inBracket = new StringBuilder();
|
||||
int level = 0;
|
||||
while (true) {
|
||||
if (str.charAt(i) == '[') {
|
||||
if (str.charAt(i) == '[')
|
||||
level++;
|
||||
}
|
||||
|
||||
if (str.charAt(i) == ']') {
|
||||
if (level == 0)
|
||||
break;
|
||||
@ -113,29 +113,29 @@ public class VariableManager {
|
||||
i++;
|
||||
}
|
||||
final String nbString = context.applyFunctionsAndVariables(memory,
|
||||
new StringLocated(inBracket.toString(), location));
|
||||
new StringLocated(inBracket.toString(), location.getLocation()));
|
||||
if (jsonValue instanceof JsonArray) {
|
||||
final int nb = Integer.parseInt(nbString);
|
||||
jsonValue = ((JsonArray) jsonValue).get(nb);
|
||||
} else if (jsonValue instanceof JsonObject) {
|
||||
jsonValue = ((JsonObject) jsonValue).get(nbString);
|
||||
} else {
|
||||
throw EaterException.unlocated("Major parsing error");
|
||||
}
|
||||
if (jsonValue == null) {
|
||||
throw EaterException.unlocated("Data parsing error");
|
||||
throw EaterException.unlocated("Major parsing error", location);
|
||||
}
|
||||
|
||||
if (jsonValue == null)
|
||||
throw EaterException.unlocated("Data parsing error", location);
|
||||
|
||||
i++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (jsonValue != null) {
|
||||
if (jsonValue.isString()) {
|
||||
if (jsonValue.isString())
|
||||
result.append(jsonValue.asString());
|
||||
} else {
|
||||
else
|
||||
result.append(jsonValue.toString());
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
@ -146,13 +146,13 @@ public class VariableManager {
|
||||
return null;
|
||||
}
|
||||
final String varname = memory.variablesNames3().getLonguestMatchStartingIn(s.substring(pos));
|
||||
if (varname.length() == 0) {
|
||||
if (varname.length() == 0)
|
||||
return null;
|
||||
}
|
||||
|
||||
if (pos + varname.length() == s.length()
|
||||
|| TLineType.isLetterOrUnderscoreOrDigit(s.charAt(pos + varname.length())) == false) {
|
||||
|| TLineType.isLetterOrUnderscoreOrDigit(s.charAt(pos + varname.length())) == false)
|
||||
return varname;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -47,18 +47,12 @@ import net.sourceforge.plantuml.tim.TContext;
|
||||
import net.sourceforge.plantuml.tim.TFunction;
|
||||
import net.sourceforge.plantuml.tim.TFunctionSignature;
|
||||
import net.sourceforge.plantuml.tim.TMemory;
|
||||
import net.sourceforge.plantuml.utils.LineLocation;
|
||||
|
||||
public class ReversePolishInterpretor {
|
||||
|
||||
private final TValue result;
|
||||
private final boolean trace = false;
|
||||
|
||||
public ReversePolishInterpretor(TokenStack queue, Knowledge knowledge, TMemory memory, TContext context)
|
||||
throws EaterException, EaterExceptionLocated {
|
||||
this(null, queue, knowledge, memory, context);
|
||||
}
|
||||
|
||||
public ReversePolishInterpretor(StringLocated location, TokenStack queue, Knowledge knowledge, TMemory memory,
|
||||
TContext context) throws EaterException, EaterExceptionLocated {
|
||||
|
||||
@ -79,45 +73,45 @@ public class ReversePolishInterpretor {
|
||||
final TValue v2 = stack.removeFirst();
|
||||
final TValue v1 = stack.removeFirst();
|
||||
final TokenOperator op = token.getTokenOperator();
|
||||
if (op == null) {
|
||||
throw EaterException.unlocated("bad op");
|
||||
}
|
||||
if (op == null)
|
||||
throw EaterException.unlocated("bad op", location);
|
||||
|
||||
final TValue tmp = op.operate(v1, v2);
|
||||
stack.addFirst(tmp);
|
||||
} else if (token.getTokenType() == TokenType.OPEN_PAREN_FUNC) {
|
||||
final int nb = Integer.parseInt(token.getSurface());
|
||||
final Token token2 = it.nextToken();
|
||||
if (token2.getTokenType() != TokenType.FUNCTION_NAME) {
|
||||
throw EaterException.unlocated("rpn43");
|
||||
}
|
||||
if (token2.getTokenType() != TokenType.FUNCTION_NAME)
|
||||
throw EaterException.unlocated("rpn43", location);
|
||||
|
||||
if (trace)
|
||||
System.err.println("token2=" + token2);
|
||||
final TFunction function = knowledge.getFunction(new TFunctionSignature(token2.getSurface(), nb));
|
||||
if (trace)
|
||||
System.err.println("function=" + function);
|
||||
if (function == null) {
|
||||
throw EaterException.unlocated("Unknown built-in function " + token2.getSurface());
|
||||
}
|
||||
if (function.canCover(nb, Collections.<String>emptySet()) == false) {
|
||||
throw EaterException
|
||||
.unlocated("Bad number of arguments for " + function.getSignature().getFunctionName());
|
||||
}
|
||||
if (function == null)
|
||||
throw EaterException.unlocated("Unknown built-in function " + token2.getSurface(), location);
|
||||
|
||||
if (function.canCover(nb, Collections.<String>emptySet()) == false)
|
||||
throw EaterException.unlocated(
|
||||
"Bad number of arguments for " + function.getSignature().getFunctionName(), location);
|
||||
|
||||
final List<TValue> args = new ArrayList<>();
|
||||
for (int i = 0; i < nb; i++) {
|
||||
for (int i = 0; i < nb; i++)
|
||||
args.add(0, stack.removeFirst());
|
||||
}
|
||||
|
||||
if (trace)
|
||||
System.err.println("args=" + args);
|
||||
if (location == null) {
|
||||
throw EaterException.unlocated("rpn44");
|
||||
}
|
||||
if (location == null)
|
||||
throw EaterException.unlocated("rpn44", location);
|
||||
|
||||
final TValue r = function.executeReturnFunction(context, memory, location, args,
|
||||
Collections.<String, TValue>emptyMap());
|
||||
if (trace)
|
||||
System.err.println("r=" + r);
|
||||
stack.addFirst(r);
|
||||
} else {
|
||||
throw EaterException.unlocated("rpn41");
|
||||
throw EaterException.unlocated("rpn41", location);
|
||||
}
|
||||
}
|
||||
result = stack.removeFirst();
|
||||
|
@ -37,6 +37,7 @@ package net.sourceforge.plantuml.tim.expression;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Deque;
|
||||
|
||||
import net.sourceforge.plantuml.text.StringLocated;
|
||||
import net.sourceforge.plantuml.tim.EaterException;
|
||||
import net.sourceforge.plantuml.tim.EaterExceptionLocated;
|
||||
|
||||
@ -58,7 +59,8 @@ public class ShuntingYard {
|
||||
System.err.println("");
|
||||
}
|
||||
|
||||
public ShuntingYard(TokenIterator it, Knowledge knowledge) throws EaterException, EaterExceptionLocated {
|
||||
public ShuntingYard(TokenIterator it, Knowledge knowledge, StringLocated location)
|
||||
throws EaterException, EaterExceptionLocated {
|
||||
|
||||
while (it.hasMoreTokens()) {
|
||||
final Token token = it.nextToken();
|
||||
@ -74,7 +76,7 @@ public class ShuntingYard {
|
||||
final TValue variable = knowledge.getVariable(name);
|
||||
if (variable == null) {
|
||||
if (isVariableName(name) == false)
|
||||
throw EaterException.unlocated("Parsing syntax error about " + name);
|
||||
throw EaterException.unlocated("Parsing syntax error about " + name, location);
|
||||
|
||||
ouputQueue.add(new Token(name, TokenType.QUOTED_STRING, null));
|
||||
} else {
|
||||
|
@ -48,7 +48,6 @@ import net.sourceforge.plantuml.tim.EaterException;
|
||||
import net.sourceforge.plantuml.tim.EaterExceptionLocated;
|
||||
import net.sourceforge.plantuml.tim.TContext;
|
||||
import net.sourceforge.plantuml.tim.TMemory;
|
||||
import net.sourceforge.plantuml.utils.LineLocation;
|
||||
|
||||
public class TokenStack {
|
||||
|
||||
@ -96,7 +95,7 @@ public class TokenStack {
|
||||
eater.skipSpaces();
|
||||
final char ch = eater.peekChar();
|
||||
if (ch == 0)
|
||||
throw EaterException.unlocated("until001");
|
||||
throw EaterException.unlocated("until001", eater.getStringLocated());
|
||||
|
||||
if (level == 0 && (ch == ',' || ch == ')'))
|
||||
return result;
|
||||
@ -114,12 +113,12 @@ public class TokenStack {
|
||||
}
|
||||
}
|
||||
|
||||
static public void eatUntilCloseParenthesisOrComma(TokenIterator it) throws EaterException {
|
||||
static public void eatUntilCloseParenthesisOrComma(TokenIterator it, StringLocated location) throws EaterException {
|
||||
int level = 0;
|
||||
while (true) {
|
||||
final Token ch = it.peekToken();
|
||||
if (ch == null)
|
||||
throw EaterException.unlocated("until002");
|
||||
throw EaterException.unlocated("until002", location);
|
||||
|
||||
final TokenType typech = ch.getTokenType();
|
||||
if (level == 0 && (typech == TokenType.COMMA || typech == TokenType.CLOSE_PAREN_MATH)
|
||||
@ -136,7 +135,7 @@ public class TokenStack {
|
||||
}
|
||||
}
|
||||
|
||||
private int countFunctionArg(TokenIterator it) throws EaterException {
|
||||
private int countFunctionArg(TokenIterator it, StringLocated location) throws EaterException {
|
||||
// return 42;
|
||||
final TokenType type1 = it.peekToken().getTokenType();
|
||||
if (type1 == TokenType.CLOSE_PAREN_MATH || type1 == TokenType.CLOSE_PAREN_FUNC)
|
||||
@ -144,7 +143,7 @@ public class TokenStack {
|
||||
|
||||
int result = 1;
|
||||
while (it.hasMoreTokens()) {
|
||||
eatUntilCloseParenthesisOrComma(it);
|
||||
eatUntilCloseParenthesisOrComma(it, location);
|
||||
final Token token = it.nextToken();
|
||||
final TokenType type = token.getTokenType();
|
||||
if (type == TokenType.CLOSE_PAREN_MATH || type == TokenType.CLOSE_PAREN_FUNC)
|
||||
@ -152,13 +151,13 @@ public class TokenStack {
|
||||
else if (type == TokenType.COMMA)
|
||||
result++;
|
||||
else
|
||||
throw EaterException.unlocated("count13");
|
||||
throw EaterException.unlocated("count13", location);
|
||||
|
||||
}
|
||||
throw EaterException.unlocated("count12");
|
||||
throw EaterException.unlocated("count12", location);
|
||||
}
|
||||
|
||||
public void guessFunctions() throws EaterException {
|
||||
public void guessFunctions(StringLocated location) throws EaterException {
|
||||
final Deque<Integer> open = new ArrayDeque<>();
|
||||
final Map<Integer, Integer> parens = new HashMap<Integer, Integer>();
|
||||
for (int i = 0; i < tokens.size(); i++) {
|
||||
@ -178,7 +177,7 @@ public class TokenStack {
|
||||
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, null));
|
||||
final int nbArg = countFunctionArg(subTokenStack(iopen + 1).tokenIterator());
|
||||
final int nbArg = countFunctionArg(subTokenStack(iopen + 1).tokenIterator(), location);
|
||||
tokens.set(iopen, new Token("" + nbArg, TokenType.OPEN_PAREN_FUNC, null));
|
||||
tokens.set(iclose, new Token(")", TokenType.CLOSE_PAREN_FUNC, null));
|
||||
}
|
||||
@ -215,9 +214,9 @@ public class TokenStack {
|
||||
throws EaterException, EaterExceptionLocated {
|
||||
final Knowledge knowledge = context.asKnowledge(memory, location.getLocation());
|
||||
final TokenStack tmp = withoutSpace();
|
||||
tmp.guessFunctions();
|
||||
tmp.guessFunctions(location);
|
||||
final TokenIterator it = tmp.tokenIterator();
|
||||
final ShuntingYard shuntingYard = new ShuntingYard(it, knowledge);
|
||||
final ShuntingYard shuntingYard = new ShuntingYard(it, knowledge, location);
|
||||
final ReversePolishInterpretor rpn = new ReversePolishInterpretor(location, shuntingYard.getQueue(), knowledge,
|
||||
memory, context);
|
||||
return rpn.getResult();
|
||||
|
@ -34,6 +34,7 @@
|
||||
*/
|
||||
package net.sourceforge.plantuml.tim.iterator;
|
||||
|
||||
import net.sourceforge.plantuml.text.StringLocated;
|
||||
import net.sourceforge.plantuml.tim.EaterException;
|
||||
import net.sourceforge.plantuml.tim.EaterExceptionLocated;
|
||||
|
||||
@ -45,16 +46,19 @@ public abstract class AbstractCodeIterator implements CodeIterator {
|
||||
this.source = source;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void next() throws EaterException, EaterExceptionLocated {
|
||||
source.next();
|
||||
}
|
||||
|
||||
@Override
|
||||
final public CodePosition getCodePosition() {
|
||||
return source.getCodePosition();
|
||||
}
|
||||
|
||||
final public void jumpToCodePosition(CodePosition newPosition) throws EaterException {
|
||||
source.jumpToCodePosition(newPosition);
|
||||
@Override
|
||||
final public void jumpToCodePosition(CodePosition newPosition, StringLocated location) throws EaterException {
|
||||
source.jumpToCodePosition(newPosition, location);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -39,7 +39,7 @@ import net.sourceforge.plantuml.tim.EaterException;
|
||||
import net.sourceforge.plantuml.tim.EaterExceptionLocated;
|
||||
|
||||
public interface CodeIterator {
|
||||
// ::remove folder when __HAXE__
|
||||
// ::remove folder when __HAXE__
|
||||
|
||||
public StringLocated peek() throws EaterException, EaterExceptionLocated;
|
||||
|
||||
@ -47,6 +47,6 @@ public interface CodeIterator {
|
||||
|
||||
public CodePosition getCodePosition();
|
||||
|
||||
public void jumpToCodePosition(CodePosition newPosition) throws EaterException;
|
||||
public void jumpToCodePosition(CodePosition newPosition, StringLocated location) throws EaterException;
|
||||
|
||||
}
|
||||
|
@ -58,6 +58,7 @@ public class CodeIteratorAffectation extends AbstractCodeIterator {
|
||||
this.logs = log;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StringLocated peek() throws EaterException, EaterExceptionLocated {
|
||||
while (true) {
|
||||
final StringLocated result = source.peek();
|
||||
@ -81,9 +82,9 @@ public class CodeIteratorAffectation extends AbstractCodeIterator {
|
||||
this.executeAffectation(context, memory, result);
|
||||
return;
|
||||
} catch (ParseException e) {
|
||||
if (e.getColumn() <= lastLocation) {
|
||||
throw EaterException.located("Error in JSON format");
|
||||
}
|
||||
if (e.getColumn() <= lastLocation)
|
||||
throw EaterException.located("Error in JSON format", result);
|
||||
|
||||
lastLocation = e.getColumn();
|
||||
next();
|
||||
final StringLocated forward = source.peek();
|
||||
|
@ -65,9 +65,8 @@ public class CodeIteratorForeach extends AbstractCodeIterator {
|
||||
int level = 0;
|
||||
while (true) {
|
||||
final StringLocated result = source.peek();
|
||||
if (result == null) {
|
||||
if (result == null)
|
||||
return null;
|
||||
}
|
||||
|
||||
final ExecutionContextForeach foreach = memory.peekForeach();
|
||||
if (foreach != null && foreach.isSkipMe()) {
|
||||
@ -91,15 +90,15 @@ public class CodeIteratorForeach extends AbstractCodeIterator {
|
||||
continue;
|
||||
} else if (result.getType() == TLineType.ENDFOREACH) {
|
||||
logs.add(result);
|
||||
if (foreach == null) {
|
||||
throw EaterException.located("No foreach related to this endforeach");
|
||||
}
|
||||
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());
|
||||
source.jumpToCodePosition(foreach.getStartForeach(), result);
|
||||
}
|
||||
next();
|
||||
continue;
|
||||
@ -114,18 +113,18 @@ public class CodeIteratorForeach extends AbstractCodeIterator {
|
||||
condition.analyze(context, memory);
|
||||
final ExecutionContextForeach foreach = ExecutionContextForeach.fromValue(condition.getVarname(),
|
||||
condition.getJsonArray(), source.getCodePosition());
|
||||
if (condition.isSkip()) {
|
||||
if (condition.isSkip())
|
||||
foreach.skipMeNow();
|
||||
} else {
|
||||
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);
|
||||
memory.putVariable(foreach.getVarname(), TValue.fromJson(first), TVariableScope.GLOBAL, position);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -118,18 +118,17 @@ public class CodeIteratorIf extends AbstractCodeIterator {
|
||||
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");
|
||||
}
|
||||
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) {
|
||||
if (isTrue)
|
||||
poll.nowInSomeElseIf();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -149,17 +148,17 @@ public class CodeIteratorIf extends AbstractCodeIterator {
|
||||
|
||||
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");
|
||||
}
|
||||
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");
|
||||
}
|
||||
if (poll == null)
|
||||
throw EaterException.located("No if related to this endif", s);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -62,34 +62,38 @@ public class CodeIteratorImpl implements CodeIterator {
|
||||
this.list = list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StringLocated peek() {
|
||||
if (current == list.size()) {
|
||||
if (current == list.size())
|
||||
return null;
|
||||
}
|
||||
if (current > list.size()) {
|
||||
|
||||
if (current > list.size())
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
return list.get(current);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void next() {
|
||||
if (current >= list.size()) {
|
||||
if (current >= list.size())
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
assert current < list.size();
|
||||
current++;
|
||||
assert current <= list.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CodePosition getCodePosition() {
|
||||
return new Position(current);
|
||||
}
|
||||
|
||||
public void jumpToCodePosition(CodePosition newPosition) throws EaterException {
|
||||
@Override
|
||||
public void jumpToCodePosition(CodePosition newPosition, StringLocated location) throws EaterException {
|
||||
this.countJump++;
|
||||
if (this.countJump > 999) {
|
||||
throw EaterException.unlocated("Infinite loop?");
|
||||
}
|
||||
if (this.countJump > 999)
|
||||
throw EaterException.unlocated("Infinite loop?", location);
|
||||
|
||||
final Position pos = (Position) newPosition;
|
||||
this.current = pos.pos;
|
||||
|
||||
|
@ -67,13 +67,13 @@ public class CodeIteratorSub extends AbstractCodeIterator {
|
||||
}
|
||||
|
||||
public StringLocated peek() throws EaterException, EaterExceptionLocated {
|
||||
if (readingInProgress != null) {
|
||||
if (readingInProgress != null)
|
||||
return readingInProgress.peek();
|
||||
}
|
||||
|
||||
StringLocated result = source.peek();
|
||||
if (result == null) {
|
||||
if (result == null)
|
||||
return null;
|
||||
}
|
||||
|
||||
if (result.getType() == TLineType.STARTSUB) {
|
||||
final EaterStartsub eater = new EaterStartsub(result.getTrimmed());
|
||||
eater.analyze(context, memory);
|
||||
@ -83,7 +83,7 @@ public class CodeIteratorSub extends AbstractCodeIterator {
|
||||
StringLocated s = null;
|
||||
while ((s = source.peek()) != null) {
|
||||
if (s.getType() == TLineType.STARTSUB) {
|
||||
throw EaterException.located("Cannot nest sub");
|
||||
throw EaterException.located("Cannot nest sub", result);
|
||||
} else if (s.getType() == TLineType.ENDSUB) {
|
||||
source.next();
|
||||
readingInProgress = new CodeIteratorImpl(created.lines());
|
||||
@ -94,9 +94,9 @@ public class CodeIteratorSub extends AbstractCodeIterator {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (readingInProgress != null) {
|
||||
if (readingInProgress != null)
|
||||
return readingInProgress.peek();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -107,9 +107,9 @@ public class CodeIteratorSub extends AbstractCodeIterator {
|
||||
return;
|
||||
}
|
||||
readingInProgress.next();
|
||||
if (readingInProgress.peek() == null) {
|
||||
if (readingInProgress.peek() == null)
|
||||
readingInProgress = null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -64,9 +64,8 @@ public class CodeIteratorWhile extends AbstractCodeIterator {
|
||||
int level = 0;
|
||||
while (true) {
|
||||
final StringLocated result = source.peek();
|
||||
if (result == null) {
|
||||
if (result == null)
|
||||
return null;
|
||||
}
|
||||
|
||||
final ExecutionContextWhile currentWhile = memory.peekWhile();
|
||||
if (currentWhile != null && currentWhile.isSkipMe()) {
|
||||
@ -91,14 +90,14 @@ public class CodeIteratorWhile extends AbstractCodeIterator {
|
||||
} else if (result.getType() == TLineType.ENDWHILE) {
|
||||
logs.add(result);
|
||||
if (currentWhile == null)
|
||||
throw EaterException.located("No while related to this endwhile");
|
||||
throw EaterException.located("No while related to this endwhile", result);
|
||||
|
||||
final TValue value = currentWhile.conditionValue(result, context, memory);
|
||||
if (value.toBoolean()) {
|
||||
source.jumpToCodePosition(currentWhile.getStartWhile());
|
||||
} else {
|
||||
if (value.toBoolean())
|
||||
source.jumpToCodePosition(currentWhile.getStartWhile(), result);
|
||||
else
|
||||
memory.pollWhile();
|
||||
}
|
||||
|
||||
next();
|
||||
continue;
|
||||
}
|
||||
|
@ -65,9 +65,9 @@ public class CallUserFunction extends SimpleReturnFunction {
|
||||
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 EaterException.unlocated("Cannot find void function " + fname);
|
||||
}
|
||||
if (func == null)
|
||||
throw EaterException.unlocated("Cannot find void function " + fname, location);
|
||||
|
||||
return func.executeReturnFunction(context, memory, location, args, named);
|
||||
}
|
||||
|
||||
|
@ -71,7 +71,7 @@ public class Darken extends SimpleReturnFunction {
|
||||
color = color.darken(ratio);
|
||||
return TValue.fromString(color.asString());
|
||||
} catch (NoSuchColorException e) {
|
||||
throw EaterException.located("No such color");
|
||||
throw EaterException.located("No such color", location);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -71,10 +71,11 @@ public class DateFunction extends SimpleReturnFunction {
|
||||
now = 1000L * values.get(1).toInt();
|
||||
else
|
||||
now = System.currentTimeMillis();
|
||||
|
||||
try {
|
||||
return TValue.fromString(new SimpleDateFormat(format).format(now));
|
||||
} catch (Exception e) {
|
||||
throw EaterException.unlocated("Bad date pattern");
|
||||
throw EaterException.unlocated("Bad date pattern", location);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -99,7 +99,8 @@ public class GetAllStdlib extends SimpleReturnFunction {
|
||||
}
|
||||
|
||||
default:
|
||||
throw EaterException.located("Error on get_all_stdlib: Too many arguments");
|
||||
assert false; // Should not append because of canCover()
|
||||
throw EaterException.located("Error on get_all_stdlib: Too many arguments", location);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -65,7 +65,8 @@ public class GetJsonKey extends SimpleReturnFunction {
|
||||
Map<String, TValue> named) throws EaterException, EaterExceptionLocated {
|
||||
final TValue data = values.get(0);
|
||||
if (data.isJson() == false)
|
||||
throw EaterException.unlocated("Not JSON data");
|
||||
throw EaterException.unlocated("Not JSON data", location);
|
||||
|
||||
final JsonValue json = data.toJson();
|
||||
if (json.isObject()) {
|
||||
final JsonObject object = (JsonObject) json;
|
||||
@ -87,7 +88,7 @@ public class GetJsonKey extends SimpleReturnFunction {
|
||||
return TValue.fromJson(result);
|
||||
}
|
||||
|
||||
throw EaterException.unlocated("Bad JSON type");
|
||||
throw EaterException.unlocated("Bad JSON type", location);
|
||||
|
||||
}
|
||||
|
||||
|
@ -71,7 +71,7 @@ public class InvokeProcedure implements TFunction {
|
||||
final TFunctionSignature signature = new TFunctionSignature(fname, sublist.size());
|
||||
final TFunction func = context.getFunctionSmart(signature);
|
||||
if (func == null)
|
||||
throw EaterException.located("Cannot find void function " + fname);
|
||||
throw EaterException.located("Cannot find void function " + fname, location);
|
||||
|
||||
func.executeProcedureInternal(context, memory, location, sublist, named);
|
||||
}
|
||||
|
@ -69,7 +69,7 @@ public class IsDark extends SimpleReturnFunction {
|
||||
final HColor color = HColorSet.instance().getColorLEGACY(colorString);
|
||||
return TValue.fromBoolean(color.isDark());
|
||||
} catch (NoSuchColorException e) {
|
||||
throw EaterException.located("No such color");
|
||||
throw EaterException.located("No such color", location);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -69,7 +69,7 @@ public class IsLight extends SimpleReturnFunction {
|
||||
final HColor color = HColorSet.instance().getColorLEGACY(colorString);
|
||||
return TValue.fromBoolean(!color.isDark());
|
||||
} catch (NoSuchColorException e) {
|
||||
throw EaterException.located("No such color");
|
||||
throw EaterException.located("No such color", location);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -71,7 +71,7 @@ public class Lighten extends SimpleReturnFunction {
|
||||
color = color.lighten(ratio);
|
||||
return TValue.fromString(color.asString());
|
||||
} catch (NoSuchColorException e) {
|
||||
throw EaterException.located("No such color");
|
||||
throw EaterException.located("No such color", location);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -120,10 +120,11 @@ public class LoadJson extends SimpleReturnFunction {
|
||||
return TValue.fromJson(jsonValue);
|
||||
} catch (ParseException pe) {
|
||||
Logme.error(pe);
|
||||
throw EaterException.unlocated("JSON parse issue in source " + path + " on location " + pe.getLocation());
|
||||
throw EaterException.unlocated("JSON parse issue in source " + path + " on location " + pe.getLocation(),
|
||||
location);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
Logme.error(e);
|
||||
throw EaterException.unlocated("JSON encoding issue in source " + path + ": " + e.getMessage());
|
||||
throw EaterException.unlocated("JSON encoding issue in source " + path + ": " + e.getMessage(), location);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -77,7 +77,8 @@ public class RandomFunction extends SimpleReturnFunction {
|
||||
return TValue.fromInt(random.nextInt(max - min) + min);
|
||||
|
||||
default:
|
||||
throw EaterException.located("Error on Random: Too many argument");
|
||||
assert false; // Should not append because of canCover()
|
||||
throw EaterException.located("Error on Random: Too many argument", location);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -69,7 +69,7 @@ public class ReverseColor extends SimpleReturnFunction {
|
||||
color = color.reverse();
|
||||
return TValue.fromString(color.asString());
|
||||
} catch (NoSuchColorException e) {
|
||||
throw EaterException.located("No such color");
|
||||
throw EaterException.located("No such color", location);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -69,7 +69,7 @@ public class ReverseHsluvColor extends SimpleReturnFunction {
|
||||
color = color.reverseHsluv();
|
||||
return TValue.fromString(color.asString());
|
||||
} catch (NoSuchColorException e) {
|
||||
throw EaterException.located("No such color");
|
||||
throw EaterException.located("No such color", location);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -66,7 +66,7 @@ public class SetVariableValue extends SimpleReturnFunction {
|
||||
// }
|
||||
final String name = values.get(0).toString();
|
||||
final TValue value = values.get(1);
|
||||
memory.putVariable(name, value, TVariableScope.GLOBAL);
|
||||
memory.putVariable(name, value, TVariableScope.GLOBAL, location);
|
||||
return TValue.fromString("");
|
||||
}
|
||||
|
||||
|
@ -46,7 +46,7 @@ public class Version {
|
||||
|
||||
// Warning, "version" should be the same in gradle.properties and Version.java
|
||||
// Any idea anyone how to magically synchronize those :-) ?
|
||||
private static final String version = "1.2024.4beta2";
|
||||
private static final String version = "1.2024.4beta3";
|
||||
|
||||
public static String versionString() {
|
||||
return version;
|
||||
|
Loading…
Reference in New Issue
Block a user