Skip to content

Commit

Permalink
changes for IntelliJ lexer/parser compatibility
Browse files Browse the repository at this point in the history
  • Loading branch information
ivangsa committed Aug 16, 2023
1 parent e768d5e commit 2a453d2
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 64 deletions.
122 changes: 70 additions & 52 deletions src/main/antlr4/io.github.zenwave360.zdl.antlr/Zdl.g4
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
grammar Zdl;

@members {
@lexer::members {
private int _currentRuleType = Token.INVALID_TYPE;
public int getCurrentRuleType() {
Expand All @@ -10,8 +10,23 @@ grammar Zdl;
public void setCurrentRuleType(int ruleType) {
this._currentRuleType = ruleType;
}

@Override
public Token emit() {
return super.emit();
}
}

LPAREN: '(';
RPAREN: ')';
LBRACE: '{';
RBRACE: '}';
LBRACK: '[';
RBRACK: ']';
OR: '|';
COMMA: ',';
COLON: ':';

// Keywords
CONFIG: 'config';
Expand All @@ -36,18 +51,19 @@ FOR: 'for';
WITH_EVENTS: 'withEvents';

// options with reserved tokens
CONFIG_OPTION: '@config';
APIS_OPTION: '@apis';
ASYNCAPI_OPTION: '@asyncapi';
OPENAPI_OPTION: '@openapi';
ENTITY_OPTION: '@entity';
SERVICE_OPTION: '@service';
INPUT_OPTION: '@input';
OUTPUT_OPTION: '@output';
EVENT_OPTION: '@event';
RELATIONSHIP_OPTION: '@relationship';
ENUM_OPTION: '@enum';
PAGINATED_OPTION: '@paginated';
fragment CONFIG_OPTION: '@config';
fragment APIS_OPTION: '@apis';
fragment ASYNCAPI_OPTION: '@asyncapi';
fragment OPENAPI_OPTION: '@openapi';
fragment ENTITY_OPTION: '@entity';
fragment SERVICE_OPTION: '@service';
fragment INPUT_OPTION: '@input';
fragment OUTPUT_OPTION: '@output';
fragment EVENT_OPTION: '@event';
fragment RELATIONSHIP_OPTION: '@relationship';
fragment ENUM_OPTION: '@enum';
fragment PAGINATED_OPTION: '@paginated';
RESERVED_OPTIONS: CONFIG_OPTION | APIS_OPTION | ASYNCAPI_OPTION | OPENAPI_OPTION | ENTITY_OPTION | SERVICE_OPTION | INPUT_OPTION | OUTPUT_OPTION | EVENT_OPTION | RELATIONSHIP_OPTION | ENUM_OPTION | PAGINATED_OPTION;

REQUIRED: 'required';
UNIQUE: 'unique';
Expand All @@ -61,17 +77,17 @@ ARRAY: '[]';
TRUE: 'true';
FALSE: 'false';
NULL: 'null';
EQUALS: '=';

FIELD_SEPARATOR: ',';

fragment DIGIT : [0-9] ;

ID: [a-zA-Z_][a-zA-Z0-9_]*;
INT: DIGIT+ ;
NUMBER: DIGIT+ ([.] DIGIT+)? ;

LEGACY_CONSTANT: [A-Z0-9_]+ '=' DIGIT+;

LEGACY_CONSTANT: LEGACY_CONSTANT_NAME ' '* EQUALS ' '* INT;
LEGACY_CONSTANT_NAME: [A-Z0-9_]+;

// Comments
//SUFFIX_JAVADOC: {getCharPositionInLine() > 10}? '/**' .*? '*/';
Expand All @@ -98,105 +114,107 @@ PATTERN_REGEX: '/' .*? '/' ; // TODO: improve regex
ERRCHAR: . -> channel(HIDDEN);
// Rules
zdl: global_javadoc? legacy_constants? config? apis? (entity | enum | input | output | event | relationships | service | service_legacy)* EOF;
zdl: global_javadoc? legacy_constants config? apis? (entity | enum | input | output | event | relationships | service | service_legacy)* EOF;
global_javadoc: JAVADOC;
javadoc: JAVADOC;
suffix_javadoc: JAVADOC;
legacy_constants: LEGACY_CONSTANT*;
config: CONFIG config_body;
config_body: '{' config_option* '}';
config_body: LBRACE config_option* RBRACE;
config_option: option_name option_value;
apis: APIS '{' api* '}';
api: javadoc? (option)* api_type ('(' api_role ')')? api_name api_body;
apis: APIS apis_body;
apis_body: LBRACE api* RBRACE;
api: javadoc? annotations api_type (LPAREN api_role RPAREN)? api_name api_body;
api_type: ASYNCAPI | OPENAPI;
api_role: ID;
api_name: ID;
api_body: '{' api_configs '}';
api_body: LBRACE api_configs RBRACE;
api_configs: (api_config)*;
api_config: option_name option_value;
// values
value: simple | object;
simple: ID | SINGLE_QUOTED_STRING | DOUBLE_QUOTED_STRING | INT | NUMBER | TRUE | FALSE | NULL;
pair: ID ':' value;
object: '{' pair (',' pair)* '}';
array: '['? value (',' value)* ']'?;
pair: ID COLON value;
object: LBRACE pair (COMMA pair)* RBRACE;
array: LBRACK? value (COMMA value)* RBRACK?;
// @options
option: reserved_option ('(' option_value ')')? | '@' option_name ('(' option_value ')')?;
reserved_option: CONFIG_OPTION | APIS_OPTION | OPENAPI_OPTION | ASYNCAPI_OPTION | ENTITY_OPTION | SERVICE_OPTION | INPUT_OPTION | OUTPUT_OPTION | EVENT_OPTION | RELATIONSHIP_OPTION | ENUM_OPTION | PAGINATED_OPTION;
annotations: option*;
option: reserved_option (LPAREN option_value RPAREN)? | '@' option_name (LPAREN option_value RPAREN)?;
//reserved_option: CONFIG_OPTION | APIS_OPTION | OPENAPI_OPTION | ASYNCAPI_OPTION | ENTITY_OPTION | SERVICE_OPTION | INPUT_OPTION | OUTPUT_OPTION | EVENT_OPTION | RELATIONSHIP_OPTION | ENUM_OPTION | PAGINATED_OPTION;
reserved_option: RESERVED_OPTIONS;
option_name: ID;
option_value: value | array | object;
// entities
entity: javadoc? (option)* ENTITY entity_name entity_table_name? entity_body;
entity: javadoc? annotations ENTITY entity_definition entity_body;
entity_definition: entity_name entity_table_name?;
entity_name: ID;
entity_table_name: '(' ID ')';
entity_body: '{' fields '}';
entity_table_name: LPAREN ID RPAREN;
entity_body: LBRACE fields RBRACE;
fields: (field FIELD_SEPARATOR?)*;
field: javadoc? (option)* field_name field_type entity_table_name? (field_validations)* suffix_javadoc? (nested_field)?;
nested_field: '{' (field)* '}' nested_field_validations*;
fields: (field COMMA?)*;
field: javadoc? annotations field_name field_type entity_table_name? (field_validations)* suffix_javadoc? (nested_field)?;
nested_field: LBRACE (field)* RBRACE nested_field_validations*;
field_name: ID;
field_type: ID | ID ARRAY;
//field_validations: REQUIRED | UNIQUE | min_validation | max_validation | minlength_validation | maxlength_validation | pattern_validation;
field_validations: field_validation_name ('(' field_validation_value ')')?;
field_validations: field_validation_name (LPAREN field_validation_value RPAREN)?;
field_validation_name: REQUIRED | UNIQUE | MIN | MAX | MINLENGTH | MAXLENGTH | PATTERN;
field_validation_value: INT | ID | PATTERN_REGEX;
nested_field_validations: nested_field_validation_name ('(' nested_field_validation_value ')')?;
nested_field_validations: nested_field_validation_name (LPAREN nested_field_validation_value RPAREN)?;
nested_field_validation_name: REQUIRED | UNIQUE;
nested_field_validation_value: INT | ID | PATTERN_REGEX;
// enums
enum: javadoc? (option)* ENUM enum_name enum_body;
enum: javadoc? annotations ENUM enum_name enum_body;
enum_name: ID;
enum_body: '{' (enum_value FIELD_SEPARATOR?)* '}';
enum_value: javadoc? enum_value_name ('(' enum_value_value ')')? suffix_javadoc?;
enum_body: LBRACE (enum_value)* RBRACE;
enum_value: javadoc? enum_value_name (LPAREN enum_value_value RPAREN)? suffix_javadoc? COMMA?;
enum_value_name: ID;
enum_value_value: value;
// inputs
input: javadoc? (option)* INPUT input_name '{' fields '}';
input: javadoc? annotations INPUT input_name LBRACE fields RBRACE;
input_name: ID;
// outputs
output: javadoc? (option)* OUTPUT output_name '{' fields '}';
output: javadoc? annotations OUTPUT output_name LBRACE fields RBRACE;
output_name: ID;
// events
event: javadoc? (option)* EVENT event_name ('(' event_channel ')')? '{' fields '}';
event: javadoc? annotations EVENT event_name (LPAREN event_channel RPAREN)? LBRACE fields RBRACE;
event_name: ID;
event_channel: ID;
// relationships
relationships: RELATIONSHIP relationship_type '{' relationship* '}';
relationships: RELATIONSHIP relationship_type LBRACE relationship* RBRACE;
relationship_type: MANY_TO_MANY | MANY_TO_ONE| ONE_TO_MANY | ONE_TO_ONE;
relationship: relationship_from 'to'relationship_to;
relationship_from: relationship_javadoc? relationship_options relationship_definition;
relationship_to: relationship_javadoc? relationship_options relationship_definition;
relationship_javadoc: JAVADOC?;
relationship_options: (option)*;
relationship_definition: relationship_entity_name ('{' relationship_field_name relationship_description_field? '}')?;
relationship: relationship_from 'to' relationship_to;
relationship_from: javadoc? annotations relationship_definition;
relationship_to: javadoc? annotations relationship_definition;
relationship_definition: relationship_entity_name (LBRACE relationship_field_name relationship_description_field? RBRACE)?;
relationship_entity_name: ID;
relationship_field_name: ID;
relationship_description_field: '(' ID ')';
relationship_description_field: LPAREN ID RPAREN;
// services
service: javadoc? (option)* SERVICE ID FOR '(' service_aggregates ')' '{' service_method* '}';
service_aggregates: ID (',' ID)*;
service_method: javadoc? (option)* service_method_name '(' service_method_parameter_id? ','? service_method_parameter? ')' service_method_return? service_method_with_events? suffix_javadoc?;
service: javadoc? annotations SERVICE ID FOR LPAREN service_aggregates RPAREN LBRACE service_method* RBRACE;
service_aggregates: ID (COMMA ID)*;
service_method: javadoc? annotations service_method_name LPAREN service_method_parameter_id? COMMA? service_method_parameter? RPAREN service_method_return? service_method_with_events? suffix_javadoc?;
service_method_name: ID;
service_method_parameter_id: 'id';
service_method_parameter: ID;
service_method_return: ID | ID ARRAY;
service_method_with_events: WITH_EVENTS (service_method_events)*;
service_method_events: service_method_event | service_method_events_or;
service_method_event: ID;
service_method_events_or: '(' ID ('|' ID)* ')' | '[' ID ('|' ID)* ']';
service_method_events_or: LPAREN ID (OR ID)* RPAREN | LBRACK ID (OR ID)* RBRACK;
service_legacy: SERVICE service_aggregates 'with' ID;
Expand Down
19 changes: 10 additions & 9 deletions src/main/java/io/github/zenwave360/zdl/antlr/ZdlListenerImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public void enterGlobal_javadoc(io.github.zenwave360.zdl.antlr.ZdlParser.Global_

@Override
public void enterLegacy_constants(io.github.zenwave360.zdl.antlr.ZdlParser.Legacy_constantsContext ctx) {
ctx.LEGACY_CONSTANT().stream().map(TerminalNode::getText).map(c -> c.split("=")).forEach(c -> model.appendTo("constants", c[0], c[1]));
ctx.LEGACY_CONSTANT().stream().map(TerminalNode::getText).map(c -> c.split(" *= *")).forEach(c -> model.appendTo("constants", c[0], c[1]));
}

@Override
Expand Down Expand Up @@ -94,17 +94,18 @@ public void exitApi(io.github.zenwave360.zdl.antlr.ZdlParser.ApiContext ctx) {

@Override
public void enterEntity(io.github.zenwave360.zdl.antlr.ZdlParser.EntityContext ctx) {
var name = ctx.entity_name().getText();
var entity = ctx.entity_definition();
var name = entity.entity_name().getText();
var javadoc = getText(ctx.javadoc());
var tableName = ctx.entity_table_name() != null? ctx.entity_table_name().ID().getText() : null;
var tableName = entity.entity_table_name() != null? entity.entity_table_name().ID().getText() : null;
currentStack.push(processEntity(name, javadoc, tableName).with("type", "entity"));
model.appendTo("entities", name, currentStack.peek());
currentCollection = "entities";

var entityLocation = currentCollection + "." + name;
model.setLocation(entityLocation, getLocations(ctx));
model.setLocation(entityLocation + ".name", getLocations(ctx.entity_name()));
model.setLocation(entityLocation + ".tableName", getLocations(ctx.entity_table_name()));
model.setLocation(entityLocation + ".name", getLocations(entity.entity_name()));
model.setLocation(entityLocation + ".tableName", getLocations(entity.entity_table_name()));
model.setLocation(entityLocation + ".body", getLocations(ctx.entity_body()));
}

Expand Down Expand Up @@ -263,13 +264,13 @@ public void enterRelationship(io.github.zenwave360.zdl.antlr.ZdlParser.Relations

var from = getText(ctx.relationship_from().relationship_definition().relationship_entity_name());
var fromField = getText(ctx.relationship_from().relationship_definition().relationship_field_name());
var commentInFrom = getText(ctx.relationship_from().relationship_javadoc());
var fromOptions = relationshipOptions(ctx.relationship_from().relationship_options().option());
var commentInFrom = getText(ctx.relationship_from().javadoc());
var fromOptions = relationshipOptions(ctx.relationship_from().annotations().option());

var to = getText(ctx.relationship_to().relationship_definition().relationship_entity_name());
var toField = getText(ctx.relationship_to().relationship_definition().relationship_field_name());
var commentInTo = getText(ctx.relationship_to().relationship_javadoc());
var toOptions = relationshipOptions(ctx.relationship_to().relationship_options().option());
var commentInTo = getText(ctx.relationship_to().javadoc());
var toOptions = relationshipOptions(ctx.relationship_to().annotations().option());

var relationship = new FluentMap()
.with("type", relationshipType)
Expand Down
7 changes: 4 additions & 3 deletions src/test/resources/simple.zdl
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
* Global javadoc comment
*/

MAX_LENGTH=100
MIN_LENGTH=100
MAX_LENGTH = 100

config {
basePackage "io.zenwave360.example"
Expand Down Expand Up @@ -43,8 +44,8 @@ enum OrderStatus {
/** order completed */
COMPLETED("3")
/**
* order cancelled
*/
* order cancelled
*/
CANCELLED('4')
}

Expand Down

0 comments on commit 2a453d2

Please sign in to comment.