Consistent agent flag handling in parser
This commit is contained in:
parent
93c1e9cb8e
commit
dc3d930544
|
@ -49,7 +49,7 @@ define(['core/ArrayUtilities'], (array) => {
|
||||||
'agent define': this.handleAgentDefine.bind(this),
|
'agent define': this.handleAgentDefine.bind(this),
|
||||||
'agent begin': this.handleAgentBegin.bind(this),
|
'agent begin': this.handleAgentBegin.bind(this),
|
||||||
'agent end': this.handleAgentEnd.bind(this),
|
'agent end': this.handleAgentEnd.bind(this),
|
||||||
'connection': this.handleConnection.bind(this),
|
'connect': this.handleConnect.bind(this),
|
||||||
'note over': this.handleNote.bind(this),
|
'note over': this.handleNote.bind(this),
|
||||||
'note left': this.handleNote.bind(this),
|
'note left': this.handleNote.bind(this),
|
||||||
'note right': this.handleNote.bind(this),
|
'note right': this.handleNote.bind(this),
|
||||||
|
@ -171,13 +171,13 @@ define(['core/ArrayUtilities'], (array) => {
|
||||||
this.addStage({type: 'async', target}, false);
|
this.addStage({type: 'async', target}, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
handleConnection({agents, label, options}) {
|
handleConnect({agents, label, options}) {
|
||||||
const colAgents = agents.map(convertAgent);
|
const colAgents = agents.map(convertAgent);
|
||||||
this.setAgentVis(colAgents, true, 'box');
|
this.setAgentVis(colAgents, true, 'box');
|
||||||
this.defineAgents(colAgents);
|
this.defineAgents(colAgents);
|
||||||
|
|
||||||
this.addStage({
|
this.addStage({
|
||||||
type: 'connection',
|
type: 'connect',
|
||||||
agentNames: agents.map(getAgentName),
|
agentNames: agents.map(getAgentName),
|
||||||
label,
|
label,
|
||||||
options,
|
options,
|
||||||
|
|
|
@ -3,7 +3,7 @@ defineDescribe('Sequence Generator', ['./Generator'], (Generator) => {
|
||||||
|
|
||||||
const generator = new Generator();
|
const generator = new Generator();
|
||||||
|
|
||||||
const parsed = {
|
const PARSED = {
|
||||||
blockBegin: (mode, label) => {
|
blockBegin: (mode, label) => {
|
||||||
return {type: 'block begin', mode, label};
|
return {type: 'block begin', mode, label};
|
||||||
},
|
},
|
||||||
|
@ -19,14 +19,14 @@ defineDescribe('Sequence Generator', ['./Generator'], (Generator) => {
|
||||||
defineAgents: (agentNames) => {
|
defineAgents: (agentNames) => {
|
||||||
return {
|
return {
|
||||||
type: 'agent define',
|
type: 'agent define',
|
||||||
agents: agentNames.map((name) => ({name})),
|
agents: agentNames.map((name) => ({name, flags: []})),
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
beginAgents: (agentNames, {mode = 'box'} = {}) => {
|
beginAgents: (agentNames, {mode = 'box'} = {}) => {
|
||||||
return {
|
return {
|
||||||
type: 'agent begin',
|
type: 'agent begin',
|
||||||
agents: agentNames.map((name) => ({name})),
|
agents: agentNames.map((name) => ({name, flags: []})),
|
||||||
mode,
|
mode,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
@ -34,7 +34,7 @@ defineDescribe('Sequence Generator', ['./Generator'], (Generator) => {
|
||||||
endAgents: (agentNames, {mode = 'cross'} = {}) => {
|
endAgents: (agentNames, {mode = 'cross'} = {}) => {
|
||||||
return {
|
return {
|
||||||
type: 'agent end',
|
type: 'agent end',
|
||||||
agents: agentNames.map((name) => ({name})),
|
agents: agentNames.map((name) => ({name, flags: []})),
|
||||||
mode,
|
mode,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
@ -46,8 +46,8 @@ defineDescribe('Sequence Generator', ['./Generator'], (Generator) => {
|
||||||
right = false,
|
right = false,
|
||||||
} = {}) => {
|
} = {}) => {
|
||||||
return {
|
return {
|
||||||
type: 'connection',
|
type: 'connect',
|
||||||
agents: agentNames.map((name) => ({name})),
|
agents: agentNames.map((name) => ({name, flags: []})),
|
||||||
label,
|
label,
|
||||||
options: {
|
options: {
|
||||||
line,
|
line,
|
||||||
|
@ -64,14 +64,14 @@ defineDescribe('Sequence Generator', ['./Generator'], (Generator) => {
|
||||||
} = {}) => {
|
} = {}) => {
|
||||||
return {
|
return {
|
||||||
type,
|
type,
|
||||||
agents: agentNames.map((name) => ({name})),
|
agents: agentNames.map((name) => ({name, flags: []})),
|
||||||
mode,
|
mode,
|
||||||
label,
|
label,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const generated = {
|
const GENERATED = {
|
||||||
beginAgents: (agentNames, {
|
beginAgents: (agentNames, {
|
||||||
mode = jasmine.anything(),
|
mode = jasmine.anything(),
|
||||||
} = {}) => {
|
} = {}) => {
|
||||||
|
@ -99,7 +99,7 @@ defineDescribe('Sequence Generator', ['./Generator'], (Generator) => {
|
||||||
right = jasmine.anything(),
|
right = jasmine.anything(),
|
||||||
} = {}) => {
|
} = {}) => {
|
||||||
return {
|
return {
|
||||||
type: 'connection',
|
type: 'connect',
|
||||||
agentNames,
|
agentNames,
|
||||||
label,
|
label,
|
||||||
options: {
|
options: {
|
||||||
|
@ -169,9 +169,9 @@ defineDescribe('Sequence Generator', ['./Generator'], (Generator) => {
|
||||||
|
|
||||||
it('returns aggregated agents', () => {
|
it('returns aggregated agents', () => {
|
||||||
const sequence = generator.generate({stages: [
|
const sequence = generator.generate({stages: [
|
||||||
parsed.connect(['A', 'B']),
|
PARSED.connect(['A', 'B']),
|
||||||
parsed.connect(['C', 'D']),
|
PARSED.connect(['C', 'D']),
|
||||||
parsed.beginAgents(['E']),
|
PARSED.beginAgents(['E']),
|
||||||
]});
|
]});
|
||||||
expect(sequence.agents).toEqual([
|
expect(sequence.agents).toEqual([
|
||||||
{name: '[', anchorRight: true},
|
{name: '[', anchorRight: true},
|
||||||
|
@ -186,7 +186,7 @@ defineDescribe('Sequence Generator', ['./Generator'], (Generator) => {
|
||||||
|
|
||||||
it('always puts the implicit right agent on the right', () => {
|
it('always puts the implicit right agent on the right', () => {
|
||||||
const sequence = generator.generate({stages: [
|
const sequence = generator.generate({stages: [
|
||||||
parsed.connect([']', 'B']),
|
PARSED.connect([']', 'B']),
|
||||||
]});
|
]});
|
||||||
expect(sequence.agents).toEqual([
|
expect(sequence.agents).toEqual([
|
||||||
{name: '[', anchorRight: true},
|
{name: '[', anchorRight: true},
|
||||||
|
@ -197,8 +197,8 @@ defineDescribe('Sequence Generator', ['./Generator'], (Generator) => {
|
||||||
|
|
||||||
it('accounts for define calls when ordering agents', () => {
|
it('accounts for define calls when ordering agents', () => {
|
||||||
const sequence = generator.generate({stages: [
|
const sequence = generator.generate({stages: [
|
||||||
parsed.defineAgents(['B']),
|
PARSED.defineAgents(['B']),
|
||||||
parsed.connect(['A', 'B']),
|
PARSED.connect(['A', 'B']),
|
||||||
]});
|
]});
|
||||||
expect(sequence.agents).toEqual([
|
expect(sequence.agents).toEqual([
|
||||||
{name: '[', anchorRight: true},
|
{name: '[', anchorRight: true},
|
||||||
|
@ -210,32 +210,32 @@ defineDescribe('Sequence Generator', ['./Generator'], (Generator) => {
|
||||||
|
|
||||||
it('creates implicit begin stages for agents when used', () => {
|
it('creates implicit begin stages for agents when used', () => {
|
||||||
const sequence = generator.generate({stages: [
|
const sequence = generator.generate({stages: [
|
||||||
parsed.connect(['A', 'B']),
|
PARSED.connect(['A', 'B']),
|
||||||
parsed.connect(['B', 'C']),
|
PARSED.connect(['B', 'C']),
|
||||||
]});
|
]});
|
||||||
expect(sequence.stages).toEqual([
|
expect(sequence.stages).toEqual([
|
||||||
generated.beginAgents(['A', 'B']),
|
GENERATED.beginAgents(['A', 'B']),
|
||||||
jasmine.anything(),
|
jasmine.anything(),
|
||||||
generated.beginAgents(['C']),
|
GENERATED.beginAgents(['C']),
|
||||||
jasmine.anything(),
|
jasmine.anything(),
|
||||||
jasmine.anything(),
|
jasmine.anything(),
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('passes connections through', () => {
|
it('passes connects through', () => {
|
||||||
const sequence = generator.generate({stages: [
|
const sequence = generator.generate({stages: [
|
||||||
parsed.connect(['A', 'B']),
|
PARSED.connect(['A', 'B']),
|
||||||
]});
|
]});
|
||||||
expect(sequence.stages).toEqual([
|
expect(sequence.stages).toEqual([
|
||||||
jasmine.anything(),
|
jasmine.anything(),
|
||||||
generated.connect(['A', 'B']),
|
GENERATED.connect(['A', 'B']),
|
||||||
jasmine.anything(),
|
jasmine.anything(),
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('propagates connection information', () => {
|
it('propagates connect information', () => {
|
||||||
const sequence = generator.generate({stages: [
|
const sequence = generator.generate({stages: [
|
||||||
parsed.connect(['A', 'B'], {
|
PARSED.connect(['A', 'B'], {
|
||||||
label: 'foo',
|
label: 'foo',
|
||||||
line: 'bar',
|
line: 'bar',
|
||||||
left: true,
|
left: true,
|
||||||
|
@ -244,7 +244,7 @@ defineDescribe('Sequence Generator', ['./Generator'], (Generator) => {
|
||||||
]});
|
]});
|
||||||
expect(sequence.stages).toEqual([
|
expect(sequence.stages).toEqual([
|
||||||
jasmine.anything(),
|
jasmine.anything(),
|
||||||
generated.connect(['A', 'B'], {
|
GENERATED.connect(['A', 'B'], {
|
||||||
label: 'foo',
|
label: 'foo',
|
||||||
line: 'bar',
|
line: 'bar',
|
||||||
left: true,
|
left: true,
|
||||||
|
@ -260,65 +260,65 @@ defineDescribe('Sequence Generator', ['./Generator'], (Generator) => {
|
||||||
terminators: 'foo',
|
terminators: 'foo',
|
||||||
},
|
},
|
||||||
stages: [
|
stages: [
|
||||||
parsed.connect(['A', 'B']),
|
PARSED.connect(['A', 'B']),
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
expect(sequence.stages).toEqual([
|
expect(sequence.stages).toEqual([
|
||||||
jasmine.anything(),
|
jasmine.anything(),
|
||||||
jasmine.anything(),
|
jasmine.anything(),
|
||||||
generated.endAgents(['A', 'B'], {mode: 'foo'}),
|
GENERATED.endAgents(['A', 'B'], {mode: 'foo'}),
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('defaults to mode "none" for implicit end stages', () => {
|
it('defaults to mode "none" for implicit end stages', () => {
|
||||||
const sequence = generator.generate({stages: [
|
const sequence = generator.generate({stages: [
|
||||||
parsed.connect(['A', 'B']),
|
PARSED.connect(['A', 'B']),
|
||||||
]});
|
]});
|
||||||
expect(sequence.stages).toEqual([
|
expect(sequence.stages).toEqual([
|
||||||
jasmine.anything(),
|
jasmine.anything(),
|
||||||
jasmine.anything(),
|
jasmine.anything(),
|
||||||
generated.endAgents(['A', 'B'], {mode: 'none'}),
|
GENERATED.endAgents(['A', 'B'], {mode: 'none'}),
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('defaults to mode "cross" for explicit end stages', () => {
|
it('defaults to mode "cross" for explicit end stages', () => {
|
||||||
const sequence = generator.generate({stages: [
|
const sequence = generator.generate({stages: [
|
||||||
parsed.connect(['A', 'B']),
|
PARSED.connect(['A', 'B']),
|
||||||
parsed.endAgents(['A', 'B']),
|
PARSED.endAgents(['A', 'B']),
|
||||||
]});
|
]});
|
||||||
expect(sequence.stages).toEqual([
|
expect(sequence.stages).toEqual([
|
||||||
jasmine.anything(),
|
jasmine.anything(),
|
||||||
jasmine.anything(),
|
jasmine.anything(),
|
||||||
generated.endAgents(['A', 'B'], {mode: 'cross'}),
|
GENERATED.endAgents(['A', 'B'], {mode: 'cross'}),
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('does not create duplicate begin stages', () => {
|
it('does not create duplicate begin stages', () => {
|
||||||
const sequence = generator.generate({stages: [
|
const sequence = generator.generate({stages: [
|
||||||
parsed.beginAgents(['A', 'B', 'C']),
|
PARSED.beginAgents(['A', 'B', 'C']),
|
||||||
parsed.connect(['A', 'B']),
|
PARSED.connect(['A', 'B']),
|
||||||
parsed.connect(['B', 'C']),
|
PARSED.connect(['B', 'C']),
|
||||||
]});
|
]});
|
||||||
expect(sequence.stages).toEqual([
|
expect(sequence.stages).toEqual([
|
||||||
generated.beginAgents(['A', 'B', 'C']),
|
GENERATED.beginAgents(['A', 'B', 'C']),
|
||||||
generated.connect(jasmine.anything()),
|
GENERATED.connect(jasmine.anything()),
|
||||||
generated.connect(jasmine.anything()),
|
GENERATED.connect(jasmine.anything()),
|
||||||
generated.endAgents(['A', 'B', 'C']),
|
GENERATED.endAgents(['A', 'B', 'C']),
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('redisplays agents if they have been hidden', () => {
|
it('redisplays agents if they have been hidden', () => {
|
||||||
const sequence = generator.generate({stages: [
|
const sequence = generator.generate({stages: [
|
||||||
parsed.beginAgents(['A', 'B']),
|
PARSED.beginAgents(['A', 'B']),
|
||||||
parsed.connect(['A', 'B']),
|
PARSED.connect(['A', 'B']),
|
||||||
parsed.endAgents(['B']),
|
PARSED.endAgents(['B']),
|
||||||
parsed.connect(['A', 'B']),
|
PARSED.connect(['A', 'B']),
|
||||||
]});
|
]});
|
||||||
expect(sequence.stages).toEqual([
|
expect(sequence.stages).toEqual([
|
||||||
jasmine.anything(),
|
jasmine.anything(),
|
||||||
jasmine.anything(),
|
jasmine.anything(),
|
||||||
generated.endAgents(['B']),
|
GENERATED.endAgents(['B']),
|
||||||
generated.beginAgents(['B']),
|
GENERATED.beginAgents(['B']),
|
||||||
jasmine.anything(),
|
jasmine.anything(),
|
||||||
jasmine.anything(),
|
jasmine.anything(),
|
||||||
]);
|
]);
|
||||||
|
@ -326,69 +326,69 @@ defineDescribe('Sequence Generator', ['./Generator'], (Generator) => {
|
||||||
|
|
||||||
it('collapses adjacent begin statements', () => {
|
it('collapses adjacent begin statements', () => {
|
||||||
const sequence = generator.generate({stages: [
|
const sequence = generator.generate({stages: [
|
||||||
parsed.connect(['A', 'B']),
|
PARSED.connect(['A', 'B']),
|
||||||
parsed.beginAgents(['D']),
|
PARSED.beginAgents(['D']),
|
||||||
parsed.connect(['B', 'C']),
|
PARSED.connect(['B', 'C']),
|
||||||
parsed.connect(['C', 'D']),
|
PARSED.connect(['C', 'D']),
|
||||||
]});
|
]});
|
||||||
expect(sequence.stages).toEqual([
|
expect(sequence.stages).toEqual([
|
||||||
generated.beginAgents(['A', 'B']),
|
GENERATED.beginAgents(['A', 'B']),
|
||||||
generated.connect(jasmine.anything()),
|
GENERATED.connect(jasmine.anything()),
|
||||||
generated.beginAgents(['D', 'C']),
|
GENERATED.beginAgents(['D', 'C']),
|
||||||
generated.connect(jasmine.anything()),
|
GENERATED.connect(jasmine.anything()),
|
||||||
generated.connect(jasmine.anything()),
|
GENERATED.connect(jasmine.anything()),
|
||||||
jasmine.anything(),
|
jasmine.anything(),
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('removes superfluous begin statements', () => {
|
it('removes superfluous begin statements', () => {
|
||||||
const sequence = generator.generate({stages: [
|
const sequence = generator.generate({stages: [
|
||||||
parsed.connect(['A', 'B']),
|
PARSED.connect(['A', 'B']),
|
||||||
parsed.beginAgents(['A', 'C', 'D']),
|
PARSED.beginAgents(['A', 'C', 'D']),
|
||||||
parsed.beginAgents(['C', 'E']),
|
PARSED.beginAgents(['C', 'E']),
|
||||||
]});
|
]});
|
||||||
expect(sequence.stages).toEqual([
|
expect(sequence.stages).toEqual([
|
||||||
generated.beginAgents(['A', 'B']),
|
GENERATED.beginAgents(['A', 'B']),
|
||||||
generated.connect(jasmine.anything()),
|
GENERATED.connect(jasmine.anything()),
|
||||||
generated.beginAgents(['C', 'D', 'E']),
|
GENERATED.beginAgents(['C', 'D', 'E']),
|
||||||
jasmine.anything(),
|
jasmine.anything(),
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('removes superfluous end statements', () => {
|
it('removes superfluous end statements', () => {
|
||||||
const sequence = generator.generate({stages: [
|
const sequence = generator.generate({stages: [
|
||||||
parsed.defineAgents(['E']),
|
PARSED.defineAgents(['E']),
|
||||||
parsed.beginAgents(['C', 'D']),
|
PARSED.beginAgents(['C', 'D']),
|
||||||
parsed.connect(['A', 'B']),
|
PARSED.connect(['A', 'B']),
|
||||||
parsed.endAgents(['A', 'B', 'C']),
|
PARSED.endAgents(['A', 'B', 'C']),
|
||||||
parsed.endAgents(['A', 'D', 'E']),
|
PARSED.endAgents(['A', 'D', 'E']),
|
||||||
]});
|
]});
|
||||||
expect(sequence.stages).toEqual([
|
expect(sequence.stages).toEqual([
|
||||||
jasmine.anything(),
|
jasmine.anything(),
|
||||||
generated.connect(jasmine.anything()),
|
GENERATED.connect(jasmine.anything()),
|
||||||
generated.endAgents(['A', 'B', 'C', 'D']),
|
GENERATED.endAgents(['A', 'B', 'C', 'D']),
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('does not merge different modes of end', () => {
|
it('does not merge different modes of end', () => {
|
||||||
const sequence = generator.generate({stages: [
|
const sequence = generator.generate({stages: [
|
||||||
parsed.beginAgents(['C', 'D']),
|
PARSED.beginAgents(['C', 'D']),
|
||||||
parsed.connect(['A', 'B']),
|
PARSED.connect(['A', 'B']),
|
||||||
parsed.endAgents(['A', 'B', 'C']),
|
PARSED.endAgents(['A', 'B', 'C']),
|
||||||
]});
|
]});
|
||||||
expect(sequence.stages).toEqual([
|
expect(sequence.stages).toEqual([
|
||||||
jasmine.anything(),
|
jasmine.anything(),
|
||||||
generated.connect(jasmine.anything()),
|
GENERATED.connect(jasmine.anything()),
|
||||||
generated.endAgents(['A', 'B', 'C'], {mode: 'cross'}),
|
GENERATED.endAgents(['A', 'B', 'C'], {mode: 'cross'}),
|
||||||
generated.endAgents(['D'], {mode: 'none'}),
|
GENERATED.endAgents(['D'], {mode: 'none'}),
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('creates virtual agents for block statements', () => {
|
it('creates virtual agents for block statements', () => {
|
||||||
const sequence = generator.generate({stages: [
|
const sequence = generator.generate({stages: [
|
||||||
parsed.blockBegin('if', 'abc'),
|
PARSED.blockBegin('if', 'abc'),
|
||||||
parsed.connect(['A', 'B']),
|
PARSED.connect(['A', 'B']),
|
||||||
parsed.blockEnd(),
|
PARSED.blockEnd(),
|
||||||
]});
|
]});
|
||||||
|
|
||||||
expect(sequence.agents).toEqual([
|
expect(sequence.agents).toEqual([
|
||||||
|
@ -403,14 +403,14 @@ defineDescribe('Sequence Generator', ['./Generator'], (Generator) => {
|
||||||
|
|
||||||
it('positions virtual block agents near involved agents', () => {
|
it('positions virtual block agents near involved agents', () => {
|
||||||
const sequence = generator.generate({stages: [
|
const sequence = generator.generate({stages: [
|
||||||
parsed.connect(['A', 'B']),
|
PARSED.connect(['A', 'B']),
|
||||||
parsed.blockBegin('if', 'abc'),
|
PARSED.blockBegin('if', 'abc'),
|
||||||
parsed.connect(['C', 'D']),
|
PARSED.connect(['C', 'D']),
|
||||||
parsed.blockBegin('if', 'abc'),
|
PARSED.blockBegin('if', 'abc'),
|
||||||
parsed.connect(['E', 'F']),
|
PARSED.connect(['E', 'F']),
|
||||||
parsed.blockEnd(),
|
PARSED.blockEnd(),
|
||||||
parsed.blockEnd(),
|
PARSED.blockEnd(),
|
||||||
parsed.connect(['G', 'H']),
|
PARSED.connect(['G', 'H']),
|
||||||
]});
|
]});
|
||||||
|
|
||||||
expect(sequence.agents).toEqual([
|
expect(sequence.agents).toEqual([
|
||||||
|
@ -433,9 +433,9 @@ defineDescribe('Sequence Generator', ['./Generator'], (Generator) => {
|
||||||
|
|
||||||
it('records virtual block agent names in blocks', () => {
|
it('records virtual block agent names in blocks', () => {
|
||||||
const sequence = generator.generate({stages: [
|
const sequence = generator.generate({stages: [
|
||||||
parsed.blockBegin('if', 'abc'),
|
PARSED.blockBegin('if', 'abc'),
|
||||||
parsed.connect(['A', 'B']),
|
PARSED.connect(['A', 'B']),
|
||||||
parsed.blockEnd(),
|
PARSED.blockEnd(),
|
||||||
]});
|
]});
|
||||||
|
|
||||||
const block0 = sequence.stages[0];
|
const block0 = sequence.stages[0];
|
||||||
|
@ -446,35 +446,35 @@ defineDescribe('Sequence Generator', ['./Generator'], (Generator) => {
|
||||||
|
|
||||||
it('records all sections within blocks', () => {
|
it('records all sections within blocks', () => {
|
||||||
const sequence = generator.generate({stages: [
|
const sequence = generator.generate({stages: [
|
||||||
parsed.blockBegin('if', 'abc'),
|
PARSED.blockBegin('if', 'abc'),
|
||||||
parsed.connect(['A', 'B']),
|
PARSED.connect(['A', 'B']),
|
||||||
parsed.blockSplit('else', 'xyz'),
|
PARSED.blockSplit('else', 'xyz'),
|
||||||
parsed.connect(['A', 'C']),
|
PARSED.connect(['A', 'C']),
|
||||||
parsed.blockEnd(),
|
PARSED.blockEnd(),
|
||||||
]});
|
]});
|
||||||
|
|
||||||
const block0 = sequence.stages[0];
|
const block0 = sequence.stages[0];
|
||||||
expect(block0.sections).toEqual([
|
expect(block0.sections).toEqual([
|
||||||
{mode: 'if', label: 'abc', stages: [
|
{mode: 'if', label: 'abc', stages: [
|
||||||
generated.beginAgents(['A', 'B']),
|
GENERATED.beginAgents(['A', 'B']),
|
||||||
generated.connect(['A', 'B']),
|
GENERATED.connect(['A', 'B']),
|
||||||
]},
|
]},
|
||||||
{mode: 'else', label: 'xyz', stages: [
|
{mode: 'else', label: 'xyz', stages: [
|
||||||
generated.beginAgents(['C']),
|
GENERATED.beginAgents(['C']),
|
||||||
generated.connect(['A', 'C']),
|
GENERATED.connect(['A', 'C']),
|
||||||
]},
|
]},
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('records virtual block agents in nested blocks', () => {
|
it('records virtual block agents in nested blocks', () => {
|
||||||
const sequence = generator.generate({stages: [
|
const sequence = generator.generate({stages: [
|
||||||
parsed.blockBegin('if', 'abc'),
|
PARSED.blockBegin('if', 'abc'),
|
||||||
parsed.connect(['A', 'B']),
|
PARSED.connect(['A', 'B']),
|
||||||
parsed.blockSplit('else', 'xyz'),
|
PARSED.blockSplit('else', 'xyz'),
|
||||||
parsed.blockBegin('if', 'def'),
|
PARSED.blockBegin('if', 'def'),
|
||||||
parsed.connect(['A', 'C']),
|
PARSED.connect(['A', 'C']),
|
||||||
parsed.blockEnd(),
|
PARSED.blockEnd(),
|
||||||
parsed.blockEnd(),
|
PARSED.blockEnd(),
|
||||||
]});
|
]});
|
||||||
|
|
||||||
expect(sequence.agents).toEqual([
|
expect(sequence.agents).toEqual([
|
||||||
|
@ -501,12 +501,12 @@ defineDescribe('Sequence Generator', ['./Generator'], (Generator) => {
|
||||||
|
|
||||||
it('preserves block boundaries when agents exist outside', () => {
|
it('preserves block boundaries when agents exist outside', () => {
|
||||||
const sequence = generator.generate({stages: [
|
const sequence = generator.generate({stages: [
|
||||||
parsed.connect(['A', 'B']),
|
PARSED.connect(['A', 'B']),
|
||||||
parsed.blockBegin('if', 'abc'),
|
PARSED.blockBegin('if', 'abc'),
|
||||||
parsed.blockBegin('if', 'def'),
|
PARSED.blockBegin('if', 'def'),
|
||||||
parsed.connect(['A', 'B']),
|
PARSED.connect(['A', 'B']),
|
||||||
parsed.blockEnd(),
|
PARSED.blockEnd(),
|
||||||
parsed.blockEnd(),
|
PARSED.blockEnd(),
|
||||||
]});
|
]});
|
||||||
|
|
||||||
expect(sequence.agents).toEqual([
|
expect(sequence.agents).toEqual([
|
||||||
|
@ -532,10 +532,10 @@ defineDescribe('Sequence Generator', ['./Generator'], (Generator) => {
|
||||||
|
|
||||||
it('allows empty block parts after split', () => {
|
it('allows empty block parts after split', () => {
|
||||||
const sequence = generator.generate({stages: [
|
const sequence = generator.generate({stages: [
|
||||||
parsed.blockBegin('if', 'abc'),
|
PARSED.blockBegin('if', 'abc'),
|
||||||
parsed.connect(['A', 'B']),
|
PARSED.connect(['A', 'B']),
|
||||||
parsed.blockSplit('else', 'xyz'),
|
PARSED.blockSplit('else', 'xyz'),
|
||||||
parsed.blockEnd(),
|
PARSED.blockEnd(),
|
||||||
]});
|
]});
|
||||||
|
|
||||||
const block0 = sequence.stages[0];
|
const block0 = sequence.stages[0];
|
||||||
|
@ -550,10 +550,10 @@ defineDescribe('Sequence Generator', ['./Generator'], (Generator) => {
|
||||||
|
|
||||||
it('allows empty block parts before split', () => {
|
it('allows empty block parts before split', () => {
|
||||||
const sequence = generator.generate({stages: [
|
const sequence = generator.generate({stages: [
|
||||||
parsed.blockBegin('if', 'abc'),
|
PARSED.blockBegin('if', 'abc'),
|
||||||
parsed.blockSplit('else', 'xyz'),
|
PARSED.blockSplit('else', 'xyz'),
|
||||||
parsed.connect(['A', 'B']),
|
PARSED.connect(['A', 'B']),
|
||||||
parsed.blockEnd(),
|
PARSED.blockEnd(),
|
||||||
]});
|
]});
|
||||||
|
|
||||||
const block0 = sequence.stages[0];
|
const block0 = sequence.stages[0];
|
||||||
|
@ -568,11 +568,11 @@ defineDescribe('Sequence Generator', ['./Generator'], (Generator) => {
|
||||||
|
|
||||||
it('removes entirely empty blocks', () => {
|
it('removes entirely empty blocks', () => {
|
||||||
const sequence = generator.generate({stages: [
|
const sequence = generator.generate({stages: [
|
||||||
parsed.blockBegin('if', 'abc'),
|
PARSED.blockBegin('if', 'abc'),
|
||||||
parsed.blockSplit('else', 'xyz'),
|
PARSED.blockSplit('else', 'xyz'),
|
||||||
parsed.blockBegin('if', 'abc'),
|
PARSED.blockBegin('if', 'abc'),
|
||||||
parsed.blockEnd(),
|
PARSED.blockEnd(),
|
||||||
parsed.blockEnd(),
|
PARSED.blockEnd(),
|
||||||
]});
|
]});
|
||||||
|
|
||||||
expect(sequence.stages).toEqual([]);
|
expect(sequence.stages).toEqual([]);
|
||||||
|
@ -580,10 +580,10 @@ defineDescribe('Sequence Generator', ['./Generator'], (Generator) => {
|
||||||
|
|
||||||
it('removes blocks containing only define statements / markers', () => {
|
it('removes blocks containing only define statements / markers', () => {
|
||||||
const sequence = generator.generate({stages: [
|
const sequence = generator.generate({stages: [
|
||||||
parsed.blockBegin('if', 'abc'),
|
PARSED.blockBegin('if', 'abc'),
|
||||||
parsed.defineAgents(['A']),
|
PARSED.defineAgents(['A']),
|
||||||
{type: 'mark', name: 'foo'},
|
{type: 'mark', name: 'foo'},
|
||||||
parsed.blockEnd(),
|
PARSED.blockEnd(),
|
||||||
]});
|
]});
|
||||||
|
|
||||||
expect(sequence.stages).toEqual([]);
|
expect(sequence.stages).toEqual([]);
|
||||||
|
@ -591,11 +591,11 @@ defineDescribe('Sequence Generator', ['./Generator'], (Generator) => {
|
||||||
|
|
||||||
it('does not create virtual agents for empty blocks', () => {
|
it('does not create virtual agents for empty blocks', () => {
|
||||||
const sequence = generator.generate({stages: [
|
const sequence = generator.generate({stages: [
|
||||||
parsed.blockBegin('if', 'abc'),
|
PARSED.blockBegin('if', 'abc'),
|
||||||
parsed.blockSplit('else', 'xyz'),
|
PARSED.blockSplit('else', 'xyz'),
|
||||||
parsed.blockBegin('if', 'abc'),
|
PARSED.blockBegin('if', 'abc'),
|
||||||
parsed.blockEnd(),
|
PARSED.blockEnd(),
|
||||||
parsed.blockEnd(),
|
PARSED.blockEnd(),
|
||||||
]});
|
]});
|
||||||
|
|
||||||
expect(sequence.agents).toEqual([
|
expect(sequence.agents).toEqual([
|
||||||
|
@ -606,12 +606,12 @@ defineDescribe('Sequence Generator', ['./Generator'], (Generator) => {
|
||||||
|
|
||||||
it('removes entirely empty nested blocks', () => {
|
it('removes entirely empty nested blocks', () => {
|
||||||
const sequence = generator.generate({stages: [
|
const sequence = generator.generate({stages: [
|
||||||
parsed.blockBegin('if', 'abc'),
|
PARSED.blockBegin('if', 'abc'),
|
||||||
parsed.connect(['A', 'B']),
|
PARSED.connect(['A', 'B']),
|
||||||
parsed.blockSplit('else', 'xyz'),
|
PARSED.blockSplit('else', 'xyz'),
|
||||||
parsed.blockBegin('if', 'abc'),
|
PARSED.blockBegin('if', 'abc'),
|
||||||
parsed.blockEnd(),
|
PARSED.blockEnd(),
|
||||||
parsed.blockEnd(),
|
PARSED.blockEnd(),
|
||||||
]});
|
]});
|
||||||
|
|
||||||
const block0 = sequence.stages[0];
|
const block0 = sequence.stages[0];
|
||||||
|
@ -626,56 +626,56 @@ defineDescribe('Sequence Generator', ['./Generator'], (Generator) => {
|
||||||
|
|
||||||
it('rejects unterminated blocks', () => {
|
it('rejects unterminated blocks', () => {
|
||||||
expect(() => generator.generate({stages: [
|
expect(() => generator.generate({stages: [
|
||||||
parsed.blockBegin('if', 'abc'),
|
PARSED.blockBegin('if', 'abc'),
|
||||||
parsed.connect(['A', 'B']),
|
PARSED.connect(['A', 'B']),
|
||||||
]})).toThrow();
|
]})).toThrow();
|
||||||
|
|
||||||
expect(() => generator.generate({stages: [
|
expect(() => generator.generate({stages: [
|
||||||
parsed.blockBegin('if', 'abc'),
|
PARSED.blockBegin('if', 'abc'),
|
||||||
parsed.blockBegin('if', 'def'),
|
PARSED.blockBegin('if', 'def'),
|
||||||
parsed.connect(['A', 'B']),
|
PARSED.connect(['A', 'B']),
|
||||||
parsed.blockEnd(),
|
PARSED.blockEnd(),
|
||||||
]})).toThrow();
|
]})).toThrow();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('rejects extra block terminations', () => {
|
it('rejects extra block terminations', () => {
|
||||||
expect(() => generator.generate({stages: [
|
expect(() => generator.generate({stages: [
|
||||||
parsed.blockEnd(),
|
PARSED.blockEnd(),
|
||||||
]})).toThrow();
|
]})).toThrow();
|
||||||
|
|
||||||
expect(() => generator.generate({stages: [
|
expect(() => generator.generate({stages: [
|
||||||
parsed.blockBegin('if', 'abc'),
|
PARSED.blockBegin('if', 'abc'),
|
||||||
parsed.connect(['A', 'B']),
|
PARSED.connect(['A', 'B']),
|
||||||
parsed.blockEnd(),
|
PARSED.blockEnd(),
|
||||||
parsed.blockEnd(),
|
PARSED.blockEnd(),
|
||||||
]})).toThrow();
|
]})).toThrow();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('rejects block splitting without a block', () => {
|
it('rejects block splitting without a block', () => {
|
||||||
expect(() => generator.generate({stages: [
|
expect(() => generator.generate({stages: [
|
||||||
parsed.blockSplit('else', 'xyz'),
|
PARSED.blockSplit('else', 'xyz'),
|
||||||
]})).toThrow();
|
]})).toThrow();
|
||||||
|
|
||||||
expect(() => generator.generate({stages: [
|
expect(() => generator.generate({stages: [
|
||||||
parsed.blockBegin('if', 'abc'),
|
PARSED.blockBegin('if', 'abc'),
|
||||||
parsed.connect(['A', 'B']),
|
PARSED.connect(['A', 'B']),
|
||||||
parsed.blockEnd(),
|
PARSED.blockEnd(),
|
||||||
parsed.blockSplit('else', 'xyz'),
|
PARSED.blockSplit('else', 'xyz'),
|
||||||
]})).toThrow();
|
]})).toThrow();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('rejects block splitting in non-splittable blocks', () => {
|
it('rejects block splitting in non-splittable blocks', () => {
|
||||||
expect(() => generator.generate({stages: [
|
expect(() => generator.generate({stages: [
|
||||||
parsed.blockBegin('repeat', 'abc'),
|
PARSED.blockBegin('repeat', 'abc'),
|
||||||
parsed.blockSplit('else', 'xyz'),
|
PARSED.blockSplit('else', 'xyz'),
|
||||||
parsed.connect(['A', 'B']),
|
PARSED.connect(['A', 'B']),
|
||||||
parsed.blockEnd(),
|
PARSED.blockEnd(),
|
||||||
]})).toThrow();
|
]})).toThrow();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('passes notes through', () => {
|
it('passes notes through', () => {
|
||||||
const sequence = generator.generate({stages: [
|
const sequence = generator.generate({stages: [
|
||||||
parsed.note(['A', 'B'], {
|
PARSED.note(['A', 'B'], {
|
||||||
type: 'note right',
|
type: 'note right',
|
||||||
mode: 'foo',
|
mode: 'foo',
|
||||||
label: 'bar',
|
label: 'bar',
|
||||||
|
@ -683,7 +683,7 @@ defineDescribe('Sequence Generator', ['./Generator'], (Generator) => {
|
||||||
]});
|
]});
|
||||||
expect(sequence.stages).toEqual([
|
expect(sequence.stages).toEqual([
|
||||||
jasmine.anything(),
|
jasmine.anything(),
|
||||||
generated.note(['A', 'B'], {
|
GENERATED.note(['A', 'B'], {
|
||||||
type: 'note right',
|
type: 'note right',
|
||||||
mode: 'foo',
|
mode: 'foo',
|
||||||
label: 'bar',
|
label: 'bar',
|
||||||
|
@ -694,32 +694,32 @@ defineDescribe('Sequence Generator', ['./Generator'], (Generator) => {
|
||||||
|
|
||||||
it('defaults to showing notes around the entire diagram', () => {
|
it('defaults to showing notes around the entire diagram', () => {
|
||||||
const sequence = generator.generate({stages: [
|
const sequence = generator.generate({stages: [
|
||||||
parsed.note([], {type: 'note right'}),
|
PARSED.note([], {type: 'note right'}),
|
||||||
parsed.note([], {type: 'note left'}),
|
PARSED.note([], {type: 'note left'}),
|
||||||
parsed.note([], {type: 'note over'}),
|
PARSED.note([], {type: 'note over'}),
|
||||||
]});
|
]});
|
||||||
expect(sequence.stages).toEqual([
|
expect(sequence.stages).toEqual([
|
||||||
generated.note([']'], {type: 'note right'}),
|
GENERATED.note([']'], {type: 'note right'}),
|
||||||
generated.note(['['], {type: 'note left'}),
|
GENERATED.note(['['], {type: 'note left'}),
|
||||||
generated.note(['[', ']'], {type: 'note over'}),
|
GENERATED.note(['[', ']'], {type: 'note over'}),
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('rejects attempts to change implicit agents', () => {
|
it('rejects attempts to change implicit agents', () => {
|
||||||
expect(() => generator.generate({stages: [
|
expect(() => generator.generate({stages: [
|
||||||
parsed.beginAgents(['[']),
|
PARSED.beginAgents(['[']),
|
||||||
]})).toThrow();
|
]})).toThrow();
|
||||||
|
|
||||||
expect(() => generator.generate({stages: [
|
expect(() => generator.generate({stages: [
|
||||||
parsed.beginAgents([']']),
|
PARSED.beginAgents([']']),
|
||||||
]})).toThrow();
|
]})).toThrow();
|
||||||
|
|
||||||
expect(() => generator.generate({stages: [
|
expect(() => generator.generate({stages: [
|
||||||
parsed.endAgents(['[']),
|
PARSED.endAgents(['[']),
|
||||||
]})).toThrow();
|
]})).toThrow();
|
||||||
|
|
||||||
expect(() => generator.generate({stages: [
|
expect(() => generator.generate({stages: [
|
||||||
parsed.endAgents([']']),
|
PARSED.endAgents([']']),
|
||||||
]})).toThrow();
|
]})).toThrow();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -16,7 +16,7 @@ define([
|
||||||
'repeat': {type: 'block begin', mode: 'repeat', skip: []},
|
'repeat': {type: 'block begin', mode: 'repeat', skip: []},
|
||||||
};
|
};
|
||||||
|
|
||||||
const CONNECTION_TYPES = {
|
const CONNECT_TYPES = {
|
||||||
'->': {line: 'solid', left: false, right: true},
|
'->': {line: 'solid', left: false, right: true},
|
||||||
'<-': {line: 'solid', left: true, right: false},
|
'<-': {line: 'solid', left: true, right: false},
|
||||||
'<->': {line: 'solid', left: true, right: true},
|
'<->': {line: 'solid', left: true, right: true},
|
||||||
|
@ -25,7 +25,7 @@ define([
|
||||||
'<-->': {line: 'dash', left: true, right: true},
|
'<-->': {line: 'dash', left: true, right: true},
|
||||||
};
|
};
|
||||||
|
|
||||||
const AGENT_OPTIONS = {
|
const CONNECT_AGENT_FLAGS = {
|
||||||
'+': 'start',
|
'+': 'start',
|
||||||
'-': 'stop',
|
'-': 'stop',
|
||||||
};
|
};
|
||||||
|
@ -112,50 +112,43 @@ define([
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseAgentList(line, start, end) {
|
function readAgent(line, start, end, flagTypes = {}) {
|
||||||
const list = [];
|
const flags = [];
|
||||||
let current = '';
|
let p = start;
|
||||||
let first = true;
|
|
||||||
for(let i = start; i < end; ++ i) {
|
|
||||||
const token = line[i];
|
|
||||||
if(tokenKeyword(token) === ',') {
|
|
||||||
if(current) {
|
|
||||||
list.push({name: current});
|
|
||||||
current = '';
|
|
||||||
first = true;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if(!first) {
|
|
||||||
current += token.s;
|
|
||||||
} else {
|
|
||||||
first = false;
|
|
||||||
}
|
|
||||||
current += token.v;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(current) {
|
|
||||||
list.push({name: current});
|
|
||||||
}
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
|
|
||||||
function readAgentDetails(line, begin, end) {
|
|
||||||
const options = [];
|
|
||||||
let p = begin;
|
|
||||||
for(; p < end; ++ p) {
|
for(; p < end; ++ p) {
|
||||||
const option = AGENT_OPTIONS[tokenKeyword(line[p])];
|
const flag = flagTypes[tokenKeyword(line[p])];
|
||||||
if(option) {
|
if(flag) {
|
||||||
options.push(option);
|
flags.push(flag);
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
agent: {name: joinLabel(line, p, end)},
|
name: joinLabel(line, p, end),
|
||||||
options,
|
flags,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function readAgentList(line, start, end, flagTypes) {
|
||||||
|
const list = [];
|
||||||
|
let currentStart = -1;
|
||||||
|
for(let i = start; i < end; ++ i) {
|
||||||
|
const token = line[i];
|
||||||
|
if(tokenKeyword(token) === ',') {
|
||||||
|
if(currentStart !== -1) {
|
||||||
|
list.push(readAgent(line, currentStart, i, flagTypes));
|
||||||
|
currentStart = -1;
|
||||||
|
}
|
||||||
|
} else if(currentStart === -1) {
|
||||||
|
currentStart = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(currentStart !== -1) {
|
||||||
|
list.push(readAgent(line, currentStart, end, flagTypes));
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
const PARSERS = [
|
const PARSERS = [
|
||||||
(line, meta) => { // title
|
(line, meta) => { // title
|
||||||
if(tokenKeyword(line[0]) !== 'title') {
|
if(tokenKeyword(line[0]) !== 'title') {
|
||||||
|
@ -206,7 +199,7 @@ define([
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return Object.assign({
|
return Object.assign({
|
||||||
agents: parseAgentList(line, 1, line.length),
|
agents: readAgentList(line, 1, line.length),
|
||||||
}, type);
|
}, type);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -232,8 +225,8 @@ define([
|
||||||
|
|
||||||
(line) => { // note
|
(line) => { // note
|
||||||
const mode = NOTE_TYPES[tokenKeyword(line[0])];
|
const mode = NOTE_TYPES[tokenKeyword(line[0])];
|
||||||
const labelSplit = findToken(line, ':');
|
const labelSep = findToken(line, ':');
|
||||||
if(!mode || labelSplit === -1) {
|
if(!mode || labelSep === -1) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
const type = mode.types[tokenKeyword(line[1])];
|
const type = mode.types[tokenKeyword(line[1])];
|
||||||
|
@ -242,7 +235,7 @@ define([
|
||||||
}
|
}
|
||||||
let skip = 2;
|
let skip = 2;
|
||||||
skip = skipOver(line, skip, type.skip);
|
skip = skipOver(line, skip, type.skip);
|
||||||
const agents = parseAgentList(line, skip, labelSplit);
|
const agents = readAgentList(line, skip, labelSep);
|
||||||
if(
|
if(
|
||||||
agents.length < type.min ||
|
agents.length < type.min ||
|
||||||
(type.max !== null && agents.length > type.max)
|
(type.max !== null && agents.length > type.max)
|
||||||
|
@ -256,37 +249,35 @@ define([
|
||||||
type: type.type,
|
type: type.type,
|
||||||
agents,
|
agents,
|
||||||
mode: mode.mode,
|
mode: mode.mode,
|
||||||
label: joinLabel(line, labelSplit + 1),
|
label: joinLabel(line, labelSep + 1),
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
(line) => { // connection
|
(line) => { // connect
|
||||||
let labelSplit = findToken(line, ':');
|
let labelSep = findToken(line, ':');
|
||||||
if(labelSplit === -1) {
|
if(labelSep === -1) {
|
||||||
labelSplit = line.length;
|
labelSep = line.length;
|
||||||
}
|
}
|
||||||
let typeSplit = -1;
|
let typePos = -1;
|
||||||
let options = null;
|
let options = null;
|
||||||
for(let j = 0; j < line.length; ++ j) {
|
for(let j = 0; j < line.length; ++ j) {
|
||||||
const opts = CONNECTION_TYPES[tokenKeyword(line[j])];
|
const opts = CONNECT_TYPES[tokenKeyword(line[j])];
|
||||||
if(opts) {
|
if(opts) {
|
||||||
typeSplit = j;
|
typePos = j;
|
||||||
options = opts;
|
options = opts;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(typeSplit <= 0 || typeSplit >= labelSplit - 1) {
|
if(typePos <= 0 || typePos >= labelSep - 1) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
const from = readAgentDetails(line, 0, typeSplit);
|
|
||||||
const to = readAgentDetails(line, typeSplit + 1, labelSplit);
|
|
||||||
return {
|
return {
|
||||||
type: 'connection',
|
type: 'connect',
|
||||||
agents: [
|
agents: [
|
||||||
from.agent,
|
readAgent(line, 0, typePos, CONNECT_AGENT_FLAGS),
|
||||||
to.agent,
|
readAgent(line, typePos + 1, labelSep, CONNECT_AGENT_FLAGS),
|
||||||
],
|
],
|
||||||
label: joinLabel(line, labelSplit + 1),
|
label: joinLabel(line, labelSep + 1),
|
||||||
options,
|
options,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
|
@ -4,15 +4,15 @@ defineDescribe('Sequence Parser', ['./Parser'], (Parser) => {
|
||||||
const parser = new Parser();
|
const parser = new Parser();
|
||||||
|
|
||||||
const PARSED = {
|
const PARSED = {
|
||||||
connection: (agentNames, {
|
connect: (agentNames, {
|
||||||
line = jasmine.anything(),
|
line = jasmine.anything(),
|
||||||
left = jasmine.anything(),
|
left = jasmine.anything(),
|
||||||
right = jasmine.anything(),
|
right = jasmine.anything(),
|
||||||
label = jasmine.anything(),
|
label = jasmine.anything(),
|
||||||
} = {}) => {
|
} = {}) => {
|
||||||
return {
|
return {
|
||||||
type: 'connection',
|
type: 'connect',
|
||||||
agents: agentNames.map((name) => ({name})),
|
agents: agentNames.map((name) => ({name, flags: []})),
|
||||||
label,
|
label,
|
||||||
options: {
|
options: {
|
||||||
line,
|
line,
|
||||||
|
@ -53,44 +53,59 @@ defineDescribe('Sequence Parser', ['./Parser'], (Parser) => {
|
||||||
it('converts entries into abstract form', () => {
|
it('converts entries into abstract form', () => {
|
||||||
const parsed = parser.parse('A -> B');
|
const parsed = parser.parse('A -> B');
|
||||||
expect(parsed.stages).toEqual([
|
expect(parsed.stages).toEqual([
|
||||||
PARSED.connection(['A', 'B']),
|
PARSED.connect(['A', 'B']),
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('combines multiple tokens into single entries', () => {
|
it('combines multiple tokens into single entries', () => {
|
||||||
const parsed = parser.parse('A B -> C D');
|
const parsed = parser.parse('A B -> C D');
|
||||||
expect(parsed.stages).toEqual([
|
expect(parsed.stages).toEqual([
|
||||||
PARSED.connection(['A B', 'C D']),
|
PARSED.connect(['A B', 'C D']),
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('respects spacing within agent names', () => {
|
it('respects spacing within agent names', () => {
|
||||||
const parsed = parser.parse('A+B -> C D');
|
const parsed = parser.parse('A+B -> C D');
|
||||||
expect(parsed.stages).toEqual([
|
expect(parsed.stages).toEqual([
|
||||||
PARSED.connection(['A+B', 'C D']),
|
PARSED.connect(['A+B', 'C D']),
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('parses optional labels', () => {
|
it('parses optional labels', () => {
|
||||||
const parsed = parser.parse('A B -> C D: foo bar');
|
const parsed = parser.parse('A B -> C D: foo bar');
|
||||||
expect(parsed.stages).toEqual([
|
expect(parsed.stages).toEqual([
|
||||||
PARSED.connection(['A B', 'C D'], {label: 'foo bar'}),
|
PARSED.connect(['A B', 'C D'], {label: 'foo bar'}),
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('parses optional flags', () => {
|
||||||
|
const parsed = parser.parse('+A -> -B');
|
||||||
|
expect(parsed.stages).toEqual([
|
||||||
|
{
|
||||||
|
type: 'connect',
|
||||||
|
agents: [
|
||||||
|
{name: 'A', flags: ['start']},
|
||||||
|
{name: 'B', flags: ['stop']},
|
||||||
|
],
|
||||||
|
label: jasmine.anything(),
|
||||||
|
options: jasmine.anything(),
|
||||||
|
},
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('converts multiple entries', () => {
|
it('converts multiple entries', () => {
|
||||||
const parsed = parser.parse('A -> B\nB -> A');
|
const parsed = parser.parse('A -> B\nB -> A');
|
||||||
expect(parsed.stages).toEqual([
|
expect(parsed.stages).toEqual([
|
||||||
PARSED.connection(['A', 'B']),
|
PARSED.connect(['A', 'B']),
|
||||||
PARSED.connection(['B', 'A']),
|
PARSED.connect(['B', 'A']),
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('ignores blank lines', () => {
|
it('ignores blank lines', () => {
|
||||||
const parsed = parser.parse('A -> B\n\nB -> A\n');
|
const parsed = parser.parse('A -> B\n\nB -> A\n');
|
||||||
expect(parsed.stages).toEqual([
|
expect(parsed.stages).toEqual([
|
||||||
PARSED.connection(['A', 'B']),
|
PARSED.connect(['A', 'B']),
|
||||||
PARSED.connection(['B', 'A']),
|
PARSED.connect(['B', 'A']),
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -104,37 +119,37 @@ defineDescribe('Sequence Parser', ['./Parser'], (Parser) => {
|
||||||
'A <--> B\n'
|
'A <--> B\n'
|
||||||
);
|
);
|
||||||
expect(parsed.stages).toEqual([
|
expect(parsed.stages).toEqual([
|
||||||
PARSED.connection(['A', 'B'], {
|
PARSED.connect(['A', 'B'], {
|
||||||
line: 'solid',
|
line: 'solid',
|
||||||
left: false,
|
left: false,
|
||||||
right: true,
|
right: true,
|
||||||
label: '',
|
label: '',
|
||||||
}),
|
}),
|
||||||
PARSED.connection(['A', 'B'], {
|
PARSED.connect(['A', 'B'], {
|
||||||
line: 'solid',
|
line: 'solid',
|
||||||
left: true,
|
left: true,
|
||||||
right: false,
|
right: false,
|
||||||
label: '',
|
label: '',
|
||||||
}),
|
}),
|
||||||
PARSED.connection(['A', 'B'], {
|
PARSED.connect(['A', 'B'], {
|
||||||
line: 'solid',
|
line: 'solid',
|
||||||
left: true,
|
left: true,
|
||||||
right: true,
|
right: true,
|
||||||
label: '',
|
label: '',
|
||||||
}),
|
}),
|
||||||
PARSED.connection(['A', 'B'], {
|
PARSED.connect(['A', 'B'], {
|
||||||
line: 'dash',
|
line: 'dash',
|
||||||
left: false,
|
left: false,
|
||||||
right: true,
|
right: true,
|
||||||
label: '',
|
label: '',
|
||||||
}),
|
}),
|
||||||
PARSED.connection(['A', 'B'], {
|
PARSED.connect(['A', 'B'], {
|
||||||
line: 'dash',
|
line: 'dash',
|
||||||
left: true,
|
left: true,
|
||||||
right: false,
|
right: false,
|
||||||
label: '',
|
label: '',
|
||||||
}),
|
}),
|
||||||
PARSED.connection(['A', 'B'], {
|
PARSED.connect(['A', 'B'], {
|
||||||
line: 'dash',
|
line: 'dash',
|
||||||
left: true,
|
left: true,
|
||||||
right: true,
|
right: true,
|
||||||
|
@ -149,13 +164,13 @@ defineDescribe('Sequence Parser', ['./Parser'], (Parser) => {
|
||||||
'A -> B: B <- A\n'
|
'A -> B: B <- A\n'
|
||||||
);
|
);
|
||||||
expect(parsed.stages).toEqual([
|
expect(parsed.stages).toEqual([
|
||||||
PARSED.connection(['A', 'B'], {
|
PARSED.connect(['A', 'B'], {
|
||||||
line: 'solid',
|
line: 'solid',
|
||||||
left: true,
|
left: true,
|
||||||
right: false,
|
right: false,
|
||||||
label: 'B -> A',
|
label: 'B -> A',
|
||||||
}),
|
}),
|
||||||
PARSED.connection(['A', 'B'], {
|
PARSED.connect(['A', 'B'], {
|
||||||
line: 'solid',
|
line: 'solid',
|
||||||
left: false,
|
left: false,
|
||||||
right: true,
|
right: true,
|
||||||
|
@ -168,7 +183,7 @@ defineDescribe('Sequence Parser', ['./Parser'], (Parser) => {
|
||||||
const parsed = parser.parse('note over A: hello there');
|
const parsed = parser.parse('note over A: hello there');
|
||||||
expect(parsed.stages).toEqual([{
|
expect(parsed.stages).toEqual([{
|
||||||
type: 'note over',
|
type: 'note over',
|
||||||
agents: [{name: 'A'}],
|
agents: [{name: 'A', flags: []}],
|
||||||
mode: 'note',
|
mode: 'note',
|
||||||
label: 'hello there',
|
label: 'hello there',
|
||||||
}]);
|
}]);
|
||||||
|
@ -185,31 +200,31 @@ defineDescribe('Sequence Parser', ['./Parser'], (Parser) => {
|
||||||
expect(parsed.stages).toEqual([
|
expect(parsed.stages).toEqual([
|
||||||
{
|
{
|
||||||
type: 'note left',
|
type: 'note left',
|
||||||
agents: [{name: 'A'}],
|
agents: [{name: 'A', flags: []}],
|
||||||
mode: 'note',
|
mode: 'note',
|
||||||
label: 'hello there',
|
label: 'hello there',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'note left',
|
type: 'note left',
|
||||||
agents: [{name: 'A'}],
|
agents: [{name: 'A', flags: []}],
|
||||||
mode: 'note',
|
mode: 'note',
|
||||||
label: 'hello there',
|
label: 'hello there',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'note right',
|
type: 'note right',
|
||||||
agents: [{name: 'A'}],
|
agents: [{name: 'A', flags: []}],
|
||||||
mode: 'note',
|
mode: 'note',
|
||||||
label: 'hello there',
|
label: 'hello there',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'note right',
|
type: 'note right',
|
||||||
agents: [{name: 'A'}],
|
agents: [{name: 'A', flags: []}],
|
||||||
mode: 'note',
|
mode: 'note',
|
||||||
label: 'hello there',
|
label: 'hello there',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'note between',
|
type: 'note between',
|
||||||
agents: [{name: 'A'}, {name: 'B'}],
|
agents: [{name: 'A', flags: []}, {name: 'B', flags: []}],
|
||||||
mode: 'note',
|
mode: 'note',
|
||||||
label: 'hi',
|
label: 'hi',
|
||||||
},
|
},
|
||||||
|
@ -220,7 +235,7 @@ defineDescribe('Sequence Parser', ['./Parser'], (Parser) => {
|
||||||
const parsed = parser.parse('note over A B, C D: hi');
|
const parsed = parser.parse('note over A B, C D: hi');
|
||||||
expect(parsed.stages).toEqual([{
|
expect(parsed.stages).toEqual([{
|
||||||
type: 'note over',
|
type: 'note over',
|
||||||
agents: [{name: 'A B'}, {name: 'C D'}],
|
agents: [{name: 'A B', flags: []}, {name: 'C D', flags: []}],
|
||||||
mode: 'note',
|
mode: 'note',
|
||||||
label: 'hi',
|
label: 'hi',
|
||||||
}]);
|
}]);
|
||||||
|
@ -234,7 +249,7 @@ defineDescribe('Sequence Parser', ['./Parser'], (Parser) => {
|
||||||
const parsed = parser.parse('state over A: doing stuff');
|
const parsed = parser.parse('state over A: doing stuff');
|
||||||
expect(parsed.stages).toEqual([{
|
expect(parsed.stages).toEqual([{
|
||||||
type: 'note over',
|
type: 'note over',
|
||||||
agents: [{name: 'A'}],
|
agents: [{name: 'A', flags: []}],
|
||||||
mode: 'state',
|
mode: 'state',
|
||||||
label: 'doing stuff',
|
label: 'doing stuff',
|
||||||
}]);
|
}]);
|
||||||
|
@ -248,7 +263,7 @@ defineDescribe('Sequence Parser', ['./Parser'], (Parser) => {
|
||||||
const parsed = parser.parse('text right of A: doing stuff');
|
const parsed = parser.parse('text right of A: doing stuff');
|
||||||
expect(parsed.stages).toEqual([{
|
expect(parsed.stages).toEqual([{
|
||||||
type: 'note right',
|
type: 'note right',
|
||||||
agents: [{name: 'A'}],
|
agents: [{name: 'A', flags: []}],
|
||||||
mode: 'text',
|
mode: 'text',
|
||||||
label: 'doing stuff',
|
label: 'doing stuff',
|
||||||
}]);
|
}]);
|
||||||
|
@ -263,16 +278,16 @@ defineDescribe('Sequence Parser', ['./Parser'], (Parser) => {
|
||||||
expect(parsed.stages).toEqual([
|
expect(parsed.stages).toEqual([
|
||||||
{
|
{
|
||||||
type: 'agent define',
|
type: 'agent define',
|
||||||
agents: [{name: 'A'}, {name: 'B'}],
|
agents: [{name: 'A', flags: []}, {name: 'B', flags: []}],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'agent begin',
|
type: 'agent begin',
|
||||||
agents: [{name: 'A'}, {name: 'B'}],
|
agents: [{name: 'A', flags: []}, {name: 'B', flags: []}],
|
||||||
mode: 'box',
|
mode: 'box',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'agent end',
|
type: 'agent end',
|
||||||
agents: [{name: 'A'}, {name: 'B'}],
|
agents: [{name: 'A', flags: []}, {name: 'B', flags: []}],
|
||||||
mode: 'cross',
|
mode: 'cross',
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
@ -315,12 +330,12 @@ defineDescribe('Sequence Parser', ['./Parser'], (Parser) => {
|
||||||
);
|
);
|
||||||
expect(parsed.stages).toEqual([
|
expect(parsed.stages).toEqual([
|
||||||
{type: 'block begin', mode: 'if', label: 'something happens'},
|
{type: 'block begin', mode: 'if', label: 'something happens'},
|
||||||
PARSED.connection(['A', 'B']),
|
PARSED.connect(['A', 'B']),
|
||||||
{type: 'block split', mode: 'else', label: 'something else'},
|
{type: 'block split', mode: 'else', label: 'something else'},
|
||||||
PARSED.connection(['A', 'C']),
|
PARSED.connect(['A', 'C']),
|
||||||
PARSED.connection(['C', 'B']),
|
PARSED.connect(['C', 'B']),
|
||||||
{type: 'block split', mode: 'else', label: ''},
|
{type: 'block split', mode: 'else', label: ''},
|
||||||
PARSED.connection(['A', 'D']),
|
PARSED.connect(['A', 'D']),
|
||||||
{type: 'block end'},
|
{type: 'block end'},
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
|
@ -67,7 +67,7 @@ define([
|
||||||
'async': this.separationAsync.bind(this),
|
'async': this.separationAsync.bind(this),
|
||||||
'agent begin': this.separationAgent.bind(this),
|
'agent begin': this.separationAgent.bind(this),
|
||||||
'agent end': this.separationAgent.bind(this),
|
'agent end': this.separationAgent.bind(this),
|
||||||
'connection': this.separationConnection.bind(this),
|
'connect': this.separationConnect.bind(this),
|
||||||
'note over': this.separationNoteOver.bind(this),
|
'note over': this.separationNoteOver.bind(this),
|
||||||
'note left': this.separationNoteSide.bind(this, false),
|
'note left': this.separationNoteSide.bind(this, false),
|
||||||
'note right': this.separationNoteSide.bind(this, true),
|
'note right': this.separationNoteSide.bind(this, true),
|
||||||
|
@ -86,7 +86,7 @@ define([
|
||||||
'async': this.renderAsync.bind(this),
|
'async': this.renderAsync.bind(this),
|
||||||
'agent begin': this.renderAgentBegin.bind(this),
|
'agent begin': this.renderAgentBegin.bind(this),
|
||||||
'agent end': this.renderAgentEnd.bind(this),
|
'agent end': this.renderAgentEnd.bind(this),
|
||||||
'connection': this.renderConnection.bind(this),
|
'connect': this.renderConnect.bind(this),
|
||||||
'note over': this.renderNoteOver.bind(this),
|
'note over': this.renderNoteOver.bind(this),
|
||||||
'note left': this.renderNoteLeft.bind(this),
|
'note left': this.renderNoteLeft.bind(this),
|
||||||
'note right': this.renderNoteRight.bind(this),
|
'note right': this.renderNoteRight.bind(this),
|
||||||
|
@ -263,7 +263,7 @@ define([
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
separationConnection({agentNames, label}) {
|
separationConnect({agentNames, label}) {
|
||||||
const config = this.theme.connect;
|
const config = this.theme.connect;
|
||||||
|
|
||||||
const labelWidth = (
|
const labelWidth = (
|
||||||
|
@ -528,7 +528,7 @@ define([
|
||||||
this.markAgentRange(agentNames);
|
this.markAgentRange(agentNames);
|
||||||
}
|
}
|
||||||
|
|
||||||
renderSelfConnection({label, agentNames, options}) {
|
renderSelfConnect({label, agentNames, options}) {
|
||||||
const config = this.theme.connect;
|
const config = this.theme.connect;
|
||||||
const from = this.agentInfos.get(agentNames[0]);
|
const from = this.agentInfos.get(agentNames[0]);
|
||||||
|
|
||||||
|
@ -601,7 +601,7 @@ define([
|
||||||
this.currentY = y1 + dy + this.theme.actionMargin;
|
this.currentY = y1 + dy + this.theme.actionMargin;
|
||||||
}
|
}
|
||||||
|
|
||||||
renderSimpleConnection({label, agentNames, options}) {
|
renderSimpleConnect({label, agentNames, options}) {
|
||||||
const config = this.theme.connect;
|
const config = this.theme.connect;
|
||||||
const from = this.agentInfos.get(agentNames[0]);
|
const from = this.agentInfos.get(agentNames[0]);
|
||||||
const to = this.agentInfos.get(agentNames[1]);
|
const to = this.agentInfos.get(agentNames[1]);
|
||||||
|
@ -659,12 +659,12 @@ define([
|
||||||
this.currentY = y + dy + this.theme.actionMargin;
|
this.currentY = y + dy + this.theme.actionMargin;
|
||||||
}
|
}
|
||||||
|
|
||||||
renderConnection(stage) {
|
renderConnect(stage) {
|
||||||
this.checkAgentRange(stage.agentNames);
|
this.checkAgentRange(stage.agentNames);
|
||||||
if(stage.agentNames[0] === stage.agentNames[1]) {
|
if(stage.agentNames[0] === stage.agentNames[1]) {
|
||||||
this.renderSelfConnection(stage);
|
this.renderSelfConnect(stage);
|
||||||
} else {
|
} else {
|
||||||
this.renderSimpleConnection(stage);
|
this.renderSimpleConnect(stage);
|
||||||
}
|
}
|
||||||
this.markAgentRange(stage.agentNames);
|
this.markAgentRange(stage.agentNames);
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,18 +25,20 @@ defineDescribe('Sequence Renderer', [
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
function connectionStage(agentNames, label = '') {
|
const GENERATED = {
|
||||||
return {
|
connect: (agentNames, label = '') => {
|
||||||
type: 'connection',
|
return {
|
||||||
agentNames,
|
type: 'connect',
|
||||||
label,
|
agentNames,
|
||||||
options: {
|
label,
|
||||||
line: 'solid',
|
options: {
|
||||||
left: false,
|
line: 'solid',
|
||||||
right: true,
|
left: false,
|
||||||
},
|
right: true,
|
||||||
};
|
},
|
||||||
}
|
};
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
describe('.render', () => {
|
describe('.render', () => {
|
||||||
it('populates the SVG with content', () => {
|
it('populates the SVG with content', () => {
|
||||||
|
@ -70,7 +72,7 @@ defineDescribe('Sequence Renderer', [
|
||||||
],
|
],
|
||||||
stages: [
|
stages: [
|
||||||
{type: 'agent begin', agentNames: ['A', 'B'], mode: 'box'},
|
{type: 'agent begin', agentNames: ['A', 'B'], mode: 'box'},
|
||||||
connectionStage(['A', 'B']),
|
GENERATED.connect(['A', 'B']),
|
||||||
{type: 'agent end', agentNames: ['A', 'B'], mode: 'none'},
|
{type: 'agent end', agentNames: ['A', 'B'], mode: 'none'},
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
@ -105,10 +107,10 @@ defineDescribe('Sequence Renderer', [
|
||||||
agentNames: ['A', 'B', 'C'],
|
agentNames: ['A', 'B', 'C'],
|
||||||
mode: 'box',
|
mode: 'box',
|
||||||
},
|
},
|
||||||
connectionStage(['[', 'A']),
|
GENERATED.connect(['[', 'A']),
|
||||||
connectionStage(['A', 'B']),
|
GENERATED.connect(['A', 'B']),
|
||||||
connectionStage(['B', 'C']),
|
GENERATED.connect(['B', 'C']),
|
||||||
connectionStage(['C', ']']),
|
GENERATED.connect(['C', ']']),
|
||||||
{
|
{
|
||||||
type: 'agent end',
|
type: 'agent end',
|
||||||
agentNames: ['A', 'B', 'C'],
|
agentNames: ['A', 'B', 'C'],
|
||||||
|
@ -151,13 +153,13 @@ defineDescribe('Sequence Renderer', [
|
||||||
],
|
],
|
||||||
stages: [
|
stages: [
|
||||||
{type: 'agent begin', agentNames: ['A', 'B'], mode: 'box'},
|
{type: 'agent begin', agentNames: ['A', 'B'], mode: 'box'},
|
||||||
connectionStage(['A', 'B'], 'short'),
|
GENERATED.connect(['A', 'B'], 'short'),
|
||||||
{type: 'agent end', agentNames: ['B'], mode: 'cross'},
|
{type: 'agent end', agentNames: ['B'], mode: 'cross'},
|
||||||
{type: 'agent begin', agentNames: ['C'], mode: 'box'},
|
{type: 'agent begin', agentNames: ['C'], mode: 'box'},
|
||||||
connectionStage(['A', 'C'], 'long description here'),
|
GENERATED.connect(['A', 'C'], 'long description here'),
|
||||||
{type: 'agent end', agentNames: ['C'], mode: 'cross'},
|
{type: 'agent end', agentNames: ['C'], mode: 'cross'},
|
||||||
{type: 'agent begin', agentNames: ['D'], mode: 'box'},
|
{type: 'agent begin', agentNames: ['D'], mode: 'box'},
|
||||||
connectionStage(['A', 'D'], 'short again'),
|
GENERATED.connect(['A', 'D'], 'short again'),
|
||||||
{type: 'agent end', agentNames: ['A', 'D'], mode: 'cross'},
|
{type: 'agent end', agentNames: ['A', 'D'], mode: 'cross'},
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue