Last active
June 28, 2019 14:50
-
-
Save spitz-dan-l/b5a4fb9527a715fff80f671584e5c254 to your computer and use it in GitHub Desktop.
Demo different parser styles
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
// This is what imperative style looks like when the parser is | |
// implemented with exceptions for control flow | |
function imperative_style_with_exceptions(p: Parser) { | |
p.consume('look at'); // could throw NoMatch | |
let who = p.split([ // could throw Split or NoMatch | |
() => p.consume('me', 'me'), | |
() => p.consume('mewtwo', 'mewtwo'), | |
() => p.consume('steven', 'steven'), | |
() => p.consume('martha', 'martha') | |
]); | |
if (who === 'steven') { | |
p.eliminate(); // throws NoMatch | |
} | |
let how = p.split([ // could throw Split or NoMatch | |
() => p.consume('happily', 'happily'), | |
() => p.consume('sadly', 'sadly'), | |
() => 'neutrally' | |
]); | |
p.submit(); // could throw NoMatch | |
return `You looked at ${who} ${how}`; | |
} | |
// This is what imperative style looks like when the parser is | |
// implemented with explicit early returns | |
function imperative_style_with_explicit_early_returns(p: Parser) { | |
let _ = p.consume('look at'); // could return NoMatch | |
if (parse_failed(_)) { | |
return _ | |
} | |
let who = p.split([ // could return Split or NoMatch | |
() => p.consume('me', 'me'), | |
() => p.consume('mewtwo', 'mewtwo'), | |
() => p.consume('steven', 'steven'), | |
() => p.consume('martha', 'martha') | |
]); | |
if (parse_failed(who)) { | |
return who; | |
} | |
if (who === 'steven') { | |
return p.eliminate(); // returns NoMatch | |
} | |
let how = p.split([ // could returns Split or NoMatch | |
() => p.consume('happily', 'happily'), | |
() => p.consume('sadly', 'sadly'), | |
() => 'neutrally' | |
]); | |
if (parse_failed(how)) { | |
return how; | |
} | |
_ = p.submit(); // could return NoMatch | |
if (parse_failed(_)) { | |
return _; | |
} | |
return `You looked at ${who} ${how}`; | |
} | |
// This is what functional style looks like regardless of the implementation | |
const functional_style = ((p: Parser) => | |
p.consume('look at', () => | |
p.split([ | |
() => p.consume('me', 'me'), | |
() => p.consume('mewtwo', 'mewtwo'), | |
() => p.consume('steven', 'steven'), | |
() => p.consume('martha', 'martha') | |
], (who) => | |
who === 'steven' | |
? p.eliminate() : | |
p.split([ | |
() => p.consume('happily', 'happily'), | |
() => p.consume('sadly', 'sadly'), | |
() => 'neutrally' | |
], (how) => | |
p.submit(() => | |
`You looked at ${who} ${how}` | |
))))); | |
let command = raw('look at me'); | |
// Run them using | |
Parser.run_thread(command, imperative_style_with_exceptions); | |
Parser.run_thread(command, imperative_style_with_explicit_early_returns); | |
Parser.run_thread(command, functional_style); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment