/* * * This the grammar we use to generate the parser jhGrammar.js. * We use the online tool http://pegjs.org/online to generate the parser. * Modifying this file won't affect the program, this is just to have a more readable grammar. */ { function concat(array1, array2){ if (array2) { for (var i = 0; i < array2.length; i++) { if (array1.indexOf(array2[i]) === -1) { array1.push(array2[i]); } } } return array1; } function flattenArray(array) { var newArray = []; array.forEach(function(element) { if (!element.length) { newArray.push(element); } else { element.forEach(function(internalElement) { newArray.push(internalElement); }); } }); return newArray; } function makeString(o) { return o.join(""); } function addCardinalityToRelationships(cardinality, relationships) { if (!relationships) { return; } relationships.forEach(function(relationship) { relationship.cardinality = cardinality; }); } var entities = []; var relationships = []; var enums = []; var dto = {}; var pagination = {}; var service = {}; var microservice = {}; var searchEngine = {}; var noClient = { list: [], excluded: [] }; var noServer = { list: [], excluded: [] }; var angularSuffixes = {}; } start = p:prog { return p; } prog = space* ed:entityDecl space* p:prog {return {"entities" : concat([ed],p.entities) , "relationships" : p.relationships, "enums" : p.enums, "dto": p.dto, "pagination": p.pagination, "service": service, "microservice": microservice, "searchEngine": searchEngine, "noClient": noClient, "noServer": noServer, "angularSuffixes": angularSuffixes};} / space* rd:relationDecl space* p:prog {return {"entities" : p.entities, "relationships" : flattenArray(concat([rd],p.relationships)), "enums" : p.enums, "dto": p.dto, "pagination": p.pagination, "service": service, "microservice": microservice, "searchEngine": searchEngine, "noClient": noClient, "noServer": noServer, "angularSuffixes": angularSuffixes};} / space* end:enumDecl space* p:prog {return {"entities" : p.entities, "relationships" : p.relationships, "enums": concat([end], p.enums), "dto": p.dto, "pagination": p.pagination, "service": service, "microservice": microservice, "searchEngine": searchEngine, "noClient": noClient, "noServer": noServer, "angularSuffixes": angularSuffixes};} / space* dto:dtoDecl space* p:prog {return {"entities": p.entities, "relationships": p.relationships, "enums": p.enums, "dto": p.dto, "pagination": p.pagination, "service": service, "microservice": microservice, "searchEngine": searchEngine, "noClient": noClient, "noServer": noServer, "angularSuffixes": angularSuffixes};} / space* pagination:pagiDecl space* p:prog {return {"entities" : p.entities, "relationships" : p.relationships, "enums": p.enums, "dto": p.dto, "pagination": p.pagination, "service": service, "microservice": microservice, "searchEngine": searchEngine, "noClient": noClient, "noServer": noServer, "angularSuffixes": angularSuffixes};} / space* service:serviceDecl space* p:prog {return {"entities" : p.entities, "relationships" : p.relationships, "enums": p.enums, "dto": p.dto, "pagination": p.pagination, "service": service, "microservice": microservice, "searchEngine": searchEngine, "noClient": noClient, "noServer": noServer, "angularSuffixes": angularSuffixes};} / space* Comment space* p:prog {return {"entities" : p.entities,"relationships": p.relationships, "enums": p.enums, "dto": p.dto, "pagination": p.pagination, "service": service, "microservice": microservice, "searchEngine": searchEngine, "noClient": noClient, "noServer": noServer, "angularSuffixes": angularSuffixes};} / space* JDLComment space* p:prog {return {"entities" : p.entities,"relationships": p.relationships, "enums": p.enums, "dto": p.dto, "pagination": p.pagination, "service": service, "microservice": microservice, "searchEngine": searchEngine, "noClient": noClient, "noServer": noServer, "angularSuffixes": angularSuffixes};} / space* microservice:microserviceDecl1 space* p:prog {return {"entities" : p.entities, "relationships" : p.relationships, "enums": p.enums, "dto": p.dto, "pagination": p.pagination, "service": service, "microservice": microservice, "searchEngine": searchEngine, "noClient": noClient, "noServer": noServer, "angularSuffixes": angularSuffixes};} / space* searchEngine:searchEngineDecl space* p:prog {return {"entities" : p.entities, "relationships" : p.relationships, "enums": p.enums, "dto": p.dto, "pagination": p.pagination, "service": service, "microservice": microservice, "searchEngine": searchEngine, "noClient": noClient, "noServer": noServer, "angularSuffixes": angularSuffixes};} / space* noClient:noClientDecl space* p:prog {return {"entities" : p.entities, "relationships" : p.relationships, "enums": p.enums, "dto": p.dto, "pagination": p.pagination, "service": service, "microservice": microservice, "searchEngine": searchEngine, "noClient": noClient, "noServer": noServer, "angularSuffixes": angularSuffixes};} / space* noServer:noServerDecl space* p:prog {return {"entities" : p.entities, "relationships" : p.relationships, "enums": p.enums, "dto": p.dto, "pagination": p.pagination, "service": service, "microservice": microservice, "searchEngine": searchEngine, "noClient": noClient, "noServer": noServer, "angularSuffixes": angularSuffixes};} / space* angularSuffixes:angularSuffixDecl space* p:prog {return {"entities" : p.entities, "relationships" : p.relationships, "enums": p.enums, "dto": p.dto, "pagination": p.pagination, "service": service, "microservice": microservice, "searchEngine": searchEngine, "noClient": noClient, "noServer": noServer, "angularSuffixes": angularSuffixes};} / "" {return {"entities" : entities,"relationships": relationships, "enums": enums, "dto": dto, "pagination": pagination, "service": service, "microservice": microservice, "searchEngine": searchEngine, "noClient": noClient, "noServer": noServer, "angularSuffixes": angularSuffixes};} //Entities entityDecl = jd:Comment? space* JDLComment? space* "entity" space* e:ENTITYNAME space* tableName:entityTableNameDecl? space* eb:entityBody? space* JDLComment? {return {"name" : e, tableName: tableName ? tableName : e, "body":eb, "javadoc":jd};} / "entity" space* e:ENTITYNAME space* eb:entityBody? {return {"name" : e, "body":eb, "javadoc":""};} entityTableNameDecl = '(' space* name:[A-z0..9_-]+ space* ')' {return name.join('');} entityBody = "{" space* JDLComment? space* fdl:fieldDeclList space* JDLComment? space* "}" {return fdl;} / "" {return [];} fieldDeclList = JDLComment? space* com:Comment? space* JDLComment? space* f:FIELDNAME space t:type space* vl:validationList? space* ","? space* JDLComment? space* fdl:fieldDeclList {return concat([{"name" : f, "type" : t, "validations" : vl, "javadoc": com}], fdl );} / com:Comment? space* f:FIELDNAME space t:type space* vl:validationList {return [{"name" : f, "type" : t, "validations" : vl, "javadoc": com}];} / "" {return [];} validationList = v:validation space* vl:validationList {return concat([v], vl);} / "" {return [];} //Relationship relationDecl = 'relationship' space rt:relationshipType space* "{" space* JDLComment? space* rb:relationshipBody space* subrb:subRelationshipBodies? "}" {rb.cardinality = rt; addCardinalityToRelationships(rt, subrb); return concat([rb], subrb);} subRelationshipBodies = ','? space* rb:relationshipBody space* morerb:subRelationshipBodies? { return concat([rb], morerb); } / ','? space* rb:relationshipBody { return rb; } relationshipBody = from:relationshipSide space* JDLComment? space* "to" space* JDLComment? space* to:relationshipSide space* JDLComment? {return {"from" : from , "to" : to};} relationshipSide = jd:Comment? space* e:ENTITYNAME space* "{" space* i:INJECTEDFIELDNAME space* "}" space* {return {"name" :e, "injectedfield" : i, "javadoc": jd};} / jd:Comment? space* e:ENTITYNAME space* ("{" space* "}")? space* {return {"name" :e, "injectedfield" : null, "javadoc": jd};} / e:ENTITYNAME space {return {"name" :e, "injectedfield" : null, "javadoc": ''};} //Enum enumDecl = 'enum' space e:ENUMNAME space* '{' space* JDLComment? space* el:enumPropList space* JDLComment? space* '}' {return {"name":e, "values" : el };} enumPropList = e:ENUMPROP space* ',' space* JDLComment? space* el:enumPropList {return concat([e],el);} / e:ENUMPROP {return [e];} exclusion = 'except' space+ sub:exclusionSub {return sub;} exclusionSub = e:ENTITYNAME space* ',' space* sub:exclusionSub {return concat([e], sub);} / e:ENTITYNAME {return [e];} // DTO dtoDecl = 'dto' space+ decl:entityList space* ex:exclusion? space* JDLComment? { dto[decl[decl.length - 1]] = dto[decl[decl.length - 1]] || { list: [], excluded: [] }; concat(dto[decl[decl.length - 1]].list, decl.slice(0, decl.length - 1)); if (ex) { concat(dto[decl[decl.length - 1]].excluded, ex); } } // Pagination pagiDecl = 'paginate' space+ decl:entityList space* ex:exclusion? space* JDLComment? { pagination[decl[decl.length - 1]] = pagination[decl[decl.length - 1]] || { list: [], excluded: [] }; concat(pagination[decl[decl.length - 1]].list, decl.slice(0, decl.length - 1)); if (ex) { concat(pagination[decl[decl.length - 1]].excluded, ex); } } // Service serviceDecl = 'service' space+ decl:entityList space* ex:exclusion? space* JDLComment? { service[decl[decl.length - 1]] = service[decl[decl.length - 1]] || { list: [], excluded: [] }; concat(service[decl[decl.length - 1]].list, decl.slice(0, decl.length - 1)); if (ex) { concat(service[decl[decl.length - 1]].excluded, ex); } } // first way of declaring microservices microserviceDecl1 = 'microservice' space+ decl:entityList space* ex:exclusion? space* JDLComment? { microservice[decl[decl.length - 1]] = microservice[decl[decl.length - 1]] || { list: [], excluded: [] }; concat(microservice[decl[decl.length - 1]].list, decl.slice(0, decl.length - 1)); if (ex) { concat(microservice[decl[decl.length - 1]].excluded, ex); } } // searchEngine searchEngineDecl = 'search' space+ decl:entityList space* ex:exclusion? space* JDLComment? { searchEngine[decl[decl.length - 1]] = searchEngine[decl[decl.length - 1]] || { list: [], excluded: [] }; concat(searchEngine[decl[decl.length - 1]].list, decl.slice(0, decl.length - 1)); if (ex) { concat(searchEngine[decl[decl.length - 1]].excluded, ex); } } // skipClient option noClientDecl = 'skipClient for' space* decl:subNoClientDecl space* ex:exclusion? space* JDLComment? { concat(noClient.list, decl); if (ex) { concat(noClient.excluded, ex); } } subNoClientDecl = e:ENTITYNAME space* ',' space* sub:subNoClientDecl {return concat([e], sub);} / '*' {return ['*'];} / 'all'{return ['*'];} / e:ENTITYNAME {return [e];} // skipServer option noServerDecl = 'skipServer for' space* decl:subNoServerDecl space* ex:exclusion? space* JDLComment? { concat(noServer.list, decl); if (ex) { concat(noServer.excluded, ex); } } subNoServerDecl = e:ENTITYNAME space* ',' space* sub:subNoServerDecl {return concat([e], sub);} / '*' {return ['*'];} / 'all'{return ['*'];} / e:ENTITYNAME {return [e];} // angularSuffix option angularSuffixDecl = 'angularSuffix' space* decl:entityList space* ex:exclusion? space* JDLComment? { angularSuffixes[decl[decl.length - 1]] = angularSuffixes[decl[decl.length - 1]] || { list: [], excluded: [] }; concat(angularSuffixes[decl[decl.length - 1]].list, decl.slice(0, decl.length - 1)); if (ex) { concat(angularSuffixes[decl[decl.length - 1]].excluded, ex); } } // common way to declare an entity list entityList = e:ENTITYNAME space* ',' space* sub:entityList {return concat([e], sub);} / '*' space* 'with' space* method:([A-z0-9-]+) {return ['*', method.toString().replace(/,/g,'')];} / 'all' space* 'with' space* method:([A-z0-9-]+) {return ['*', method.toString().replace(/,/g,'')];} / e:ENTITYNAME space* 'with' space* method:([A-z0-9-]+) {return [e, method.toString().replace(/,/g,'')];} relationshipType = "OneToOne" {return "one-to-one";} / "OneToMany" {return "one-to-many";} / "ManyToOne" {return "many-to-one";} / "ManyToMany" {return "many-to-many";} type "a type" = head:[A-Z]tail:[a-zA-Z0-9]* {return head + tail.join('');} validation = "required" {return {key:'required', value:''};} / "minlength" space* "(" space* int:INTEGER space* ")" {return {key:'minlength', value:int};} / "maxlength" space* "(" space* int:INTEGER space* ")" {return {key:'maxlength', value:int};} / "minbytes" space* "(" space* int:INTEGER space* ")" {return {key:'minlength', value:int};} / "maxbytes" space* "(" space* int:INTEGER space* ")" {return {key:'maxlength', value:int};} / "max" space* "(" space* int:INTEGER space* ")" {return {key:'max', value:int};} / "min" space* "(" space* int:INTEGER space* ")" {return {key:'min', value:int};} / "pattern" space* "(" apostrophe regexp:REGEXP apostrophe space* ")" {return {key:'pattern' , value:regexp};} apostrophe "apostrophe" = a:["|'] REGEXP "a regular expression" = word:[a-zA-Z0-9!@#$%^&*()_+\-=\[\]{};':\\|,.<>\/? ]* {return makeString(word);} ENUMNAME "an enum name" = head:[A-Z]tail:[a-zA-Z0-9]* {return head + tail.join('');} ENUMPROP "an enum property" = underscore:[_]*head:[A-Z0-9]tail:[A-Z0-9_]* { return underscore.join('') + head + tail.join(''); } INTEGER "integer" = int:[0-9]+ {return parseInt(int.join(""), 10);} INJECTEDFIELDNAME "an injected field" = head:[a-zA-Z]tail:[a-zA-Z0-9()]* {return head + tail.join('');} ENTITYNAME "an entity name" = head:[A-Z]tail:[a-zA-Z0-9]* {return head + tail.join('');} FIELDNAME "a field name" = head:[a-zA-Z]tail:[a-zA-Z0-9]* {return head + tail.join('');} space "a space" = space:['\n'|'\t'|'\r'|' '|\u2028|\u2029]+ /****************** COMMENT ***********************/ Comment = ComStart nc:Not_Com* ComStop {return makeString(nc);} ComStart = "/*" [*]* ComStop = [*]+ "/" // a completely ignored comment, will not be a Javadoc comment JDLComment = "//" [^\n\r]* Not_Com = (!ComStop !ComStart char:.) {return char;}