/* PEG grammar for a subset of wikitext, useful in the MediaWiki frontend */ start = e:expression* { return e.length > 1 ? [ "CONCAT" ].concat(e) : e[0]; } expression = template / link / extlink / replacement / literal paramExpression = template / link / extlink / replacement / literalWithoutBar template = "{{" t:templateContents "}}" { return t; } templateContents = twr:templateWithReplacement p:templateParam* { return twr.concat(p) } / twr:templateWithOutReplacement p:templateParam* { return twr.concat(p) } / t:templateName p:templateParam* { return p.length ? [ t, p ] : [ t ] } templateWithReplacement = t:templateName ":" r:replacement { return [ t, r ] } templateWithOutReplacement = t:templateName ":" p:paramExpression { return [ t, p ] } templateParam = "|" e:paramExpression* { return e.length > 1 ? [ "CONCAT" ].concat(e) : e[0]; } templateName = tn:[A-Za-z_]+ { return tn.join('').toUpperCase() } /* TODO: Update to reflect separate piped and unpiped handling */ link = "[[" w:expression "]]" { return [ 'WLINK', w ]; } extlink = "[" url:url whitespace text:expression "]" { return [ 'LINK', url, text ] } url = url:[^ ]+ { return url.join(''); } whitespace = [ ]+ replacement = '$' digits:digits { return [ 'REPLACE', parseInt( digits, 10 ) - 1 ] } digits = [0-9]+ literal = lit:escapedOrRegularLiteral+ { return lit.join(''); } literalWithoutBar = lit:escapedOrLiteralWithoutBar+ { return lit.join(''); } escapedOrRegularLiteral = escapedLiteral / regularLiteral escapedOrLiteralWithoutBar = escapedLiteral / regularLiteralWithoutBar escapedLiteral = "\\" escaped:. { return escaped; } regularLiteral = [^{}\[\]$\\] regularLiteralWithoutBar = [^{}\[\]$\\|]