@polagram/core 0.0.4 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (119) hide show
  1. package/dist/index.d.ts +102 -113
  2. package/dist/polagram-core.js +1524 -1392
  3. package/dist/polagram-core.umd.cjs +23 -22
  4. package/package.json +3 -2
  5. package/dist/src/api.d.ts +0 -84
  6. package/dist/src/api.js +0 -183
  7. package/dist/src/ast/ast.test.d.ts +0 -1
  8. package/dist/src/ast/ast.test.js +0 -146
  9. package/dist/src/ast/index.d.ts +0 -119
  10. package/dist/src/ast/index.js +0 -2
  11. package/dist/src/config/index.d.ts +0 -1
  12. package/dist/src/config/index.js +0 -1
  13. package/dist/src/config/schema.d.ts +0 -198
  14. package/dist/src/config/schema.js +0 -82
  15. package/dist/src/config/schema.test.d.ts +0 -1
  16. package/dist/src/config/schema.test.js +0 -94
  17. package/dist/src/generator/base/walker.d.ts +0 -19
  18. package/dist/src/generator/base/walker.js +0 -56
  19. package/dist/src/generator/base/walker.test.d.ts +0 -1
  20. package/dist/src/generator/base/walker.test.js +0 -49
  21. package/dist/src/generator/generators/mermaid.d.ts +0 -24
  22. package/dist/src/generator/generators/mermaid.js +0 -140
  23. package/dist/src/generator/generators/mermaid.test.d.ts +0 -1
  24. package/dist/src/generator/generators/mermaid.test.js +0 -70
  25. package/dist/src/generator/generators/plantuml.d.ts +0 -17
  26. package/dist/src/generator/generators/plantuml.js +0 -131
  27. package/dist/src/generator/generators/plantuml.test.d.ts +0 -1
  28. package/dist/src/generator/generators/plantuml.test.js +0 -143
  29. package/dist/src/generator/interface.d.ts +0 -17
  30. package/dist/src/generator/interface.js +0 -1
  31. package/dist/src/index.d.ts +0 -13
  32. package/dist/src/index.js +0 -21
  33. package/dist/src/parser/base/lexer.d.ts +0 -18
  34. package/dist/src/parser/base/lexer.js +0 -95
  35. package/dist/src/parser/base/lexer.test.d.ts +0 -1
  36. package/dist/src/parser/base/lexer.test.js +0 -53
  37. package/dist/src/parser/base/parser.d.ts +0 -14
  38. package/dist/src/parser/base/parser.js +0 -43
  39. package/dist/src/parser/base/parser.test.d.ts +0 -1
  40. package/dist/src/parser/base/parser.test.js +0 -90
  41. package/dist/src/parser/base/token.d.ts +0 -18
  42. package/dist/src/parser/base/token.js +0 -1
  43. package/dist/src/parser/base/tokens.d.ts +0 -8
  44. package/dist/src/parser/base/tokens.js +0 -1
  45. package/dist/src/parser/format-detector.d.ts +0 -55
  46. package/dist/src/parser/format-detector.js +0 -98
  47. package/dist/src/parser/index.d.ts +0 -11
  48. package/dist/src/parser/index.js +0 -33
  49. package/dist/src/parser/index.test.d.ts +0 -1
  50. package/dist/src/parser/index.test.js +0 -23
  51. package/dist/src/parser/interface.d.ts +0 -8
  52. package/dist/src/parser/interface.js +0 -1
  53. package/dist/src/parser/languages/mermaid/constants.d.ts +0 -7
  54. package/dist/src/parser/languages/mermaid/constants.js +0 -20
  55. package/dist/src/parser/languages/mermaid/index.d.ts +0 -4
  56. package/dist/src/parser/languages/mermaid/index.js +0 -11
  57. package/dist/src/parser/languages/mermaid/lexer.d.ts +0 -14
  58. package/dist/src/parser/languages/mermaid/lexer.js +0 -152
  59. package/dist/src/parser/languages/mermaid/lexer.test.d.ts +0 -1
  60. package/dist/src/parser/languages/mermaid/lexer.test.js +0 -58
  61. package/dist/src/parser/languages/mermaid/parser.d.ts +0 -22
  62. package/dist/src/parser/languages/mermaid/parser.js +0 -340
  63. package/dist/src/parser/languages/mermaid/parser.test.d.ts +0 -1
  64. package/dist/src/parser/languages/mermaid/parser.test.js +0 -252
  65. package/dist/src/parser/languages/mermaid/tokens.d.ts +0 -9
  66. package/dist/src/parser/languages/mermaid/tokens.js +0 -1
  67. package/dist/src/parser/languages/plantuml/index.d.ts +0 -4
  68. package/dist/src/parser/languages/plantuml/index.js +0 -11
  69. package/dist/src/parser/languages/plantuml/lexer.d.ts +0 -15
  70. package/dist/src/parser/languages/plantuml/lexer.js +0 -143
  71. package/dist/src/parser/languages/plantuml/parser.d.ts +0 -23
  72. package/dist/src/parser/languages/plantuml/parser.js +0 -481
  73. package/dist/src/parser/languages/plantuml/parser.test.d.ts +0 -1
  74. package/dist/src/parser/languages/plantuml/parser.test.js +0 -236
  75. package/dist/src/parser/languages/plantuml/tokens.d.ts +0 -9
  76. package/dist/src/parser/languages/plantuml/tokens.js +0 -1
  77. package/dist/src/transformer/cleaners/prune-empty.d.ts +0 -9
  78. package/dist/src/transformer/cleaners/prune-empty.js +0 -27
  79. package/dist/src/transformer/cleaners/prune-empty.test.d.ts +0 -1
  80. package/dist/src/transformer/cleaners/prune-empty.test.js +0 -69
  81. package/dist/src/transformer/cleaners/prune-unused.d.ts +0 -5
  82. package/dist/src/transformer/cleaners/prune-unused.js +0 -48
  83. package/dist/src/transformer/cleaners/prune-unused.test.d.ts +0 -1
  84. package/dist/src/transformer/cleaners/prune-unused.test.js +0 -71
  85. package/dist/src/transformer/filters/focus.d.ts +0 -13
  86. package/dist/src/transformer/filters/focus.js +0 -71
  87. package/dist/src/transformer/filters/focus.test.d.ts +0 -1
  88. package/dist/src/transformer/filters/focus.test.js +0 -50
  89. package/dist/src/transformer/filters/remove.d.ts +0 -12
  90. package/dist/src/transformer/filters/remove.js +0 -82
  91. package/dist/src/transformer/filters/remove.test.d.ts +0 -1
  92. package/dist/src/transformer/filters/remove.test.js +0 -38
  93. package/dist/src/transformer/filters/resolve.d.ts +0 -9
  94. package/dist/src/transformer/filters/resolve.js +0 -32
  95. package/dist/src/transformer/filters/resolve.test.d.ts +0 -1
  96. package/dist/src/transformer/filters/resolve.test.js +0 -48
  97. package/dist/src/transformer/index.d.ts +0 -10
  98. package/dist/src/transformer/index.js +0 -10
  99. package/dist/src/transformer/lens.d.ts +0 -12
  100. package/dist/src/transformer/lens.js +0 -58
  101. package/dist/src/transformer/lens.test.d.ts +0 -1
  102. package/dist/src/transformer/lens.test.js +0 -60
  103. package/dist/src/transformer/orchestration/engine.d.ts +0 -5
  104. package/dist/src/transformer/orchestration/engine.js +0 -24
  105. package/dist/src/transformer/orchestration/engine.test.d.ts +0 -1
  106. package/dist/src/transformer/orchestration/engine.test.js +0 -52
  107. package/dist/src/transformer/orchestration/registry.d.ts +0 -10
  108. package/dist/src/transformer/orchestration/registry.js +0 -27
  109. package/dist/src/transformer/selector/matcher.d.ts +0 -9
  110. package/dist/src/transformer/selector/matcher.js +0 -62
  111. package/dist/src/transformer/selector/matcher.test.d.ts +0 -1
  112. package/dist/src/transformer/selector/matcher.test.js +0 -70
  113. package/dist/src/transformer/traverse/walker.d.ts +0 -14
  114. package/dist/src/transformer/traverse/walker.js +0 -67
  115. package/dist/src/transformer/traverse/walker.test.d.ts +0 -1
  116. package/dist/src/transformer/traverse/walker.test.js +0 -111
  117. package/dist/src/transformer/types.d.ts +0 -47
  118. package/dist/src/transformer/types.js +0 -1
  119. package/dist/tsconfig.tsbuildinfo +0 -1
