diff --git a/README.jrf b/README.jrf
index 972bcd4e..7ec47b8d 100644
--- a/README.jrf
+++ b/README.jrf
@@ -1,5 +1,5 @@
# This is a Jamal reference file containing serialized base64 encoded macros
-# Created: 2024-12-10 17:58:05 +0100
+# Created: 2024-12-11 13:19:58 +0100
# id|openStr|closeStr|verbatim|tailParameter|pure|content|parameters
# TOC
VE9D|eyU=|JX0=|0|0|0|Ci4gPDxJbnN0YWxsYXRpb24+PgouIDw8R1M+PgouIDw8Q29uZmlndXJhdGlvbj4+Ci4gPDxGZWF0dXJlcz4+Ci4gPDxDb250cmlidXRpbmc+PgouIDw8RG9jdW1lbnRhdGlvbj4+Ci4gPDxMaWNlbnNlPj4KLiA8PENoYW5nZWxvZz4+Ci4gPDxSb2FkbWFwPj4KLiA8PFN1cHBvcnQ+PgouIDw8RkFRPj4KLiA8PE1haW50ZW5hbmNlPj4=|
diff --git a/jamal-api/src/main/java/javax0/jamal/api/BadSyntaxAt.java b/jamal-api/src/main/java/javax0/jamal/api/BadSyntaxAt.java
index c5038750..9ad55ec9 100644
--- a/jamal-api/src/main/java/javax0/jamal/api/BadSyntaxAt.java
+++ b/jamal-api/src/main/java/javax0/jamal/api/BadSyntaxAt.java
@@ -58,20 +58,12 @@ public BadSyntaxAt(String message, Position pos, Throwable cause) {
this.pos = pos;
}
- public static String posFormat(Position pos) {
- if (pos == null) {
- return "";
- } else {
- return pos.file + "/" + pos.line + ":" + pos.column;
- }
- }
-
@Override
public String getMessage() {
if (pos == null) {
return super.getMessage();
} else {
- return super.getMessage() + " at " + posFormat(pos);
+ return super.getMessage() + " at " + pos.posFormat();
}
}
diff --git a/jamal-api/src/main/java/javax0/jamal/api/Input.java b/jamal-api/src/main/java/javax0/jamal/api/Input.java
index c0ff827e..5ce31e5d 100644
--- a/jamal-api/src/main/java/javax0/jamal/api/Input.java
+++ b/jamal-api/src/main/java/javax0/jamal/api/Input.java
@@ -20,7 +20,7 @@ public interface Input extends CharSequence {
*
implement the methods in a way that they do not use this method.
*
- *
+ *
* Get the {@link StringBuilder} that contains the characters of the input. The processing many times works directly
* on the {@link StringBuilder} deleting characters from the start of it as the processing progresses, thus
* essentially modifying/mutating the {@code Input} object.
@@ -38,7 +38,6 @@ public interface Input extends CharSequence {
*/
Position getPosition();
-
/**
* @return the reference file name that the input was read from
*/
diff --git a/jamal-api/src/main/java/javax0/jamal/api/Position.java b/jamal-api/src/main/java/javax0/jamal/api/Position.java
index 7556dfc0..d8772e13 100644
--- a/jamal-api/src/main/java/javax0/jamal/api/Position.java
+++ b/jamal-api/src/main/java/javax0/jamal/api/Position.java
@@ -1,5 +1,7 @@
package javax0.jamal.api;
+import java.util.ArrayList;
+
/**
* The {@code Position} contains the name of a file, a line number and the column number. This serves as a parameter
* when an error happens. The exception {@link BadSyntaxAt} gets an object of this type as a parameter, and later it is
@@ -10,19 +12,30 @@
*/
public class Position {
public final String file;
+ public final ArrayList segment = new ArrayList<>();
public int line;
public int column;
public int charpos = 0;
public final Position parent;
+ /**
+ * This is the position that this position is a clone of. This is needed when segments are to be added to or
+ * removed from a position. The method {@link Input#getPosition()} returns a clone of the position but in the case
+ * when we want to add a segment we need the original position as we want to modify it.
+ */
+ public final Position cloneOf;
+
public Position(String file, int line, int column, Position parent) {
this.file = file;
this.line = line;
this.column = column;
this.parent = parent;
+ this.cloneOf = this;
}
+
public Position(Position clone) {
+ cloneOf = clone;
if (clone == null) {
file = null;
line = 1;
@@ -60,6 +73,14 @@ public Position clone() {
return new Position(this);
}
+ public void pushSegment(String segment) {
+ this.segment.add(segment);
+ }
+
+ public void popSegment() {
+ this.segment.remove(this.segment.size() - 1);
+ }
+
/**
* @return return the position, which is the same as the position of the input, but references the position of the
* input as parent. This means that we will have two positions, with the same file/line:column information, but
@@ -83,12 +104,20 @@ public Position fork() {
*/
public Position top() {
var top = this;
- while ( top.parent != null) {
+ while (top.parent != null) {
top = top.parent;
}
return top;
}
+ public String posFormat() {
+ if (segment.isEmpty()) {
+ return file + "/" + line + ":" + column;
+ } else {
+ return file + "[" + String.join(">", segment) + "]" + line + ":" + column;
+ }
+ }
+
@Override
public String toString() {
return file + ":" + line + ":" + column;
diff --git a/jamal-cmd/src/main/java/javax0/jamal/cmd/JamalMain.java b/jamal-cmd/src/main/java/javax0/jamal/cmd/JamalMain.java
index 1db44c90..5039059c 100644
--- a/jamal-cmd/src/main/java/javax0/jamal/cmd/JamalMain.java
+++ b/jamal-cmd/src/main/java/javax0/jamal/cmd/JamalMain.java
@@ -137,7 +137,7 @@ public static void main(String[] args) {
private static final System.Logger LOGGER = System.getLogger("JAMAL");
private static void log(final System.Logger.Level level, final Position pos, final String format, final String... params) {
- final var msg = String.format(format, (Object[]) params) + (pos == null ? "" : " at ") + BadSyntaxAt.posFormat(pos);
+ final var msg = String.format(format, (Object[]) params) + (pos == null ? "" : " at " + pos.posFormat());
LOGGER.log(level, msg);
}
diff --git a/jamal-engine/src/main/java/javax0/jamal/engine/Processor.java b/jamal-engine/src/main/java/javax0/jamal/engine/Processor.java
index fcbd5be0..7efe41ca 100644
--- a/jamal-engine/src/main/java/javax0/jamal/engine/Processor.java
+++ b/jamal-engine/src/main/java/javax0/jamal/engine/Processor.java
@@ -200,7 +200,7 @@ public String process(final Input input) throws BadSyntax {
skipWhiteSpaces(input);
try {
processMacro(input, output);
- }catch(LinkageError le){
+ } catch (LinkageError le) {
throw new BadSyntax("Linkage error", le);
}
} else {
@@ -215,7 +215,7 @@ public String process(final Input input) throws BadSyntax {
}
processingException = badSyntax;
throw badSyntax;
- }finally {
+ } finally {
closeProcessWithExceptionHandling(output, processingException);
}
traceRecordFactory.dump(null);
@@ -511,7 +511,14 @@ private void pushBadSyntax(BadSyntax bs, final Position ref) throws BadSyntaxAt
private String evaluateBuiltinMacro(final Input input, final Position ref, final MacroQualifier qualifier) throws BadSyntaxAt {
try {
lastInvokedBuiltInMacro = qualifier.macroId;
- return qualifier.macro.evaluate(input, this);
+ input.getPosition().cloneOf.pushSegment(qualifier.macro.getId());
+ final String s;
+ try {
+ s = qualifier.macro.evaluate(input, this);
+ } finally {
+ input.getPosition().cloneOf.popSegment();
+ }
+ return s;
} catch (BadSyntax bs) {
pushBadSyntax(bs, ref);
return "";
diff --git a/jamal-maven-plugin/src/main/java/com/javax0/jamal/maven/JamalLogger.java b/jamal-maven-plugin/src/main/java/com/javax0/jamal/maven/JamalLogger.java
index bd62ee81..4680a65d 100644
--- a/jamal-maven-plugin/src/main/java/com/javax0/jamal/maven/JamalLogger.java
+++ b/jamal-maven-plugin/src/main/java/com/javax0/jamal/maven/JamalLogger.java
@@ -7,7 +7,7 @@ public class JamalLogger {
public static void log(final System.Logger.Level level, final Position pos, final String format, final String... params) {
org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger("jamal");
- final var msg = String.format(format, (Object[]) params) + (pos == null ? "" : " at ") + BadSyntaxAt.posFormat(pos);
+ final var msg = String.format(format, (Object[]) params) + (pos == null ? "" : " at " + pos.posFormat());
switch (level) {
case DEBUG:
log.debug(msg);
diff --git a/jamal-snippet/README.adoc b/jamal-snippet/README.adoc
index b16a677c..ba7f8cef 100644
--- a/jamal-snippet/README.adoc
+++ b/jamal-snippet/README.adoc
@@ -3816,7 +3816,7 @@ will result in the output
.output
[source]
----
-2024-12-10 17:58:06
+2024-12-11 13:19:58
----
diff --git a/jamal-sql/demodb.mv.db b/jamal-sql/demodb.mv.db
index 5e88ffee..46535c89 100644
Binary files a/jamal-sql/demodb.mv.db and b/jamal-sql/demodb.mv.db differ
diff --git a/jamal-testsupport/src/main/java/javax0/jamal/testsupport/TestThat.java b/jamal-testsupport/src/main/java/javax0/jamal/testsupport/TestThat.java
index 5e077bfd..f6bf6b4a 100644
--- a/jamal-testsupport/src/main/java/javax0/jamal/testsupport/TestThat.java
+++ b/jamal-testsupport/src/main/java/javax0/jamal/testsupport/TestThat.java
@@ -69,7 +69,7 @@ private TestThat(Class extends Macro> klass) {
private final List logItems = new ArrayList<>();
private void log(final System.Logger.Level level, final Position pos, final String format, final String... params) {
- logItems.add("[" + level.getName() + "] " + String.format(format, (Object[]) params) + (pos == null ? "" : " at ") + BadSyntaxAt.posFormat(pos));
+ logItems.add("[" + level.getName() + "] " + String.format(format, (Object[]) params) + (pos == null ? "" : " at " + pos.posFormat()));
}
public List getLogs() {
diff --git a/jamal-tools/src/main/java/javax0/jamal/tools/Input.java b/jamal-tools/src/main/java/javax0/jamal/tools/Input.java
index 665d60f7..fd28a156 100644
--- a/jamal-tools/src/main/java/javax0/jamal/tools/Input.java
+++ b/jamal-tools/src/main/java/javax0/jamal/tools/Input.java
@@ -7,8 +7,11 @@
*/
public class Input implements javax0.jamal.api.Input {
private final StringBuilder input;
- private final Position pos;
+ private Position pos;
+ Position getPos() {
+ return pos;
+ }
/**
* Create an empty input, which may also serve as an output where the characters are collected.
@@ -147,7 +150,6 @@ public void stepColumn() {
pos.charpos++;
}
-
@Override
public StringBuilder getSB() {
return input;
diff --git a/jamal-word/src/test/resources/demoConverted.docx b/jamal-word/src/test/resources/demoConverted.docx
index b281023a..98f89ff6 100644
Binary files a/jamal-word/src/test/resources/demoConverted.docx and b/jamal-word/src/test/resources/demoConverted.docx differ
diff --git a/jamal-word/src/test/resources/includetestConverted.docx b/jamal-word/src/test/resources/includetestConverted.docx
index 53f0a886..723905c4 100644
Binary files a/jamal-word/src/test/resources/includetestConverted.docx and b/jamal-word/src/test/resources/includetestConverted.docx differ
diff --git a/jamal-word/src/test/resources/pictureConverted.docx b/jamal-word/src/test/resources/pictureConverted.docx
index aa73805c..ad5d1ede 100644
Binary files a/jamal-word/src/test/resources/pictureConverted.docx and b/jamal-word/src/test/resources/pictureConverted.docx differ
diff --git a/jamal-word/src/test/resources/sampleConverted.docx b/jamal-word/src/test/resources/sampleConverted.docx
index a9d117f2..902cf96b 100644
Binary files a/jamal-word/src/test/resources/sampleConverted.docx and b/jamal-word/src/test/resources/sampleConverted.docx differ