mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-01-28 07:03:17 +08:00
refactor: Simplify langium by abstracting common functions
This commit is contained in:
parent
795baedbb1
commit
11b60ce3b8
@ -1,2 +1,2 @@
|
|||||||
export * from './commonLexer.js';
|
export * from './commonLexer.js';
|
||||||
export * from './commonValueConverters.js';
|
export * from './valueConverter.js';
|
||||||
|
26
packages/parser/src/language/common/tokenBuilder.ts
Normal file
26
packages/parser/src/language/common/tokenBuilder.ts
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
import type { GrammarAST, Stream, TokenBuilderOptions } from 'langium';
|
||||||
|
import type { TokenType } from '../chevrotainWrapper.js';
|
||||||
|
|
||||||
|
import { DefaultTokenBuilder } from 'langium';
|
||||||
|
|
||||||
|
export class MermaidTokenBuilder extends DefaultTokenBuilder {
|
||||||
|
private keywords: Set<string>;
|
||||||
|
constructor(public _keywords: string[]) {
|
||||||
|
super();
|
||||||
|
this.keywords = new Set<string>(_keywords);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override buildKeywordTokens(
|
||||||
|
rules: Stream<GrammarAST.AbstractRule>,
|
||||||
|
terminalTokens: TokenType[],
|
||||||
|
options?: TokenBuilderOptions
|
||||||
|
): TokenType[] {
|
||||||
|
const tokenTypes: TokenType[] = super.buildKeywordTokens(rules, terminalTokens, options);
|
||||||
|
tokenTypes.forEach((tokenType: TokenType): void => {
|
||||||
|
if (this.keywords.has(tokenType.name) && tokenType.PATTERN !== undefined) {
|
||||||
|
tokenType.PATTERN = new RegExp(tokenType.PATTERN.toString() + '(?!\\S)');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return tokenTypes;
|
||||||
|
}
|
||||||
|
}
|
@ -1,38 +1,45 @@
|
|||||||
|
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||||
import type { CstNode, GrammarAST, ValueType } from 'langium';
|
import type { CstNode, GrammarAST, ValueType } from 'langium';
|
||||||
import { DefaultValueConverter } from 'langium';
|
import { DefaultValueConverter } from 'langium';
|
||||||
|
|
||||||
import { accessibilityDescrRegex, accessibilityTitleRegex, titleRegex } from './commonMatcher.js';
|
import { accessibilityDescrRegex, accessibilityTitleRegex, titleRegex } from './commonMatcher.js';
|
||||||
|
|
||||||
export class CommonValueConverter extends DefaultValueConverter {
|
export abstract class MermaidValueConverter extends DefaultValueConverter {
|
||||||
|
/**
|
||||||
|
* A method contains convert logic to be used by class.
|
||||||
|
*
|
||||||
|
* @param rule - Parsed rule.
|
||||||
|
* @param input - Matched string.
|
||||||
|
* @param cstNode - Node in the Concrete Syntax Tree (CST).
|
||||||
|
* @returns converted the value if it's available or `undefined` if it's not.
|
||||||
|
*/
|
||||||
|
protected abstract runCustomConverter(
|
||||||
|
rule: GrammarAST.AbstractRule,
|
||||||
|
input: string,
|
||||||
|
cstNode: CstNode
|
||||||
|
): ValueType | undefined;
|
||||||
|
|
||||||
protected override runConverter(
|
protected override runConverter(
|
||||||
rule: GrammarAST.AbstractRule,
|
rule: GrammarAST.AbstractRule,
|
||||||
input: string,
|
input: string,
|
||||||
cstNode: CstNode
|
cstNode: CstNode
|
||||||
): ValueType {
|
): ValueType {
|
||||||
const value: ValueType | undefined = CommonValueConverter.customRunConverter(
|
let value: ValueType | undefined = this.runCommonConverter(rule, input, cstNode);
|
||||||
rule,
|
|
||||||
input,
|
if (value === undefined) {
|
||||||
cstNode
|
value = this.runCustomConverter(rule, input, cstNode);
|
||||||
);
|
}
|
||||||
|
|
||||||
if (value === undefined) {
|
if (value === undefined) {
|
||||||
return super.runConverter(rule, input, cstNode);
|
return super.runConverter(rule, input, cstNode);
|
||||||
} else {
|
|
||||||
return value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private runCommonConverter(
|
||||||
* 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,
|
rule: GrammarAST.AbstractRule,
|
||||||
input: string,
|
input: string,
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
||||||
_cstNode: CstNode
|
_cstNode: CstNode
|
||||||
): ValueType | undefined {
|
): ValueType | undefined {
|
||||||
let regex: RegExp | undefined;
|
let regex: RegExp | undefined;
|
||||||
@ -72,3 +79,13 @@ export class CommonValueConverter extends DefaultValueConverter {
|
|||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class CommonValueConverter extends MermaidValueConverter {
|
||||||
|
protected runCustomConverter(
|
||||||
|
_rule: GrammarAST.AbstractRule,
|
||||||
|
_input: string,
|
||||||
|
_cstNode: CstNode
|
||||||
|
): ValueType | undefined {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
}
|
@ -9,7 +9,7 @@ import { EmptyFileSystem, createDefaultModule, createDefaultSharedModule, inject
|
|||||||
|
|
||||||
import { MermaidGeneratedSharedModule, InfoGeneratedModule } from '../generated/module.js';
|
import { MermaidGeneratedSharedModule, InfoGeneratedModule } from '../generated/module.js';
|
||||||
import { CommonLexer } from '../common/commonLexer.js';
|
import { CommonLexer } from '../common/commonLexer.js';
|
||||||
import { CommonValueConverter } from '../common/commonValueConverters.js';
|
import { CommonValueConverter } from '../common/valueConverter.js';
|
||||||
import { InfoTokenBuilder } from './infoTokenBuilder.js';
|
import { InfoTokenBuilder } from './infoTokenBuilder.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,24 +1,7 @@
|
|||||||
import type { GrammarAST, Stream, TokenBuilderOptions } from 'langium';
|
import { MermaidTokenBuilder } from '../common/tokenBuilder.js';
|
||||||
import { DefaultTokenBuilder } from 'langium';
|
|
||||||
|
|
||||||
import type { TokenType } from '../chevrotainWrapper.js';
|
export class InfoTokenBuilder extends MermaidTokenBuilder {
|
||||||
|
constructor() {
|
||||||
export class InfoTokenBuilder extends DefaultTokenBuilder {
|
super(['info', 'showInfo']);
|
||||||
protected override buildKeywordTokens(
|
|
||||||
rules: Stream<GrammarAST.AbstractRule>,
|
|
||||||
terminalTokens: TokenType[],
|
|
||||||
options?: TokenBuilderOptions
|
|
||||||
): TokenType[] {
|
|
||||||
const tokenTypes: TokenType[] = super.buildKeywordTokens(rules, terminalTokens, options);
|
|
||||||
// to restrict users, they mustn't have any non-whitespace characters after the keyword.
|
|
||||||
tokenTypes.forEach((tokenType: TokenType): void => {
|
|
||||||
if (
|
|
||||||
(tokenType.name === 'info' || tokenType.name === 'showInfo') &&
|
|
||||||
tokenType.PATTERN !== undefined
|
|
||||||
) {
|
|
||||||
tokenType.PATTERN = new RegExp(tokenType.PATTERN.toString() + '(?!\\S)');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return tokenTypes;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,23 +1,7 @@
|
|||||||
import type { GrammarAST, Stream, TokenBuilderOptions } from 'langium';
|
import { MermaidTokenBuilder } from '../common/tokenBuilder.js';
|
||||||
import { DefaultTokenBuilder } from 'langium';
|
|
||||||
|
|
||||||
import type { TokenType } from '../chevrotainWrapper.js';
|
export class PieTokenBuilder extends MermaidTokenBuilder {
|
||||||
|
constructor() {
|
||||||
export class PieTokenBuilder extends DefaultTokenBuilder {
|
super(['pie', 'showData']);
|
||||||
protected override buildKeywordTokens(
|
|
||||||
rules: Stream<GrammarAST.AbstractRule>,
|
|
||||||
terminalTokens: TokenType[],
|
|
||||||
options?: TokenBuilderOptions
|
|
||||||
): TokenType[] {
|
|
||||||
const tokenTypes: TokenType[] = super.buildKeywordTokens(rules, terminalTokens, options);
|
|
||||||
tokenTypes.forEach((tokenType: TokenType): void => {
|
|
||||||
if (
|
|
||||||
(tokenType.name === 'pie' || tokenType.name === 'showData') &&
|
|
||||||
tokenType.PATTERN !== undefined
|
|
||||||
) {
|
|
||||||
tokenType.PATTERN = new RegExp(tokenType.PATTERN.toString() + '(?!\\S)');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return tokenTypes;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,49 +1,17 @@
|
|||||||
import type { CstNode, GrammarAST, ValueType } from 'langium';
|
import type { CstNode, GrammarAST, ValueType } from 'langium';
|
||||||
import { DefaultValueConverter } from 'langium';
|
import { MermaidValueConverter } from '../common/valueConverter.js';
|
||||||
|
|
||||||
import { CommonValueConverter } from '../common/commonValueConverters.js';
|
export class PieValueConverter extends MermaidValueConverter {
|
||||||
|
override runCustomConverter(
|
||||||
export class PieValueConverter extends DefaultValueConverter {
|
|
||||||
protected override runConverter(
|
|
||||||
rule: GrammarAST.AbstractRule,
|
|
||||||
input: string,
|
|
||||||
cstNode: CstNode
|
|
||||||
): ValueType {
|
|
||||||
let value: ValueType | undefined = CommonValueConverter.customRunConverter(
|
|
||||||
rule,
|
|
||||||
input,
|
|
||||||
cstNode
|
|
||||||
);
|
|
||||||
if (value === undefined) {
|
|
||||||
value = PieValueConverter.customRunConverter(rule, input, cstNode);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (value === undefined) {
|
|
||||||
return super.runConverter(rule, input, cstNode);
|
|
||||||
}
|
|
||||||
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 pie rule or `null` if it's not.
|
|
||||||
*/
|
|
||||||
public static customRunConverter(
|
|
||||||
rule: GrammarAST.AbstractRule,
|
rule: GrammarAST.AbstractRule,
|
||||||
input: string,
|
input: string,
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
_cstNode: CstNode
|
_cstNode: CstNode
|
||||||
): ValueType | undefined {
|
): ValueType | undefined {
|
||||||
if (rule.name === 'PIE_SECTION_LABEL') {
|
if (rule.name !== 'PIE_SECTION_LABEL') {
|
||||||
return input
|
return undefined;
|
||||||
.replace(/"/g, '')
|
|
||||||
.trim()
|
|
||||||
.replaceAll(/[\t ]{2,}/gm, ' ');
|
|
||||||
}
|
}
|
||||||
return undefined;
|
|
||||||
|
return input.replace(/"/g, '').trim();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user