X-Git-Url: https://git.auder.net/?p=erdiag.git;a=blobdiff_plain;f=parser.js;h=8fc65edc3330eedf29ac02c7d9a9e957ab217a3f;hp=51a05e0815f2b9d60c29b2f104f610d2bab86f9d;hb=c728aeca9ef83bb786ed0c886a2b3dc4faf3dc45;hpb=eabe4071112a744a7be577263013a9bb0e4eb524 diff --git a/parser.js b/parser.js index 51a05e0..8fc65ed 100644 --- a/parser.js +++ b/parser.js @@ -26,7 +26,9 @@ class ErDiags "*": "0,n", "+": "1,n", "?": "0,1", - "1": "1,1" + "1": "1,1", + "?R": "(0,1)", + "1R": "(1,1)", }; } @@ -67,7 +69,7 @@ class ErDiags { case '[': // Entity = { name: { attributes, [weak] } } - let name = lines[start].match(/[^\[\]\s]+/)[0]; + let name = lines[start].match(/[^\[\]"\s]+/)[0]; let entity = { attributes: this.parseAttributes(lines, start+1, end) }; if (lines[start].charAt(1) == '[') entity.weak = true; @@ -79,7 +81,7 @@ class ErDiags case '{': //association // Association = { [name], [attributes], [weak], entities: ArrayOf entity indices } let relationship = { }; - let nameRes = lines[start].match(/[^{}\s]+/); + let nameRes = lines[start].match(/[^{}"\s]+/); if (nameRes !== null) relationship.name = nameRes[0]; if (lines[start].charAt(1) == '{') @@ -102,7 +104,7 @@ class ErDiags field.isKey = true; line = line.slice(1); } - field.name = line.match(/[^()\s]+/)[0]; + field.name = line.match(/[^()"\s]+/)[0]; let parenthesis = line.match(/\((.+)\)/); if (parenthesis !== null) { @@ -136,7 +138,10 @@ class ErDiags return inheritance; } - // Association (parsed here): { entities: ArrayOf entity names + cardinality, [attributes: ArrayOf {name, [isKey], [type], [qualifiers]}] } + // Association (parsed here): { + // entities: ArrayOf entity names + cardinality, + // [attributes: ArrayOf {name, [isKey], [type], [qualifiers]}] + // } parseAssociation(lines, start, end) { let assoce = { }; @@ -192,30 +197,30 @@ class ErDiags mcdDot += 'rankdir="LR";\n'; // Nodes: if (mcdStyle == "compact") - mcdDot += "node [shape=plaintext];\n"; + mcdDot += 'node [shape=plaintext];\n'; _.shuffle(Object.keys(this.entities)).forEach( name => { if (mcdStyle == "bubble") { - mcdDot += name + '[shape=rectangle, label="' + name + '"'; + mcdDot += '"' + name + '" [shape=rectangle, label="' + name + '"'; if (this.entities[name].weak) mcdDot += ', peripheries=2'; mcdDot += '];\n'; if (!!this.entities[name].attributes) { - _.shuffle(this.entities[name].attributes).forEach( a => { + this.entities[name].attributes.forEach( a => { let label = (a.isKey ? '#' : '') + a.name; let attrName = name + '_' + a.name; - mcdDot += attrName + '[shape=ellipse, label="' + label + '"];\n'; + mcdDot += '"' + attrName + '" [shape=ellipse, label="' + label + '"];\n'; if (Math.random() < 0.5) - mcdDot += attrName + ' -- ' + name + ';\n'; + mcdDot += '"' + attrName + '" -- "' + name + '";\n'; else - mcdDot += name + ' -- ' + attrName + ';\n'; + mcdDot += '"' + name + '" -- "' + attrName + '";\n'; }); } } else { - mcdDot += name + '[label=<'; + mcdDot += '"' + name + '" [label=<'; if (this.entities[name].weak) { mcdDot += '' + @@ -238,44 +243,68 @@ class ErDiags } }); // Inheritances: - this.inheritances.forEach( i => { + _.shuffle(this.inheritances).forEach( i => { + // TODO: node shape = triangle fill yellow. See + // https://merise.developpez.com/faq/?page=MCD#CIF-ou-dependance-fonctionnelle-de-A-a-Z + // https://merise.developpez.com/faq/?page=MLD#Comment-transformer-un-MCD-en-MLD + // https://www.developpez.net/forums/d1088964/general-developpement/alm/modelisation/structure-agregation-l-association-d-association/ _.shuffle(i.children).forEach( c => { if (Math.random() < 0.5) - mcdDot += c + ':name -- ' + i.parent; + mcdDot += '"' + c + '":name -- "' + i.parent; else - mcdDot += i.parent + ':name -- ' + c; - mcdDot += ':name [dir="forward", arrowhead="vee", style="dashed"];\n'; + mcdDot += '"' + i.parent + '":name -- "' + c; + mcdDot += '":name [dir="forward", arrowhead="vee", style="dashed"];\n'; }); }); // Relationships: + if (mcdStyle == "compact") + mcdDot += 'node [shape=rectangle, style=rounded];\n'; let assoceCounter = 0; _.shuffle(this.associations).forEach( a => { let name = !!a.name && a.name.length > 0 ? a.name : '_assoce' + assoceCounter++; - mcdDot += name + '[shape="diamond", style="filled", color="lightgrey", label="' + (!!a.name ? a.name : '') + '"'; - if (a.weak) - mcdDot += ', peripheries=2'; - mcdDot += '];\n'; + if (mcdStyle == "bubble") + { + mcdDot += '"' + name + '" [shape="diamond", style="filled", color="lightgrey", label="' + name + '"'; + if (a.weak) + mcdDot += ', peripheries=2'; + mcdDot += '];\n'; + if (!!a.attributes) + { + a.attributes.forEach( attr => { + let label = (attr.isKey ? '#' : '') + attr.name; + mcdDot += '"' + name + '_' + attr.name + '" [shape=ellipse, label="' + label + '"];\n'; + let attrName = name + '_' + attr.name; + if (Math.random() < 0.5) + mcdDot += '"' + attrName + '" -- "' + name + '";\n'; + else + mcdDot += '"' + name + '" -- "' + attrName + '";\n'; + }); + } + } + else + { + let label = name; + if (!!a.attributes) + { + a.attributes.forEach( attr => { + let attrLabel = (attr.isKey ? '#' : '') + attr.name; + label += '\\n<' + attrLabel + '>'; + }); + } + mcdDot += '"' + name + '" [color="lightgrey", label="' + label + '"'; + if (a.weak) + mcdDot += ', peripheries=2'; + mcdDot += '];\n'; + } _.shuffle(a.entities).forEach( e => { if (Math.random() < 0.5) - mcdDot += e.name + ':name -- ' + name; + mcdDot += '"' + e.name + '":name -- "' + name + '"'; else - mcdDot += name + ' -- ' + e.name + ':name'; + mcdDot += '"' + name + '" -- "' + e.name + '":name'; mcdDot += '[label="' + ErDiags.CARDINAL[e.card] + '"];\n'; }); - if (!!a.attributes) - { - _.shuffle(a.attributes).forEach( attr => { - let label = (attr.isKey ? '#' : '') + attr.name; - mcdDot += name + '_' + attr.name + '[shape=ellipse, label="' + label + '"];\n'; - let attrName = name + '_' + attr.name; - if (Math.random() < 0.5) - mcdDot += attrName + ' -- ' + name + ';\n'; - else - mcdDot += name + ' -- ' + attrName + ';\n'; - }); - } }); mcdDot += '}'; console.log(mcdDot);