Skip to content

Commit 4aae7ab

Browse files
committed
Accept 'subgraph' form in edge parsing
1 parent 2070187 commit 4aae7ab

2 files changed

Lines changed: 52 additions & 22 deletions

File tree

src/lexer.ts

Lines changed: 18 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -510,13 +510,9 @@ function parseGraph(lexer: Lexer): NormalizedGraph {
510510

511511
function parseStatement(owner: NormalizedGraph | NormalizedSubgraph): void {
512512
// stmt: node_stmt | edge_stmt | attr_stmt | ID '=' ID | subgraph
513-
if (lexer.peekIsLiteral('{')) {
514-
const subgraph = owner.upsertSubgraph(null);
515-
parseStatementList(subgraph);
513+
if (lexer.peekIsLiteral('{') || lexer.optionalKeyword('subgraph')) {
514+
const tailNodes = parseSubgraph(owner);
516515
if (optionalEdgeOp()) {
517-
const tailNodes: NodeID[] = subgraph
518-
.sortedNodes()
519-
.map((node) => [node, undefined]);
520516
parseEdges(tailNodes, owner);
521517
}
522518
return;
@@ -547,15 +543,8 @@ function parseGraph(lexer: Lexer): NormalizedGraph {
547543
}
548544

549545
case 'subgraph': {
550-
const name = lexer.peekIsLiteral('{')
551-
? null
552-
: lexer.expectID('subgraph name').value;
553-
const subgraph = owner.upsertSubgraph(name);
554-
parseStatementList(subgraph);
546+
const tailNodes = parseSubgraph(owner);
555547
if (optionalEdgeOp()) {
556-
const tailNodes: NodeID[] = subgraph
557-
.sortedNodes()
558-
.map((node) => [node, undefined]);
559548
parseEdges(tailNodes, owner);
560549
}
561550
break;
@@ -579,20 +568,27 @@ function parseGraph(lexer: Lexer): NormalizedGraph {
579568
}
580569
}
581570

571+
function parseSubgraph(
572+
owner: NormalizedGraph | NormalizedSubgraph,
573+
): NodeID[] {
574+
const name = lexer.peekIsLiteral('{')
575+
? null
576+
: lexer.expectID('subgraph name').value;
577+
const subgraph = owner.upsertSubgraph(name);
578+
parseStatementList(subgraph);
579+
return subgraph.sortedNodes().map((node) => [node, undefined]);
580+
}
581+
582582
function parseEdges(
583583
tailNodes: NodeID[],
584584
owner: NormalizedGraph | NormalizedSubgraph,
585585
) {
586586
const newEdges = new Set<NormalizedEdge>();
587587
do {
588-
let headNodes: NodeID[];
589-
if (lexer.peekIsLiteral('{')) {
590-
const subgraph = owner.upsertSubgraph(null);
591-
parseStatementList(subgraph);
592-
headNodes = subgraph.sortedNodes().map((node) => [node, undefined]);
593-
} else {
594-
headNodes = [parseNodeID(owner)];
595-
}
588+
const headNodes =
589+
lexer.peekIsLiteral('{') || lexer.optionalKeyword('subgraph')
590+
? parseSubgraph(owner)
591+
: [parseNodeID(owner)];
596592

597593
for (const tail of tailNodes) {
598594
for (const head of headNodes) {

test/dot-language.test.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -428,4 +428,38 @@ describe('Dot language support', () => {
428428
}
429429
`);
430430
});
431+
432+
it('connect nodes in subgraphs with edges', () => {
433+
const result = renderString(`
434+
digraph {
435+
subgraph tails { a b } -> subgraph heads { c d }
436+
}
437+
`);
438+
expectSuccessResult(result).toMatchInlineSnapshot(`
439+
digraph {
440+
graph [bb="0,0,126,108"];
441+
node [label="\\N"];
442+
subgraph tails {
443+
a [height=0.5,
444+
pos="27,90",
445+
width=0.75];
446+
b [height=0.5,
447+
pos="99,90",
448+
width=0.75];
449+
}
450+
subgraph heads {
451+
c [height=0.5,
452+
pos="27,18",
453+
width=0.75];
454+
d [height=0.5,
455+
pos="99,18",
456+
width=0.75];
457+
}
458+
a -> c [pos="e,27,36.104 27,71.697 27,64.407 27,55.726 27,47.536"];
459+
a -> d [pos="e,84.101,33.485 41.918,74.496 51.765,64.923 64.861,52.19 76.026,41.336"];
460+
b -> c [pos="e,41.899,33.485 84.082,74.496 74.235,64.923 61.139,52.19 49.974,41.336"];
461+
b -> d [pos="e,99,36.104 99,71.697 99,64.407 99,55.726 99,47.536"];
462+
}
463+
`);
464+
});
431465
});

0 commit comments

Comments
 (0)