define ENTITY_NAME that allows some non-alphanumeric chars; spec re-arrange

This commit is contained in:
Ashley Engelund (weedySeaDragon @ github)
2022-09-23 11:34:52 -07:00
parent 338ba704ba
commit 4bedc49b4d
2 changed files with 126 additions and 30 deletions

View File

@@ -24,6 +24,7 @@ accDescr\s*"{"\s* { this.begin("acc_descr_multili
[\n]+ return 'NEWLINE'; [\n]+ return 'NEWLINE';
\s+ /* skip whitespace */ \s+ /* skip whitespace */
[\s]+ return 'SPACE'; [\s]+ return 'SPACE';
\"[A-Za-z0-9\!\@\#\$\^\&\*\(\)\-_\=\+\[\]\{\};:\.\?]+\" return 'ENTITY_NAME';
\"[^"]*\" return 'WORD'; \"[^"]*\" return 'WORD';
"erDiagram" return 'ER_DIAGRAM'; "erDiagram" return 'ER_DIAGRAM';
"{" { this.begin("block"); return 'BLOCK_START'; } "{" { this.begin("block"); return 'BLOCK_START'; }
@@ -102,8 +103,8 @@ statement
; ;
entityName entityName
: 'ALPHANUM' { $$ = $1; /*console.log('Entity: ' + $1);*/ } : 'ALPHANUM' { $$ = $1; }
| 'ALPHANUM' '.' entityName { $$ = $1 + $2 + $3; } | 'ENTITY_NAME' { $$ = $1.replace(/"/g, ''); }
; ;
attributes attributes
@@ -156,6 +157,7 @@ relType
role role
: 'WORD' { $$ = $1.replace(/"/g, ''); } : 'WORD' { $$ = $1.replace(/"/g, ''); }
| 'ENTITY_NAME' { $$ = $1.replace(/"/g, ''); }
| 'ALPHANUM' { $$ = $1; } | 'ALPHANUM' { $$ = $1; }
; ;

View File

@@ -1,6 +1,6 @@
import { setConfig } from '../../../config'; import { setConfig } from '../../../config';
import erDb from '../erDb'; import erDb from '../erDb';
import erDiagram from './erDiagram'; import erDiagram from './erDiagram'; // jison file
setConfig({ setConfig({
securityLevel: 'strict', securityLevel: 'strict',
@@ -21,14 +21,112 @@ describe('when parsing ER diagram it...', function () {
expect(erDb.getRelationships().length).toBe(0); expect(erDb.getRelationships().length).toBe(0);
}); });
it('should allow hyphens and underscores in entity names', function () { describe('entity name', () => {
const line1 = 'DUCK-BILLED-PLATYPUS'; it('cannot be empty quotes ""', function () {
const line2 = 'CHARACTER_SET'; const name = '""';
erDiagram.parser.parse(`erDiagram\n${line1}\n${line2}`); expect(() => {
erDiagram.parser.parse(`erDiagram\n ${name}\n`);
const entities = erDb.getEntities();
expect(entities.hasOwnProperty(name)).toBe(false);
}).toThrow();
});
describe('has non A-Za-z0-9_- chars', function () {
const allowed = [
'!',
'@',
'#',
'$',
'^',
'&',
'*',
'(',
')',
'-',
'_',
'=',
'+',
'[',
']',
'{',
'}',
';',
':',
'.',
'?',
];
const entities = erDb.getEntities(); allowed.forEach((allowedChar) => {
expect(entities.hasOwnProperty('DUCK-BILLED-PLATYPUS')).toBe(true); const singleOccurrence = `Blo${allowedChar}rf`;
expect(entities.hasOwnProperty('CHARACTER_SET')).toBe(true); const repeatedOccurrence = `Blo${allowedChar}${allowedChar}rf`;
const cannontStartWith = `${allowedChar}Blorf`;
const endsWith = `Blorf${allowedChar}`;
it(`${singleOccurrence} fails if not surrounded by quotes`, function () {
const name = singleOccurrence;
expect(() => {
erDiagram.parser.parse(`erDiagram\n ${name}\n`);
const entities = erDb.getEntities();
expect(entities.hasOwnProperty(name)).toBe(false);
}).toThrow();
});
it(`"${singleOccurrence}" single occurrence`, function () {
const name = singleOccurrence;
erDiagram.parser.parse(`erDiagram\n "${name}"\n`);
const entities = erDb.getEntities();
expect(entities.hasOwnProperty(name)).toBe(true);
});
it(`"${repeatedOccurrence}" repeated occurrence`, function () {
const name = repeatedOccurrence;
erDiagram.parser.parse(`erDiagram\n "${name}"\n`);
const entities = erDb.getEntities();
expect(entities.hasOwnProperty(name)).toBe(true);
});
it(`"${singleOccurrence}" ends with`, function () {
const name = endsWith;
erDiagram.parser.parse(`erDiagram\n "${name}"\n`);
const entities = erDb.getEntities();
expect(entities.hasOwnProperty(name)).toBe(true);
});
it(`"${cannontStartWith}" cannot start with the character`, function () {
const name = repeatedOccurrence;
expect(() => {
erDiagram.parser.parse(`erDiagram\n "${name}"\n`);
const entities = erDb.getEntities();
expect(entities.hasOwnProperty(name)).toBe(false);
}).toThrow();
});
});
const allCombined = allowed.join('');
it(`a${allCombined} (all non-alphanumerics) in one, starting with 'a'`, function () {
const name = 'a' + allCombined;
erDiagram.parser.parse(`erDiagram\n "${name}"\n`);
const entities = erDb.getEntities();
expect(entities.hasOwnProperty(name)).toBe(true);
});
});
it('cannot contain % because it interfers with parsing comments', function () {
expect(() => {
erDiagram.parser.parse(`erDiagram\n "Blo%rf"\n`);
const entities = erDb.getEntities();
expect(entities.hasOwnProperty(name)).toBe(false);
}).toThrow();
});
it('can contain - _ ', function () {
const hyphens = 'DUCK-BILLED-PLATYPUS';
const underscores = 'CHARACTER_SET';
erDiagram.parser.parse(`erDiagram\n${hyphens}\n${underscores}\n`);
const entities = erDb.getEntities();
expect(entities.hasOwnProperty('DUCK-BILLED-PLATYPUS')).toBe(true);
expect(entities.hasOwnProperty('CHARACTER_SET')).toBe(true);
});
}); });
it('should allow an entity with a single attribute to be defined', function () { it('should allow an entity with a single attribute to be defined', function () {
@@ -447,27 +545,23 @@ describe('when parsing ER diagram it...', function () {
}).toThrowError(); }).toThrowError();
}); });
it('should allow an empty quoted label', function () { describe('relationship labels', function () {
erDiagram.parser.parse('erDiagram\nCUSTOMER ||--|{ ORDER : ""'); it('should allow an empty quoted label', function () {
const rels = erDb.getRelationships(); erDiagram.parser.parse('erDiagram\nCUSTOMER ||--|{ ORDER : ""');
expect(rels[0].roleA).toBe(''); const rels = erDb.getRelationships();
}); expect(rels[0].roleA).toBe('');
});
it('should allow an non-empty quoted label', function () { it('should allow an non-empty quoted label', function () {
erDiagram.parser.parse('erDiagram\nCUSTOMER ||--|{ ORDER : "places"'); erDiagram.parser.parse('erDiagram\nCUSTOMER ||--|{ ORDER : "places"');
const rels = erDb.getRelationships(); const rels = erDb.getRelationships();
expect(rels[0].roleA).toBe('places'); expect(rels[0].roleA).toBe('places');
}); });
it('should allow an non-empty unquoted label', function () { it('should allow an non-empty unquoted label', function () {
erDiagram.parser.parse('erDiagram\nCUSTOMER ||--|{ ORDER : places'); erDiagram.parser.parse('erDiagram\nCUSTOMER ||--|{ ORDER : places');
const rels = erDb.getRelationships(); const rels = erDb.getRelationships();
expect(rels[0].roleA).toBe('places'); expect(rels[0].roleA).toBe('places');
}); });
it('should allow an entity name with a dot', function () {
erDiagram.parser.parse('erDiagram\nCUSTOMER.PROP ||--|{ ORDER : places');
const rels = erDb.getRelationships();
expect(rels[0].entityA).toBe('CUSTOMER.PROP');
}); });
}); });