Fixup documentation

This commit is contained in:
Johan Maasing 2025-04-20 12:15:42 +02:00
parent e87599708e
commit bc458299dc

View file

@ -37,10 +37,10 @@ Endgen currently contains two separate parsers:
* endpoint - A DSL for expressing HTTP endpoints. * endpoint - A DSL for expressing HTTP endpoints.
* state - A DSL for expressing state and transitions. * state - A DSL for expressing state and transitions.
Which parser that is used to read the input file is determined by the file name ending Only one parser will be sued when reading a file. Determined by the file name ending;
'.endpoints' or '.states' or by a command line argument. '.endpoints', or '.states', or by a command line argument.
The endpoint DSL and the state DSL share the grammar for expressing configuration and data types The endpoint-DSL and the state-DSL share the grammar for expressing configuration and data types
,see below for details. ,see below for details.
## How to Run ## How to Run
@ -89,15 +89,20 @@ a very limited DSL, you can for example not express what type of HTTP Verb to us
no plans to extend the DSL to do that either. no plans to extend the DSL to do that either.
## DSL ## DSL
This is the ANTLR grammar for the root of the DSL This is the ANTLR grammar for the root of the Endpoint-DSL
```antlrv4 ```antlrv4
document : generatorconfig? (namedTypeDeclaration|endpoint)* ; document : generatorconfig? (namedTypeDeclaration|endpoint)* ;
``` ```
the corresponding grammar for the root of the State-DSL
```antlrv4
document : generatorconfig? transition (',' transition)* ;
```
### Configuration block ### Configuration block
Meaning that the DSL file has an optional `generatorconfig` block at the top. Then you can write either; a type Both types of DSL files has an optional `generatorconfig` block at the top.
definition, or an endpoint declaration, as many times as you like.
Here is an example: Here is an example:
``` ```
@ -105,25 +110,32 @@ Here is an example:
package: se.rutdev.senash, package: se.rutdev.senash,
mykey: myvalue mykey: myvalue
} }
```
This consists of a config block with 2 items, the 'package' and the 'mykey' definition. These are available to be used
in the freemarker template as a Map of String-keys to String-values.
### Endpoint DSL
After the optional configuration block you can write either; a type definition, or an endpoint declaration, and repeat
as many times as you like.
Here is an example:
```
/some/endpoint <- SomeType(foo:String) /some/endpoint <- SomeType(foo:String)
Embedded(foo:Bar) Embedded(foo:Bar)
/some/other/endpoint <- (bar:Seq[Embedded]) /some/other/endpoint <- (bar:Seq[Embedded])
``` ```
This consists of a config block with 2 items, the 'package' and the 'mykey' definition. These are available to be used
in the freemarker template as a Map of String-keys to String-values.
### Endpoint definition ### Endpoint definition
`/some/endpoint <- SomeType(foo:String)` is an endpoint definition. It declares one endpoint that have a request body `/some/endpoint <- SomeType(foo:String)` is an endpoint definition. It declares one endpoint that have a request body
data type called `SomeType` that has a field called `foo` of the type `String`. data type called `SomeType` that has a field called `foo` of the type `String`.
### Data types ### Data types
The DSL uses Scala convention of writing data types after the field name separated by a colon. Of course the DSL parser Both DSL-grammars use the Scala convention of writing data types after the field name separated by a colon. Of course
does not know anything about java or scala types, as far as it is concerned these are 2 strings and the first one is the parsers do not know anything about java or scala types, as far as the parser is concerned these are 2 strings and
just named field-name and the other string is named field-type. the first one is just named: field-name and the other string is named: field-type.
`Embedded(foo:Bar)` is a `namedTypeDeclaration` which is parsed the same way as the request type above. But isn't tied `Embedded(foo:Bar)` is a `namedTypeDeclaration` which is parsed the same way as the request type above. But isn't tied
to a specific endpoint. to a specific endpoint.
@ -148,30 +160,29 @@ It is possible to have an optional response data type declared like so:
The right pointing arrow `->` denotes a response type, it can be an anonymous data type in which case the parser till The right pointing arrow `->` denotes a response type, it can be an anonymous data type in which case the parser till
name it from the last path segment and add 'Response' to the end of the data type name. name it from the last path segment and add 'Response' to the end of the data type name.
### State grammar ### State DSL
This is an example of a state file: This is an example of a state file:
``` ```
start -> middle: message, start -> middle: message,
middle -> middle: selfmessage, middle -> middle: selfmessage,
middle -> end: endmessage middle -> end: endmessage
``` ```
The file declares 3 transitions. The first line states: Transition from the 'start' state to the 'middle' state with
the message 'message'.
It contains 3 state definitions `start`, `middle` and `end`. A state definition will be parsed as a data type with From this we can see that the file contains 3 state definitions `start`, `middle` and `end`.
the name of the state as the type name. A state definition will be parsed as a data type with the name of the state as the type name. It also contains 3
message definitions `message`, `selfmessage` and `endmessage`. Message definitions will also be parsed as data types.
It also contains 3 message definitions `message`, `selfmessage` and `endmessage`. Message definitions will also be
parsed as data types.
Since the parser will extract datatypes it is possible to define the fields of the data types. This is a slightly more Since the parser will extract datatypes it is possible to define the fields of the data types. This is a slightly more
complicated example: complicated example:
``` ```
start(foo:Foo) -> middle: message(a: String), start -> middle: message(a: String),
middle(bar:Bar) -> middle: selfmessage, middle(bar:Bar) -> middle: selfmessage,
middle -> end: endmessage middle -> end: endmessage
``` ```
Where for example the data type for `middle` will have the field declaration with the name `bar` and the type `Bar`. The data type for `middle` will have a field declaration with the name `bar` and the type `Bar`.
Fields for the same state data type, or message data type, will be merged. Here is a complex example: Fields for the same state data type, or message data type, will be merged. Here is a complex example:
@ -181,12 +192,12 @@ middle -> middle(bar:bar): selfmessage(bar:bar),
middle -> end: message(bar:baz) middle -> end: message(bar:baz)
``` ```
Not that we can declare fields on both the `from` and `to` state declarations. The `middle` datat type will have field Note that we can declare fields on both the `from` and `to` state declarations. The `middle` datat type will have field
definitons for `foo` and `bar`. definitons for `foo` and `bar`.
The data type for `message` will have fields for `foo` and `bar`. The data type for `message` will have fields for `foo` and `bar`.
One restriction is that states and messages may not have the same name, i.e. be parsed as the same data type. One restriction is that a state and a messages may share have the same name, i.e. be parsed as the same data type.
## Generating ## Generating
If the parser is successful it will hold the following data in the AST If the parser is successful it will hold the following data in the AST
@ -221,8 +232,8 @@ that writes the value for a config key called 'package'.
`package ${config.package}` `package ${config.package}`
### Data types ### Data types
These are all the data types the parser have collected, either from explicit declarations, request payloads and response These are all the data types the parser have collected, either from explicit declarations, request payloads, response
bodies. bodies, states or messages.
```java ```java
public record TypeNode(String name, List<FieldNode> fields) { } public record TypeNode(String name, List<FieldNode> fields) { }
@ -281,11 +292,15 @@ The set of states will hold items of this shape:
public record StateNode(String name, String data, Set<TransitionNode> transitions) { public record StateNode(String name, String data, Set<TransitionNode> transitions) {
} }
``` ```
* `name` is the name of the state.
* `data` is the name of the data type for the state.
* `transistions` are the outgoing arrows from the named state.
and the transitions has this structure: Transitions have this structure:
```injectedfreemarker ```injectedfreemarker
public record TransitionNode(String message, String toState) { public record TransitionNode(String message, String toState) {
} }
``` ```
* `name` is the message name.
* `toState` is the name of the target state.