mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-09-13 20:39:38 +02:00
feat(parser): create common
directory for langium parsers
This commit is contained in:
51
packages/parser/src/language/chevrotainWrapper.ts
Normal file
51
packages/parser/src/language/chevrotainWrapper.ts
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
|
|
||||||
|
type CustomPatternMatcherReturn = [string] & { payload?: any };
|
||||||
|
|
||||||
|
export type CustomPatternMatcherFunc = (
|
||||||
|
text: string,
|
||||||
|
offset: number,
|
||||||
|
tokens: IToken[],
|
||||||
|
groups: {
|
||||||
|
[groupName: string]: IToken[];
|
||||||
|
}
|
||||||
|
) => CustomPatternMatcherReturn | RegExpExecArray | null;
|
||||||
|
|
||||||
|
interface ICustomPattern {
|
||||||
|
exec: CustomPatternMatcherFunc;
|
||||||
|
}
|
||||||
|
|
||||||
|
type TokenPattern = RegExp | string | CustomPatternMatcherFunc | ICustomPattern;
|
||||||
|
|
||||||
|
export interface IToken {
|
||||||
|
image: string;
|
||||||
|
startOffset: number;
|
||||||
|
startLine?: number;
|
||||||
|
startColumn?: number;
|
||||||
|
endOffset?: number;
|
||||||
|
endLine?: number;
|
||||||
|
endColumn?: number;
|
||||||
|
isInsertedInRecovery?: boolean;
|
||||||
|
tokenTypeIdx: number;
|
||||||
|
tokenType: TokenType;
|
||||||
|
payload?: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TokenType {
|
||||||
|
name: string;
|
||||||
|
GROUP?: string;
|
||||||
|
PATTERN?: TokenPattern;
|
||||||
|
LABEL?: string;
|
||||||
|
LONGER_ALT?: TokenType | TokenType[];
|
||||||
|
POP_MODE?: boolean;
|
||||||
|
PUSH_MODE?: string;
|
||||||
|
LINE_BREAKS?: boolean;
|
||||||
|
CATEGORIES?: TokenType[];
|
||||||
|
tokenTypeIdx?: number;
|
||||||
|
categoryMatches?: number[];
|
||||||
|
categoryMatchesMap?: {
|
||||||
|
[tokType: number]: boolean;
|
||||||
|
};
|
||||||
|
isParent?: boolean;
|
||||||
|
START_CHARS_HINT?: (string | number)[];
|
||||||
|
}
|
14
packages/parser/src/language/common/common.langium
Normal file
14
packages/parser/src/language/common/common.langium
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
fragment TitleAndAccessibilities:
|
||||||
|
((accDescr=ACC_DESCR | accTitle=ACC_TITLE | title=TITLE) NEWLINE+)+
|
||||||
|
;
|
||||||
|
|
||||||
|
terminal NEWLINE: /\r?\n/;
|
||||||
|
terminal ACC_DESCR: /accDescr(?:[\t ]*:[\t ]*[^\n\r]*?(?=%%)|\s*{[^}]*})|accDescr(?:[\t ]*:[\t ]*[^\n\r]*|\s*{[^}]*})/;
|
||||||
|
terminal ACC_TITLE: /accTitle[\t ]*:[\t ]*[^\n\r]*?(?=%%)|accTitle[\t ]*:[\t ]*[^\n\r]*/;
|
||||||
|
terminal TITLE: /title(?:[\t ]+[^\n\r]*?|)(?=%%)|title(?:[\t ]+[^\n\r]*|)/;
|
||||||
|
|
||||||
|
hidden terminal WHITESPACE: /[\t ]+/;
|
||||||
|
// TODO: add YAML_COMMENT hidden rule without interfere actual grammar
|
||||||
|
hidden terminal YAML: /---[\t ]*\r?\n[\S\s]*?---[\t ]*(?!.)/;
|
||||||
|
hidden terminal DIRECTIVE: /[\t ]*%%{[\S\s]*?}%%\s*/;
|
||||||
|
hidden terminal SINGLE_LINE_COMMENT: /[\t ]*%%[^\n\r]*/;
|
8
packages/parser/src/language/common/commonLexer.ts
Normal file
8
packages/parser/src/language/common/commonLexer.ts
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
import type { LexerResult } from 'langium';
|
||||||
|
import { DefaultLexer } from 'langium';
|
||||||
|
|
||||||
|
export class CommonLexer extends DefaultLexer {
|
||||||
|
public override tokenize(text: string): LexerResult {
|
||||||
|
return super.tokenize(text + '\n');
|
||||||
|
}
|
||||||
|
}
|
14
packages/parser/src/language/common/commonMatcher.ts
Normal file
14
packages/parser/src/language/common/commonMatcher.ts
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
/**
|
||||||
|
* Matches single and multiline accessible description
|
||||||
|
*/
|
||||||
|
export const accessibilityDescrRegex = /accDescr(?:[\t ]*:[\t ]*([^\n\r]*)|\s*{([^}]*)})/;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Matches single line accessible title
|
||||||
|
*/
|
||||||
|
export const accessibilityTitleRegex = /accTitle[\t ]*:[\t ]*([^\n\r]*)/;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Matches a single line title
|
||||||
|
*/
|
||||||
|
export const titleRegex = /title([\t ]+([^\n\r]*)|)/;
|
74
packages/parser/src/language/common/commonValueConverters.ts
Normal file
74
packages/parser/src/language/common/commonValueConverters.ts
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
import type { CstNode, GrammarAST, ValueType } from 'langium';
|
||||||
|
import { DefaultValueConverter } from 'langium';
|
||||||
|
|
||||||
|
import { accessibilityDescrRegex, accessibilityTitleRegex, titleRegex } from './commonMatcher.js';
|
||||||
|
|
||||||
|
export class CommonValueConverter extends DefaultValueConverter {
|
||||||
|
protected override runConverter(
|
||||||
|
rule: GrammarAST.AbstractRule,
|
||||||
|
input: string,
|
||||||
|
cstNode: CstNode
|
||||||
|
): ValueType {
|
||||||
|
const value: ValueType | undefined = CommonValueConverter.customRunConverter(
|
||||||
|
rule,
|
||||||
|
input,
|
||||||
|
cstNode
|
||||||
|
);
|
||||||
|
if (value === undefined) {
|
||||||
|
return super.runConverter(rule, input, cstNode);
|
||||||
|
} else {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A method contains convert logic to be used by class itself or `MermaidValueConverter`.
|
||||||
|
*
|
||||||
|
* @param rule - Parsed rule.
|
||||||
|
* @param input - Matched string.
|
||||||
|
* @param _cstNode - Node in the Concrete Syntax Tree (CST).
|
||||||
|
* @returns converted the value if it's common rule or `undefined` if it's not.
|
||||||
|
*/
|
||||||
|
public static customRunConverter(
|
||||||
|
rule: GrammarAST.AbstractRule,
|
||||||
|
input: string,
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
_cstNode: CstNode
|
||||||
|
): ValueType | undefined {
|
||||||
|
let regex: RegExp | undefined;
|
||||||
|
switch (rule.name) {
|
||||||
|
case 'ACC_DESCR': {
|
||||||
|
regex = new RegExp(accessibilityDescrRegex.source);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'ACC_TITLE': {
|
||||||
|
regex = new RegExp(accessibilityTitleRegex.source);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'TITLE': {
|
||||||
|
regex = new RegExp(titleRegex.source);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (regex === undefined) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
const match = regex.exec(input);
|
||||||
|
if (match === null) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
// single line title, accTitle, accDescr
|
||||||
|
if (match[1] !== undefined) {
|
||||||
|
return match[1].trim().replaceAll(/[\t ]{2,}/gm, ' ');
|
||||||
|
}
|
||||||
|
// multi line accDescr
|
||||||
|
if (match[2] !== undefined) {
|
||||||
|
return match[2]
|
||||||
|
.replaceAll(/^\s*/gm, '')
|
||||||
|
.replaceAll(/\s+$/gm, '')
|
||||||
|
.replaceAll(/[\t ]{2,}/gm, ' ')
|
||||||
|
.replaceAll(/[\n\r]{2,}/gm, '\n');
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
}
|
2
packages/parser/src/language/common/index.ts
Normal file
2
packages/parser/src/language/common/index.ts
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
export * from './commonLexer.js';
|
||||||
|
export * from './commonValueConverters.js';
|
5
packages/parser/src/language/index.ts
Normal file
5
packages/parser/src/language/index.ts
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
export * from './generated/ast.js';
|
||||||
|
export * from './generated/grammar.js';
|
||||||
|
export * from './generated/module.js';
|
||||||
|
|
||||||
|
export * from './common/index.js';
|
Reference in New Issue
Block a user