peasy
Version:
an easy but powerful parser
59 lines (47 loc) • 1.94 kB
text/coffeescript
{inCharset, letters, charset, BaseParser} = peasy = require '../peasy'
identifierHeadChars = '$_'+letters
endTextCharset = charset(')@'+identifierHeadChars)
identifierHeadCharset = charset(identifierHeadChars)
exports.TemplateParser = class TemplateParser extends BaseParser
constructor: ->
super
[at, lpar, rpar, exclam] = for c in '@()!' then do(c=c) =>
mayExclam =
error = (msg) => throw [-20..+20]+' '++': '+msg
tcall = => (f = tfield()) and lpar() and (args = template()) and ((rpar() and f+'('+args+')') or error('expect )'))
tfield =
field = => (id=) and mayExclam() and "t.transform(e.#{id})"
text = =>
data =
start = cur =
result = ''
while 1
c = data[cur]
if (not c) then break
else if c=='!'
cur++
c = data[cur]
if inCharset(c, identifierHeadCharset)
= cur
id =
cur =
result += id
else if c=='!' or c=='@' or c==')'
result += c
cur++
else if c
result += '!'+c
cur++
else break
else if c=='\n' then cur++; result +='\\n'
else if inCharset(c, endTextCharset) then break
else result += c; cur++
if cur==start then return
= cur
if '"' in result then "'"+result+"'"
else '"'+result+'"'
anySegment =
template = => (x = anySegment()) and x.join(',')
= => (t = template()) and (( and t) or error('unexpected )'))
templateParser = new TemplateParser
exports.parseTemplate = parseTemplate = (text) -> templateParser.parse(text)