@@ -1,90 +0,0 @@
1
- import { describe, expect, it } from 'vitest';
2
- import { BaseLexer } from './lexer';
3
- import { BaseParser } from './parser';
4
- // Mocks
5
- class MockLexer extends BaseLexer {
6
- constructor(tokens) {
7
- super("");
8
- Object.defineProperty(this, "tokens", {
9
- enumerable: true,
10
- configurable: true,
11
- writable: true,
12
- value: void 0
13
- });
14
- Object.defineProperty(this, "index", {
15
- enumerable: true,
16
- configurable: true,
17
- writable: true,
18
- value: 0
19
- });
20
- this.tokens = tokens;
21
- }
22
- nextToken() {
23
- if (this.index >= this.tokens.length) {
24
- return { type: 'EOF', literal: '', line: 0, column: 0, start: 0, end: 0 };
25
- }
26
- return this.tokens[this.index++];
27
- }
28
- }
29
- class TestParser extends BaseParser {
30
- parse() {
31
- return { kind: 'root', meta: { version: '1.0.0', source: 'unknown' }, participants: [], groups: [], events: [] };
32
- }
33
- // Expose protected methods
34
- getCurr() { return this.currToken; }
35
- getPeek() { return this.peekToken; }
36
- testAdvance() { this.advance(); }
37
- testCurTokenIs(t) { return this.curTokenIs(t); }
38
- testPeakTokenIs(t) { return this.peekTokenIs(t); }
39
- testExpectPeek(t) { return this.expectPeek(t); }
40
- }
41
- describe('BaseParser', () => {
42
- const tokens = [
43
- { type: 'IDENTIFIER', literal: 'A', line: 1, column: 0, start: 0, end: 1 },
44
- { type: 'ARROW', literal: '->', line: 1, column: 1, start: 1, end: 3 },
45
- { type: 'IDENTIFIER', literal: 'B', line: 1, column: 3, start: 3, end: 4 },
46
- ];
47
- it('should initialize curr and peek tokens', () => {
48
- const lexer = new MockLexer(tokens);
49
- const parser = new TestParser(lexer);
50
- // Constructor called advance twice.
51
- // 1st advance: curr=undefined, peek=Tokens[0]
52
- // 2nd advance: curr=Tokens[0], peek=Tokens[1]
53
- expect(parser.getCurr().type).toBe('IDENTIFIER');
54
- expect(parser.getCurr().literal).toBe('A');
55
- expect(parser.getPeek().type).toBe('ARROW');
56
- });
57
- it('should advance tokens', () => {
58
- const lexer = new MockLexer(tokens);
59
- const parser = new TestParser(lexer);
60
- parser.testAdvance();
61
- // curr=Tokens[1] (ARROW), peek=Tokens[2] (IDENTIFIER B)
62
- expect(parser.getCurr().type).toBe('ARROW');
63
- expect(parser.getPeek().type).toBe('IDENTIFIER');
64
- });
65
- it('should check current and peek token types', () => {
66
- const lexer = new MockLexer(tokens);
67
- const parser = new TestParser(lexer);
68
- expect(parser.testCurTokenIs('IDENTIFIER')).toBe(true);
69
- expect(parser.testPeakTokenIs('ARROW')).toBe(true);
70
- expect(parser.testPeakTokenIs('EOF')).toBe(false);
71
- });
72
- it('should expect peek token and advance if match', () => {
73
- const lexer = new MockLexer(tokens);
74
- const parser = new TestParser(lexer);
75
- // Peek is ARROW. Expect ARROW should likely succeed?
76
- // Method signature: expectPeek(t). If peek matches, advance and return true.
77
- const result = parser.testExpectPeek('ARROW');
78
- expect(result).toBe(true);
79
- // After advance, curr is ARROW.
80
- expect(parser.getCurr().type).toBe('ARROW');
81
- });
82
- it('should expect peek token and return false if mismatch', () => {
83
- const lexer = new MockLexer(tokens);
84
- const parser = new TestParser(lexer);
85
- const result = parser.testExpectPeek('EOF'); // Peek is ARROW
86
- expect(result).toBe(false);
87
- // Should not have advanced
88
- expect(parser.getCurr().type).toBe('IDENTIFIER');
89
- });
90
- });
@@ -1,18 +0,0 @@
1
- /**
2
- * Base token interface that all token types should extend.
3
- * Represents a lexical token with position information.
4
- */
5
- export interface BaseToken {
6
- /** Token type identifier */
7
- type: string;
8
- /** Literal string value of the token */
9
- literal: string;
10
- /** Line number (1-indexed) */
11
- line: number;
12
- /** Column number (0-indexed) */
13
- column: number;
14
- /** Start position in source (0-indexed) */
15
- start: number;
16
- /** End position in source (0-indexed) */
17
- end: number;
18
- }
@@ -1 +0,0 @@
1
- export {};
@@ -1,8 +0,0 @@
1
- export interface BaseToken {
2
- type: string;
3
- literal: string;
4
- line: number;
5
- column: number;
6
- start: number;
7
- end: number;
8
- }
@@ -1 +0,0 @@
1
- export {};
@@ -1,55 +0,0 @@
1
- /**
2
- * Supported diagram formats
3
- */
4
- export type DiagramFormat = 'mermaid' | 'plantuml';
5
- /**
6
- * Format detection utilities for diagram source code.
7
- * Detects diagram format based on file extension and content analysis.
8
- */
9
- export declare class FormatDetector {
10
- /**
11
- * File extensions mapped to their diagram formats
12
- */
13
- private static readonly EXTENSION_MAP;
14
- /**
15
- * Content patterns for format detection
16
- */
17
- private static readonly CONTENT_PATTERNS;
18
- /**
19
- * Detect diagram format from file path and content.
20
- *
21
- * @param filePath - Path to the diagram file
22
- * @param content - Content of the diagram file
23
- * @returns Detected format, or null if format cannot be determined
24
- *
25
- * @example
26
- * ```typescript
27
- * const format = FormatDetector.detect('diagram.puml', content);
28
- * if (format === 'plantuml') {
29
- * // Process as PlantUML
30
- * }
31
- * ```
32
- */
33
- static detect(filePath: string, content: string): DiagramFormat | null;
34
- /**
35
- * Detect format based on file extension.
36
- *
37
- * @param filePath - Path to the diagram file
38
- * @returns Detected format, or null if extension is not recognized
39
- */
40
- static detectByExtension(filePath: string): DiagramFormat | null;
41
- /**
42
- * Detect format based on content patterns.
43
- *
44
- * @param content - Content of the diagram file
45
- * @returns Detected format, or null if no pattern matches
46
- */
47
- static detectByContent(content: string): DiagramFormat | null;
48
- /**
49
- * Get file extension for a given format.
50
- *
51
- * @param format - Diagram format
52
- * @returns Default file extension for the format
53
- */
54
- static getDefaultExtension(format: DiagramFormat): string;
55
- }
@@ -1,98 +0,0 @@
1
- /**
2
- * Format detection utilities for diagram source code.
3
- * Detects diagram format based on file extension and content analysis.
4
- */
5
- export class FormatDetector {
6
- /**
7
- * Detect diagram format from file path and content.
8
- *
9
- * @param filePath - Path to the diagram file
10
- * @param content - Content of the diagram file
11
- * @returns Detected format, or null if format cannot be determined
12
- *
13
- * @example
14
- * ```typescript
15
- * const format = FormatDetector.detect('diagram.puml', content);
16
- * if (format === 'plantuml') {
17
- * // Process as PlantUML
18
- * }
19
- * ```
20
- */
21
- static detect(filePath, content) {
22
- // Try extension-based detection first
23
- const extensionFormat = this.detectByExtension(filePath);
24
- if (extensionFormat) {
25
- return extensionFormat;
26
- }
27
- // Fall back to content-based detection
28
- return this.detectByContent(content);
29
- }
30
- /**
31
- * Detect format based on file extension.
32
- *
33
- * @param filePath - Path to the diagram file
34
- * @returns Detected format, or null if extension is not recognized
35
- */
36
- static detectByExtension(filePath) {
37
- const ext = filePath.toLowerCase().match(/\.[^.]+$/)?.[0];
38
- if (!ext) {
39
- return null;
40
- }
41
- return this.EXTENSION_MAP[ext] || null;
42
- }
43
- /**
44
- * Detect format based on content patterns.
45
- *
46
- * @param content - Content of the diagram file
47
- * @returns Detected format, or null if no pattern matches
48
- */
49
- static detectByContent(content) {
50
- for (const { pattern, format } of this.CONTENT_PATTERNS) {
51
- if (pattern.test(content)) {
52
- return format;
53
- }
54
- }
55
- return null;
56
- }
57
- /**
58
- * Get file extension for a given format.
59
- *
60
- * @param format - Diagram format
61
- * @returns Default file extension for the format
62
- */
63
- static getDefaultExtension(format) {
64
- switch (format) {
65
- case 'plantuml':
66
- return '.puml';
67
- case 'mermaid':
68
- return '.mmd';
69
- }
70
- }
71
- }
72
- /**
73
- * File extensions mapped to their diagram formats
74
- */
75
- Object.defineProperty(FormatDetector, "EXTENSION_MAP", {
76
- enumerable: true,
77
- configurable: true,
78
- writable: true,
79
- value: {
80
- '.puml': 'plantuml',
81
- '.plantuml': 'plantuml',
82
- '.pu': 'plantuml',
83
- '.mmd': 'mermaid',
84
- '.mermaid': 'mermaid',
85
- }
86
- });
87
- /**
88
- * Content patterns for format detection
89
- */
90
- Object.defineProperty(FormatDetector, "CONTENT_PATTERNS", {
91
- enumerable: true,
92
- configurable: true,
93
- writable: true,
94
- value: [
95
- { pattern: /^\s*@startuml/m, format: 'plantuml' },
96
- { pattern: /^\s*sequenceDiagram/m, format: 'mermaid' },
97
- ]
98
- });
@@ -1,11 +0,0 @@
1
- import { DiagramParser } from './interface';
2
- /**
3
- * Parser Factory
4
- * Centralizes retrieval of parser strategies.
5
- */
6
- export declare class ParserFactory {
7
- private static parsers;
8
- static register(language: string, parser: DiagramParser): void;
9
- static getParser(language: string): DiagramParser;
10
- }
11
- export { FormatDetector, type DiagramFormat } from './format-detector';
@@ -1,33 +0,0 @@
1
- var _a;
2
- import { mermaidParser } from './languages/mermaid';
3
- import { plantumlParser } from './languages/plantuml';
4
- /**
5
- * Parser Factory
6
- * Centralizes retrieval of parser strategies.
7
- */
8
- export class ParserFactory {
9
- static register(language, parser) {
10
- this.parsers.set(language, parser);
11
- }
12
- static getParser(language) {
13
- const parser = this.parsers.get(language);
14
- if (!parser) {
15
- throw new Error(`Parser for language '${language}' not found.`);
16
- }
17
- return parser;
18
- }
19
- }
20
- _a = ParserFactory;
21
- Object.defineProperty(ParserFactory, "parsers", {
22
- enumerable: true,
23
- configurable: true,
24
- writable: true,
25
- value: new Map()
26
- });
27
- (() => {
28
- // Register built-in parsers
29
- _a.register('mermaid', mermaidParser);
30
- _a.register('plantuml', plantumlParser);
31
- })();
32
- // Re-export format detector
33
- export { FormatDetector } from './format-detector';
@@ -1 +0,0 @@
1
- export {};
@@ -1,23 +0,0 @@
1
- import { describe, expect, it } from 'vitest';
2
- import { ParserFactory } from './index';
3
- describe('ParserFactory', () => {
4
- it('should retrieve registered parser', () => {
5
- const parser = ParserFactory.getParser('mermaid');
6
- expect(parser).toBeDefined();
7
- // Since we import implemented parser, we expect checking it conforms to interface
8
- expect(typeof parser.parse).toBe('function');
9
- });
10
- it('should throw error for unknown language', () => {
11
- expect(() => {
12
- ParserFactory.getParser('unknown-lang');
13
- }).toThrow("Parser for language 'unknown-lang' not found.");
14
- });
15
- it('should allow registering new parser', () => {
16
- const mockParser = {
17
- parse: (_code) => ({ kind: 'root', meta: { version: '1.0.0', source: 'unknown' }, participants: [], groups: [], events: [] })
18
- };
19
- ParserFactory.register('test-lang', mockParser);
20
- const retrieved = ParserFactory.getParser('test-lang');
21
- expect(retrieved).toBe(mockParser);
22
- });
23
- });
@@ -1,8 +0,0 @@
1
- import { PolagramRoot } from '../ast';
2
- /**
3
- * Strategy Interface for Diagram Parsing.
4
- * Implements the Strategy Pattern: different formats implement this interface.
5
- */
6
- export interface DiagramParser {
7
- parse(code: string): PolagramRoot;
8
- }
@@ -1 +0,0 @@
1
- export {};
@@ -1,7 +0,0 @@
1
- import { MessageNode } from '../../../ast';
2
- export declare const ARROW_MAPPING: Record<string, {
3
- type: MessageNode['type'];
4
- style: MessageNode['style'];
5
- }>;
6
- export declare const REVERSE_ARROW_MAPPING: Record<string, string>;
7
- export declare function getArrowString(type: MessageNode['type'], style: MessageNode['style']): string;
@@ -1,20 +0,0 @@
1
- export const ARROW_MAPPING = {
2
- '->': { type: 'sync', style: { line: 'solid', head: 'open' } },
3
- '->>': { type: 'sync', style: { line: 'solid', head: 'arrow' } },
4
- '-->': { type: 'reply', style: { line: 'dotted', head: 'open' } },
5
- '-->>': { type: 'reply', style: { line: 'dotted', head: 'arrow' } },
6
- '-)': { type: 'async', style: { line: 'solid', head: 'async' } },
7
- '--)': { type: 'async', style: { line: 'dotted', head: 'async' } },
8
- '-x': { type: 'destroy', style: { line: 'solid', head: 'cross' } },
9
- '--x': { type: 'destroy', style: { line: 'dotted', head: 'cross' } },
10
- };
11
- export const REVERSE_ARROW_MAPPING = Object.entries(ARROW_MAPPING).reduce((acc, [key, value]) => {
12
- // Create a unique key for the style + type combination to map back to the string
13
- const lookupKey = JSON.stringify({ type: value.type, style: value.style });
14
- acc[lookupKey] = key;
15
- return acc;
16
- }, {});
17
- export function getArrowString(type, style) {
18
- const key = JSON.stringify({ type, style });
19
- return REVERSE_ARROW_MAPPING[key] || '->>'; // Default fallthrough
20
- }
@@ -1,4 +0,0 @@
1
- import { DiagramParser } from '../../interface';
2
- export declare const mermaidParser: DiagramParser;
3
- export { Lexer } from './lexer';
4
- export { Parser } from './parser';
@@ -1,11 +0,0 @@
1
- import { Lexer } from './lexer';
2
- import { Parser } from './parser';
3
- export const mermaidParser = {
4
- parse: (code) => {
5
- const lexer = new Lexer(code);
6
- const parser = new Parser(lexer);
7
- return parser.parse();
8
- }
9
- };
10
- export { Lexer } from './lexer';
11
- export { Parser } from './parser';
@@ -1,14 +0,0 @@
1
- import { BaseLexer } from '../../base/lexer';
2
- import { Token } from './tokens';
3
- export declare class Lexer extends BaseLexer<Token> {
4
- constructor(input: string);
5
- nextToken(): Token;
6
- private newToken;
7
- private readIdentifier;
8
- private readNumber;
9
- private readString;
10
- private isArrowStart;
11
- private readArrow;
12
- private readMulti;
13
- private lookupIdent;
14
- }
@@ -1,152 +0,0 @@
1
- import { BaseLexer } from '../../base/lexer';
2
- export class Lexer extends BaseLexer {
3
- constructor(input) {
4
- super(input);
5
- }
6
- nextToken() {
7
- this.skipWhitespace();
8
- const start = this.position;
9
- const startColumn = this.column;
10
- let tok;
11
- switch (this.ch) {
12
- case ':':
13
- tok = this.newToken('COLON', this.ch, start, startColumn);
14
- break;
15
- case ',':
16
- tok = this.newToken('COMMA', this.ch, start, startColumn);
17
- break;
18
- case '+':
19
- tok = this.newToken('PLUS', this.ch, start, startColumn);
20
- break;
21
- case '-':
22
- if (this.isArrowStart()) {
23
- const literal = this.readArrow();
24
- tok = this.newToken('ARROW', literal, start, startColumn);
25
- return tok;
26
- }
27
- else {
28
- tok = this.newToken('MINUS', this.ch, start, startColumn);
29
- }
30
- break;
31
- case '"':
32
- // eslint-disable-next-line no-case-declarations
33
- const str = this.readString();
34
- tok = this.newToken('STRING', str, start, startColumn);
35
- return tok;
36
- case '\n':
37
- tok = this.newToken('NEWLINE', this.ch, start, startColumn);
38
- break;
39
- case '':
40
- tok = this.newToken('EOF', '', start, startColumn);
41
- break;
42
- default:
43
- if (this.isLetter(this.ch)) {
44
- const literal = this.readIdentifier();
45
- const type = this.lookupIdent(literal);
46
- return this.newToken(type, literal, start, startColumn);
47
- }
48
- else if (this.isDigit(this.ch)) {
49
- const literal = this.readNumber();
50
- return this.newToken('IDENTIFIER', literal, start, startColumn);
51
- }
52
- else {
53
- tok = this.newToken('UNKNOWN', this.ch, start, startColumn);
54
- }
55
- }
56
- this.readChar();
57
- return tok;
58
- }
59
- newToken(type, literal, start, startColumn) {
60
- return {
61
- type: type,
62
- literal,
63
- line: this.line,
64
- column: startColumn,
65
- start,
66
- // If the lexer position has advanced beyond the start (consumed tokens like String/Arrow), use that position.
67
- // Otherwise (simple chars), assume length-based calculation.
68
- end: (this.position > start) ? this.position : start + literal.length
69
- };
70
- }
71
- readIdentifier() {
72
- const position = this.position;
73
- while (this.isLetter(this.ch) || this.isDigit(this.ch)) {
74
- this.readChar();
75
- }
76
- return this.input.slice(position, this.position);
77
- }
78
- readNumber() {
79
- const position = this.position;
80
- while (this.isDigit(this.ch)) {
81
- this.readChar();
82
- }
83
- return this.input.slice(position, this.position);
84
- }
85
- readString() {
86
- const position = this.position + 1;
87
- this.readChar();
88
- while (this.ch !== '"' && this.ch !== '' && this.ch !== '\n') {
89
- this.readChar();
90
- }
91
- const str = this.input.slice(position, this.position);
92
- if (this.ch === '"') {
93
- // Logic handled in nextToken via readChar or here?
94
- // In BaseLexer readChar advances.
95
- // Original logic was slightly tricky.
96
- // Let's keep consistent with valid implementation.
97
- }
98
- this.readChar();
99
- return str;
100
- }
101
- isArrowStart() {
102
- if (this.ch !== '-')
103
- return false;
104
- const next = this.peekChar();
105
- return next === '>' || next === '-' || next === ')' || next === 'x';
106
- }
107
- readArrow() {
108
- const potential4 = this.input.slice(this.position, this.position + 4);
109
- if (potential4 === '-->>') {
110
- this.readMulti(4);
111
- return '-->>';
112
- }
113
- const potential3 = this.input.slice(this.position, this.position + 3);
114
- if (potential3 === '-->' || potential3 === '--)' || potential3 === '->>' || potential3 === '--x') {
115
- this.readMulti(3);
116
- return potential3;
117
- }
118
- const potential2 = this.input.slice(this.position, this.position + 2);
119
- if (potential2 === '->' || potential2 === '-)' || potential2 === '-x') {
120
- this.readMulti(2);
121
- return potential2;
122
- }
123
- return '-';
124
- }
125
- readMulti(count) {
126
- for (let i = 0; i < count; i++)
127
- this.readChar();
128
- }
129
- lookupIdent(ident) {
130
- const keywords = {
131
- 'sequenceDiagram': 'SEQUENCE_DIAGRAM',
132
- 'participant': 'PARTICIPANT',
133
- 'actor': 'ACTOR',
134
- 'loop': 'LOOP',
135
- 'alt': 'ALT',
136
- 'opt': 'OPT',
137
- 'end': 'END',
138
- 'else': 'ELSE',
139
- 'note': 'NOTE',
140
- 'left': 'LEFT',
141
- 'right': 'RIGHT',
142
- 'over': 'OVER',
143
- 'of': 'OF',
144
- 'as': 'AS',
145
- 'title': 'TITLE',
146
- 'activate': 'ACTIVATE',
147
- 'deactivate': 'DEACTIVATE',
148
- 'box': 'BOX'
149
- };
150
- return keywords[ident] || 'IDENTIFIER';
151
- }
152
- }
@@ -1 +0,0 @@
1
- export {};
@@ -1,58 +0,0 @@
1
- import { describe, expect, it } from 'vitest';
2
- import { Lexer } from './lexer';
3
- describe('Mermaid Lexer', () => {
4
- const checkValues = (input, expected) => {
5
- const lexer = new Lexer(input);
6
- for (const [type, literal] of expected) {
7
- const token = lexer.nextToken();
8
- expect(token.type).toBe(type);
9
- expect(token.literal).toBe(literal);
10
- }
11
- };
12
- it('should parse simple tokens', () => {
13
- const input = 'sequenceDiagram participant :';
14
- checkValues(input, [
15
- ['SEQUENCE_DIAGRAM', 'sequenceDiagram'],
16
- ['PARTICIPANT', 'participant'],
17
- ['COLON', ':']
18
- ]);
19
- });
20
- it('should parse keywords correctly', () => {
21
- // Re-verify 'participant'
22
- const lexer = new Lexer('participant actor loop');
23
- const t1 = lexer.nextToken();
24
- expect(t1.type).toBe('PARTICIPANT');
25
- const t2 = lexer.nextToken();
26
- expect(t2.type).toBe('ACTOR');
27
- const t3 = lexer.nextToken();
28
- expect(t3.type).toBe('LOOP');
29
- });
30
- it('should parse arrows', () => {
31
- checkValues('-> --> ->> -->> -) --) -x --x', [
32
- ['ARROW', '->'],
33
- ['ARROW', '-->'],
34
- ['ARROW', '->>'],
35
- ['ARROW', '-->>'],
36
- ['ARROW', '-)'],
37
- ['ARROW', '--)'],
38
- // Let's debug my lexer readArrow implementation logic mentally.
39
- // potential3: '--)' is checked.
40
- // So expected is ARROW '--)'
41
- ]);
42
- const l2 = new Lexer('--)');
43
- const t = l2.nextToken();
44
- expect(t.type).toBe('ARROW');
45
- expect(t.literal).toBe('--)');
46
- });
47
- it('should parse strings', () => {
48
- checkValues('"hello world"', [
49
- ['STRING', 'hello world']
50
- ]);
51
- });
52
- it('should parse plus and minus', () => {
53
- checkValues('+ -', [
54
- ['PLUS', '+'],
55
- ['MINUS', '-']
56
- ]);
57
- });
58
- });
@@ -1,22 +0,0 @@
1
- import { PolagramRoot } from '../../../ast';
2
- import { BaseParser } from '../../base/parser';
3
- import { Lexer } from './lexer';
4
- import { Token } from './tokens';
5
- export declare class Parser extends BaseParser<Token> {
6
- private currentGroup;
7
- private idCounters;
8
- constructor(lexer: Lexer);
9
- parse(): PolagramRoot;
10
- private parseBlock;
11
- private isParticipantToken;
12
- private parseGroup;
13
- private parseFragment;
14
- private parseParticipant;
15
- private parseNote;
16
- private parseActivation;
17
- private parseMessage;
18
- private resolveArrow;
19
- private generateId;
20
- private readRestOfLine;
21
- private ensureParticipant;
22
- }