1
0
mirror of https://github.com/octoleo/plantuml.git synced 2024-06-01 16:10:48 +00:00
plantuml/src/net/sourceforge/plantuml/tim/TContext.java

802 lines
29 KiB
Java
Raw Normal View History

2019-03-29 22:14:07 +00:00
/* ========================================================================
* PlantUML : a free UML diagram generator
* ========================================================================
*
2023-02-22 18:43:48 +00:00
* (C) Copyright 2009-2024, Arnaud Roques
2019-03-29 22:14:07 +00:00
*
2023-02-22 18:43:48 +00:00
* Project Info: https://plantuml.com
2019-03-29 22:14:07 +00:00
*
* If you like this project or if you find it useful, you can support us at:
*
2023-02-22 18:43:48 +00:00
* https://plantuml.com/patreon (only 1$ per month!)
* https://plantuml.com/paypal
2019-03-29 22:14:07 +00:00
*
* 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 static java.util.Objects.requireNonNull;
2019-03-29 22:14:07 +00:00
import java.io.IOException;
import java.io.Reader;
import java.nio.charset.Charset;
2019-03-29 22:14:07 +00:00
import java.util.ArrayList;
2020-03-18 10:50:02 +00:00
import java.util.Collections;
2019-03-29 22:14:07 +00:00
import java.util.HashMap;
2019-05-24 19:59:31 +00:00
import java.util.HashSet;
2019-03-29 22:14:07 +00:00
import java.util.List;
import java.util.Map;
2019-05-24 19:59:31 +00:00
import java.util.Set;
2019-03-29 22:14:07 +00:00
2019-06-26 19:24:49 +00:00
import net.sourceforge.plantuml.DefinitionsContainer;
2019-03-29 22:14:07 +00:00
import net.sourceforge.plantuml.FileSystem;
import net.sourceforge.plantuml.command.CommandExecutionResult;
2020-04-19 16:04:39 +00:00
import net.sourceforge.plantuml.json.Json;
2019-07-14 20:09:26 +00:00
import net.sourceforge.plantuml.json.JsonValue;
2022-08-17 17:34:24 +00:00
import net.sourceforge.plantuml.log.Logme;
2019-04-21 20:40:01 +00:00
import net.sourceforge.plantuml.preproc.Defines;
2019-03-29 22:14:07 +00:00
import net.sourceforge.plantuml.preproc.FileWithSuffix;
import net.sourceforge.plantuml.preproc.ImportedFiles;
import net.sourceforge.plantuml.preproc.ReadLine;
2019-06-26 19:24:49 +00:00
import net.sourceforge.plantuml.preproc.ReadLineList;
2019-03-29 22:14:07 +00:00
import net.sourceforge.plantuml.preproc.ReadLineReader;
2019-05-24 19:59:31 +00:00
import net.sourceforge.plantuml.preproc.StartDiagramExtractReader;
2020-01-12 22:13:17 +00:00
import net.sourceforge.plantuml.preproc.Sub;
2019-05-24 19:59:31 +00:00
import net.sourceforge.plantuml.preproc.UncommentReadLine;
import net.sourceforge.plantuml.preproc2.PreprocessorIncludeStrategy;
2020-01-12 22:13:17 +00:00
import net.sourceforge.plantuml.preproc2.PreprocessorUtils;
2020-05-30 15:20:23 +00:00
import net.sourceforge.plantuml.security.SFile;
import net.sourceforge.plantuml.security.SURL;
2023-02-02 17:59:43 +00:00
import net.sourceforge.plantuml.text.StringLocated;
import net.sourceforge.plantuml.text.TLineType;
import net.sourceforge.plantuml.theme.ThemeUtils;
2019-03-29 22:14:07 +00:00
import net.sourceforge.plantuml.tim.expression.Knowledge;
import net.sourceforge.plantuml.tim.expression.TValue;
2020-03-03 22:29:34 +00:00
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.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;
2020-04-19 16:04:39 +00:00
import net.sourceforge.plantuml.tim.iterator.CodeIteratorProcedure;
import net.sourceforge.plantuml.tim.iterator.CodeIteratorReturnFunction;
2020-03-03 22:29:34 +00:00
import net.sourceforge.plantuml.tim.iterator.CodeIteratorShortComment;
import net.sourceforge.plantuml.tim.iterator.CodeIteratorSub;
import net.sourceforge.plantuml.tim.iterator.CodeIteratorWhile;
2019-05-24 19:59:31 +00:00
import net.sourceforge.plantuml.tim.stdlib.AlwaysFalse;
import net.sourceforge.plantuml.tim.stdlib.AlwaysTrue;
import net.sourceforge.plantuml.tim.stdlib.CallUserFunction;
2021-11-09 17:47:19 +00:00
import net.sourceforge.plantuml.tim.stdlib.Chr;
2021-05-03 20:11:48 +00:00
import net.sourceforge.plantuml.tim.stdlib.Darken;
2019-04-21 20:40:01 +00:00
import net.sourceforge.plantuml.tim.stdlib.DateFunction;
2021-07-25 10:41:36 +00:00
import net.sourceforge.plantuml.tim.stdlib.Dec2hex;
2019-04-21 20:40:01 +00:00
import net.sourceforge.plantuml.tim.stdlib.Dirpath;
2021-06-27 16:50:40 +00:00
import net.sourceforge.plantuml.tim.stdlib.Eval;
2021-05-03 20:11:48 +00:00
import net.sourceforge.plantuml.tim.stdlib.Feature;
2019-04-21 20:40:01 +00:00
import net.sourceforge.plantuml.tim.stdlib.FileExists;
import net.sourceforge.plantuml.tim.stdlib.Filename;
2019-05-24 19:59:31 +00:00
import net.sourceforge.plantuml.tim.stdlib.FunctionExists;
import net.sourceforge.plantuml.tim.stdlib.GetAllStdlib;
import net.sourceforge.plantuml.tim.stdlib.GetAllTheme;
2022-01-29 18:00:48 +00:00
import net.sourceforge.plantuml.tim.stdlib.GetJsonKey;
import net.sourceforge.plantuml.tim.stdlib.GetJsonType;
2019-05-24 19:59:31 +00:00
import net.sourceforge.plantuml.tim.stdlib.GetVariableValue;
2019-11-03 17:40:03 +00:00
import net.sourceforge.plantuml.tim.stdlib.GetVersion;
2019-04-21 20:40:01 +00:00
import net.sourceforge.plantuml.tim.stdlib.Getenv;
2021-07-25 10:41:36 +00:00
import net.sourceforge.plantuml.tim.stdlib.Hex2dec;
import net.sourceforge.plantuml.tim.stdlib.HslColor;
2019-05-24 19:59:31 +00:00
import net.sourceforge.plantuml.tim.stdlib.IntVal;
2020-04-19 16:04:39 +00:00
import net.sourceforge.plantuml.tim.stdlib.InvokeProcedure;
2021-05-03 20:11:48 +00:00
import net.sourceforge.plantuml.tim.stdlib.IsDark;
import net.sourceforge.plantuml.tim.stdlib.IsLight;
2022-02-12 17:27:51 +00:00
import net.sourceforge.plantuml.tim.stdlib.JsonKeyExists;
2021-05-03 20:11:48 +00:00
import net.sourceforge.plantuml.tim.stdlib.Lighten;
import net.sourceforge.plantuml.tim.stdlib.LoadJson;
2022-11-25 17:50:02 +00:00
import net.sourceforge.plantuml.tim.stdlib.LogicalAnd;
2022-11-29 18:57:22 +00:00
import net.sourceforge.plantuml.tim.stdlib.LogicalNand;
import net.sourceforge.plantuml.tim.stdlib.LogicalNor;
2019-05-24 19:59:31 +00:00
import net.sourceforge.plantuml.tim.stdlib.LogicalNot;
2022-11-29 18:57:22 +00:00
import net.sourceforge.plantuml.tim.stdlib.LogicalNxor;
2022-11-25 17:50:02 +00:00
import net.sourceforge.plantuml.tim.stdlib.LogicalOr;
2022-11-29 18:57:22 +00:00
import net.sourceforge.plantuml.tim.stdlib.LogicalXor;
import net.sourceforge.plantuml.tim.stdlib.Lower;
2020-12-01 21:39:27 +00:00
import net.sourceforge.plantuml.tim.stdlib.Newline;
2022-07-21 13:40:34 +00:00
import net.sourceforge.plantuml.tim.stdlib.Now;
import net.sourceforge.plantuml.tim.stdlib.Ord;
2024-02-01 22:31:08 +00:00
import net.sourceforge.plantuml.tim.stdlib.RandomFunction;
2020-04-19 16:04:39 +00:00
import net.sourceforge.plantuml.tim.stdlib.RetrieveProcedure;
2021-05-23 15:35:13 +00:00
import net.sourceforge.plantuml.tim.stdlib.ReverseColor;
2021-06-27 16:50:40 +00:00
import net.sourceforge.plantuml.tim.stdlib.ReverseHsluvColor;
2019-05-24 19:59:31 +00:00
import net.sourceforge.plantuml.tim.stdlib.SetVariableValue;
2021-11-09 17:47:19 +00:00
import net.sourceforge.plantuml.tim.stdlib.Size;
import net.sourceforge.plantuml.tim.stdlib.SplitStr;
2020-04-19 16:04:39 +00:00
import net.sourceforge.plantuml.tim.stdlib.StringFunction;
2019-03-29 22:14:07 +00:00
import net.sourceforge.plantuml.tim.stdlib.Strlen;
2019-04-21 20:40:01 +00:00
import net.sourceforge.plantuml.tim.stdlib.Strpos;
import net.sourceforge.plantuml.tim.stdlib.Substr;
import net.sourceforge.plantuml.tim.stdlib.Upper;
2019-05-24 19:59:31 +00:00
import net.sourceforge.plantuml.tim.stdlib.VariableExists;
2022-12-17 11:01:10 +00:00
import net.sourceforge.plantuml.utils.LineLocation;
2019-03-29 22:14:07 +00:00
public class TContext {
2021-05-14 08:42:57 +00:00
private final List<StringLocated> resultList = new ArrayList<>();
private final List<StringLocated> debug = new ArrayList<>();
2020-03-03 22:29:34 +00:00
public final FunctionsSet functionsSet = new FunctionsSet();
2019-05-24 19:59:31 +00:00
private ImportedFiles importedFiles;
private final Charset charset;
2019-03-29 22:14:07 +00:00
2020-01-12 22:13:17 +00:00
private final Map<String, Sub> subs = new HashMap<String, Sub>();
2019-06-26 19:24:49 +00:00
private final DefinitionsContainer definitionsContainer;
2019-05-24 19:59:31 +00:00
2021-05-14 08:42:57 +00:00
// private final Set<FileWithSuffix> usedFiles = new HashSet<>();
private final Set<FileWithSuffix> filesUsedCurrent = new HashSet<>();
2019-03-29 22:14:07 +00:00
2020-03-18 10:50:02 +00:00
public Set<FileWithSuffix> getFilesUsedCurrent() {
return Collections.unmodifiableSet(filesUsedCurrent);
}
2019-04-21 20:40:01 +00:00
private void addStandardFunctions(Defines defines) {
2020-03-03 22:29:34 +00:00
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());
2020-04-19 16:04:39 +00:00
functionsSet.addFunction(new InvokeProcedure());
2020-03-03 22:29:34 +00:00
functionsSet.addFunction(new AlwaysFalse());
functionsSet.addFunction(new AlwaysTrue());
functionsSet.addFunction(new LogicalNot());
functionsSet.addFunction(new FunctionExists());
functionsSet.addFunction(new VariableExists());
functionsSet.addFunction(new CallUserFunction());
2020-04-19 16:04:39 +00:00
functionsSet.addFunction(new RetrieveProcedure());
2020-03-03 22:29:34 +00:00
functionsSet.addFunction(new SetVariableValue());
functionsSet.addFunction(new GetVariableValue());
functionsSet.addFunction(new IntVal());
functionsSet.addFunction(new GetVersion());
functionsSet.addFunction(new Upper());
functionsSet.addFunction(new Lower());
2020-04-19 16:04:39 +00:00
functionsSet.addFunction(new StringFunction());
2020-12-01 21:39:27 +00:00
functionsSet.addFunction(new Newline());
2021-05-03 20:11:48 +00:00
functionsSet.addFunction(new Feature());
functionsSet.addFunction(new Lighten());
functionsSet.addFunction(new Darken());
functionsSet.addFunction(new IsDark());
functionsSet.addFunction(new IsLight());
2021-05-23 15:35:13 +00:00
functionsSet.addFunction(new ReverseHsluvColor());
functionsSet.addFunction(new ReverseColor());
2021-06-27 16:50:40 +00:00
functionsSet.addFunction(new Eval());
2021-07-25 10:41:36 +00:00
functionsSet.addFunction(new Hex2dec());
functionsSet.addFunction(new Dec2hex());
functionsSet.addFunction(new HslColor());
functionsSet.addFunction(new LoadJson());
2022-08-26 16:00:28 +00:00
// functionsSet.addFunction(new LoadJsonLegacy());
2021-11-09 17:47:19 +00:00
functionsSet.addFunction(new Chr());
functionsSet.addFunction(new Size());
2022-01-29 18:00:48 +00:00
functionsSet.addFunction(new GetJsonKey());
functionsSet.addFunction(new GetJsonType());
functionsSet.addFunction(new SplitStr());
2022-02-12 17:27:51 +00:00
functionsSet.addFunction(new JsonKeyExists());
2022-07-21 13:40:34 +00:00
functionsSet.addFunction(new Now());
2022-11-25 17:50:02 +00:00
functionsSet.addFunction(new LogicalAnd());
functionsSet.addFunction(new LogicalOr());
2022-11-29 18:57:22 +00:00
functionsSet.addFunction(new LogicalXor());
functionsSet.addFunction(new LogicalNand());
functionsSet.addFunction(new LogicalNor());
functionsSet.addFunction(new LogicalNxor());
functionsSet.addFunction(new Ord());
functionsSet.addFunction(new RandomFunction());
functionsSet.addFunction(new GetAllTheme());
functionsSet.addFunction(new GetAllStdlib());
2021-05-03 20:11:48 +00:00
// %standard_exists_function
// %str_replace
2019-05-24 19:59:31 +00:00
// !exit
// !log
// %min
// %max
// Regexp
// %time
// %trim
}
public TContext(ImportedFiles importedFiles, Defines defines, Charset charset,
2019-06-26 19:24:49 +00:00
DefinitionsContainer definitionsContainer) {
this.definitionsContainer = definitionsContainer;
2019-03-29 22:14:07 +00:00
this.importedFiles = importedFiles;
this.charset = requireNonNull(charset);
2019-04-21 20:40:01 +00:00
this.addStandardFunctions(defines);
2019-03-29 22:14:07 +00:00
}
2020-04-19 16:04:39 +00:00
public Knowledge asKnowledge(final TMemory memory, final LineLocation location) {
2019-03-29 22:14:07 +00:00
return new Knowledge() {
2020-04-19 16:04:39 +00:00
public TValue getVariable(String name) throws EaterException, EaterExceptionLocated {
if (name.contains(".") || name.contains("[")) {
final TValue result = fromJson(memory, name, location);
return result;
2020-03-03 22:29:34 +00:00
}
2019-03-29 22:14:07 +00:00
return memory.getVariable(name);
}
public TFunction getFunction(TFunctionSignature name) {
2020-03-03 22:29:34 +00:00
return functionsSet.getFunctionSmart(name);
2019-03-29 22:14:07 +00:00
}
};
}
2020-04-19 16:04:39 +00:00
private TValue fromJson(TMemory memory, String name, LineLocation location)
throws EaterException, EaterExceptionLocated {
final String result = applyFunctionsAndVariables(memory, location, name);
try {
final JsonValue json = Json.parse(result);
return TValue.fromJson(json);
} catch (Exception e) {
return TValue.fromString(result);
}
}
2020-03-03 22:29:34 +00:00
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);
2020-04-19 16:04:39 +00:00
final CodeIterator it60 = new CodeIteratorReturnFunction(it50, this, memory, functionsSet, debug);
final CodeIterator it61 = new CodeIteratorProcedure(it60, this, memory, functionsSet, debug);
final CodeIterator it70 = new CodeIteratorIf(it61, this, memory, debug);
2020-03-03 22:29:34 +00:00
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);
final CodeIterator it = it110;
return it;
}
2020-04-19 16:04:39 +00:00
public TValue executeLines(TMemory memory, List<StringLocated> body, TFunctionType ftype, boolean modeSpecial)
2020-03-03 22:29:34 +00:00
throws EaterExceptionLocated {
final CodeIterator it = buildCodeIterator(memory, body);
StringLocated s = null;
try {
while ((s = it.peek()) != null) {
2020-04-19 16:04:39 +00:00
final TValue result = executeOneLineSafe(memory, s, ftype, modeSpecial);
2022-11-17 17:56:16 +00:00
if (result != null)
2020-04-19 16:04:39 +00:00
return result;
2022-11-17 17:56:16 +00:00
2020-03-03 22:29:34 +00:00
it.next();
2019-03-29 22:14:07 +00:00
}
2020-04-19 16:04:39 +00:00
return null;
2020-03-03 22:29:34 +00:00
} catch (EaterException e) {
throw e.withLocation(s);
2019-03-29 22:14:07 +00:00
}
2019-05-24 19:59:31 +00:00
2020-03-03 22:29:34 +00:00
}
2019-05-24 19:59:31 +00:00
2020-03-03 22:29:34 +00:00
private void executeLinesInternal(TMemory memory, List<StringLocated> body, TFunctionType ftype)
throws EaterExceptionLocated, EaterException {
final CodeIterator it = buildCodeIterator(memory, body);
2019-05-24 19:59:31 +00:00
2020-03-03 22:29:34 +00:00
StringLocated s = null;
while ((s = it.peek()) != null) {
2020-04-19 16:04:39 +00:00
executeOneLineSafe(memory, s, ftype, false);
2020-03-03 22:29:34 +00:00
it.next();
2019-05-24 19:59:31 +00:00
}
2020-03-03 22:29:34 +00:00
}
2019-03-29 22:14:07 +00:00
2020-04-19 16:04:39 +00:00
private TValue executeOneLineSafe(TMemory memory, StringLocated s, TFunctionType ftype, boolean modeSpecial)
2020-03-03 22:29:34 +00:00
throws EaterException, EaterExceptionLocated {
try {
this.debug.add(s);
2020-04-19 16:04:39 +00:00
return executeOneLineNotSafe(memory, s, ftype, modeSpecial);
2020-03-03 22:29:34 +00:00
} catch (Exception e) {
if (e instanceof EaterException)
throw (EaterException) e;
if (e instanceof EaterExceptionLocated)
throw (EaterExceptionLocated) e;
2022-08-17 17:34:24 +00:00
Logme.error(e);
2020-05-17 21:15:50 +00:00
throw EaterException.located("Fatal parsing error");
2019-05-24 19:59:31 +00:00
}
2020-03-03 22:29:34 +00:00
}
2019-03-29 22:14:07 +00:00
2020-04-19 16:04:39 +00:00
private TValue executeOneLineNotSafe(TMemory memory, StringLocated s, TFunctionType ftype, boolean modeSpecial)
2020-03-03 22:29:34 +00:00
throws EaterException, EaterExceptionLocated {
final TLineType type = s.getType();
2019-05-24 19:59:31 +00:00
2020-03-03 22:29:34 +00:00
if (type == TLineType.INCLUDESUB) {
this.executeIncludesub(memory, s);
2020-04-19 16:04:39 +00:00
return null;
} else if (type == TLineType.THEME) {
this.executeTheme(memory, s);
return null;
2020-03-03 22:29:34 +00:00
} else if (type == TLineType.INCLUDE) {
this.executeInclude(memory, s);
2020-04-19 16:04:39 +00:00
return null;
2020-03-03 22:29:34 +00:00
} else if (type == TLineType.INCLUDE_DEF) {
this.executeIncludeDef(memory, s);
2020-04-19 16:04:39 +00:00
return null;
2020-03-03 22:29:34 +00:00
} else if (type == TLineType.IMPORT) {
this.executeImport(memory, s);
2020-04-19 16:04:39 +00:00
return null;
2020-01-12 22:13:17 +00:00
}
2019-05-24 19:59:31 +00:00
if (type == TLineType.DUMP_MEMORY) {
2020-03-03 22:29:34 +00:00
this.executeDumpMemory(memory, s.getTrimmed());
2020-04-19 16:04:39 +00:00
return null;
2019-05-24 19:59:31 +00:00
} else if (type == TLineType.ASSERT) {
2020-03-03 22:29:34 +00:00
this.executeAssert(memory, s.getTrimmed());
2020-04-19 16:04:39 +00:00
return null;
2019-05-24 19:59:31 +00:00
} else if (type == TLineType.UNDEF) {
this.executeUndef(memory, s);
2020-04-19 16:04:39 +00:00
return null;
} else if (ftype != TFunctionType.RETURN_FUNCTION && type == TLineType.PLAIN) {
2019-05-24 19:59:31 +00:00
this.addPlain(memory, s);
2020-04-19 16:04:39 +00:00
return null;
} else if (ftype == TFunctionType.RETURN_FUNCTION && type == TLineType.RETURN) {
if (modeSpecial) {
final EaterReturn eaterReturn = new EaterReturn(s);
eaterReturn.analyze(this, memory);
final TValue result = eaterReturn.getValue2();
return result;
}
2019-05-24 19:59:31 +00:00
// Actually, ignore because we are in a if
2020-04-19 16:04:39 +00:00
return null;
} else if (ftype == TFunctionType.RETURN_FUNCTION && type == TLineType.PLAIN) {
this.simulatePlain(memory, s);
return null;
2019-05-24 19:59:31 +00:00
} else if (type == TLineType.AFFECTATION_DEFINE) {
2020-03-03 22:29:34 +00:00
this.executeAffectationDefine(memory, s);
2020-04-19 16:04:39 +00:00
return null;
2020-03-03 22:29:34 +00:00
} else if (ftype == null && type == TLineType.END_FUNCTION) {
2019-05-24 19:59:31 +00:00
CommandExecutionResult.error("error endfunc");
2020-04-19 16:04:39 +00:00
return null;
2019-05-24 19:59:31 +00:00
} else if (type == TLineType.LOG) {
this.executeLog(memory, s);
2020-04-19 16:04:39 +00:00
return null;
} else if (s.getString().matches("^\\s+$")) {
return null;
2019-05-24 19:59:31 +00:00
} else {
2020-05-17 21:15:50 +00:00
throw EaterException.located("Compile Error " + ftype + " " + type);
2019-05-24 19:59:31 +00:00
}
2019-03-29 22:14:07 +00:00
}
2020-03-03 22:29:34 +00:00
private void addPlain(TMemory memory, StringLocated s) throws EaterException, EaterExceptionLocated {
2020-12-01 21:39:27 +00:00
final StringLocated tmp[] = applyFunctionsAndVariablesInternal(memory, s);
2019-03-29 22:14:07 +00:00
if (tmp != null) {
if (pendingAdd != null) {
2020-12-01 21:39:27 +00:00
tmp[0] = new StringLocated(pendingAdd + tmp[0].getString(), tmp[0].getLocation());
2019-03-29 22:14:07 +00:00
pendingAdd = null;
}
2022-08-17 17:34:24 +00:00
for (StringLocated line : tmp)
2020-12-01 21:39:27 +00:00
resultList.add(line);
2022-08-17 17:34:24 +00:00
2019-03-29 22:14:07 +00:00
}
}
2020-04-19 16:04:39 +00:00
private void simulatePlain(TMemory memory, StringLocated s) throws EaterException, EaterExceptionLocated {
2020-12-01 21:39:27 +00:00
final StringLocated ignored[] = applyFunctionsAndVariablesInternal(memory, s);
2020-04-19 16:04:39 +00:00
}
2020-03-03 22:29:34 +00:00
private void executeAffectationDefine(TMemory memory, StringLocated s)
throws EaterException, EaterExceptionLocated {
new EaterAffectationDefine(s).analyze(this, memory);
2019-03-29 22:14:07 +00:00
}
2020-03-03 22:29:34 +00:00
private void executeDumpMemory(TMemory memory, StringLocated s) throws EaterException {
2019-05-24 19:59:31 +00:00
final EaterDumpMemory condition = new EaterDumpMemory(s);
2020-03-03 22:29:34 +00:00
condition.analyze(this, memory);
2019-05-24 19:59:31 +00:00
}
2020-03-03 22:29:34 +00:00
private void executeAssert(TMemory memory, StringLocated s) throws EaterException, EaterExceptionLocated {
2019-04-21 20:40:01 +00:00
final EaterAssert condition = new EaterAssert(s);
2020-03-03 22:29:34 +00:00
condition.analyze(this, memory);
2019-03-29 22:14:07 +00:00
}
2019-05-24 19:59:31 +00:00
private void executeUndef(TMemory memory, StringLocated s) throws EaterException {
final EaterUndef undef = new EaterUndef(s);
2020-03-03 22:29:34 +00:00
undef.analyze(this, memory);
2019-03-29 22:14:07 +00:00
}
2020-12-01 21:39:27 +00:00
private StringLocated[] applyFunctionsAndVariablesInternal(TMemory memory, StringLocated located)
2020-03-03 22:29:34 +00:00
throws EaterException, EaterExceptionLocated {
2022-08-17 17:34:24 +00:00
if (memory.isEmpty() && functionsSet.size() == 0)
2020-12-01 21:39:27 +00:00
return new StringLocated[] { located };
2022-08-17 17:34:24 +00:00
2020-03-03 22:29:34 +00:00
final String result = applyFunctionsAndVariables(memory, located.getLocation(), located.getString());
2022-08-17 17:34:24 +00:00
if (result == null)
2019-03-29 22:14:07 +00:00
return null;
2022-08-17 17:34:24 +00:00
2020-12-01 21:39:27 +00:00
final String[] splited = result.split("\n");
final StringLocated[] tab = new StringLocated[splited.length];
2022-08-17 17:34:24 +00:00
for (int i = 0; i < splited.length; i++)
2020-12-01 21:39:27 +00:00
tab[i] = new StringLocated(splited[i], located.getLocation());
return tab;
2019-03-29 22:14:07 +00:00
}
private String pendingAdd = null;
2020-12-19 21:21:54 +00:00
public String applyFunctionsAndVariables(TMemory memory, LineLocation location, final String str)
2020-03-03 22:29:34 +00:00
throws EaterException, EaterExceptionLocated {
2019-03-29 22:14:07 +00:00
// 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
2022-11-17 17:56:16 +00:00
if (memory.isEmpty() && functionsSet.size() == 0)
2020-03-03 22:29:34 +00:00
return str;
2022-11-17 17:56:16 +00:00
2019-03-29 22:14:07 +00:00
final StringBuilder result = new StringBuilder();
2020-03-03 22:29:34 +00:00
for (int i = 0; i < str.length(); i++) {
final char c = str.charAt(i);
final String presentFunction = getFunctionNameAt(str, i);
2019-03-29 22:14:07 +00:00
if (presentFunction != null) {
2020-03-03 22:29:34 +00:00
final String sub = str.substring(i);
final EaterFunctionCall call = new EaterFunctionCall(new StringLocated(sub, location),
isLegacyDefine(presentFunction), isUnquoted(presentFunction));
call.analyze(this, memory);
2020-05-17 21:15:50 +00:00
final TFunctionSignature signature = new TFunctionSignature(presentFunction, call.getValues().size(),
call.getNamedArguments().keySet());
final TFunction function = functionsSet.getFunctionSmart(signature);
2022-08-17 17:34:24 +00:00
if (function == null)
2020-05-17 21:15:50 +00:00
throw EaterException.located("Function not found " + presentFunction);
2022-08-17 17:34:24 +00:00
2020-04-19 16:04:39 +00:00
if (function.getFunctionType() == TFunctionType.PROCEDURE) {
2019-06-26 19:24:49 +00:00
this.pendingAdd = result.toString();
2020-12-19 21:21:54 +00:00
executeVoid3(location, memory, sub, function, call);
i += call.getCurrentPosition();
final String remaining = str.substring(i);
2022-08-17 17:34:24 +00:00
if (remaining.length() > 0)
2020-12-19 21:21:54 +00:00
appendToLastResult(remaining);
2022-08-17 17:34:24 +00:00
2019-03-29 22:14:07 +00:00
return null;
}
if (function.getFunctionType() == TFunctionType.LEGACY_DEFINELONG) {
2020-03-03 22:29:34 +00:00
this.pendingAdd = str.substring(0, i);
2020-12-19 21:21:54 +00:00
executeVoid3(location, memory, sub, function, call);
2019-03-29 22:14:07 +00:00
return null;
}
2020-04-19 16:04:39 +00:00
assert function.getFunctionType() == TFunctionType.RETURN_FUNCTION
2019-03-29 22:14:07 +00:00
|| function.getFunctionType() == TFunctionType.LEGACY_DEFINE;
2020-05-17 21:15:50 +00:00
final TValue functionReturn = function.executeReturnFunction(this, memory, location, call.getValues(),
call.getNamedArguments());
2019-03-29 22:14:07 +00:00
result.append(functionReturn.toString());
i += call.getCurrentPosition() - 1;
2020-03-03 22:29:34 +00:00
} 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);
2019-03-29 22:14:07 +00:00
}
}
return result.toString();
}
2020-12-19 21:21:54 +00:00
private void appendToLastResult(String remaining) {
final StringLocated last = this.resultList.get(this.resultList.size() - 1);
this.resultList.set(this.resultList.size() - 1, last.append(remaining));
}
private void executeVoid3(LineLocation location, TMemory memory, String s, TFunction function,
EaterFunctionCall call) throws EaterException, EaterExceptionLocated {
function.executeProcedureInternal(this, memory, call.getValues(), call.getNamedArguments());
// function.executeProcedure(this, memory, location, s, call.getValues(),
// call.getNamedArguments());
2019-05-24 19:59:31 +00:00
}
2020-03-03 22:29:34 +00:00
private void executeImport(TMemory memory, StringLocated s) throws EaterException, EaterExceptionLocated {
final EaterImport _import = new EaterImport(s.getTrimmed());
_import.analyze(this, memory);
2019-03-29 22:14:07 +00:00
try {
2020-05-30 15:20:23 +00:00
final SFile file = FileSystem.getInstance()
2020-03-03 22:29:34 +00:00
.getFile(applyFunctionsAndVariables(memory, s.getLocation(), _import.getLocation()));
2019-03-29 22:14:07 +00:00
if (file.exists() && file.isDirectory() == false) {
importedFiles.add(file);
2019-05-24 19:59:31 +00:00
return;
2019-03-29 22:14:07 +00:00
}
} catch (IOException e) {
2022-08-17 17:34:24 +00:00
Logme.error(e);
2020-05-17 21:15:50 +00:00
throw EaterException.located("Cannot import " + e.getMessage());
2019-03-29 22:14:07 +00:00
}
2020-05-17 21:15:50 +00:00
throw EaterException.located("Cannot import");
2019-03-29 22:14:07 +00:00
}
2020-03-03 22:29:34 +00:00
private void executeLog(TMemory memory, StringLocated s) throws EaterException, EaterExceptionLocated {
final EaterLog log = new EaterLog(s.getTrimmed());
log.analyze(this, memory);
2019-05-24 19:59:31 +00:00
}
2021-05-14 08:42:57 +00:00
public FileWithSuffix getFileWithSuffix(String from, String realName) throws IOException {
final String s = ThemeUtils.getFullPath(from, realName);
final FileWithSuffix file = importedFiles.getFile(s, null);
return file;
}
2020-03-03 22:29:34 +00:00
private void executeIncludesub(TMemory memory, StringLocated s) throws EaterException, EaterExceptionLocated {
2019-09-14 18:12:04 +00:00
ImportedFiles saveImportedFiles = null;
try {
2020-03-03 22:29:34 +00:00
final EaterIncludesub include = new EaterIncludesub(s.getTrimmed());
include.analyze(this, memory);
2019-09-14 18:12:04 +00:00
final String location = include.getLocation();
final int idx = location.indexOf('!');
2020-01-12 22:13:17 +00:00
Sub sub = null;
if (idx != -1) {
2019-09-14 18:12:04 +00:00
final String filename = location.substring(0, idx);
final String blocname = location.substring(idx + 1);
try {
2020-01-12 22:13:17 +00:00
final FileWithSuffix f2 = importedFiles.getFile(filename, null);
2019-09-14 18:12:04 +00:00
if (f2.fileOk()) {
saveImportedFiles = this.importedFiles;
this.importedFiles = this.importedFiles.withCurrentDir(f2.getParentFile());
final Reader reader = f2.getReader(charset);
2022-08-17 17:34:24 +00:00
if (reader == null)
2020-05-30 15:20:23 +00:00
throw EaterException.located("cannot include " + location);
2022-08-17 17:34:24 +00:00
try {
ReadLine readerline = ReadLineReader.create(reader, location, s.getLocation());
readerline = new UncommentReadLine(readerline);
sub = Sub.fromFile(readerline, blocname, this, memory);
} finally {
reader.close();
}
2019-09-14 18:12:04 +00:00
}
} catch (IOException e) {
2022-08-17 17:34:24 +00:00
Logme.error(e);
2020-05-30 15:20:23 +00:00
throw EaterException.located("cannot include " + location);
2019-05-24 19:59:31 +00:00
}
2020-01-12 22:13:17 +00:00
}
2022-08-17 17:34:24 +00:00
if (sub == null)
2019-09-14 18:12:04 +00:00
sub = subs.get(location);
2022-08-17 17:34:24 +00:00
if (sub == null)
2020-05-17 21:15:50 +00:00
throw EaterException.located("cannot include " + location);
2022-08-17 17:34:24 +00:00
2020-03-03 22:29:34 +00:00
executeLinesInternal(memory, sub.lines(), null);
2019-09-14 18:12:04 +00:00
} finally {
2022-08-17 17:34:24 +00:00
if (saveImportedFiles != null)
2019-09-14 18:12:04 +00:00
this.importedFiles = saveImportedFiles;
2022-08-17 17:34:24 +00:00
2019-05-24 19:59:31 +00:00
}
}
2020-03-03 22:29:34 +00:00
private void executeIncludeDef(TMemory memory, StringLocated s) throws EaterException, EaterExceptionLocated {
final EaterIncludeDef include = new EaterIncludeDef(s.getTrimmed());
include.analyze(this, memory);
2019-06-26 19:24:49 +00:00
final String definitionName = include.getLocation();
2020-01-12 22:13:17 +00:00
final List<String> definition = definitionsContainer.getDefinition(definitionName);
final ReadLine reader2 = new ReadLineList(definition, s.getLocation());
2019-06-26 19:24:49 +00:00
try {
2021-05-14 08:42:57 +00:00
final List<StringLocated> body = new ArrayList<>();
2019-06-26 19:24:49 +00:00
do {
final StringLocated sl = reader2.readLine();
if (sl == null) {
2020-03-03 22:29:34 +00:00
executeLinesInternal(memory, body, null);
2019-06-26 19:24:49 +00:00
return;
}
2020-03-03 22:29:34 +00:00
body.add(sl);
2019-06-26 19:24:49 +00:00
} while (true);
} catch (IOException e) {
2022-08-17 17:34:24 +00:00
Logme.error(e);
2020-05-17 21:15:50 +00:00
throw EaterException.located("" + e);
} finally {
try {
reader2.close();
} catch (IOException e) {
2022-08-17 17:34:24 +00:00
Logme.error(e);
}
2019-06-26 19:24:49 +00:00
}
}
private void executeTheme(TMemory memory, StringLocated s) throws EaterException, EaterExceptionLocated {
2021-11-10 18:18:02 +00:00
final EaterTheme eater = new EaterTheme(s.getTrimmed(), importedFiles);
2021-05-14 08:42:57 +00:00
eater.analyze(this, memory);
final ReadLine reader = eater.getTheme();
2022-08-17 17:34:24 +00:00
if (reader == null)
2021-05-14 08:42:57 +00:00
throw EaterException.located("No such theme " + eater.getName());
2022-08-17 17:34:24 +00:00
try {
2021-05-14 08:42:57 +00:00
final List<StringLocated> body = new ArrayList<>();
do {
final StringLocated sl = reader.readLine();
if (sl == null) {
executeLines(memory, body, null, false);
return;
}
body.add(sl);
} while (true);
} catch (IOException e) {
2022-08-17 17:34:24 +00:00
Logme.error(e);
throw EaterException.located("Error reading theme " + e);
} finally {
try {
reader.close();
} catch (IOException e) {
2022-08-17 17:34:24 +00:00
Logme.error(e);
}
}
}
2020-03-03 22:29:34 +00:00
private void executeInclude(TMemory memory, StringLocated s) throws EaterException, EaterExceptionLocated {
final EaterInclude include = new EaterInclude(s.getTrimmed());
include.analyze(this, memory);
2019-03-29 22:14:07 +00:00
String location = include.getLocation();
2019-05-24 19:59:31 +00:00
final PreprocessorIncludeStrategy strategy = include.getPreprocessorIncludeStrategy();
2019-03-29 22:14:07 +00:00
final int idx = location.lastIndexOf('!');
String suf = null;
if (idx != -1) {
suf = location.substring(idx + 1);
location = location.substring(0, idx);
}
ReadLine reader = null;
2019-05-24 19:59:31 +00:00
ImportedFiles saveImportedFiles = null;
2019-03-29 22:14:07 +00:00
try {
if (location.startsWith("http://") || location.startsWith("https://")) {
2020-05-30 15:20:23 +00:00
final SURL url = SURL.create(location);
2022-08-17 17:34:24 +00:00
if (url == null)
2020-05-30 15:20:23 +00:00
throw EaterException.located("Cannot open URL");
2022-08-17 17:34:24 +00:00
2021-05-14 08:42:57 +00:00
reader = PreprocessorUtils.getReaderIncludeUrl(url, s, suf, charset);
} else if (location.startsWith("<") && location.endsWith(">")) {
reader = PreprocessorUtils.getReaderStdlibInclude(s, location.substring(1, location.length() - 1));
2023-02-28 21:22:51 +00:00
// ::comment when __CORE__
2023-02-22 18:43:48 +00:00
} else if (location.startsWith("[") && location.endsWith("]")) {
reader = PreprocessorUtils.getReaderNonstandardInclude(s, location.substring(1, location.length() - 1));
// ::done
2020-01-12 22:13:17 +00:00
} else {
final FileWithSuffix f2 = importedFiles.getFile(location, suf);
2019-03-29 22:14:07 +00:00
if (f2.fileOk()) {
2022-08-17 17:34:24 +00:00
if (strategy == PreprocessorIncludeStrategy.DEFAULT && filesUsedCurrent.contains(f2))
2019-05-24 19:59:31 +00:00
return;
2022-08-17 17:34:24 +00:00
if (strategy == PreprocessorIncludeStrategy.ONCE && filesUsedCurrent.contains(f2))
2020-05-17 21:15:50 +00:00
throw EaterException.located("This file has already been included");
2019-05-24 19:59:31 +00:00
if (StartDiagramExtractReader.containsStartDiagram(f2, s, charset)) {
reader = StartDiagramExtractReader.build(f2, s, charset);
2019-05-24 19:59:31 +00:00
} else {
final Reader tmp = f2.getReader(charset);
2022-08-17 17:34:24 +00:00
if (tmp == null)
2020-05-17 21:15:50 +00:00
throw EaterException.located("Cannot include file");
2022-08-17 17:34:24 +00:00
reader = ReadLineReader.create(tmp, location, s.getLocation());
2019-05-24 19:59:31 +00:00
}
saveImportedFiles = this.importedFiles;
this.importedFiles = this.importedFiles.withCurrentDir(f2.getParentFile());
assert reader != null;
2019-05-24 19:59:31 +00:00
filesUsedCurrent.add(f2);
2019-03-29 22:14:07 +00:00
}
}
if (reader != null) {
2019-05-24 19:59:31 +00:00
try {
2021-05-14 08:42:57 +00:00
final List<StringLocated> body = new ArrayList<>();
2019-05-24 19:59:31 +00:00
do {
final StringLocated sl = reader.readLine();
2019-05-24 19:59:31 +00:00
if (sl == null) {
2020-04-19 16:04:39 +00:00
executeLines(memory, body, null, false);
2019-05-24 19:59:31 +00:00
return;
}
2020-03-03 22:29:34 +00:00
body.add(sl);
2019-05-24 19:59:31 +00:00
} while (true);
} finally {
2022-08-17 17:34:24 +00:00
if (saveImportedFiles != null)
2019-05-24 19:59:31 +00:00
this.importedFiles = saveImportedFiles;
2022-08-17 17:34:24 +00:00
2019-05-24 19:59:31 +00:00
}
2019-03-29 22:14:07 +00:00
}
} catch (IOException e) {
2022-08-17 17:34:24 +00:00
Logme.error(e);
2020-05-17 21:15:50 +00:00
throw EaterException.located("cannot include " + e);
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
2022-08-17 17:34:24 +00:00
Logme.error(e);
}
}
2019-03-29 22:14:07 +00:00
}
2020-05-17 21:15:50 +00:00
throw EaterException.located("cannot include " + location);
2019-03-29 22:14:07 +00:00
}
public boolean isLegacyDefine(String functionName) {
2022-08-17 17:34:24 +00:00
for (Map.Entry<TFunctionSignature, TFunction> ent : functionsSet.functions().entrySet())
if (ent.getKey().getFunctionName().equals(functionName) && ent.getValue().getFunctionType().isLegacy())
2019-03-29 22:14:07 +00:00
return true;
2022-08-17 17:34:24 +00:00
2019-03-29 22:14:07 +00:00
return false;
}
public boolean isUnquoted(String functionName) {
2022-08-17 17:34:24 +00:00
for (Map.Entry<TFunctionSignature, TFunction> ent : functionsSet.functions().entrySet())
if (ent.getKey().getFunctionName().equals(functionName) && ent.getValue().isUnquoted())
2019-03-29 22:14:07 +00:00
return true;
2022-08-17 17:34:24 +00:00
2019-03-29 22:14:07 +00:00
return false;
}
public boolean doesFunctionExist(String functionName) {
2022-08-17 17:34:24 +00:00
for (Map.Entry<TFunctionSignature, TFunction> ent : functionsSet.functions().entrySet())
if (ent.getKey().getFunctionName().equals(functionName))
2019-03-29 22:14:07 +00:00
return true;
2022-08-17 17:34:24 +00:00
2019-03-29 22:14:07 +00:00
return false;
}
private String getFunctionNameAt(String s, int pos) {
2020-03-03 22:29:34 +00:00
if (pos > 0 && TLineType.isLetterOrUnderscoreOrDigit(s.charAt(pos - 1))
2022-08-17 17:34:24 +00:00
&& VariableManager.justAfterBackslashN(s, pos) == false)
2019-07-14 20:09:26 +00:00
return null;
2022-08-17 17:34:24 +00:00
2020-03-03 22:29:34 +00:00
final String fname = functionsSet.getLonguestMatchStartingIn(s.substring(pos));
2022-08-17 17:34:24 +00:00
if (fname.length() == 0)
2019-03-29 22:14:07 +00:00
return null;
2022-08-17 17:34:24 +00:00
2019-03-29 22:14:07 +00:00
return fname.substring(0, fname.length() - 1);
}
2019-08-26 17:07:21 +00:00
public List<StringLocated> getResultList() {
return resultList;
2019-03-29 22:14:07 +00:00
}
2019-05-24 19:59:31 +00:00
public List<StringLocated> getDebug() {
return debug;
2019-03-29 22:14:07 +00:00
}
2019-08-26 17:07:21 +00:00
public String extractFromResultList(int n1) {
final StringBuilder sb = new StringBuilder();
while (resultList.size() > n1) {
sb.append(resultList.get(n1).getString());
resultList.remove(n1);
2022-08-17 17:34:24 +00:00
if (resultList.size() > n1)
2019-08-26 17:07:21 +00:00
sb.append("\\n");
2022-08-17 17:34:24 +00:00
2019-08-26 17:07:21 +00:00
}
return sb.toString();
}
2019-09-14 18:12:04 +00:00
public void appendEndOfLine(String endOfLine) {
if (endOfLine.length() > 0) {
final int idx = resultList.size() - 1;
StringLocated last = resultList.get(idx);
last = last.append(endOfLine);
resultList.set(idx, last);
}
}
2020-03-03 22:29:34 +00:00
public TFunction getFunctionSmart(TFunctionSignature signature) {
return functionsSet.getFunctionSmart(signature);
}
2019-03-29 22:14:07 +00:00
}