|
// |
|
// This code is a stripped version of actual production code hich employs this JISON clone: |
|
// |
|
// https://github.com/GerHobbelt/jison |
|
// |
|
// hence make sure to diff that one against vanilla to see differences/features. |
|
// |
|
// --- |
|
// |
|
// code shows .yy.parseError, lexer.post_lex, parser.post_parser, how to get |
|
// the token identifier strings from the JISON-generated parser class, etc. |
|
// |
|
// Note that the event reg/unreg/trigger functions are quick replacements for this gist only, |
|
// use your own event system here. The key is that this works, even when you fire events |
|
// from user action code inside the lexer or parser itself, hence more powerful than simply |
|
// hooking .yy.parseError only! |
|
// |
|
|
|
|
|
V.P = function () { |
|
var parser = function () { |
|
}; |
|
|
|
// `parserWithTokens` is the 'class' generated by JISON |
|
// |
|
// `parser` / `V.P` is the user-defined 'wrapper class' |
|
|
|
parser.parse = function (userInput, options) { |
|
// the array of JISON terminal strings: used to convert parser-internal numeric IDs to human legible strings for these. |
|
var terminals = parserWithTokens.terminals_; |
|
|
|
options = options || {}; |
|
|
|
var catch_nasty_deep_parse_errors_f = function (d) { |
|
// d: { message: ..., attributes } |
|
// console.log("≈≈≈ onParseError catching deep parser errors: ", d); |
|
|
|
// When the parser or lexer themselves already detected the error, we don't need to mark it up! |
|
// This is for catching those DEEP errors only |
|
if (d.parserErrorHash || d.lexerErrorHash) |
|
return; |
|
|
|
... |
|
}; |
|
|
|
register_listener_for_parse_error_event(catch_nasty_deep_parse_errors_f); |
|
|
|
// override the default parseError method! Do this every time again as it references closure variables (resultOutput) which it will patch. |
|
parserWithTokens.yy.parseError = function (str, hash) { |
|
//console.log("≈≈≈ parse error: ", str, hash); |
|
if (hash.expected /* parser error? */) { |
|
fire_parse_error_event({ |
|
message: "Parser error: " + str, |
|
parserErrorHash: hash |
|
}); |
|
|
|
//var faulty_str = this.lexer.upcomingInput(-1); // get all the remaining input to parse: |
|
... |
|
return null; |
|
} else { |
|
/* lexer error */ |
|
fire_parse_error_event({ |
|
message: "Lexer error: " + str, |
|
lexerErrorHash: hash |
|
}); |
|
|
|
assert(this.lexer.ERROR); |
|
return this.lexer.ERROR; |
|
} |
|
}; |
|
|
|
// logging the tokens+types as part of each lex() run: |
|
parserWithTokens.lexer.options.post_lex = function (token) { |
|
//assert(this === parserWithTokens.yy.lexer); |
|
|
|
if (!log_it && token === this.ERROR) { |
|
/* |
|
* consume one character of pending input: |
|
* this is the minimum amount that we should move forward if we don't want the error to 'stick', |
|
* for we ALWAYS want to end at the EOF token at the very end of the run. |
|
*/ |
|
log_it = this.input(); |
|
} |
|
if (log_it /* not EOF and match isn't simply whitespace */) { |
|
//gives the tokens |
|
var token_str = (terminals[token] || token); |
|
log_token(log_it, token_str); |
|
} |
|
|
|
return token; |
|
}; |
|
|
|
parserWithTokens.post_parse = function (yy, retval) { |
|
/* |
|
Make sure we've lexed the entire input, even when an error occurred! |
|
We will need that when we are parsing erroneous input where we want to analyze the tokenArray anyhow... |
|
*/ |
|
var token; |
|
var lexer = yy.lexer; |
|
... |
|
do { |
|
token = lexer.lex(); |
|
... |
|
} while (token !== parserWithTokens.lexer.EOF); |
|
|
|
... |
|
return retval; |
|
}; |
|
|
|
try { |
|
resultOutput = parserWithTokens.parse(userInput); |
|
... |
|
} catch (e) { |
|
... |
|
fire_parse_error_event({ |
|
message: (e.name || "Error") + ": " + e.message, |
|
exception: e |
|
}); |
|
... |
|
} |
|
|
|
// make sure the handler we registered before is now detached again so any later calls cannot print their errors through /our/ lingering handler... |
|
unregister_listener_for_parse_error_event(catch_nasty_deep_parse_errors_f); |
|
|
|
return resultOutput; |
|
}; |
|
|
|
return parser; |
|
}; |