Skip to content

Commit

Permalink
fix parser for CLASS inside DEFINE (#93)
Browse files Browse the repository at this point in the history
  • Loading branch information
jmgrassau committed Sep 4, 2023
1 parent b5ae3c7 commit 22acce5
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -319,14 +319,19 @@ final void addOpener(LevelOpener opener) {
openers.put(key, opener);
}

final String getErrorMessageForMissingOpener() {
StringBuilder openersList = new StringBuilder();
final String getOpenersList() { return getOpenersList("/"); }
final String getOpenersList(String separator) {
StringBuilder result = new StringBuilder();
for (Map.Entry<String, LevelOpener> kvp : openers.entrySet()) {
if (openersList.length() > 0)
openersList.append("/");
openersList.append(kvp.getValue().text);
if (result.length() > 0)
result.append("/");
result.append(kvp.getValue().text);
}
return text + " found, but no corresponding " + openersList;
return result.toString();
}

final boolean isCloserFor(LevelOpener levelOpener) {
return getOpeners().containsKey(getLevelCloserKey(levelOpener.text));
}
}

Expand Down Expand Up @@ -521,15 +526,34 @@ final void addNext(Command newCommand) throws UnexpectedSyntaxException {

newCommand.initialBlockLevel = initialBlockLevel + blockLevelDiff;

if (getOpensLevel() && !newCommand.getClosesLevel()) {
addChild(newCommand);
} else if (!getOpensLevel() && newCommand.getClosesLevel()) {
if (parent != null)
if (getOpensLevel()) {
if (!newCommand.getClosesLevel()) {
addChild(newCommand);
} else if (newCommand.usedLevelCloser.isCloserFor(usedLevelOpener)) {
// newCommand directly closes this Command
addSibling(newCommand);
} else if (newCommand.usedLevelCloser.requiresOpener) {
throw new UnexpectedSyntaxException(this,
"expected " + usedLevelOpener.getClosersList() + ", but found " + newCommand.usedLevelCloser.text + ". " +
"Opening command (line " + Cult.format(this.sourceLineNumStart) + "): " + this.toStringForErrorMessage());
} else {
// remove an optional level closer that does not apply in this case, e.g. 'DEFINE any_macro. CLASS &1 DEFINITION.'
newCommand.usedLevelCloser = null;
addChild(newCommand);
}

} else if (newCommand.getClosesLevel()) {
if (parent != null && newCommand.usedLevelCloser.isCloserFor(parent.usedLevelOpener)) {
parent.addSibling(newCommand);
else if (newCommand.usedLevelCloser.requiresOpener)
throw new UnexpectedSyntaxException(this, newCommand.usedLevelCloser.getErrorMessageForMissingOpener());
else
} else if (newCommand.usedLevelCloser.requiresOpener) {
throw new UnexpectedSyntaxException(this,
newCommand.usedLevelCloser.text + " found in line " + Cult.format(newCommand.sourceLineNumStart) +
", but no corresponding " + newCommand.usedLevelCloser.getOpenersList());
} else {
newCommand.usedLevelCloser = null;
addSibling(newCommand);
}

} else {
addSibling(newCommand);
}
Expand Down Expand Up @@ -557,14 +581,6 @@ else if (newCommand.usedLevelCloser.requiresOpener)
}

private void addSibling(Command newCommand) throws UnexpectedSyntaxException {
if (newCommand.getClosesLevel()) {
if (!newCommand.usedLevelCloser.getOpeners().containsKey(getLevelCloserKey(usedLevelOpener.text))) {
throw new UnexpectedSyntaxException(this,
"expected " + usedLevelOpener.getClosersList() + ", but found " + newCommand.usedLevelCloser.text + ". " +
"Opening command (line " + Cult.format(this.sourceLineNumStart) + "): " + this.toStringForErrorMessage());
}
}

newCommand.parent = parent;
newCommand.prevSibling = this;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1081,4 +1081,26 @@ void testWriteAt() {

testParseCode();
}

@Test
void testDefineWithClassDefinition() {
// ensure that CLASS can be nested in DEFINE: CLASS is an optional level closer in the context of a REPORT,
// but does NOT close a level in this case

buildSrc("DEFINE any_macro.");
buildSrc(" \" comment");
buildSrc(" CLASS &1 DEFINITION FOR TESTING INHERITING FROM cx_static_check.");
buildSrc(" ENDCLASS.");
buildSrc("END-OF-DEFINITION.");
buildSrc("");
buildSrc("DEFINE other_macro.");
buildSrc(" CLASS &1 DEFINITION FOR TESTING INHERITING FROM cx_static_check.");
buildSrc(" ENDCLASS.");
buildSrc("");
buildSrc(" CLASS &1 IMPLEMENTATION.");
buildSrc(" ENDCLASS.");
buildSrc("END-OF-DEFINITION.");

testParseCode();
}
}

0 comments on commit 22acce5

Please sign in to comment.