Now jison can parse xAxis and yAxis

This commit is contained in:
Subhash Halder 2023-07-01 20:07:15 +05:30
parent 0a731e1ee1
commit 29ab2dec59
2 changed files with 201 additions and 4 deletions

View File

@ -12,6 +12,15 @@
%x acc_title
%x acc_descr
%x acc_descr_multiline
%x chart_config
%x chart_orientation
%x x_axis
%x y_axis
%x axis_title
%x axis_data
%x axis_data_band
%x axis_data_band_capture
%x axis_data_band_str
%%
\%\%\{ { this.begin('open_directive'); return 'open_directive'; }
<open_directive>((?:(?!\}\%\%)[^:.])*) { this.begin('type_directive'); return 'type_directive'; }
@ -34,6 +43,34 @@ accDescr\s*"{"\s* { this.begin("acc_descr_multiline");}
<acc_descr_multiline>[\}] { this.popState(); }
<acc_descr_multiline>[^\}]* return "acc_descr_multiline_value";
" "*"xychart-beta" {this.begin("chart_config"); return 'XYCHART';}
<chart_config>" "+("vertical"|"horizontal") {this.begin("chart_orientation"); return 'chart_orientation';}
<chart_orientation>[\s]* {this.popState(); this.popState(); return 'CHART_CONFIG_END';}
<chart_config>[\s]* {this.popState(); return 'CHART_CONFIG_END';}
"x-axis"" "* { this.begin("x_axis"); return "X_AXIS";}
"y-axis"" "* { this.begin("y_axis"); return "Y_AXIS";}
<x_axis,y_axis>["] {this.begin("axis_title");}
<axis_title>[^"]+ {return 'AXIS_TITLE';}
<axis_title>["]" "*(\r?\n) {this.popState(); this.popState();}
<axis_title>["]" "* {this.popState(); this.begin("axis_data");}
<x_axis,y_axis>[^\s]+" "*(\r?\n) {this.popState(); return 'AXIS_TITLE';}
<x_axis,y_axis>[^\s]+" "* {this.begin("axis_data"); return 'AXIS_TITLE'; }
<axis_data>[+-]?\d+(\.\d+)?" "*"-->"" "*[+-]?\d+(\.\d+)?" "* { return 'AXIS_RANGE_DATA';}
<axis_data>[\[]" "* {this.begin("axis_data_band"); this.begin("axis_data_band_capture")}
<axis_data_band>[,]" "* {this.begin("axis_data_band_capture")}
<axis_data_band_capture>["] {this.begin("axis_data_band_str");}
<axis_data_band_str>[^"]+ {return "AXIS_BAND_DATA";}
<axis_data_band_str>["]" "* {this.popState(); this.popState();}
<axis_data_band_capture>[^\s]+" "* {this.popState(); return "AXIS_BAND_DATA"}
<axis_data_band>[\]]" "* {this.popState(); return "AXIS_BAND_DATA_END"}
<axis_data>[\r\n]+ {this.popState(); this.popState();}
["][`] { this.begin("md_string");}
<md_string>[^`"]+ { return "MD_STR";}
@ -42,8 +79,6 @@ accDescr\s*"{"\s* { this.begin("acc_descr_multiline");}
<string>["] this.popState();
<string>[^"]* return "STR";
" "*"xychart"" "* return 'XYCHART';
[A-Za-z]+ return 'ALPHA';
":" return 'COLON';
\+ return 'PLUS';
@ -72,9 +107,14 @@ start
: eol start
| SPACE start
| directive start
| XYCHART document
| XYCHART chartConfig CHART_CONFIG_END document
| XYCHART CHART_CONFIG_END document
;
chartConfig
: chart_orientation {yy.setOrientation($1.trim());}
;
document
: /* empty */
| document line
@ -88,8 +128,25 @@ statement
:
| SPACE statement
| directive
| X_AXIS parseXAxis
| Y_AXIS parseYAxis
;
parseXAxis
: AXIS_TITLE {yy.setXAxisTitle($1.trim());}
| AXIS_TITLE xAxisBandData {yy.setXAxisTitle($1.trim());}
| AXIS_TITLE AXIS_RANGE_DATA {yy.setXAxisTitle($1.trim()); $$ = $2.split("-->"); yy.setXAxisRangeData(Number($$[0]), Number($$[1]));}
;
xAxisBandData
: AXIS_BAND_DATA xAxisBandData {yy.addXAxisBand($1.trim());}
| AXIS_BAND_DATA_END
;
parseYAxis
: AXIS_TITLE {yy.setYAxisTitle($1.trim());}
| AXIS_TITLE AXIS_RANGE_DATA {yy.setYAxisTitle($1.trim()); $$ = $2.split("-->"); yy.setYAxisRangeData(Number($$[0]), Number($$[1]));}
;
directive
: openDirective typeDirective closeDirective
@ -115,7 +172,7 @@ argDirective
;
closeDirective
: close_directive { yy.parseDirective('}%%', 'close_directive', 'quadrantChart'); }
: close_directive { yy.parseDirective('}%%', 'close_directive', 'xychart'); }
;
text: alphaNumToken

View File

@ -0,0 +1,140 @@
// @ts-ignore: TODO Fix ts errors
import { parser } from './xychart.jison';
import { Mock, vi } from 'vitest';
const parserFnConstructor = (str: string) => {
return () => {
parser.parse(str);
};
};
const mockDB: Record<string, Mock<any, any>> = {
parseDirective: vi.fn(),
setOrientation: vi.fn(),
setXAxisTitle: vi.fn(),
setXAxisRangeData: vi.fn(),
addXAxisBand: vi.fn(),
setYAxisTitle: vi.fn(),
setYAxisRangeData: vi.fn(),
addYAxisBand: vi.fn(),
};
function clearMocks() {
for (const key in mockDB) {
mockDB[key].mockRestore();
}
}
describe('Testing xychart jison file', () => {
beforeEach(() => {
parser.yy = mockDB;
clearMocks();
});
it('should throw error if xychart-beta text is not there', () => {
const str = 'xychart-beta-1';
expect(parserFnConstructor(str)).toThrow();
});
it('should not throw error if only xychart is there', () => {
const str = 'xychart-beta';
expect(parserFnConstructor(str)).not.toThrow();
});
it('should be able to parse directive', () => {
const str =
'%%{init: {"xychart": {"chartWidth": 600, "chartHeight": 600} } }%% \n xychart-beta';
expect(parserFnConstructor(str)).not.toThrow();
expect(mockDB.parseDirective.mock.calls[0]).toEqual(['%%{', 'open_directive']);
expect(mockDB.parseDirective.mock.calls[1]).toEqual(['init', 'type_directive']);
expect(mockDB.parseDirective.mock.calls[2]).toEqual([
'{"xychart": {"chartWidth": 600, "chartHeight": 600} }',
'arg_directive',
]);
expect(mockDB.parseDirective.mock.calls[3]).toEqual(['}%%', 'close_directive', 'xychart']);
});
it('parse chart orientation', () => {
let str = 'xychart-beta vertical';
expect(parserFnConstructor(str)).not.toThrow();
expect(mockDB.setOrientation).toHaveBeenCalledWith('vertical');
clearMocks();
str = 'xychart-beta horizontal ';
expect(parserFnConstructor(str)).not.toThrow();
expect(mockDB.setOrientation).toHaveBeenCalledWith('horizontal');
str = 'xychart-beta abc';
expect(parserFnConstructor(str)).toThrow();
});
it('parse x-axis', () => {
let str = 'xychart-beta \nx-axis xAxisName\n';
expect(parserFnConstructor(str)).not.toThrow();
expect(mockDB.setXAxisTitle).toHaveBeenCalledWith('xAxisName');
clearMocks();
str = 'xychart-beta \nx-axis xAxisName \n';
expect(parserFnConstructor(str)).not.toThrow();
expect(mockDB.setXAxisTitle).toHaveBeenCalledWith('xAxisName');
clearMocks();
str = 'xychart-beta \n x-axis "xAxisName has space"\n';
expect(parserFnConstructor(str)).not.toThrow();
expect(mockDB.setXAxisTitle).toHaveBeenCalledWith('xAxisName has space');
clearMocks();
str = 'xychart-beta \n x-axis " xAxisName has space " \n';
expect(parserFnConstructor(str)).not.toThrow();
expect(mockDB.setXAxisTitle).toHaveBeenCalledWith('xAxisName has space');
clearMocks();
str = 'xychart-beta \nx-axis xAxisName 45.5 --> 33 \n';
expect(parserFnConstructor(str)).not.toThrow();
expect(mockDB.setXAxisTitle).toHaveBeenCalledWith('xAxisName');
expect(mockDB.setXAxisRangeData).toHaveBeenCalledWith(45.5, 33);
clearMocks();
str = 'xychart-beta \nx-axis xAxisName [ "cat1" , cat2 ] \n';
expect(parserFnConstructor(str)).not.toThrow();
expect(mockDB.setXAxisTitle).toHaveBeenCalledWith('xAxisName');
expect(mockDB.addXAxisBand).toHaveBeenCalledTimes(2);
expect(mockDB.addXAxisBand).toHaveBeenNthCalledWith(1, "cat2");
expect(mockDB.addXAxisBand).toHaveBeenNthCalledWith(2, "cat1");
});
it('parse y-axis', () => {
let str = 'xychart-beta \ny-axis yAxisName\n';
expect(parserFnConstructor(str)).not.toThrow();
expect(mockDB.setYAxisTitle).toHaveBeenCalledWith('yAxisName');
clearMocks();
str = 'xychart-beta \ny-axis yAxisName \n';
expect(parserFnConstructor(str)).not.toThrow();
expect(mockDB.setYAxisTitle).toHaveBeenCalledWith('yAxisName');
clearMocks();
str = 'xychart-beta \n y-axis "yAxisName has space"\n';
expect(parserFnConstructor(str)).not.toThrow();
expect(mockDB.setYAxisTitle).toHaveBeenCalledWith('yAxisName has space');
clearMocks();
str = 'xychart-beta \n y-axis " yAxisName has space " \n';
expect(parserFnConstructor(str)).not.toThrow();
expect(mockDB.setYAxisTitle).toHaveBeenCalledWith('yAxisName has space');
clearMocks();
str = 'xychart-beta \ny-axis yAxisName 45.5 --> 33 \n';
expect(parserFnConstructor(str)).not.toThrow();
expect(mockDB.setYAxisTitle).toHaveBeenCalledWith('yAxisName');
expect(mockDB.setYAxisRangeData).toHaveBeenCalledWith(45.5, 33);
});
});