Added types declarations
This commit is contained in:
parent
620999a992
commit
857f9c63a6
6 changed files with 165 additions and 53 deletions
|
@ -32,6 +32,7 @@
|
|||
-->
|
||||
<execution>
|
||||
<id>jjtree-javacc</id>
|
||||
<phase>generate-sources</phase>
|
||||
<goals>
|
||||
<goal>jjtree-javacc</goal>
|
||||
</goals>
|
||||
|
|
6
parser/src/main/java/nu/zoom/tapir/DataTypeNode.java
Normal file
6
parser/src/main/java/nu/zoom/tapir/DataTypeNode.java
Normal file
|
@ -0,0 +1,6 @@
|
|||
package nu.zoom.tapir;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public record DataTypeNode(String name, List<FieldNode> fields) {
|
||||
}
|
|
@ -39,19 +39,25 @@ public class Generator implements Callable<Integer> {
|
|||
validateTemplateDirectory();
|
||||
validateInputFile();
|
||||
validateOutputDirectory();
|
||||
var rootNode = new TapirParser(Files.newBufferedReader(this.file)).endpoints();
|
||||
var rootNode = new TapirParser(Files.newBufferedReader(this.file)).specification();
|
||||
if (this.verbose) {
|
||||
System.out.println("====== Parse Tree ======");
|
||||
rootNode.dump("");
|
||||
}
|
||||
var endpoints = NodeTransformer.transform(rootNode);
|
||||
if (endpoints.isEmpty()) {
|
||||
NodeTransformer transformer = new NodeTransformer();
|
||||
transformer.transform(rootNode);
|
||||
if (transformer.getEndpoints().isEmpty()) {
|
||||
System.err.println("No tapir endpoints found.");
|
||||
return 2;
|
||||
}
|
||||
if (this.verbose) {
|
||||
System.out.println("\n====== AST ======");
|
||||
endpoints.forEach(endpoint -> {
|
||||
System.out.println("\n====== Types ======");
|
||||
transformer.getDataTypes().forEach(type -> {
|
||||
System.out.println(type);
|
||||
});
|
||||
System.out.println("\n====== Endpoints ======");
|
||||
transformer.getEndpoints().forEach(endpoint -> {
|
||||
System.out.println(endpoint);
|
||||
});
|
||||
}
|
||||
|
@ -59,7 +65,7 @@ public class Generator implements Callable<Integer> {
|
|||
this.verbose,
|
||||
this.outputDir,
|
||||
this.templateDir,
|
||||
endpoints
|
||||
transformer.getEndpoints()
|
||||
);
|
||||
targetGenerator.generate();
|
||||
return 0;
|
||||
|
|
|
@ -9,16 +9,97 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
|
||||
public class NodeTransformer {
|
||||
private final List<EndpointNode> endpoints = new ArrayList<>();
|
||||
private final List<DataTypeNode> dataTypes = new ArrayList<>();
|
||||
|
||||
public static List<EndpointNode> transform(SimpleNode rootNode) throws ParseException {
|
||||
ArrayList<EndpointNode> endpoints = new ArrayList<>();
|
||||
for (int i = 0; i < rootNode.jjtGetNumChildren(); i++) {
|
||||
SimpleNode endpoint = assertSimpleNode(rootNode.jjtGetChild(i));
|
||||
endpoints.add(handleEndpoint(endpoint));
|
||||
}
|
||||
public List<EndpointNode> getEndpoints() {
|
||||
return endpoints;
|
||||
}
|
||||
|
||||
public List<DataTypeNode> getDataTypes() {
|
||||
return dataTypes;
|
||||
}
|
||||
|
||||
public void transform(SimpleNode rootNode) throws ParseException {
|
||||
assertSimpleNodeType(rootNode, TapirParserTreeConstants.JJTSPECIFICATION);
|
||||
int numChildren = rootNode.jjtGetNumChildren();
|
||||
if (numChildren == 2) {
|
||||
this.dataTypes.addAll(
|
||||
handleDataTypes(
|
||||
assertSimpleNodeType(
|
||||
rootNode.jjtGetChild(0),
|
||||
TapirParserTreeConstants.JJTDATATYPES
|
||||
)
|
||||
)
|
||||
);
|
||||
this.endpoints.addAll(
|
||||
handleEndpoints(
|
||||
assertSimpleNodeType(
|
||||
rootNode.jjtGetChild(1),
|
||||
TapirParserTreeConstants.JJTENDPOINTS
|
||||
)
|
||||
)
|
||||
);
|
||||
} else if (numChildren == 1) {
|
||||
this.endpoints.addAll(
|
||||
handleEndpoints(
|
||||
assertSimpleNodeType(
|
||||
rootNode.jjtGetChild(1),
|
||||
TapirParserTreeConstants.JJTENDPOINTS
|
||||
)
|
||||
)
|
||||
);
|
||||
} else {
|
||||
throw new ParseException("Expected specification to have 1 or 2 children but had " + numChildren);
|
||||
}
|
||||
}
|
||||
|
||||
private static List<EndpointNode> handleEndpoints(SimpleNode endpoints) throws ParseException {
|
||||
ArrayList<EndpointNode> endpointNodes = new ArrayList<>();
|
||||
for (int i = 0; i < endpoints.jjtGetNumChildren(); i++) {
|
||||
endpointNodes.add(
|
||||
handleEndpoint(
|
||||
assertSimpleNodeType(
|
||||
endpoints.jjtGetChild(i),
|
||||
TapirParserTreeConstants.JJTENDPOINT
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
return endpointNodes;
|
||||
}
|
||||
|
||||
private static List<DataTypeNode> handleDataTypes(SimpleNode dataTypesDeclaration) throws ParseException {
|
||||
List<DataTypeNode> dataTypes = new ArrayList<>();
|
||||
for (int i = 0; i < dataTypesDeclaration.jjtGetNumChildren(); i++) {
|
||||
dataTypes.add(
|
||||
handleCompoundDataType(
|
||||
assertSimpleNodeType(
|
||||
dataTypesDeclaration.jjtGetChild(i),
|
||||
TapirParserTreeConstants.JJTCOMPOUNDDATATYPE
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
return dataTypes;
|
||||
}
|
||||
|
||||
private static DataTypeNode handleCompoundDataType(SimpleNode dataTypeNode) throws ParseException {
|
||||
String typename = getStringValue(
|
||||
assertSimpleNodeType(
|
||||
dataTypeNode.jjtGetChild(0),
|
||||
TapirParserTreeConstants.JJTCOMPUNDDATATYPENAME
|
||||
)
|
||||
);
|
||||
List<FieldNode> fields = handleFields(
|
||||
assertSimpleNodeType(
|
||||
dataTypeNode.jjtGetChild(1),
|
||||
TapirParserTreeConstants.JJTDATATYPEFIELDS
|
||||
)
|
||||
);
|
||||
return new DataTypeNode(typename, fields);
|
||||
}
|
||||
|
||||
private static EndpointNode handleEndpoint(SimpleNode node) throws ParseException {
|
||||
int numChildren = node.jjtGetNumChildren();
|
||||
if (numChildren != 2) {
|
||||
|
@ -27,13 +108,13 @@ public class NodeTransformer {
|
|||
SimpleNode pathsParseNode =
|
||||
assertSimpleNodeType(
|
||||
node.jjtGetChild(0),
|
||||
TapirParserTreeConstants.JJTPATHS
|
||||
TapirParserTreeConstants.JJTPATH
|
||||
);
|
||||
PathsNode pathsNode = handlePaths(pathsParseNode);
|
||||
SimpleNode handlerParseNode =
|
||||
assertSimpleNodeType(
|
||||
node.jjtGetChild(1),
|
||||
TapirParserTreeConstants.JJTHANDLERSPEC
|
||||
TapirParserTreeConstants.JJTCOMPOUNDDATATYPE
|
||||
);
|
||||
HandlerNode handlerNode = handleHandler(handlerParseNode);
|
||||
return new EndpointNode(pathsNode, handlerNode);
|
||||
|
@ -47,25 +128,25 @@ public class NodeTransformer {
|
|||
String handlerName = getStringValue(
|
||||
assertSimpleNodeType(
|
||||
handlerSpec.jjtGetChild(0),
|
||||
TapirParserTreeConstants.JJTHANDLERNAME
|
||||
TapirParserTreeConstants.JJTCOMPUNDDATATYPENAME
|
||||
)
|
||||
);
|
||||
SimpleNode payloadFieldsParseNode =
|
||||
assertSimpleNodeType(
|
||||
handlerSpec.jjtGetChild(1),
|
||||
TapirParserTreeConstants.JJTPAYLOADFIELDS
|
||||
TapirParserTreeConstants.JJTDATATYPEFIELDS
|
||||
);
|
||||
List<FieldNode> fields = handleFields(payloadFieldsParseNode);
|
||||
return new HandlerNode(handlerName, fields);
|
||||
}
|
||||
|
||||
private static List<FieldNode> handleFields(SimpleNode payloadFieldsParseNode) throws ParseException {
|
||||
private static List<FieldNode> handleFields(SimpleNode compoundDatatTypeFields) throws ParseException {
|
||||
ArrayList<FieldNode> fields = new ArrayList<>();
|
||||
for (int i = 0; i < payloadFieldsParseNode.jjtGetNumChildren(); i++) {
|
||||
for (int i = 0; i < compoundDatatTypeFields.jjtGetNumChildren(); i++) {
|
||||
SimpleNode payloadFieldParseNode =
|
||||
assertSimpleNodeType(
|
||||
payloadFieldsParseNode.jjtGetChild(i),
|
||||
TapirParserTreeConstants.JJTPAYLOADFIELD
|
||||
compoundDatatTypeFields.jjtGetChild(i),
|
||||
TapirParserTreeConstants.JJTDATATYPEFIELDS
|
||||
);
|
||||
int numFieldNodes = payloadFieldParseNode.jjtGetNumChildren();
|
||||
if (numFieldNodes != 2) {
|
||||
|
@ -74,13 +155,13 @@ public class NodeTransformer {
|
|||
String fieldName = getStringValue(
|
||||
assertSimpleNodeType(
|
||||
payloadFieldParseNode.jjtGetChild(0),
|
||||
TapirParserTreeConstants.JJTPAYLOADFIELDNAME
|
||||
TapirParserTreeConstants.JJTDATATYPEFIELDNAME
|
||||
)
|
||||
);
|
||||
String fieldType = getStringValue(
|
||||
assertSimpleNodeType(
|
||||
payloadFieldParseNode.jjtGetChild(1),
|
||||
TapirParserTreeConstants.JJTPAYLOADFIELDTYPE
|
||||
TapirParserTreeConstants.JJTDATATYPEFIELDTYPE
|
||||
)
|
||||
);
|
||||
fields.add(new FieldNode(fieldName, fieldType));
|
||||
|
|
|
@ -24,6 +24,7 @@ public class TargetGenerator {
|
|||
public TargetGeneratorException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public TargetGeneratorException(Exception cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
@ -47,7 +48,8 @@ public class TargetGenerator {
|
|||
this.endpoints = Objects.requireNonNull(endpoints);
|
||||
}
|
||||
|
||||
public void generate() throws TargetGeneratorException, IOException, TemplateException {
|
||||
public void generate() throws TargetGeneratorException {
|
||||
try {
|
||||
Configuration cfg = new Configuration(Configuration.VERSION_2_3_34);
|
||||
cfg.setDirectoryForTemplateLoading(this.templatePath.toFile());
|
||||
cfg.setDefaultEncoding("UTF-8");
|
||||
|
@ -65,5 +67,8 @@ public class TargetGenerator {
|
|||
templateData.put("endpoints", endpoints);
|
||||
temp.process(templateData, outputFile);
|
||||
}
|
||||
} catch (TemplateException | IOException ex) {
|
||||
throw new TargetGeneratorException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ SKIP: {
|
|||
TOKEN : {
|
||||
<OPENPARANTHESIS: "(">
|
||||
| <CLOSEPARANTHESIS: ")">
|
||||
| <SEMICOLON: ";">
|
||||
| <TRANSITION: "->">
|
||||
| <SLASH: "/">
|
||||
| <COLON: ":">
|
||||
|
@ -32,63 +33,75 @@ TOKEN : {
|
|||
| <IDENTIFIER: <FIRST_LETTER> (<LETTER>)* >
|
||||
}
|
||||
|
||||
void path() :
|
||||
void pathSegment() :
|
||||
{Token t;}
|
||||
{
|
||||
t=<IDENTIFIER>{jjtThis.value = t.image;} <SLASH>
|
||||
}
|
||||
|
||||
void paths() :
|
||||
void path() :
|
||||
{}
|
||||
{
|
||||
path() (path())*
|
||||
pathSegment() (pathSegment())*
|
||||
}
|
||||
|
||||
void payloadFieldName() :
|
||||
void dataTypeFieldType() :
|
||||
{Token t;}
|
||||
{
|
||||
t=<IDENTIFIER>{jjtThis.value = t.image;}
|
||||
}
|
||||
|
||||
void payloadFieldType() :
|
||||
void dataTypeFieldName() :
|
||||
{Token t;}
|
||||
{
|
||||
t=<IDENTIFIER>{jjtThis.value = t.image;}
|
||||
}
|
||||
|
||||
void payloadField() :
|
||||
void dataTypeField() :
|
||||
{}
|
||||
{
|
||||
payloadFieldName() <COLON> payloadFieldType()
|
||||
dataTypeFieldName() <COLON> dataTypeFieldType()
|
||||
}
|
||||
|
||||
void payloadFields() :
|
||||
void dataTypeFields() :
|
||||
{}
|
||||
{
|
||||
payloadField() (<COMMA> payloadField() )*
|
||||
dataTypeField() (<COMMA> dataTypeField() )*
|
||||
}
|
||||
|
||||
void handlerName() :
|
||||
void compundDataTypeName() :
|
||||
{Token t;}
|
||||
{
|
||||
t=<IDENTIFIER>{jjtThis.value = t.image;}
|
||||
}
|
||||
|
||||
void handlerSpec() :
|
||||
void compoundDataType() :
|
||||
{}
|
||||
{
|
||||
handlerName() <OPENPARANTHESIS> payloadFields() <CLOSEPARANTHESIS>
|
||||
compundDataTypeName() <OPENPARANTHESIS> dataTypeFields() <CLOSEPARANTHESIS>
|
||||
}
|
||||
|
||||
void dataTypes() :
|
||||
{}
|
||||
{
|
||||
(compoundDataType() )*
|
||||
}
|
||||
|
||||
void endpoint() :
|
||||
{}
|
||||
{
|
||||
paths() <TRANSITION> handlerSpec()
|
||||
path() <TRANSITION> compoundDataType()
|
||||
}
|
||||
|
||||
SimpleNode endpoints() :
|
||||
void endpoints() :
|
||||
{}
|
||||
{
|
||||
(endpoint() )*
|
||||
}
|
||||
|
||||
SimpleNode specification() :
|
||||
{}
|
||||
{
|
||||
dataTypes() endpoints()
|
||||
{ return jjtThis; }
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue