Skip to content

Instantly share code, notes, and snippets.

@tomjakubowski
Last active June 6, 2016 22:58
Show Gist options
  • Save tomjakubowski/508f585aa624a05a36a94e35ac487766 to your computer and use it in GitHub Desktop.
Save tomjakubowski/508f585aa624a05a36a94e35ac487766 to your computer and use it in GitHub Desktop.
// Grammar for pegjs
// missing: floating point numbers, sets, "discard"
{
function Sym(name, prefix) {
this.name = name;
this.prefix = prefix;
}
Sym.prototype.toString = function() {
return 'Sym(' + (this.prefix ? this.prefix + '/' : '') + this.name + ')';
};
function Keyword(name, prefix) {
this.isKeyword = true;
this.name = name;
this.prefix = prefix;
}
Keyword.prototype.toString = function() {
return 'Keyword(:' + (this.prefix ? this.prefix + '/' : '') + this.name + ')';
};
function Tagged(sym, element) {
this.sym = sym;
this.element = element;
}
Tagged.prototype.toString = function() {
return 'Tagged(' + this.symbol.toString() + ', ' + this.element.toString() + ')';
};
}
start
= value
value
= tagged_element
/ element
tagged_element
= '#' tag:tag rws elem:element { return new Tagged(tag, elem); }
tag
= name:tagname '/' prefix:tagname { return new Sym(name, prefix); }
/ t:tagname { return new Sym(t); }
tagname
= head:tagstart tail:(namerest)* { return text(); }
tagstart
= [a-zA-Z]
element
= atom
/ composite
atom
= nil
/ boolean
/ string
/ integer
/ keyword
/ symbol
nil
= 'nil' { return null; }
boolean
= 'true' { return true; }
/ 'false' { return false; }
string
= '"' xs:strchar* '"' { return xs.join(''); }
strchar
= [^"\\]
/ '\\' seq:( 't' { return '\t'; }
/ 'r' { return '\r'; }
/ 'n' { return '\n'; }
/ '"' { return '\"'; }
/ '\\' { return '\\';}) { return seq; }
integer
= x:int 'N'? { return x; }
int
= [+-]? x:[1-9] xs:[0-9]* { return parseInt(text(), 10); }
/ [+-]? x:[0-9] { return parseInt(text()); }
keyword
= ':' sym:symbol { return new Keyword(sym.name, sym.prefix); }
symbol
= prefix:name '/' name:name { return new Sym(name, prefix); }
/ name:name { return new Sym(name); }
name
= head:namestart tail:(namerest)* {
return text();
}
namestart "start of identifier"
= [a-zA-Z.*+!\-_?$%&=<>]
namerest "legal identifier character"
= namestart / [0-9#:]
composite
= map
/ vector
map
= '{' ws
pairs:(
head:kvpair
tail:(rws kv:kvpair { return kv; })*
{ return [head].concat(tail); }
)?
ws '}' {
let ob = {};
if (!pairs) return ob;
for (let i = 0; i < pairs.length; i++) {
ob[pairs[i][0]] = pairs[i][1];
}
return ob;
}
kvpair
= key:value rws val: value { return [key, val]; }
vector
= '[' ws
values:(
head:value
tail:(rws v:value { return v; })*
{ return [head].concat(tail); }
)?
ws ']' { return values ? values : []; }
_ "whitespace"
= [ \t\n\r,]
/ ';' [^\n]* '\n'
// optional whitespace
ws "whitespace"
= _*
// required whitespace
rws "whitespace"
= _+
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment