Last active
October 9, 2021 03:55
-
-
Save conartist6/9ce56e4de54bba2bb4f8ddfe5ba0f5ba to your computer and use it in GitHub Desktop.
Basic moo/nearley parser for JS errors
This file contains hidden or 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
@{% | |
const lexer = moo.states({ | |
error: { | |
CausedBy: { match: /^\s*[cC]ause(?:d [bB]y)?:/, value: () => "Caused by:" }, | |
At: { match: /^[ \t]*at /, push: "frame", value: () => "at " }, | |
Space: /[ \t]+/, | |
Newline: { match: "\n", lineBreaks: true }, | |
// Any line ending with file:line:col is a stack frame | |
// file:line:col may be wrapped in parens, or may be the literal 'native' | |
Text: /.+$/, | |
}, | |
frame: { | |
CN: ":", | |
LP: "(", | |
RP: ")", | |
Number: { match: /\d+/, value: (str) => parseInt(str, 10)}, | |
NL: { match: "\n", lineBreaks: true, pop: true }, | |
Space: /[ \t]+/, | |
FrameFragment: /[^(): \d\t\n]+/, | |
}, | |
}); | |
%} | |
@lexer lexer | |
Error -> Message (NL Stack):? (NL CausedBy Error):? {% (d) => { | |
const props = [{ message: d[0] }]; | |
if (d[1]) props.push({ stack: d[1][1] }); | |
if (d[2]) props.push({ cause: d[2][3] }); | |
return Object.assign({}, ...props); | |
}%} | |
Message -> Text (NL _ Text):* {% (d) => d[0] + stringFrom(d[1].flat()) %} | |
Text -> _Text:+ {% (d) => stringFrom(d[0]) %} | |
_Text -> %Text {% (d) => d[0].text %} | |
Stack -> Frame (NL Frame):* {% (d) => [d[0], ...(d[1] ? d[1].map(d => d[1]) : [])] %} | |
Frame -> At FrameFragments _ LP FrameFragments CN Number CN Number RP {% (d) => ({ function: d[1], file: d[4], line: d[6], col: d[8] }) %} | |
| At FrameFragments CN Number CN Number {% (d) => ({ function: undefined, file: d[1], line: d[3], col: d[5] }) %} | |
FrameFragments -> (FrameFragment | Number | CN | LP | RP | _ ):* {% (d) => stringFrom(d[0].flat()) %} | |
FrameFragment -> %FrameFragment {% (d) => d[0].text %} | |
Number -> %Number {% (d) => d[0].value %} | |
At -> %At _:? {% () => null %} | |
CausedBy -> %CausedBy _ {% () => null %} | |
CN -> %CN {% (d) => d[0].text %} # Colon `:` | |
LP -> %LP {% (d) => d[0].text %} # Left paren `(` | |
RP -> %RP {% (d) => d[0].text %} # Right paren `)` | |
NL -> %NL {% (d) => d[0].text %} # Newline | |
_ -> %Space {% (d) => d[0].value %} | |
@{% | |
function stringFrom(iterable) { | |
let str = ''; | |
for (const f of iterable) { | |
str += f; | |
} | |
return str; | |
} | |
%} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment