Skip to content

Commit b34f990

Browse files
committed
further work on zaach#363 fixing the ARROW_ACTION action by placing the received user-defined action code within () braces so that the generated parser will certainly treat the entire blurb as a single JavaScript *expression* rather than a single or compound *statement*; also note commit SHA-1: 1c8c89d :: BNF parser: produce stricter action code for arrow action in any jison grammar so that we can more easily check coding mistakes in a production's arrow code, e.g. unwanted semicolons, multiple statements, etc., which can currently slip through the net and cause hard-to-diagnose havoc down the line.
Adjusted unit tests accordingly.
1 parent aad81e9 commit b34f990

File tree

4 files changed

+23
-21
lines changed

4 files changed

+23
-21
lines changed

examples/parser-to-lexer-communication-test-w-debug.jison

+18-18
Original file line numberDiff line numberDiff line change
@@ -44,54 +44,54 @@
4444

4545

4646
S
47-
: init x x e -> parser.trace('S:complete = ', $e);
47+
: init x x e { parser.trace('S:complete = ', $e); }
4848
;
4949

5050
init
51-
: %epsilon -> parser.trace('init:epsilon');
51+
: %epsilon { parser.trace('init:epsilon'); }
5252
;
5353

5454
x
55-
: %epsilon -> parser.trace('X:epsilon'); $$ = '<X-epsilon>';
55+
: %epsilon { parser.trace('X:epsilon'); $$ = '<X-epsilon>'; }
5656
;
5757

5858
e
59-
: cmd e -> parser.trace('e:cmd=', $cmd); $$ = $cmd + ' | ' + $e;
60-
| %epsilon -> parser.trace('e:epsilon'); $$ = '<E-epsilon>';
59+
: cmd e { parser.trace('e:cmd=', $cmd); $$ = $cmd + ' | ' + $e; }
60+
| %epsilon { parser.trace('e:epsilon'); $$ = '<E-epsilon>'; }
6161
;
6262

6363
cmd
64-
: a -> parser.trace('cmd:a'); $$ = $a;
65-
| f_a -> parser.trace('cmd:function a()'); $$ = $f_a;
66-
| b -> parser.trace('cmd:b'); $$ = $b;
67-
| f_b -> parser.trace('cmd:function b()'); $$ = $f_b;
68-
| error -> parser.trace('cmd:error', get_reduced_error_info_obj($error) || $error); yyerrok; yyclearin; $$ = 'ERROR';
64+
: a { parser.trace('cmd:a'); $$ = $a; }
65+
| f_a { parser.trace('cmd:function a()'); $$ = $f_a; }
66+
| b { parser.trace('cmd:b'); $$ = $b; }
67+
| f_b { parser.trace('cmd:function b()'); $$ = $f_b; }
68+
| error { parser.trace('cmd:error', get_reduced_error_info_obj($error) || $error); yyerrok; yyclearin; $$ = 'ERROR'; }
6969
;
7070

7171
a
72-
: A -> parser.trace('a:A'); $$ = 'A[' + $A + ']';
72+
: A { parser.trace('a:A'); $$ = 'A[' + $A + ']'; }
7373
;
7474

7575
f_a
76-
: A lb e rb -> parser.trace('function a:', $e); $$ = 'A' + $lb + $e + $rb;
76+
: A lb e rb { parser.trace('function a:', $e); $$ = 'A' + $lb + $e + $rb; }
7777
;
7878

7979
b
80-
: B -> parser.trace('b:B'); $$ = 'B[' + $B + ']';
80+
: B { parser.trace('b:B'); $$ = 'B[' + $B + ']'; }
8181
;
8282

8383
f_b
84-
: B lb e rb -> parser.trace('function b:', $e); $$ = 'B' + $lb + $e + $rb;
84+
: B lb e rb { parser.trace('function b:', $e); $$ = 'B' + $lb + $e + $rb; }
8585
;
8686

8787
lb
88-
: '(' -> parser.trace('lb+PUSH:[(] '); yy.lexer.pushState('alt'); $$ = '(';
89-
| BEGIN -> parser.trace('lb:[alt-(] '); $$ = '{';
88+
: '(' { parser.trace('lb+PUSH:[(] '); yy.lexer.pushState('alt'); $$ = '('; }
89+
| BEGIN { parser.trace('lb:[alt-(] '); $$ = '{'; }
9090
;
9191

9292
rb
93-
: ')' -> parser.trace('lb:[)] '); $$ = ')';
94-
| END -> parser.trace('lb+POP:[alt-)] '); yy.lexer.popState(); $$ = '}';
93+
: ')' { parser.trace('lb:[)] '); $$ = ')'; }
94+
| END { parser.trace('lb+POP:[alt-)] '); yy.lexer.popState(); $$ = '}'; }
9595
;
9696

9797
%%

packages/ebnf-parser/parser.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,7 @@ import XRegExp from '@gerhobbelt/xregexp'; // for helping out the `%option
382382
import fs from 'fs';
383383
import transform from './ebnf-transform';
384384

385+
385386
// See also:
386387
// http://stackoverflow.com/questions/1382107/whats-a-good-way-to-extend-error-in-javascript/#35881508
387388
// but we keep the prototype.constructor and prototype.name assignment lines too for compatibility
@@ -435,6 +436,7 @@ JisonParserError.prototype.name = 'JisonParserError';
435436

436437

437438

439+
438440
// helper: reconstruct the productions[] table
439441
function bp(s) {
440442
var rv = [];
@@ -2350,7 +2352,7 @@ case 115:
23502352
// END of default action (generated by JISON mode classic/merge :: 1,VT,VA,VU,-,LT,LA,-,-)
23512353

23522354

2353-
this.$ = '$$ = ' + yyvstack[yysp];
2355+
this.$ = '$$ = (' + yyvstack[yysp] + ');';
23542356
break;
23552357

23562358
case 119:

packages/ebnf-parser/tests/bnf_parse.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,7 @@ describe("BNF parser", function () {
266266

267267
it("test expression action", function () {
268268
var grammar = "%% test: foo bar -> $foo\n;";
269-
var expected = {bnf: {test: [["foo bar","$$ = $foo"]]}};
269+
var expected = {bnf: {test: [["foo bar","$$ = ($foo);"]]}};
270270

271271
assert.deepEqual(bnf.parse(grammar), expected, "grammar should be parsed correctly");
272272
});

tests/parser/generator.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -374,7 +374,7 @@ describe("Parser Generator API", function () {
374374
'expressions\n : e EOF\n {return $1;}\n ;\n\n' +
375375
'e\n : phrase+ \'joy\'? -> $1 + \' \' + yytext \n ;\n\n' +
376376
'phrase\n : \'happy\' \'happy\' \'joy\' \'joy\' ' +
377-
' -> [$1, $2, $3, $4].join(\' \'); \n ;';
377+
' -> [$1, $2, $3, $4].join(\' \') \n ;';
378378

379379
var parser = new Jison.Parser(grammar);
380380
var generated = parser.generate();

0 commit comments

Comments
 (0)