/* this parser is heavily based on Alex Warth's bootstrap js parser */

ometa LKJSParser <: Parser {
    isLKParser  = ''                                                    -> true,
  
    fromTo :x :y    = seq(x) (~seq(y) char)*:cs seq(y)                  -> cs,
    nl              = '\n' | '\r'                                       -> '\n',
	nameFirst       = letter | '$' | '_',
  	nameRest        = nameFirst | digit,
  	iName           = firstAndRest(#nameFirst, #nameRest):r		        -> r.join(''),
  	isKeyword :x    = ?BSJSParser._isKeyword(x),
  	name            = iName:n ~isKeyword(n)								-> n,
  	keyword         = iName:k isKeyword(k)									-> k,
  	escapeChar   = '\\' char:c                                              -> ometaUnescape('\\' + c),
  	str     = '\'' (escapeChar | ~'\'' char)*:cs '\''                   -> { '\'' + cs.join('') + '\'' }
  	        | '"' (escapeChar | ~'"' char)*:cs '"'                   -> { '"' + cs.join('') + '"' },
    
    comment         = fromTo('//', '\n'):c                              -> { '//' + c.join('')}
                    | fromTo('/*', '*/'):c                              -> { '/*' + c.join('') + '*/' },
  
    optNl           = spacesNoNl (nl:n                                  -> n
                    | empty                                             -> ''
                    ),
    spacesNoNl      = (~nl space)*:spcs									-> '\t',
    sc              = spacesNoNl (nl:n								    -> n
					| &'}' | end)						                -> ''
                    | ";"	optNl:nl									    -> { ';' + nl },
    srcElem         = "function":f (formal | empty):n funcRest:fr             -> { lively.Text.createText(f).concat(fr) }
                    | stmt:s											-> s,
    funcRest        = "(" listOf(#formal, ','):fs ")" "{" optNl:nl srcElems:body "}" -> { lively.Text.createText('(' + fs + ') {' + nl).concat(body).concat(lively.Text.createText('}')) },
    formal          = spaces:sps name:n								    -> { sps.join('') + n},
    srcElems        = srcElem*:ss                                       -> ss.inject(lively.Text.createText(''), function(text, ea) { return text.concat(ea) }) ,
    stmt            = something:sth                                     ->  { sth },
   something        =  spacesNoNl:spcs ( partStmt )+:parts sc:end            ->  {  parts.inject(lively.Text.createText(spcs), function(text, ea) {
                                                                                        return text.concat(ea)
                                                                                    }).concat(lively.Text.createText(end)) },
	partStmt = str:s                                                ->  { lively.Text.createText(s, {color: Color.green}) }
	            | keyword:k									        ->  { lively.Text.createText(k, {color: Color.red}) }
				| name:n											->  { lively.Text.createText(n) }
				| (~sc anything:a)									->  { lively.Text.createText(a) }
};


LKJSParser;