From 10a4e115d92f5c14ebf7fe996cb55d6fa4353b44 Mon Sep 17 00:00:00 2001 From: Johan Maasing Date: Fri, 18 Apr 2025 08:19:38 +0200 Subject: [PATCH 1/3] Split grammar --- .gitignore | 4 +- parser/pom.xml | 1 + parser/src/main/antlr4/imports/Common.g4 | 40 +++++++++++++++++++ .../antlr4/nu/zoom/dsl/parser/Endpoints.g4 | 31 ++------------ 4 files changed, 48 insertions(+), 28 deletions(-) create mode 100644 parser/src/main/antlr4/imports/Common.g4 diff --git a/.gitignore b/.gitignore index 48010bb..7acc024 100644 --- a/.gitignore +++ b/.gitignore @@ -32,4 +32,6 @@ build/ .vscode/ ### Mac OS ### -.DS_Store \ No newline at end of file +.DS_Store + +/endpoints-output/** \ No newline at end of file diff --git a/parser/pom.xml b/parser/pom.xml index 02c7c9c..a81607b 100644 --- a/parser/pom.xml +++ b/parser/pom.xml @@ -57,6 +57,7 @@ org.apache.maven.plugins maven-jar-plugin + 3.4.2 diff --git a/parser/src/main/antlr4/imports/Common.g4 b/parser/src/main/antlr4/imports/Common.g4 new file mode 100644 index 0000000..fbcbd0d --- /dev/null +++ b/parser/src/main/antlr4/imports/Common.g4 @@ -0,0 +1,40 @@ +// Copyright 2025 "Johan Maasing" +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +grammar Common; +generatorconfig : '{' (configitem)? (',' configitem)* '}'; +configitem : configkey ':' configvalue ; +configkey : IDENTIFIER ; +configvalue : (IDENTIFIER|VALUE) ; +namedTypeDeclaration : typeName typeDeclaration ; +typeName : IDENTIFIER ; +typeDeclaration : '(' typeField (',' typeField)* ')' ; +typeField : fieldName ':' fieldType ; +fieldName : IDENTIFIER ; +fieldType : IDENTIFIER ; + +fragment LOWERCASE : [a-z] ; +fragment UPPERCASE : [A-Z] ; +fragment GENERICS : '['|']'|'<'|'>' ; +fragment DOT : '.' ; +fragment COMMENT_BEGIN : '/*' ; +fragment COMMENT_END : '*/' ; +fragment DIGIT : [0-9] ; + +WS : [ \t\n\r]+ -> skip; +COMMENT : COMMENT_BEGIN .*? COMMENT_END -> skip; +IDENTIFIER : (LOWERCASE | UPPERCASE) (LOWERCASE | UPPERCASE | DIGIT | GENERICS | DOT)* ; +VALUE : ~[ ,{}:()/="#';*\n\r\t]+ ; +LEFT_ARROW : '<-' ; +RIGHT_ARROW : '->' ; +SLASH : '/' ; \ No newline at end of file diff --git a/parser/src/main/antlr4/nu/zoom/dsl/parser/Endpoints.g4 b/parser/src/main/antlr4/nu/zoom/dsl/parser/Endpoints.g4 index 4f47bf8..f15a207 100644 --- a/parser/src/main/antlr4/nu/zoom/dsl/parser/Endpoints.g4 +++ b/parser/src/main/antlr4/nu/zoom/dsl/parser/Endpoints.g4 @@ -12,35 +12,12 @@ // See the License for the specific language governing permissions and // limitations under the License. grammar Endpoints; +import Common; + document : generatorconfig? (namedTypeDeclaration|endpoint)* ; -generatorconfig : '{' (configitem)? (',' configitem)* '}'; -configitem : configkey ':' configvalue ; -configkey : IDENTIFIER ; -configvalue : (IDENTIFIER|VALUE) ; -namedTypeDeclaration : typeName typeDeclaration ; -typeName : IDENTIFIER ; -typeDeclaration : '(' typeField (',' typeField)* ')' ; -typeField : fieldName ':' fieldType ; -fieldName : IDENTIFIER ; -fieldType : IDENTIFIER ; -requestBody : REQUEST_PREFIX (namedTypeDeclaration | typeDeclaration | IDENTIFIER) ; -responseBody : RESPONSE_PREFIX (namedTypeDeclaration | typeDeclaration | IDENTIFIER) ; +requestBody : LEFT_ARROW (namedTypeDeclaration | typeDeclaration | IDENTIFIER) ; +responseBody : RIGHT_ARROW (namedTypeDeclaration | typeDeclaration | IDENTIFIER) ; endpoint : path requestBody responseBody?; path : (pathSegment)+ ; pathSegment : SLASH (IDENTIFIER|VALUE) ; - -fragment DIGIT : [0-9] ; -fragment LOWERCASE : [a-z] ; -fragment UPPERCASE : [A-Z] ; -fragment GENERICS : '['|']'|'<'|'>' ; -fragment DOT : '.' ; -fragment COMMENT_BEGIN : '/*' ; -fragment COMMENT_END : '*/' ; -WS : [ \t\n\r]+ -> skip; -COMMENT : COMMENT_BEGIN .*? COMMENT_END -> skip; -REQUEST_PREFIX : '<-' ; -RESPONSE_PREFIX : '->' ; -SLASH : '/' ; -IDENTIFIER : (LOWERCASE | UPPERCASE) (LOWERCASE | UPPERCASE | DIGIT | GENERICS | DOT)* ; -VALUE : ~[ ,{}:()/="#';*\n\r\t]+ ; From 8050d35811bc5023e4f42d606b64f7b7662b5f86 Mon Sep 17 00:00:00 2001 From: Johan Maasing Date: Fri, 18 Apr 2025 10:22:18 +0200 Subject: [PATCH 2/3] WIP state visitor --- parser/src/main/antlr4/imports/Common.g4 | 9 +-- .../antlr4/nu/zoom/dsl/parser/Endpoints.g4 | 1 - .../main/antlr4/nu/zoom/dsl/parser/States.g4 | 22 ++++++++ .../java/nu/zoom/dsl/ast/DocumentNode.java | 6 +- .../dsl/ast/EndpointsVisitorTransformer.java | 9 +-- .../nu/zoom/dsl/ast/ParseTreeTransformer.java | 14 +++++ .../java/nu/zoom/dsl/ast/ParserWrapper.java | 28 ++++++++-- .../main/java/nu/zoom/dsl/ast/StateNode.java | 6 ++ .../dsl/ast/StatesVisitorTransformer.java | 56 +++++++++++++++++++ .../java/nu/zoom/dsl/ast/TransitionNode.java | 4 ++ .../java/nu/zoom/dsl/cli/EndpointsCLI.java | 24 +++++++- 11 files changed, 162 insertions(+), 17 deletions(-) create mode 100644 parser/src/main/antlr4/nu/zoom/dsl/parser/States.g4 create mode 100644 parser/src/main/java/nu/zoom/dsl/ast/ParseTreeTransformer.java create mode 100644 parser/src/main/java/nu/zoom/dsl/ast/StateNode.java create mode 100644 parser/src/main/java/nu/zoom/dsl/ast/StatesVisitorTransformer.java create mode 100644 parser/src/main/java/nu/zoom/dsl/ast/TransitionNode.java diff --git a/parser/src/main/antlr4/imports/Common.g4 b/parser/src/main/antlr4/imports/Common.g4 index fbcbd0d..8844343 100644 --- a/parser/src/main/antlr4/imports/Common.g4 +++ b/parser/src/main/antlr4/imports/Common.g4 @@ -19,7 +19,7 @@ configvalue : (IDENTIFIER|VALUE) ; namedTypeDeclaration : typeName typeDeclaration ; typeName : IDENTIFIER ; typeDeclaration : '(' typeField (',' typeField)* ')' ; -typeField : fieldName ':' fieldType ; +typeField : fieldName COLON fieldType ; fieldName : IDENTIFIER ; fieldType : IDENTIFIER ; @@ -33,8 +33,9 @@ fragment DIGIT : [0-9] ; WS : [ \t\n\r]+ -> skip; COMMENT : COMMENT_BEGIN .*? COMMENT_END -> skip; -IDENTIFIER : (LOWERCASE | UPPERCASE) (LOWERCASE | UPPERCASE | DIGIT | GENERICS | DOT)* ; -VALUE : ~[ ,{}:()/="#';*\n\r\t]+ ; LEFT_ARROW : '<-' ; RIGHT_ARROW : '->' ; -SLASH : '/' ; \ No newline at end of file +IDENTIFIER : (LOWERCASE | UPPERCASE) (LOWERCASE | UPPERCASE | DIGIT | GENERICS | DOT)* ; +VALUE : ~[ ,{}:()/="#';*\n\r\t]+ ; +SLASH : '/' ; +COLON : ':' ; \ No newline at end of file diff --git a/parser/src/main/antlr4/nu/zoom/dsl/parser/Endpoints.g4 b/parser/src/main/antlr4/nu/zoom/dsl/parser/Endpoints.g4 index f15a207..1a74607 100644 --- a/parser/src/main/antlr4/nu/zoom/dsl/parser/Endpoints.g4 +++ b/parser/src/main/antlr4/nu/zoom/dsl/parser/Endpoints.g4 @@ -20,4 +20,3 @@ responseBody : RIGHT_ARROW (namedTypeDeclaration | typeDeclaration | endpoint : path requestBody responseBody?; path : (pathSegment)+ ; pathSegment : SLASH (IDENTIFIER|VALUE) ; - diff --git a/parser/src/main/antlr4/nu/zoom/dsl/parser/States.g4 b/parser/src/main/antlr4/nu/zoom/dsl/parser/States.g4 new file mode 100644 index 0000000..dbfe628 --- /dev/null +++ b/parser/src/main/antlr4/nu/zoom/dsl/parser/States.g4 @@ -0,0 +1,22 @@ +// Copyright 2025 "Johan Maasing" +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +grammar States; +import Common; + +document : generatorconfig? transition (',' transition)* ; +transition : from RIGHT_ARROW to COLON message ; +from : state ; +to : state ; +message : typeName typeDeclaration? ; +state : typeName typeDeclaration? ; \ No newline at end of file diff --git a/parser/src/main/java/nu/zoom/dsl/ast/DocumentNode.java b/parser/src/main/java/nu/zoom/dsl/ast/DocumentNode.java index 24ac244..fcb8621 100644 --- a/parser/src/main/java/nu/zoom/dsl/ast/DocumentNode.java +++ b/parser/src/main/java/nu/zoom/dsl/ast/DocumentNode.java @@ -15,9 +15,11 @@ package nu.zoom.dsl.ast; import java.util.List; import java.util.Map; +import java.util.Set; public record DocumentNode( Map config, - List typeDefinitions, - List endpoints) { + Set typeDefinitions, + List endpoints, + Set states) { } diff --git a/parser/src/main/java/nu/zoom/dsl/ast/EndpointsVisitorTransformer.java b/parser/src/main/java/nu/zoom/dsl/ast/EndpointsVisitorTransformer.java index 5d846d6..e530a80 100644 --- a/parser/src/main/java/nu/zoom/dsl/ast/EndpointsVisitorTransformer.java +++ b/parser/src/main/java/nu/zoom/dsl/ast/EndpointsVisitorTransformer.java @@ -19,7 +19,8 @@ import org.antlr.v4.runtime.tree.TerminalNode; import java.util.*; -public class EndpointsVisitorTransformer extends EndpointsBaseVisitor { +public class EndpointsVisitorTransformer + extends EndpointsBaseVisitor { private final ArrayList endpoints = new ArrayList<>(); private final HashMap config = new HashMap<>(); private final HashSet dataTypes = new HashSet<>(); @@ -35,8 +36,8 @@ public class EndpointsVisitorTransformer extends EndpointsBaseVisitor getDataTypes() { - return List.copyOf(dataTypes); + public Set getDataTypes() { + return Set.copyOf(dataTypes); } @Override @@ -130,7 +131,7 @@ public class EndpointsVisitorTransformer extends EndpointsBaseVisitor getEndpoints(); + + Map getConfig(); + + List getDataTypes(); + +} diff --git a/parser/src/main/java/nu/zoom/dsl/ast/ParserWrapper.java b/parser/src/main/java/nu/zoom/dsl/ast/ParserWrapper.java index 2252cac..11a95fd 100644 --- a/parser/src/main/java/nu/zoom/dsl/ast/ParserWrapper.java +++ b/parser/src/main/java/nu/zoom/dsl/ast/ParserWrapper.java @@ -13,23 +13,43 @@ // limitations under the License. package nu.zoom.dsl.ast; -import nu.zoom.dsl.parser.EndpointsLexer; -import nu.zoom.dsl.parser.EndpointsParser; +import nu.zoom.dsl.parser.*; import org.antlr.v4.runtime.CharStreams; import org.antlr.v4.runtime.CommonTokenStream; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.nio.file.Path; +import java.util.List; +import java.util.Set; public class ParserWrapper { - public static DocumentNode parse(Path sourcePath) throws IOException { + public static DocumentNode parseEndpoints(Path sourcePath) throws IOException { var ins = CharStreams.fromPath(sourcePath, StandardCharsets.UTF_8); EndpointsLexer lexer = new EndpointsLexer(ins); EndpointsParser parser = new EndpointsParser(new CommonTokenStream(lexer)); var document = parser.document(); var astTransformer = new EndpointsVisitorTransformer(); astTransformer.visit(document); - return new DocumentNode(astTransformer.getConfig(), astTransformer.getDataTypes(), astTransformer.getEndpoints()); + return new DocumentNode( + astTransformer.getConfig(), + astTransformer.getDataTypes(), + astTransformer.getEndpoints(), + Set.of() + ); + } + public static DocumentNode parseStates(Path sourcePath) throws IOException { + var ins = CharStreams.fromPath(sourcePath, StandardCharsets.UTF_8); + StatesLexer lexer = new StatesLexer(ins); + StatesParser parser = new StatesParser(new CommonTokenStream(lexer)); + var document = parser.document(); + var astTransformer = new StatesVisitorTransformer(); + astTransformer.visit(document); + return new DocumentNode( + astTransformer.getConfig(), + astTransformer.getTypes(), + List.of(), + astTransformer.getStates() + ); } } diff --git a/parser/src/main/java/nu/zoom/dsl/ast/StateNode.java b/parser/src/main/java/nu/zoom/dsl/ast/StateNode.java new file mode 100644 index 0000000..5f8b7ff --- /dev/null +++ b/parser/src/main/java/nu/zoom/dsl/ast/StateNode.java @@ -0,0 +1,6 @@ +package nu.zoom.dsl.ast; + +import java.util.Set; + +public record StateNode(String name, String data, Set transitions) { +} diff --git a/parser/src/main/java/nu/zoom/dsl/ast/StatesVisitorTransformer.java b/parser/src/main/java/nu/zoom/dsl/ast/StatesVisitorTransformer.java new file mode 100644 index 0000000..4fd3c97 --- /dev/null +++ b/parser/src/main/java/nu/zoom/dsl/ast/StatesVisitorTransformer.java @@ -0,0 +1,56 @@ +package nu.zoom.dsl.ast; + +import nu.zoom.dsl.parser.StatesBaseVisitor; +import nu.zoom.dsl.parser.StatesParser; + +import java.util.*; + +public class StatesVisitorTransformer extends StatesBaseVisitor { + private final HashMap config = new HashMap<>(); + private final HashSet nodeTypes = new HashSet<>(); + private final HashSet messageTypes = new HashSet<>(); + // from -> + private final HashMap> transitions = new HashMap<>(); + + @Override + public StatesParser.DocumentContext visitTransition(StatesParser.TransitionContext ctx) { + String from = ctx.from().state().typeName().IDENTIFIER().getText() ; + String to = ctx.to().state().typeName().IDENTIFIER().getText() ; + String message = ctx.message().typeName().IDENTIFIER().getText() ; + this.transitions.computeIfAbsent(from, k -> new HashMap<>()).put(to, message); + return super.visitTransition(ctx); + } + + @Override + public StatesParser.DocumentContext visitState(StatesParser.StateContext ctx) { + String stateName = ctx.typeName().IDENTIFIER().getText() ; + List fields = extractFields(ctx.typeDeclaration()) ; + this.nodeTypes.add(new TypeNode(stateName, fields)); + return super.visitState(ctx); + } + + public Set getStates() { + // TODO: Calculate state nodes from this.transitions + return Set.of(); + } + + public Map getConfig() { + return Map.copyOf(config); + } + + public Set getTypes() { + // TODO calculate data types from NodeTypes and MessageTypes with duplicate check. + return Set.of() ; + } + + private List extractFields(StatesParser.TypeDeclarationContext declaration) { + return declaration + .typeField() + .stream() + .map( + ctx -> + new FieldNode(ctx.fieldName().getText(), ctx.fieldType().getText()) + ) + .toList(); + } +} diff --git a/parser/src/main/java/nu/zoom/dsl/ast/TransitionNode.java b/parser/src/main/java/nu/zoom/dsl/ast/TransitionNode.java new file mode 100644 index 0000000..90ebd3e --- /dev/null +++ b/parser/src/main/java/nu/zoom/dsl/ast/TransitionNode.java @@ -0,0 +1,4 @@ +package nu.zoom.dsl.ast; + +public record TransitionNode(String message, String toState) { +} diff --git a/parser/src/main/java/nu/zoom/dsl/cli/EndpointsCLI.java b/parser/src/main/java/nu/zoom/dsl/cli/EndpointsCLI.java index b26cb9c..e5c8eda 100644 --- a/parser/src/main/java/nu/zoom/dsl/cli/EndpointsCLI.java +++ b/parser/src/main/java/nu/zoom/dsl/cli/EndpointsCLI.java @@ -26,6 +26,7 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.List; +import java.util.Optional; import java.util.concurrent.Callable; @Command( @@ -34,6 +35,10 @@ import java.util.concurrent.Callable; description = "Generate source code from an endpoints specification file." ) public class EndpointsCLI implements Callable { + public static enum ParserType { + Endpoints, + States + } @SuppressWarnings("unused") @Parameters(index = "0", description = "The source endpoints DSL file.") private Path file; @@ -50,6 +55,9 @@ public class EndpointsCLI implements Callable { @Option(names = {"-v", "--verbose"}, description = "Print verbose debug messages.") private Boolean verbose = false; + @Option(names = {"-p", "--parser"}, description = "Force use of a specific parser instead of determining from filename. Valid values: ${COMPLETION-CANDIDATES}.") + private ParserType parser = null; + public static void main(String[] args) { int exitCode = new CommandLine(new EndpointsCLI()).execute(args); System.exit(exitCode); @@ -61,8 +69,20 @@ public class EndpointsCLI implements Callable { validateTemplateDirectory(); validateInputFile(); validateOutputDirectory(); - verbose("Parsing " + file.toAbsolutePath()); - DocumentNode rootNode = ParserWrapper.parse(file); + verbose("Parsing: " + file.toAbsolutePath()); + if (parser == null) { + if (file.getFileName().endsWith(".states")) { + parser = ParserType.States; + } + } + final DocumentNode rootNode ; + if (parser == ParserType.States) { + verbose("using state grammar.") ; + rootNode = ParserWrapper.parseStates(file); + } else { + verbose("using endpoints grammar.") ; + rootNode = ParserWrapper.parseEndpoints(file); + } verbose("AST: " + rootNode); verbose("Generating from templates in: " + templateDir.toAbsolutePath()); Generator generator = new Generator(templateDir, rootNode, outputDir); From a546d257f35408c90f7b5f5f4d6fca8d7a372b33 Mon Sep 17 00:00:00 2001 From: Johan Maasing Date: Sat, 19 Apr 2025 07:08:06 +0200 Subject: [PATCH 3/3] Grammar for states and transitions --- .../nu/zoom/dsl/ast/ParseTreeTransformer.java | 14 ----- .../dsl/ast/StatesVisitorTransformer.java | 56 ++++++++++++++++++- .../java/nu/zoom/dsl/cli/EndpointsCLI.java | 5 +- states-templates/nodes.md.ftl | 29 ++++++++++ test01.states | 4 ++ 5 files changed, 88 insertions(+), 20 deletions(-) delete mode 100644 parser/src/main/java/nu/zoom/dsl/ast/ParseTreeTransformer.java create mode 100644 states-templates/nodes.md.ftl create mode 100644 test01.states diff --git a/parser/src/main/java/nu/zoom/dsl/ast/ParseTreeTransformer.java b/parser/src/main/java/nu/zoom/dsl/ast/ParseTreeTransformer.java deleted file mode 100644 index d9ef9f9..0000000 --- a/parser/src/main/java/nu/zoom/dsl/ast/ParseTreeTransformer.java +++ /dev/null @@ -1,14 +0,0 @@ -package nu.zoom.dsl.ast; - -import java.util.List; -import java.util.Map; - -public interface ParseTreeTransformer { - - List getEndpoints(); - - Map getConfig(); - - List getDataTypes(); - -} diff --git a/parser/src/main/java/nu/zoom/dsl/ast/StatesVisitorTransformer.java b/parser/src/main/java/nu/zoom/dsl/ast/StatesVisitorTransformer.java index 4fd3c97..e1360a7 100644 --- a/parser/src/main/java/nu/zoom/dsl/ast/StatesVisitorTransformer.java +++ b/parser/src/main/java/nu/zoom/dsl/ast/StatesVisitorTransformer.java @@ -2,8 +2,10 @@ package nu.zoom.dsl.ast; import nu.zoom.dsl.parser.StatesBaseVisitor; import nu.zoom.dsl.parser.StatesParser; +import org.antlr.v4.runtime.tree.TerminalNode; import java.util.*; +import java.util.stream.Stream; public class StatesVisitorTransformer extends StatesBaseVisitor { private final HashMap config = new HashMap<>(); @@ -29,9 +31,30 @@ public class StatesVisitorTransformer extends StatesBaseVisitor fields = extractFields(ctx.typeDeclaration()) ; + this.messageTypes.add(new TypeNode(messageName, fields)); + return super.visitMessage(ctx); + } + + @Override + public StatesParser.DocumentContext visitConfigitem(StatesParser.ConfigitemContext ctx) { + String configKey = ctx.configkey().IDENTIFIER().getText(); + String configValue = getText(ctx.configvalue().IDENTIFIER(), ctx.configvalue().VALUE()); + this.config.put(configKey, configValue); + return super.visitConfigitem(ctx); + } + public Set getStates() { - // TODO: Calculate state nodes from this.transitions - return Set.of(); + HashSet states = new HashSet<>(); + this.transitions.forEach((state,v)->{ + HashSet transitionNodes = new HashSet<>(); + v.forEach((to, message) -> transitionNodes.add(new TransitionNode(message, to))); + states.add(new StateNode(state, "", transitionNodes)) ; + }) ; + return states ; } public Map getConfig() { @@ -40,10 +63,28 @@ public class StatesVisitorTransformer extends StatesBaseVisitor getTypes() { // TODO calculate data types from NodeTypes and MessageTypes with duplicate check. - return Set.of() ; + HashMap typeNodes = new HashMap<>(); + this.nodeTypes.forEach(typeNode -> { + if (typeNodes.containsKey(typeNode.name())) { + throw new RuntimeException("Duplicate type name: " + typeNode.name()); + } else { + typeNodes.put(typeNode.name(), typeNode); + } + }) ; + this.messageTypes.forEach(typeNode -> { + if (typeNodes.containsKey(typeNode.name())) { + throw new RuntimeException("Duplicate type name: " + typeNode.name()); + } else { + typeNodes.put(typeNode.name(), typeNode); + } + }) ; + return Set.of(typeNodes.values().toArray(new TypeNode[0])) ; } private List extractFields(StatesParser.TypeDeclarationContext declaration) { + if (declaration == null) { + return Collections.emptyList(); + } return declaration .typeField() .stream() @@ -53,4 +94,13 @@ public class StatesVisitorTransformer extends StatesBaseVisitor { - public static enum ParserType { + public enum ParserType { Endpoints, States } @@ -71,7 +70,7 @@ public class EndpointsCLI implements Callable { validateOutputDirectory(); verbose("Parsing: " + file.toAbsolutePath()); if (parser == null) { - if (file.getFileName().endsWith(".states")) { + if (file.getFileName().toString().endsWith(".states")) { parser = ParserType.States; } } diff --git a/states-templates/nodes.md.ftl b/states-templates/nodes.md.ftl new file mode 100644 index 0000000..89a5603 --- /dev/null +++ b/states-templates/nodes.md.ftl @@ -0,0 +1,29 @@ +``` +Copyright 2025 "Johan Maasing" + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +``` + +# The nodes + +```mermaid +--- +title: ${config.title} +--- +stateDiagram-v2 +<#list states as state> + <#list state.transitions as transition> + ${state.name} --> ${transition.toState} : ${transition.message} + + +``` \ No newline at end of file diff --git a/test01.states b/test01.states new file mode 100644 index 0000000..d1f78a9 --- /dev/null +++ b/test01.states @@ -0,0 +1,4 @@ +{ title: SomeNodes } +start(s:S) -> middle: message(foo:bar), +middle -> middle: selfmessage, +middle -> end: endmessage(bar:baz) \ No newline at end of file