gen-jhipster
Version:
VHipster - Spring Boot + Angular/React/Vue in one handy generator
609 lines (608 loc) • 22.3 kB
JavaScript
import { CstParser } from 'chevrotain';
import { NAME } from "./lexer/shared-tokens.js";
// Chevrotain actually returns a CstNode instead of this noopCst
const noopCst = undefined;
export default class JDLParser extends CstParser {
tokens;
constructor(tokens) {
super(tokens, { outputCst: true });
this.tokens = tokens;
}
parse() {
this.prog();
this.constantDeclaration();
this.entityDeclaration();
this.annotationDeclaration();
this.entityTableNameDeclaration();
this.entityBody();
this.fieldDeclaration();
this.type();
this.validation();
this.minMaxValidation();
this.pattern();
this.relationDeclaration();
this.relationshipType();
this.relationshipBody();
this.relationshipSide();
this.relationshipOptions();
this.relationshipOption();
this.enumDeclaration();
this.enumPropList();
this.enumProp();
this.entityList();
this.exclusion();
this.useOptionDeclaration();
this.unaryOptionDeclaration();
this.binaryOptionDeclaration();
this.filterDef();
this.comment();
this.deploymentDeclaration();
this.deploymentConfigDeclaration();
this.deploymentConfigValue();
this.applicationDeclaration();
this.applicationSubDeclaration();
this.applicationSubConfig();
this.applicationSubNamespaceConfig();
this.applicationSubEntities();
this.applicationConfigDeclaration();
this.configValue();
this.applicationNamespaceConfigDeclaration();
this.namespaceConfigValue();
this.qualifiedName();
this.quotedList();
this.list();
// very important to call this after all the rules have been defined.
// otherwise the parsers may not work correctly as it will lack information
// derived during the self analysis phase.
this.performSelfAnalysis();
}
prog() {
this.RULE('prog', () => {
this.MANY(() => {
this.OR([
{ ALT: () => this.SUBRULE(this.entityDeclaration) },
{ ALT: () => this.SUBRULE(this.relationDeclaration) },
{ ALT: () => this.SUBRULE(this.enumDeclaration) },
{ ALT: () => this.CONSUME(this.tokens.JAVADOC) },
{ ALT: () => this.SUBRULE(this.useOptionDeclaration) },
{ ALT: () => this.SUBRULE(this.unaryOptionDeclaration) },
{ ALT: () => this.SUBRULE(this.binaryOptionDeclaration) },
{ ALT: () => this.SUBRULE(this.applicationDeclaration) },
{ ALT: () => this.SUBRULE(this.deploymentDeclaration) },
// a constantDeclaration starts with a NAME, but any keyword is also a NAME
// So to avoid conflicts with most of the above alternatives (which start with keywords)
// this alternative must be last.
{
// - A Constant starts with a NAME
// - NAME tokens are very common
// That is why a more precise lookahead condition is used (The GATE)
// To avoid confusing errors ("expecting EQUALS but found ...")
GATE: () => this.LA(2).tokenType === this.tokens.EQUALS,
ALT: () => this.SUBRULE(this.constantDeclaration),
},
]);
});
});
return noopCst;
}
constantDeclaration() {
this.RULE('constantDeclaration', () => {
this.CONSUME(this.tokens.NAME);
this.CONSUME(this.tokens.EQUALS);
this.OR([{ ALT: () => this.CONSUME(this.tokens.DECIMAL) }, { ALT: () => this.CONSUME(this.tokens.INTEGER) }]);
});
return noopCst;
}
entityDeclaration() {
this.RULE('entityDeclaration', () => {
this.OPTION(() => {
this.CONSUME(this.tokens.JAVADOC);
});
this.MANY(() => {
this.SUBRULE(this.annotationDeclaration);
});
this.CONSUME(this.tokens.ENTITY);
this.CONSUME(this.tokens.NAME);
this.OPTION1(() => {
this.SUBRULE(this.entityTableNameDeclaration);
});
this.OPTION2(() => {
this.SUBRULE(this.entityBody);
});
});
return noopCst;
}
annotationDeclaration() {
this.RULE('annotationDeclaration', () => {
this.CONSUME(this.tokens.AT);
this.CONSUME(this.tokens.NAME, { LABEL: 'option' });
this.OPTION(() => {
this.CONSUME(this.tokens.LPAREN);
this.OR({
IGNORE_AMBIGUITIES: true,
DEF: [
{ ALT: () => this.CONSUME(this.tokens.STRING, { LABEL: 'value' }) },
{ ALT: () => this.CONSUME(this.tokens.INTEGER, { LABEL: 'value' }) },
{ ALT: () => this.CONSUME(this.tokens.DECIMAL, { LABEL: 'value' }) },
{ ALT: () => this.CONSUME(this.tokens.TRUE, { LABEL: 'value' }) },
{ ALT: () => this.CONSUME(this.tokens.FALSE, { LABEL: 'value' }) },
{ ALT: () => this.CONSUME2(this.tokens.NAME, { LABEL: 'value' }) },
],
});
this.CONSUME(this.tokens.RPAREN);
});
});
return noopCst;
}
entityTableNameDeclaration() {
this.RULE('entityTableNameDeclaration', () => {
this.CONSUME(this.tokens.LPAREN);
this.CONSUME(this.tokens.NAME);
this.CONSUME(this.tokens.RPAREN);
});
return noopCst;
}
entityBody() {
this.RULE('entityBody', () => {
this.CONSUME(this.tokens.LCURLY);
this.MANY(() => {
this.SUBRULE(this.fieldDeclaration);
this.OPTION(() => {
this.CONSUME(this.tokens.COMMA);
});
});
this.CONSUME(this.tokens.RCURLY);
});
return noopCst;
}
fieldDeclaration() {
this.RULE('fieldDeclaration', () => {
this.OPTION(() => {
this.CONSUME(this.tokens.JAVADOC);
});
this.MANY(() => {
this.SUBRULE(this.annotationDeclaration);
});
this.CONSUME(this.tokens.NAME);
this.SUBRULE(this.type);
this.MANY1(() => {
this.SUBRULE(this.validation);
});
this.OPTION2({
GATE: () => {
const prevTok = this.LA(0);
const nextTok = this.LA(1);
// simulate "SPACE_WITHOUT_NEWLINE" of the PEG parsers
return prevTok.startLine === nextTok.startLine;
},
DEF: () => {
this.CONSUME2(this.tokens.JAVADOC);
},
});
});
return noopCst;
}
type() {
this.RULE('type', () => {
this.CONSUME(this.tokens.NAME);
});
return noopCst;
}
validation() {
this.RULE('validation', () => {
this.OR([
{ ALT: () => this.CONSUME(this.tokens.REQUIRED) },
{ ALT: () => this.CONSUME(this.tokens.UNIQUE) },
{ ALT: () => this.SUBRULE(this.minMaxValidation) },
{ ALT: () => this.SUBRULE(this.pattern) },
]);
});
return noopCst;
}
minMaxValidation() {
this.RULE('minMaxValidation', () => {
// Note that "MIN_MAX_KEYWORD" is an abstract token and could match 6 different concrete token types
this.CONSUME(this.tokens.MIN_MAX_KEYWORD);
this.CONSUME(this.tokens.LPAREN);
this.OR([
{ ALT: () => this.CONSUME(this.tokens.DECIMAL) },
{ ALT: () => this.CONSUME(this.tokens.INTEGER) },
{ ALT: () => this.CONSUME(this.tokens.NAME) },
]);
this.CONSUME(this.tokens.RPAREN);
});
return noopCst;
}
pattern() {
this.RULE('pattern', () => {
this.CONSUME(this.tokens.PATTERN);
this.CONSUME(this.tokens.LPAREN);
this.CONSUME(this.tokens.REGEX);
this.CONSUME(this.tokens.RPAREN);
});
return noopCst;
}
relationDeclaration() {
this.RULE('relationDeclaration', () => {
this.CONSUME(this.tokens.RELATIONSHIP);
this.SUBRULE(this.relationshipType);
this.CONSUME(this.tokens.LCURLY);
this.AT_LEAST_ONE(() => {
this.SUBRULE(this.relationshipBody);
this.OPTION(() => {
this.CONSUME(this.tokens.COMMA);
});
});
this.CONSUME(this.tokens.RCURLY);
});
return noopCst;
}
relationshipType() {
this.RULE('relationshipType', () => {
this.CONSUME(this.tokens.RELATIONSHIP_TYPE);
});
return noopCst;
}
relationshipBody() {
this.RULE('relationshipBody', () => {
this.MANY1(() => {
this.SUBRULE1(this.annotationDeclaration, { LABEL: 'annotationOnSourceSide' });
});
this.SUBRULE1(this.relationshipSide, { LABEL: 'from' });
this.CONSUME(this.tokens.TO);
this.MANY2(() => {
this.SUBRULE2(this.annotationDeclaration, { LABEL: 'annotationOnDestinationSide' });
});
this.SUBRULE2(this.relationshipSide, { LABEL: 'to' });
this.OPTION(() => {
this.CONSUME(this.tokens.WITH);
this.SUBRULE3(this.relationshipOptions, { LABEL: 'relationshipOptions' });
});
});
return noopCst;
}
relationshipSide() {
this.RULE('relationshipSide', () => {
this.SUBRULE(this.comment);
this.CONSUME(this.tokens.NAME);
this.OPTION(() => {
this.CONSUME(this.tokens.LCURLY);
this.CONSUME2(this.tokens.NAME, { LABEL: 'injectedField' });
this.OPTION1(() => {
this.CONSUME(this.tokens.LPAREN);
this.CONSUME3(this.tokens.NAME, { LABEL: 'injectedFieldParam' });
this.CONSUME(this.tokens.RPAREN);
});
this.OPTION2(() => {
this.CONSUME(this.tokens.REQUIRED);
});
this.CONSUME(this.tokens.RCURLY);
});
});
return noopCst;
}
relationshipOptions() {
this.RULE('relationshipOptions', () => {
this.AT_LEAST_ONE_SEP({
SEP: this.tokens.COMMA_WITHOUT_NEWLINE,
DEF: () => {
this.SUBRULE(this.relationshipOption, { LABEL: 'relationshipOption' });
},
});
});
return noopCst;
}
relationshipOption() {
this.RULE('relationshipOption', () => {
this.OR([{ ALT: () => this.CONSUME(this.tokens.BUILT_IN_ENTITY) }]);
});
return noopCst;
}
enumDeclaration() {
this.RULE('enumDeclaration', () => {
this.OPTION(() => {
this.CONSUME(this.tokens.JAVADOC);
});
this.CONSUME(this.tokens.ENUM);
this.CONSUME(this.tokens.NAME);
this.CONSUME(this.tokens.LCURLY);
this.SUBRULE(this.enumPropList);
this.CONSUME(this.tokens.RCURLY);
});
return noopCst;
}
enumPropList() {
this.RULE('enumPropList', () => {
this.SUBRULE(this.enumProp);
this.MANY(() => {
this.OPTION(() => {
this.CONSUME(this.tokens.COMMA);
});
this.SUBRULE1(this.enumProp);
});
});
return noopCst;
}
enumProp() {
this.RULE('enumProp', () => {
this.OPTION(() => {
this.CONSUME(this.tokens.JAVADOC);
});
this.CONSUME(this.tokens.NAME, { LABEL: 'enumPropKey' });
this.OPTION1(() => {
this.CONSUME(this.tokens.LPAREN);
this.OR([
{ ALT: () => this.CONSUME2(this.tokens.STRING, { LABEL: 'enumPropValueWithQuotes' }) },
{ ALT: () => this.CONSUME3(this.tokens.NAME, { LABEL: 'enumPropValue' }) },
]);
this.CONSUME(this.tokens.RPAREN);
});
this.OPTION2(() => {
this.CONSUME1(this.tokens.JAVADOC);
});
});
return noopCst;
}
entityList() {
this.RULE('entityList', () => {
this.commonEntityList();
this.CONSUME(this.tokens.WITH);
this.OR1([
{ ALT: () => this.CONSUME2(this.tokens.NAME, { LABEL: 'method' }) },
{ ALT: () => this.CONSUME3(this.tokens.STRING, { LABEL: 'methodPath' }) },
]);
});
return noopCst;
}
commonEntityList() {
this.MANY({
// the next section may contain [NAME, WITH], LA(2) check is used to resolve this.
GATE: () => this.LA(2).tokenType === this.tokens.COMMA,
DEF: () => {
this.CONSUME(this.tokens.NAME);
this.CONSUME(this.tokens.COMMA);
},
});
this.OR([{ ALT: () => this.CONSUME(this.tokens.STAR) }, { ALT: () => this.CONSUME1(this.tokens.NAME) }]);
return noopCst;
}
exclusion() {
this.RULE('exclusion', () => {
this.CONSUME(this.tokens.EXCEPT);
this.CONSUME(this.tokens.NAME);
this.MANY(() => {
this.CONSUME(this.tokens.COMMA);
this.CONSUME2(this.tokens.NAME);
});
});
return noopCst;
}
useOptionDeclaration() {
this.RULE('useOptionDeclaration', () => {
this.CONSUME(this.tokens.USE);
this.MANY({
GATE: () => this.LA(2).tokenType === this.tokens.COMMA,
DEF: () => {
this.CONSUME(this.tokens.NAME);
this.CONSUME(this.tokens.COMMA);
},
});
this.CONSUME1(this.tokens.NAME);
this.CONSUME(this.tokens.FOR);
this.SUBRULE(this.filterDef);
this.OPTION(() => {
this.SUBRULE(this.exclusion);
});
});
return noopCst;
}
unaryOptionDeclaration() {
this.RULE('unaryOptionDeclaration', () => {
this.CONSUME(this.tokens.UNARY_OPTION);
this.SUBRULE(this.filterDef);
this.OPTION(() => {
this.SUBRULE(this.exclusion);
});
});
return noopCst;
}
binaryOptionDeclaration() {
this.RULE('binaryOptionDeclaration', () => {
this.CONSUME(this.tokens.BINARY_OPTION);
this.SUBRULE(this.entityList);
this.OPTION(() => {
this.SUBRULE(this.exclusion);
});
});
return noopCst;
}
filterDef() {
this.RULE('filterDef', this.commonEntityList);
return noopCst;
}
comment() {
this.RULE('comment', () => {
this.OPTION(() => {
this.CONSUME(this.tokens.JAVADOC);
});
});
return noopCst;
}
deploymentDeclaration() {
this.RULE('deploymentDeclaration', () => {
this.CONSUME(this.tokens.DEPLOYMENT);
this.CONSUME(this.tokens.LCURLY);
this.MANY(() => {
this.OR([{ ALT: () => this.CONSUME(this.tokens.JAVADOC) }, { ALT: () => this.SUBRULE(this.deploymentConfigDeclaration) }]);
});
this.CONSUME(this.tokens.RCURLY);
});
return noopCst;
}
deploymentConfigDeclaration() {
this.RULE('deploymentConfigDeclaration', () => {
this.CONSUME(this.tokens.DEPLOYMENT_KEY);
this.SUBRULE(this.deploymentConfigValue);
this.OPTION(() => {
this.CONSUME(this.tokens.COMMA);
});
});
return noopCst;
}
deploymentConfigValue() {
this.RULE('deploymentConfigValue', () => {
this.OR([
{ ALT: () => this.CONSUME(this.tokens.BOOLEAN) },
{ ALT: () => this.SUBRULE(this.qualifiedName) },
{ ALT: () => this.SUBRULE(this.list) },
{ ALT: () => this.CONSUME(this.tokens.INTEGER) },
{ ALT: () => this.CONSUME(this.tokens.STRING) },
]);
});
return noopCst;
}
applicationDeclaration() {
this.RULE('applicationDeclaration', () => {
this.CONSUME(this.tokens.APPLICATION);
this.CONSUME(this.tokens.LCURLY);
this.SUBRULE(this.applicationSubDeclaration);
this.CONSUME(this.tokens.RCURLY);
});
return noopCst;
}
applicationSubDeclaration() {
this.RULE('applicationSubDeclaration', () => {
this.MANY(() => {
this.OR([
{ ALT: () => this.SUBRULE(this.applicationSubNamespaceConfig) },
{ ALT: () => this.SUBRULE(this.applicationSubConfig) },
{ ALT: () => this.SUBRULE(this.applicationSubEntities) },
{ ALT: () => this.SUBRULE(this.unaryOptionDeclaration) },
{ ALT: () => this.SUBRULE(this.binaryOptionDeclaration) },
{ ALT: () => this.SUBRULE(this.useOptionDeclaration) },
]);
});
});
return noopCst;
}
applicationSubNamespaceConfig() {
this.RULE('applicationSubNamespaceConfig', () => {
this.CONSUME(this.tokens.CONFIG);
this.CONSUME(this.tokens.LPAREN);
this.CONSUME(this.tokens.NAME, { LABEL: 'namespace' });
this.CONSUME(this.tokens.RPAREN);
this.CONSUME(this.tokens.LCURLY);
this.MANY(() => {
this.OR([
{ ALT: () => this.CONSUME(this.tokens.JAVADOC) },
{ ALT: () => this.SUBRULE(this.applicationNamespaceConfigDeclaration) },
]);
});
this.CONSUME(this.tokens.RCURLY);
});
return noopCst;
}
applicationNamespaceConfigDeclaration() {
this.RULE('applicationNamespaceConfigDeclaration', () => {
this.CONSUME(NAME);
this.SUBRULE(this.namespaceConfigValue);
this.OPTION(() => {
this.CONSUME(this.tokens.COMMA);
});
});
return noopCst;
}
namespaceConfigValue() {
this.RULE('namespaceConfigValue', () => {
this.OR([
{ ALT: () => this.CONSUME(this.tokens.BOOLEAN) },
{ ALT: () => this.SUBRULE(this.qualifiedName) },
{ ALT: () => this.SUBRULE(this.list) },
{ ALT: () => this.CONSUME(this.tokens.INTEGER) },
{ ALT: () => this.CONSUME(this.tokens.STRING) },
]);
});
return noopCst;
}
applicationSubConfig() {
this.RULE('applicationSubConfig', () => {
this.CONSUME(this.tokens.CONFIG);
this.CONSUME(this.tokens.LCURLY);
this.MANY(() => {
this.OR([{ ALT: () => this.CONSUME(this.tokens.JAVADOC) }, { ALT: () => this.SUBRULE(this.applicationConfigDeclaration) }]);
});
this.CONSUME(this.tokens.RCURLY);
});
return noopCst;
}
applicationConfigDeclaration() {
this.RULE('applicationConfigDeclaration', () => {
this.CONSUME(this.tokens.CONFIG_KEY);
this.SUBRULE(this.configValue);
this.OPTION(() => {
this.CONSUME(this.tokens.COMMA);
});
});
return noopCst;
}
configValue() {
this.RULE('configValue', () => {
this.OR([
{ ALT: () => this.CONSUME(this.tokens.BOOLEAN) },
{ ALT: () => this.SUBRULE(this.qualifiedName) },
{ ALT: () => this.SUBRULE(this.quotedList) },
{ ALT: () => this.SUBRULE(this.list) },
{ ALT: () => this.CONSUME(this.tokens.INTEGER) },
{ ALT: () => this.CONSUME(this.tokens.STRING) },
]);
});
return noopCst;
}
qualifiedName() {
this.RULE('qualifiedName', () => {
this.AT_LEAST_ONE_SEP({
SEP: this.tokens.DOT,
DEF: () => {
this.CONSUME(this.tokens.NAME);
},
});
});
return noopCst;
}
list() {
this.RULE('list', () => {
this.CONSUME(this.tokens.LSQUARE);
this.MANY_SEP({
SEP: this.tokens.COMMA,
DEF: () => {
this.CONSUME(this.tokens.NAME);
},
});
this.CONSUME(this.tokens.RSQUARE);
});
return noopCst;
}
quotedList() {
this.RULE('quotedList', () => {
this.CONSUME(this.tokens.LSQUARE);
this.AT_LEAST_ONE_SEP({
SEP: this.tokens.COMMA,
DEF: () => {
this.CONSUME(this.tokens.STRING);
},
});
this.CONSUME(this.tokens.RSQUARE);
});
return noopCst;
}
applicationSubEntities() {
this.RULE('applicationSubEntities', () => {
this.CONSUME(this.tokens.ENTITIES);
this.SUBRULE(this.filterDef);
this.OPTION(() => {
this.SUBRULE(this.exclusion);
});
});
return noopCst;
}
}