forked from zaach/jison
-
Notifications
You must be signed in to change notification settings - Fork 20
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
- Loading branch information
1 parent
67556c0
commit 051dc5d
Showing
2 changed files
with
217 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
// A third way to observe the same LALR reduce/reduce conflict: | ||
// the departure point for both rules (opt_prefix1 and opt_prefix2) | ||
// is still the same, hence they land in the same state somewhere | ||
// and then the union operation causes reduce/reduce havoc. | ||
|
||
|
||
//%options on-demand-lookahead // camelCased: option.onDemandLookahead | ||
|
||
|
||
|
||
%lex | ||
|
||
%% | ||
|
||
\s+ /* skip whitespace */ | ||
a return 'PREFIX1'; | ||
b return 'PREFIX2'; | ||
A return 'SUFFIX1'; | ||
B return 'SUFFIX2'; | ||
X return 'COMMON1'; | ||
. return 'ERROR'; | ||
|
||
/lex | ||
|
||
|
||
%options no-default-action no-try-catch | ||
|
||
|
||
%token PREFIX1 PREFIX2 SUFFIX1 SUFFIX2 | ||
|
||
%% | ||
|
||
start: | ||
opt_prefix1 SUFFIX1 | ||
| opt_prefix2 SUFFIX2 | ||
; | ||
|
||
opt_prefix1: | ||
c1 | ||
| PREFIX1 | ||
; | ||
|
||
opt_prefix2: | ||
c1 | ||
| PREFIX2 | ||
; | ||
|
||
c1: | ||
COMMON1 | ||
; | ||
|
||
%% | ||
// feature of the GH fork: specify your own main. | ||
// | ||
// compile with | ||
// | ||
// jison -o test.js --main that/will/be/me.jison | ||
// | ||
// then run | ||
// | ||
// node ./test.js | ||
// | ||
// to see the output. | ||
var assert = require("assert"); | ||
parser.main = function () { | ||
var testset_ok = ['XA', 'XB', 'aA', 'bB']; | ||
var rv; | ||
for (var i = 0, len = testset_ok.length; i < len; i++) { | ||
try { | ||
rv = parser.parse(testset_ok[i]); | ||
console.log("test #" + i + ": '" + testset_ok[i] + "' ==> ", rv); | ||
assert.equal(rv, true); | ||
} catch (ex) { | ||
console.log("test #" + i + ": '" + testset_ok[i] + "' ==> EXCEPTION: ", ex); | ||
throw ex; | ||
} | ||
} | ||
console.log("\nAnd now the failing inputs: even these deliver a result:\n"); | ||
// set up an aborting error handler which does not throw an exception | ||
// but returns a special parse 'result' instead: | ||
var errmsg = null; | ||
var errReturnValue = false; | ||
parser.yy.parseError = function (msg, hash) { | ||
errmsg = msg; | ||
return errReturnValue; | ||
}; | ||
var testset_not_ok = ['a', 'b', 'aB', 'bA', '?', 'AA', 'BB', 'aa', 'bb', '?A', '?a']; | ||
var base = i; | ||
var rv; | ||
for (var i = 0, len = testset_not_ok.length; i < len; i++) { | ||
try { | ||
rv = parser.parse(testset_not_ok[i]); | ||
console.log("test #" + (base + i) + ": '" + testset_not_ok[i] + "' ==> ", rv); | ||
assert.strictEqual(rv, errReturnValue); | ||
} catch (ex) { | ||
console.log("test #" + (base + i) + ": '" + testset_not_ok[i] + "' ==> EXCEPTION: ", ex); | ||
throw ex; | ||
} | ||
} | ||
// if you get past the assert(), you're good. | ||
console.log("tested OK"); | ||
}; | ||
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
// A LALR work-around for the reduce/reduce conflict: | ||
// identify the two conflicting rules (opt_prefix1 and opt_prefix2) | ||
// and **expand** them into their parent; then merge | ||
// their common part in a single subrule (opt_prefix) | ||
|
||
|
||
|
||
//%options on-demand-lookahead // camelCased: option.onDemandLookahead | ||
|
||
|
||
|
||
%lex | ||
|
||
%% | ||
|
||
\s+ /* skip whitespace */ | ||
a return 'PREFIX1'; | ||
b return 'PREFIX2'; | ||
A return 'SUFFIX1'; | ||
B return 'SUFFIX2'; | ||
X return 'COMMON1'; | ||
. return 'ERROR'; | ||
|
||
/lex | ||
|
||
|
||
%options no-default-action no-try-catch | ||
|
||
|
||
%token PREFIX1 PREFIX2 SUFFIX1 SUFFIX2 | ||
|
||
%% | ||
|
||
start: | ||
opt_prefix SUFFIX1 | ||
| PREFIX1 SUFFIX2 | ||
| opt_prefix SUFFIX2 | ||
| PREFIX2 SUFFIX2 | ||
; | ||
|
||
opt_prefix: | ||
COMMON1 | ||
; | ||
|
||
%% | ||
// feature of the GH fork: specify your own main. | ||
// | ||
// compile with | ||
// | ||
// jison -o test.js --main that/will/be/me.jison | ||
// | ||
// then run | ||
// | ||
// node ./test.js | ||
// | ||
// to see the output. | ||
var assert = require("assert"); | ||
parser.main = function () { | ||
var testset_ok = ['XA', 'XB', 'aA', 'bB']; | ||
var rv; | ||
for (var i = 0, len = testset_ok.length; i < len; i++) { | ||
try { | ||
rv = parser.parse(testset_ok[i]); | ||
console.log("test #" + i + ": '" + testset_ok[i] + "' ==> ", rv); | ||
assert.equal(rv, true); | ||
} catch (ex) { | ||
console.log("test #" + i + ": '" + testset_ok[i] + "' ==> EXCEPTION: ", ex); | ||
throw ex; | ||
} | ||
} | ||
console.log("\nAnd now the failing inputs: even these deliver a result:\n"); | ||
// set up an aborting error handler which does not throw an exception | ||
// but returns a special parse 'result' instead: | ||
var errmsg = null; | ||
var errReturnValue = false; | ||
parser.yy.parseError = function (msg, hash) { | ||
errmsg = msg; | ||
return errReturnValue; | ||
}; | ||
var testset_not_ok = ['a', 'b', 'aB', 'bA', '?', 'AA', 'BB', 'aa', 'bb', '?A', '?a']; | ||
var base = i; | ||
var rv; | ||
for (var i = 0, len = testset_not_ok.length; i < len; i++) { | ||
try { | ||
rv = parser.parse(testset_not_ok[i]); | ||
console.log("test #" + (base + i) + ": '" + testset_not_ok[i] + "' ==> ", rv); | ||
assert.strictEqual(rv, errReturnValue); | ||
} catch (ex) { | ||
console.log("test #" + (base + i) + ": '" + testset_not_ok[i] + "' ==> EXCEPTION: ", ex); | ||
throw ex; | ||
} | ||
} | ||
// if you get past the assert(), you're good. | ||
console.log("tested OK"); | ||
}; | ||