added parser

This commit is contained in:
Austin Fulbright
2024-07-25 05:25:19 -04:00
parent 1a95d48852
commit d0eadebb99
5 changed files with 111 additions and 11 deletions

View File

@@ -1,12 +1,12 @@
// @ts-ignore: JISON doesn't support types // @ts-ignore: JISON doesn't support types
import gitGraphParser from './parser/gitGraph.jison'; import { parser } from './gitGraphParser.js';
import gitGraphDb from './gitGraphAst.js'; import gitGraphDb from './gitGraphAst.js';
import gitGraphRenderer from './gitGraphRenderer.js'; import gitGraphRenderer from './gitGraphRenderer.js';
import gitGraphStyles from './styles.js'; import gitGraphStyles from './styles.js';
import type { DiagramDefinition } from '../../diagram-api/types.js'; import type { DiagramDefinition } from '../../diagram-api/types.js';
export const diagram: DiagramDefinition = { export const diagram: DiagramDefinition = {
parser: gitGraphParser, parser: parser,
db: gitGraphDb, db: gitGraphDb,
renderer: gitGraphRenderer, renderer: gitGraphRenderer,
styles: gitGraphStyles, styles: gitGraphStyles,

View File

@@ -4,14 +4,78 @@ import type { ParserDefinition } from '../../diagram-api/types.js';
import { log } from '../../logger.js'; import { log } from '../../logger.js';
import { populateCommonDb } from '../common/populateCommonDb.js'; import { populateCommonDb } from '../common/populateCommonDb.js';
import db from './gitGraphAst.js'; import db from './gitGraphAst.js';
import { commitType } from './gitGraphAst.js';
import type {
CheckoutAst,
CherryPickingAst,
MergeAst,
CommitAst,
BranchAst,
} from './gitGraphTypes.js';
const populate = (ast: any) => { const populate = (ast: GitGraph) => {
populateCommonDb(ast, db); populateCommonDb(ast, db);
for (const statement of ast.statements) { for (const statement of ast.statements) {
log.debug(statement); parseStatement(statement);
} }
}; };
const parseStatement = (statement: any) => {
switch (statement.$type) {
case 'Commit':
parseCommit(statement);
break;
case 'Branch':
parseBranch(statement);
break;
case 'Merge':
parseMerge(statement);
break;
case 'Checkout':
parseCheckout(statement);
break;
case 'CherryPicking':
parseCherryPicking(statement);
break;
default:
log.warn(`Unknown statement type`);
}
};
const parseCommit = (commit: CommitAst) => {
const id = commit.id;
const message = commit.message ?? '';
const tags = commit.tags ?? [];
const type = commit.type !== undefined ? commitType[commit.type] : 0;
db.commit(message, id, type, tags);
};
const parseBranch = (branch: BranchAst) => {
const name = branch.name;
const order = branch.order ?? 0;
db.branch(name, order);
};
const parseMerge = (merge: MergeAst) => {
const branch = merge.branch;
const id = merge.id ?? '';
const tags = merge.tags ?? [];
const type = merge.type !== undefined ? commitType[merge.type] : 0;
db.merge(branch, id, type, tags);
};
const parseCheckout = (checkout: CheckoutAst) => {
const branch = checkout.branch;
db.checkout(branch);
};
const parseCherryPicking = (cherryPicking: CherryPickingAst) => {
const id = cherryPicking.id;
const tags = cherryPicking.tags ?? [];
const parent = cherryPicking.parent;
db.cherryPick(id, '', tags, parent);
};
export const parser: ParserDefinition = { export const parser: ParserDefinition = {
parse: async (input: string): Promise<void> => { parse: async (input: string): Promise<void> => {
const ast: GitGraph = await parse('gitGraph', input); const ast: GitGraph = await parse('gitGraph', input);

View File

@@ -16,7 +16,7 @@ export interface GitGraph {
statements: Statement[]; statements: Statement[];
} }
export type Statement = CommitAst | Branch | Merge | Checkout | CherryPicking; export type Statement = CommitAst | BranchAst | MergeAst | CheckoutAst | CherryPickingAst;
export interface CommitAst { export interface CommitAst {
$type: 'Commit'; $type: 'Commit';
@@ -26,13 +26,13 @@ export interface CommitAst {
type?: 'NORMAL' | 'REVERSE' | 'HIGHLIGHT'; type?: 'NORMAL' | 'REVERSE' | 'HIGHLIGHT';
} }
export interface Branch { export interface BranchAst {
$type: 'Branch'; $type: 'Branch';
name: string; name: string;
order?: number; order?: number;
} }
export interface Merge { export interface MergeAst {
$type: 'Merge'; $type: 'Merge';
branch: string; branch: string;
id?: string; id?: string;
@@ -40,12 +40,12 @@ export interface Merge {
type?: 'NORMAL' | 'REVERSE' | 'HIGHLIGHT'; type?: 'NORMAL' | 'REVERSE' | 'HIGHLIGHT';
} }
export interface Checkout { export interface CheckoutAst {
$type: 'Checkout'; $type: 'Checkout';
branch: string; branch: string;
} }
export interface CherryPicking { export interface CherryPickingAst {
$type: 'CherryPicking'; $type: 'CherryPicking';
id: string; id: string;
tags?: string[]; tags?: string[];

View File

@@ -1,6 +1,28 @@
grammar GitGraph grammar GitGraph
import "../common/common"; interface Common {
accDescr?: string;
accTitle?: string;
title?: string;
}
fragment TitleAndAccessibilities:
((accDescr=ACC_DESCR | accTitle=ACC_TITLE | title=TITLE) EOL)+
;
fragment EOL returns string:
NEWLINE+ | EOF
;
terminal NEWLINE: /\r?\n/;
terminal ACC_DESCR: /[\t ]*accDescr(?:[\t ]*:([^\n\r]*?(?=%%)|[^\n\r]*)|\s*{([^}]*)})/;
terminal ACC_TITLE: /[\t ]*accTitle[\t ]*:(?:[^\n\r]*?(?=%%)|[^\n\r]*)/;
terminal TITLE: /[\t ]*title(?:[\t ][^\n\r]*?(?=%%)|[\t ][^\n\r]*|)/;
hidden terminal WHITESPACE: /[\t ]+/;
hidden terminal YAML: /---[\t ]*\r?\n(?:[\S\s]*?\r?\n)?---(?:\r?\n|(?!\S))/;
hidden terminal DIRECTIVE: /[\t ]*%%{[\S\s]*?}%%(?:\r?\n|(?!\S))/;
hidden terminal SINGLE_LINE_COMMENT: /[\t ]*%%[^\n\r]*/;
entry GitGraph: entry GitGraph:
NEWLINE* NEWLINE*
@@ -62,6 +84,8 @@ CherryPicking:
|'parent:' id=STRING |'parent:' id=STRING
)* EOL; )* EOL;
terminal INT returns number: /[0-9]+(?=\s)/; terminal INT returns number: /[0-9]+(?=\s)/;
terminal ID returns string: /\w([-\./\w]*[-\w])?/; terminal ID returns string: /\w([-\./\w]*[-\w])?/;
terminal STRING: /"[^"]*"|'[^']*'/; terminal STRING: /"[^"]*"|'[^']*'/;

View File

@@ -8,11 +8,23 @@ describe('gitGraph', () => {
const result = parse(`gitGraph`); const result = parse(`gitGraph`);
expect(result.value.$type).toBe(GitGraph); expect(result.value.$type).toBe(GitGraph);
expect(result.value.statements).toHaveLength(0); expect(result.value.statements).toHaveLength(0);
expect(result.lexerErrors).toHaveLength(0);
expect(result.parserErrors).toHaveLength(0);
}); });
it('should handle gitGraph with one statement', () => { it('should handle gitGraph with one statement', () => {
const result = parse(`gitGraph\n A`); const result = parse(`gitGraph\n commit\n`);
expect(result.value.$type).toBe(GitGraph); expect(result.value.$type).toBe(GitGraph);
expect(result.lexerErrors).toHaveLength(0);
expect(result.parserErrors).toHaveLength(0);
expect(result.value.statements).toHaveLength(1);
});
it('should handle gitGraph with multiple statements and use accTitle', () => {
const result = parse(`gitGraph\n commit\n commit\n accTitle: title\n commit\n`);
expect(result.value.$type).toBe(GitGraph);
expect(result.lexerErrors).toHaveLength(0);
expect(result.parserErrors).toHaveLength(0);
}); });
}); });
}); });