ahh, finally. switched up our Jison configuration to provide better syntax errors. Now you get the unexpected token, instead of the expected one.

This commit is contained in:
Jeremy Ashkenas 2010-06-01 20:21:12 -04:00
parent ea1411cd07
commit 59de6b505a
6 changed files with 66 additions and 27 deletions

View File

@ -83,9 +83,6 @@
},
upcomingInput: function() {
return "";
},
showPosition: function() {
return this.pos;
}
};
// Activate CoffeeScript in the browser by having it compile and evaluate

View File

@ -121,11 +121,10 @@
}
}
} catch (err) {
if (o.watch) {
return puts(err.message);
} else {
throw err;
if (!(o.watch)) {
error(err.stack) && process.exit(1);
}
return puts(err.message);
}
};
// Attach the appropriate listeners to compile scripts incoming over **stdin**,

File diff suppressed because one or more lines are too long

View File

@ -76,7 +76,6 @@ parser.lexer: {
@tokens: tokens
@pos: 0
upcomingInput: -> ""
showPosition: -> @pos
}
# Activate CoffeeScript in the browser by having it compile and evaluate

View File

@ -95,7 +95,8 @@ compile_script: (source, code, base) ->
else if o.compile then write_js source, js, base
else if o.lint then lint js
catch err
if o.watch then puts err.message else throw err
error(err.stack) and process.exit 1 unless o.watch
puts err.message
# Attach the appropriate listeners to compile scripts incoming over **stdin**,
# and write them back to **stdout**.

View File

@ -4,7 +4,7 @@
if (typeof exports === 'undefined') {
exports = {};
} else {
} else if (typeof require !== 'undefined') {
// assume we're in commonjs land
//var system = require("system");
var typal = require('./jison/util/typal').typal;
@ -247,13 +247,15 @@ generator.buildProductions = function buildProductions(bnf, productions, nonterm
r = new Production(symbol, rhs, productions.length+1);
// precedence specified also
if (handle[2]) {
if (handle[2] && operators[handle[2].prec]) {
r.precedence = operators[handle[2].prec].precedence;
}
} else {
// only precedence specified
r = new Production(symbol, rhs, productions.length+1);
r.precedence = operators[handle[1].prec].precedence;
if (operators[handle[1].prec]) {
r.precedence = operators[handle[1].prec].precedence;
}
}
} else {
rhs = handle.trim().split(' ');
@ -304,7 +306,8 @@ generator.createParser = function createParser () {
generator.trace = function trace () { };
generator.warn = function warn () {
Jison.print.apply(null,arguments);
var args = Array.prototype.slice.call(arguments,0);
Jison.print.call(null,args.join(""));
};
generator.error = function error (msg) {
@ -537,6 +540,7 @@ lrGeneratorMixin.buildTable = function buildTable () {
this.states = this.canonicalCollection();
this.table = this.parseTable(this.states);
this.defaultActions = findDefaults(this.table);
};
lrGeneratorMixin.Item = typal.construct({
@ -781,6 +785,24 @@ lrGeneratorMixin.parseTable = function parseTable (itemSets) {
return states;
};
// find states with only one action, a reduction
function findDefaults (states) {
var defaults = {};
states.forEach(function (state, k) {
var i = 0;
for (var act in state) {
if ({}.hasOwnProperty.call(state, act)) i++;
}
if (i === 1 && state[act][0] === 2) {
// only one action in state and it's a reduction
defaults[k] = state[act];
}
});
return defaults;
}
// resolves shift-reduce and reduce-reduce conflicts
function resolveConflict (production, op, reduce, shift) {
var sln = {production: production, operator: op, r: reduce, s: shift},
@ -875,6 +897,7 @@ lrGeneratorMixin.generateModule_ = function generateModule_ () {
"productions_: " + JSON.stringify(this.productions_),
"performAction: " + String(this.performAction),
"table: " + JSON.stringify(this.table),
"defaultActions: " + JSON.stringify(this.defaultActions),
"parseError: " + String(this.parseError || (this.hasErrorRecovery ? traceParseError : parser.parseError)),
"parse: " + String(parser.parse)
].join(",\n");
@ -936,6 +959,7 @@ lrGeneratorMixin.createParser = function createParser () {
p.init({
table: this.table,
defaultActions: this.defaultActions,
productions_: this.productions_,
symbols_: this.symbols_,
terminals_: this.terminals_,
@ -999,7 +1023,6 @@ parser.parse = function parse (input) {
function checkRecover (st) {
for (var p in table[st]) if (p == TERROR) {
//print('RECOVER!!');
return true;
}
return false;
@ -1016,12 +1039,19 @@ parser.parse = function parse (input) {
};
var symbol, preErrorSymbol, state, action, a, r, yyval={},p,len,newState, expected, recovered = false;
symbol = lex();
while (true) {
// set first input
// retreive state number from top of stack
state = stack[stack.length-1];
// read action for current state and first input
action = table[state] && table[state][symbol];
// use default actions if available
if (this.defaultActions[state]) {
action = this.defaultActions[state];
} else {
if (symbol == null)
symbol = lex();
// read action for current state and first input
action = table[state] && table[state][symbol];
}
// handle parse error
if (typeof action === 'undefined' || !action.length || !action[0]) {
@ -1051,7 +1081,7 @@ parser.parse = function parse (input) {
yyleng = this.lexer.yyleng;
yytext = this.lexer.yytext;
yylineno = this.lexer.yylineno;
symbol = lex();
symbol = lex();
}
// try to recover from error
@ -1089,11 +1119,11 @@ parser.parse = function parse (input) {
stack.push(symbol);
vstack.push(this.lexer.yytext); // semantic values or junk only, no terminals
stack.push(a[1]); // push state
symbol = null;
if (!preErrorSymbol) { // normal execution/no error
yyleng = this.lexer.yyleng;
yytext = this.lexer.yytext;
yylineno = this.lexer.yylineno;
symbol = lex();
if (recovering > 0)
recovering--;
} else { // error just occurred, resume old lookahead f/ before error
@ -1142,6 +1172,7 @@ parser.parse = function parse (input) {
parser.init = function parser_init (dict) {
this.table = dict.table;
this.defaultActions = dict.defaultActions;
this.performAction = dict.performAction;
this.productions_ = dict.productions_;
this.symbols_ = dict.symbols_;
@ -1200,6 +1231,7 @@ var lalr = generator.beget(lookaheadMixin, lrGeneratorMixin, {
this.unionLookaheads();
this.table = this.parseTable(this.states);
this.defaultActions = findDefaults(this.table);
},
lookAheads: function LALR_lookaheads (state, item) {
@ -1443,12 +1475,16 @@ return function Parser (g, options) {
switch (opt.type) {
case 'lr0':
gen = new LR0Generator(g, opt);
break;
case 'slr':
gen = new SLRGenerator(g, opt);
break;
case 'lr':
gen = new LR1Generator(g, opt);
break;
case 'll':
gen = new LLGenerator(g, opt);
break;
case 'lalr':
default:
gen = new LALRGenerator(g, opt);