Created
March 23, 2017 17:55
-
-
Save biogeo/586d660a74d1f59d667763a1cdd7309b to your computer and use it in GitHub Desktop.
"Offside rule" indentation parsing with PEG.js
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
// Parse a document using "offside rule" indentation (as in Python) into lines | |
// grouped by indentation level, using PEG.js. | |
// Attempts to segregate the "stateful" rules from the other production/parsing | |
// rules by "disallowing" indentation-level-sensitive rules from consuming any | |
// text. | |
{ var margin_stack = [""]; } | |
Document | |
= content: Element+ | |
BlankLine* | |
{ return content; } | |
Element | |
= BlankLine* | |
content: (CurrentBlockElement / IndentedBlock) | |
{ return content; } | |
CurrentBlockElement | |
= &MAINTAIN_MARGIN content:Line | |
{ return content; } | |
IndentedBlock | |
= &INCREASE_MARGIN | |
first: CurrentBlockElement | |
content: Element* | |
&DECREASE_MARGIN | |
{ return [first].concat(content)]; } | |
Line | |
= BlankSpace? | |
content: $(!LineEnding .)+ LineEnding | |
{ return content; } | |
INCREASE_MARGIN | |
= indent: $BlankSpace? | |
&{ return (indent !== margin_stack[0]) | |
&& indent.startsWith(margin_stack[0]); } | |
{ margin_stack.unshift(indent); } | |
MAINTAIN_MARGIN | |
= indent: $BlankSpace? | |
&{ return indent === margin_stack[0]; } | |
DECREASE_MARGIN | |
= EOF | |
/ indent: $BlankSpace? | |
&{ return margin_stack.slice(1).includes(indent); } | |
{ margin_stack.shift(); } | |
BlankLine | |
= BlankSpace? EOL | |
/ BlankSpace EOF | |
LineEnding | |
= BlankSpace? (EOL / EOF) | |
BlankSpace | |
= [ \t]+ | |
EOL = "\r\n" / "\n" / "\r" | |
EOF = !. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
typo fixed