Skip to content

Instantly share code, notes, and snippets.

@aengelberg
Last active September 1, 2018 17:23
Show Gist options
  • Save aengelberg/6faf3bafae52145990ba735874e400ac to your computer and use it in GitHub Desktop.
Save aengelberg/6faf3bafae52145990ba735874e400ac to your computer and use it in GitHub Desktop.
*slaps roof of parser*
(ns alex.csbnf
"Framework for writing parsers using CSBNF (Car Salesman Backus-Naur Form) notation."
(:require
[instaparse.combinators :as c]
[instaparse.core :as insta]))
(def csbnf-parser
(insta/parser
"grammar = rule+
<rule> = (<'*slaps roof of'> rule-name <'*' 'this bad boy'>
| <'this'> rule-name)
<'can fit so'>
<'many' | 'much'>
<'fucking'?> <'goddamned'?>
alt
<'in it'>
rule-name = #'[a-zA-Z0-9_-]*[a-rt-zA-Z0-9_-]'
alt = cat (<'or'> cat)*
cat = token (<'followed by'> token)*
<token> = string | rhs-rule | <'('> alt <')'>
string = ( <'\"'> #'([^\"]|\\\\\")*' <'\"'>
| <\"'\"> #\"([^']|\\\\')*\" <\"'\">)
plural
rhs-rule = rule-name plural
<plural> = <'s' | \"'s\">?"
:auto-whitespace :standard
:string-ci true))
(defn csbnf
[grammar]
(->> grammar
(csbnf-parser)
(insta/transform
{:grammar vector
:cat c/cat
:alt c/alt
:string c/string
:rule-name keyword
:rhs-rule c/nt})
(insta/parser)
(comp not insta/failure?)))
(def balanced-paren-parser
(csbnf
"*slaps roof of sexpr* this bad boy can fit so many
left-parens followed by content followed by right-parens in it
this left-paren can fit so many '('s in it
this right-paren can fit so many fucking ')'s in it
this content can fit so much goddamned '' or sexprs followed by content in it"))
(balanced-paren-parser "(()((()))())")
;; => true
(balanced-paren-parser "(((")
;; => false
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment