Skip to content

Instantly share code, notes, and snippets.

@jbclements
Created April 11, 2012 17:07
Show Gist options
  • Save jbclements/2360594 to your computer and use it in GitHub Desktop.
Save jbclements/2360594 to your computer and use it in GitHub Desktop.
Pike
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<title>AST Builder</title>
<script type="text/javascript">
function cEl(tn){return document.createElement(tn)}
function byId(id){return document.getElementById(id)}
function cTN(s){return document.createTextNode(s)}
function byClass(cls){return Array.prototype.slice.call(document.body.getElementsByClassName(cls))}
function removeEl(el){if(el&&el.parentNode)el.parentNode.removeChild(el)}
function replaceEl(old,_new){old.parentNode.replaceChild(_new,old)}
//function removeEl(el){el.parentNode.removeChild(el)}
function emptyEl(el){var el_p,el_sib
el_p=el.parentNode;el_sib=el.nextSibling
el_p.removeChild(el) // DOM reflows can make clearing an element slow in older browsers so we remove from the DOM first
while(el.firstChild)el.removeChild(el.firstChild)
el_p.insertBefore(el,el_sib)}
function handleTextChange(el,f,ms){var timeout
el.onclick=el.onmouseup=el.onkeyup=handler
function handler(){
if(timeout){clearTimeout(timeout);timeout=null}
timeout=setTimeout(function(){f(el.value)},ms)}}
function xhr(method,uri,body,callback){var headers,p
// instead of a method string, the first argument can be an object with method and headers properties
if(typeof method==='object'){headers=method.headers;method=method.method}
var x=new XMLHttpRequest()
x.onreadystatechange=function(){if (x.readyState==4){callback(x)}}
x.open(method,uri,true)
if(headers) for(p in headers){x.setRequestHeader(p,headers[p])}
x.send(body)}
function GET_all(uris,cb){var pending,results
pending=uris.length
results=[]
if(!pending){cb(results)}
uris.forEach(function(uri,i,a){xhr('GET',uri,null,function(x){
results[i]=x
if(!--pending)cb(results)})})}
function boundingRect(el){
if(el.getBoundingClientRect)return el.getBoundingClientRect() // newer browsers have this
throw new Error('boundingRect unimplemented')
return {/*...*/}}
function addClass(el,_class){var x // Safari does not like "class" as an identifier
x=el.className
if(x.match(RegExp('\\b'+_class+'\\b')))return
if(x=='')return el.className=_class
el.className=x+' '+_class}
function removeClass(el,_class){var x,y
x=el.className
if(x==_class)return el.className=''
y=x.replace(RegExp('\\b'+_class+'\\b'),'')
if(y!=x)el.className=y}
function parseQueryString(s){
if(s[0]=='?')s=s.slice(1)
return s.split('&').map(function(s){var pos
if((pos=s.indexOf('='))<0)return {value:decodeURIComponent(s)}
return {key:decodeURIComponent(s.slice(0,pos)),value:decodeURIComponent(s.slice(pos+1))}})}
// XXX: these functions don't belong in this file
// unlike POSIX, this dirname() always returns a result that ends with slash
function dirname(path){var components
components=path.split('/')
if(components[components.length-1]=="") components.pop()
return components.slice(0,-1).join('/')+'/'}
// path segments, trailing slashes preserved, empty segments dropped
// '/foo/bar/' -> ['/','foo/','bar/']
// '../foo//bar' -> ['../','foo/','bar']
function path_segments(path){var ret=[]
path.split('/').forEach(function(s,i,a){if(s||!i)ret.push(s+(i<a.length-1?'/':''))})
return ret}
function resolve(base,path){var bsegs,psegs,bseg,pseg
if(path.charAt(0)=='/')return path
bsegs=path_segments(base)
psegs=path_segments(path)
// if the base is not a directory (...actually that should never happen) then remove the file component
if((bseg=bsegs.pop()).slice(-1)=='/')bsegs.push(bseg)
while(pseg=psegs.shift()){
if(pseg=='.'||pseg=='./')continue
if(pseg=='../'||pseg=='..'){bsegs.pop();if(!bsegs.length)bsegs.push('/')}
else bsegs.push(pseg)}
return bsegs.join('')}
/* Various debugging utilities and convenience functions */
function dir(o){var a=[],p;for(p in o){a.push(p)}return a.sort().join('\n')}
function test_pp(){
var a=[],f=function(x){a.push(x)},circular=[],o
circular[0]=circular
f(pp(['foo','bar',42]))
o=[{str:'foo',x:'bar\n"baz"\nquux'},{str:'baz',y:['xyzzy','quux','foo'],z:undefined,zz:null,f:f,foo:[true,false],circular:circular}]
o[1].self=o[1]
f(pp([o]))
return a.join('\n\n')}
function pp(o,depth){return pp_r(o,'',depth==undefined?32:depth)}
function pp_r(o,ss,d){var a=[],p
if(!d)return '…'
if(o===undefined)return 'undefined'
if(o===null)return 'null'
switch(typeof o){
case 'boolean':return o.toString()
case 'string':return pp_quote(o)
case 'number':return o.toString()
case 'function':return o.toString().replace(/\s+/g,'').replace(/(.{32}).+/,'$1…')}
if(o.constructor==Array){
o.forEach(function(e,i){
a.push(pp_r(o[i],' '+ss,d-1))})
return '['+a.join('\n'+ss+',')+']'}
if(o.constructor==Date)return o.toString()
for(p in o) if(o.hasOwnProperty(p))
a.push(p+':'+pp_r(o[p],(',:'+p).replace(/./g,' ')+ss,d-1))
return '{'+a.join('\n'+ss+',')+'}'}
pp=pp_smart
// pp_smart outputs sharp variables (like Mozilla), (optionally) re-orders object properties so that the largest ones come at the end (which makes reading deeply nested objects much easier), and tries to produce much more compact output by compressing properties and array members onto the same line when possible up to some specified line length (by default 80 chars)
// x, n_rows, n_cols
function pp_smart(x,opts){var parents=[],refs=[,]
opts=opts||{}
default_('rows',Infinity)
default_('cols',150)
default_('show_f',function(f){return (''+f).replace(/\s+/g,' ').replace(/(.{32}).{16,}/,'$1…')})
default_('reorder',true)
default_('string_escape',false)
default_('string_limit',64)
default_('hide',[])
parents=[]
return go(x,"")
function default_(k,v){if(opts[k]===undefined)opts[k]=v}
function lines(s){return s.split('\n').length}
function go(x,ss){var i,l,a=[],sub,cols,p,defer=[]
if(x===undefined)return 'undefined'
if(x===null)return 'null'
switch(typeof x){
case 'string':return pp_quote(x,opts).replace(/\n/g,'\n '+ss)
case 'boolean':
case 'number':return ''+x
case 'function':return opts.show_f(x)}
if(x.constructor==Date)return x.toString()
if(x instanceof RegExp)return '/'+x.source+'/'+(x.global?'g':'')+(x.ignorecase?'i':'')+(x.multiline?'m':'')
cols=opts.cols-ss.length
if((i=parents.lastIndexOf(x))>-1)refs.push(parents[i])
if((i=refs.lastIndexOf(x))>-1)return '#'+i+'#'
if(x.constructor==Array||Array.isArray&&Array.isArray(x)){
parents.push(x)
for(i=0,l=x.length;i<l;i++){
sub=(go(x[i],' '+ss))
if(a.length) sub=','+sub
if(sub.indexOf('\n')>-1){
if(a.length) a.push('\n'+ss)
a.push(sub)}
else{
if(cols-sub.length < 0){a.push('\n'+ss);cols=opts.cols-ss.length}
a.push(sub)
cols-=sub.length}}
parents.pop()
return ((i=refs.lastIndexOf(x))>-1?'#'+i+'=':'')
+ '['+a.join('')+']'}
parents.push(x)
for(p in x) if(Object.prototype.hasOwnProperty.call(x,p)){
if(opts.hide.indexOf(p)>-1)sub=p+':<hidden>'
else sub=p+':'+go(x[p],(',:'+p).replace(/./g,' ')+ss)
if(sub.indexOf('\n')>-1){
if(opts.reorder)defer.push(sub)
else{
if(a.length)sub=','+sub
if(a.length) a.push('\n'+ss)
a.push(sub)}}
else{
if(a.length)sub=','+sub
if(cols-sub.length<0 && a.length){a.push('\n'+ss);cols=opts.cols-ss.length}
a.push(sub)
cols-=sub.length}}
defer.sort(function(a,b){var la=lines(a),lb=lines(b); return la==lb?0:la>lb?1:-1})
for(i=0,l=defer.length;i<l;i++){
if(a.length) a.push('\n'+ss+',')
a.push(defer[i])}
parents.pop()
return ((i=refs.lastIndexOf(x))>-1?'#'+i+'=':'')
+ '{'+a.join('')+'}'}}
function pp_quote(s,opts){opts=opts||{}
if(opts.string_escape) s=s.replace(/\\/g,'\\\\').replace(/\n/g,'\\n')
if(opts.string_limit && s.length>opts.string_limit)s=s.slice(0,opts.string_limit)+'…'
if(s.indexOf("'")==-1)return "'"+s+"'"
return '"'+s.replace(/"/g,'\\"')+'"'}
function quote_string_single(s){
return "'"
+ s.replace(/\\/g,'\\\\').replace(/\n/g,'\\n').replace(/'/g,"\\'")
+ "'"}
function quote_string_double(s){
return '"'
+ s.replace(/\\/g,'\\\\').replace(/\n/g,'\\n').replace(/"/g,'\\"')
+ '"'}
(function(){
function create(){
function log(o){var x,s=''
if(arguments.length>1){o=[].concat(Array.prototype.slice.call(arguments))}
if(log.timing){x=+new Date;s=x-(log.time||x)+'ms\n';log.time=x}
log.log.push(s+(typeof o=='string'?o:pp(o)));return o}
log.log=[]
log.get=function(n){return '\n\n'+log.log.slice(n?-n:0).join('\n\n')}
log.count=function(){return log.log.length}
log.clear=function(){log.log=[]}
log.limit=function(n){if(log.log.length>n)log.log=log.log.slice(-n)}
return log}
log=create()
log.create=create})()
var log
function deepEq(x,y){var p
if(x===y)return true
if(typeof x!='object'
|| typeof y!='object')return false
for(p in x)if(!deepEq(x[p],y[p]))return false
for(p in y)if(!(p in x))return false
return true}
function extend(a,b){
for(var p in b)if(Object.prototype.hasOwnProperty.call(b,p))a[p]=b[p]
return arguments.length==2?a:extend.apply(null,[a].concat(Array.prototype.slice.call(arguments,2)))}
function event_interface(){var handlers
handlers={}
return {on:on
,event:event
,emit:event
}
function on(e,cb){(handlers[e]=handlers[e]||[]).push(cb)}
function event(e,a1,a2){var args=[].slice.call(arguments,1);(handlers[e]||[]).forEach(function(cb){cb.apply(null,args)})}}
</script>
<script type="text/javascript">
<!-- JSParser -->
;(function(exports){exports.names=['','Program','FunctionBody','FunctionDeclaration','FunctionExpression','FormalParameterList','','Statement','Block','VariableStatement','VariableDeclaration','VariableDeclarationNoIn','VariableDeclarationListNoIn','EmptyStatement','ExpressionStatement','IfStatement','IterationStatement','DoWhileStatement','WhileStatement','ForInStatement','ForInLeft','ForInVarLeft','ForStatement','ForInit','ForVarInit','ForTest','ForUpdate','ContinueStatement','BreakStatement','ReturnStatement','WithStatement','LabelledStatement','SwitchStatement','CaseClause','DefaultClause','ThrowStatement','TryStatement','Catch','Finally','DebuggerStatement','Expression','ExpressionNoIn','AssignmentExpression','AssignmentExpressionNoIn','AssignmentOperator','ConditionalExpression','ConditionalExpressionNoIn','LogicalOrExpression','LogicalOrExpressionNoIn','LogicalAndExpression','LogicalAndExpressionNoIn','BitwiseOrExpression','BitwiseOrExpressionNoIn','BitwiseXOrExpression','BitwiseXOrExpressionNoIn','BitwiseAndExpression','BitwiseAndExpressionNoIn','EqualityExpression','EqualityExpressionNoIn','EqualityOp','RelationalExpression','RelationalExpressionNoIn','RelationalOp','RelationalOpNoIn','ShiftExpression','ShiftOp','AdditiveExpression','AdditiveOp','MultiplicativeExpression','MultiplicativeOp','UnaryExpression','DeleteExpression','VoidExpression','TypeofExpression','PreIncrementExpression','PreDecrementExpression','UnaryPlusExpression','UnaryMinusExpression','BitwiseNotExpression','LogicalNotExpression','PostfixExpression','PostIncrementOp','PostDecrementOp','LeftHandSideExpression','','BracketAccessor','DotAccessor','Arguments','ArgumentList','','','PrimaryExpression','ArrayLiteral','ElementList','Elision','ObjectLiteral','PropertyNameAndValueList','PropertyAssignment','PropertyGetter','PropertySetter','PropertyName','PropertySetParameterList','Literal','NullLiteral','BooleanLiteral','NumericLiteral','DecimalLiteral','DecimalIntegerLiteral','DecimalDigit','ExponentPart','SignedInteger','HexIntegerLiteral','DQ','SQ','StringLiteral','RS','DoubleStringCharacter','SingleStringCharacter','LineContinuation','EscapeSequence','CharacterEscapeSequence','SingleEscapeCharacter','NonEscapeCharacter','EscapeCharacter','HexEscapeSequence','UnicodeEscapeSequence','RegularExpressionLiteral','RegularExpressionBody','RegularExpressionFirstChar','RegularExpressionChar','RegularExpressionBackslashSequence','RegularExpressionClass','RegularExpressionClassChar','RegularExpressionFlags','SourceCharacter','WhiteSpace','LF','CR','LS','PS','LineTerminator','LineTerminatorSequence','Comment','MultiLineComment','MultiLineCommentNoLB','SingleLineComment','S','SnoLB','EOS','EOSnoLB','EOF','ReservedWord','Keyword','FutureReservedWord','Identifier','IdentifierName','IdentifierStart','IdentifierPart','UnicodeLetter','HexDigit','FalseTok','TrueTok','NullTok','BreakTok','ContinueTok','DebuggerTok','InTok','InstanceOfTok','DeleteTok','FunctionTok','NewTok','ThisTok','TypeofTok','VoidTok','IfTok','ElseTok','DoTok','WhileTok','ForTok','VarTok','ReturnTok','CaseTok','DefaultTok','SwitchTok','ThrowTok','CatchTok','FinallyTok','TryTok','WithTok','_'];exports.parse=JSParser
JSParser.names=exports.names
function JSParser(out){var eof=false,s='',l=0,S=774144,T,M,F,D,R,tbl=[],x,pos=0,offset=0,buf=[],bufs=[],states=[],posns=[],c,equiv,ds,dp,failed=0,emp=0,emps=[];
equiv=rle_dec([9,0,1,1,1,2,2,1,1,3,18,0,1,1,1,4,1,5,1,0,1,6,1,7,1,8,1,9,1,10,1,11,1,12,1,13,1,14,1,15,1,16,1,17,1,18,9,19,1,20,1,21,1,22,1,23,1,24,1,25,1,0,4,26,1,27,1,26,17,28,1,29,2,28,1,30,1,31,1,32,1,33,1,34,1,0,1,35,1,36,1,37,1,38,1,39,1,40,1,41,1,42,1,43,1,28,1,44,1,45,1,46,1,47,1,48,1,49,1,28,1,50,1,51,1,52,1,53,1,54,1,55,1,56,1,57,1,58,1,59,1,60,1,61,1,62,6,0,1,1,26,0,1,1,9,0,1,28,10,0,1,28,4,0,1,28,5,0,23,28,1,0,31,28,1,0,458,28,4,0,12,28,14,0,5,28,7,0,1,28,1,0,1,28,17,0,112,63,5,28,1,0,2,28,2,0,4,28,8,0,1,28,1,0,3,28,1,0,1,28,1,0,20,28,1,0,83,28,1,0,139,28,1,0,5,63,2,0,154,28,13,0,38,28,2,0,1,28,7,0,39,28,9,0,45,63,1,0,1,63,1,0,2,63,1,0,2,63,1,0,1,63,8,0,27,28,5,0,3,28,29,0,11,63,6,0,42,28,20,63,1,0,10,63,4,0,2,28,1,63,99,28,1,0,1,28,7,63,2,0,6,63,2,28,2,63,1,0,4,63,2,28,10,63,3,28,2,0,1,28,16,0,1,28,1,63,30,28,27,63,2,0,89,28,11,63,1,28,14,0,10,63,33,28,9,63,2,28,4,0,1,28,262,0,3,63,54,28,2,0,1,63,1,28,16,63,2,0,1,28,4,63,3,0,10,28,2,63,2,0,10,63,1,0,2,28,8,0,5,28,1,0,3,63,1,0,8,28,2,0,2,28,2,0,22,28,1,0,7,28,1,0,1,28,3,0,4,28,2,0,1,63,1,28,7,63,2,0,2,63,2,0,3,63,1,28,8,0,1,63,4,0,2,28,1,0,3,28,2,63,2,0,10,63,2,28,15,0,3,63,1,0,6,28,4,0,2,28,2,0,22,28,1,0,7,28,1,0,2,28,1,0,2,28,1,0,2,28,2,0,1,63,1,0,5,63,4,0,2,63,2,0,3,63,3,0,1,63,7,0,4,28,1,0,1,28,7,0,12,63,3,28,1,63,11,0,3,63,1,0,9,28,1,0,3,28,1,0,22,28,1,0,7,28,1,0,2,28,1,0,5,28,2,0,1,63,1,28,8,63,1,0,3,63,1,0,3,63,2,0,1,28,15,0,2,28,2,63,2,0,10,63,17,0,3,63,1,0,8,28,2,0,2,28,2,0,22,28,1,0,7,28,1,0,2,28,1,0,5,28,2,0,1,63,1,28,7,63,2,0,2,63,2,0,3,63,8,0,2,63,4,0,2,28,1,0,3,28,2,63,2,0,10,63,1,0,1,28,16,0,1,63,1,28,1,0,6,28,3,0,3,28,1,0,4,28,3,0,2,28,1,0,1,28,1,0,2,28,3,0,2,28,3,0,3,28,3,0,12,28,4,0,5,63,3,0,3,63,1,0,4,63,2,0,1,28,6,0,1,63,14,0,10,63,17,0,3,63,1,0,8,28,1,0,3,28,1,0,23,28,1,0,10,28,1,0,5,28,3,0,1,28,7,63,1,0,3,63,1,0,4,63,7,0,2,63,1,0,2,28,6,0,2,28,2,63,2,0,10,63,18,0,2,63,1,0,8,28,1,0,3,28,1,0,23,28,1,0,10,28,1,0,5,28,2,0,1,63,1,28,7,63,1,0,3,63,1,0,4,63,7,0,2,63,7,0,1,28,1,0,2,28,2,63,2,0,10,63,18,0,2,63,1,0,8,28,1,0,3,28,1,0,23,28,1,0,16,28,3,0,1,28,7,63,1,0,3,63,1,0,4,63,9,0,1,63,8,0,2,28,2,63,2,0,10,63,10,0,6,28,2,0,2,63,1,0,18,28,3,0,24,28,1,0,9,28,1,0,1,28,2,0,7,28,3,0,1,63,4,0,6,63,1,0,1,63,1,0,8,63,18,0,2,63,13,0,48,28,1,63,2,28,7,63,5,0,7,28,8,63,1,0,10,63,39,0,2,28,1,0,1,28,2,0,2,28,1,0,1,28,2,0,1,28,6,0,4,28,1,0,7,28,1,0,3,28,1,0,1,28,1,0,1,28,2,0,2,28,1,0,4,28,1,63,2,28,6,63,1,0,2,63,1,28,2,0,5,28,1,0,1,28,1,0,6,63,2,0,10,63,2,0,2,28,34,0,1,28,23,0,2,63,6,0,10,63,11,0,1,63,1,0,1,63,1,0,1,63,4,0,2,63,8,28,1,0,36,28,4,0,20,63,1,0,2,63,4,28,4,0,8,63,1,0,36,63,9,0,1,63,57,0,43,28,20,63,1,28,10,63,6,0,6,28,4,63,4,28,3,63,1,28,3,63,2,28,7,63,3,28,4,63,13,28,12,63,1,28,11,63,6,0,38,28,10,0,43,28,1,0,1,28,3,0,90,28,5,0,68,28,5,0,82,28,6,0,73,28,1,0,4,28,2,0,7,28,1,0,1,28,1,0,4,28,2,0,41,28,1,0,4,28,2,0,33,28,1,0,4,28,2,0,7,28,1,0,1,28,1,0,4,28,2,0,15,28,1,0,57,28,1,0,4,28,2,0,67,28,4,0,1,63,32,0,16,28,16,0,85,28,12,0,620,28,2,0,8,28,9,0,1,1,26,28,5,0,75,28,3,0,3,28,15,0,13,28,1,0,4,28,3,63,11,0,18,28,3,63,11,0,18,28,2,63,12,0,13,28,1,0,3,28,1,0,2,63,12,0,52,28,2,0,30,63,3,0,1,28,4,0,1,28,1,63,2,0,10,63,33,0,3,63,1,1,1,0,10,63,6,0,88,28,8,0,41,28,1,63,1,28,85,0,29,28,3,0,12,63,4,0,12,63,10,0,10,63,30,28,2,0,5,28,11,0,42,28,6,0,17,63,7,28,2,63,6,0,10,63,38,0,23,28,5,63,228,0,5,63,47,28,17,63,7,28,4,0,10,63,17,0,9,63,12,0,3,63,30,28,10,63,3,0,2,28,10,63,70,0,36,28,20,63,8,0,10,63,3,0,3,28,10,63,36,28,130,0,192,28,39,63,23,0,2,63,278,28,2,0,6,28,2,0,38,28,2,0,6,28,2,0,8,28,1,0,1,28,1,0,1,28,1,0,1,28,1,0,31,28,2,0,53,28,1,0,7,28,1,0,1,28,3,0,3,28,1,0,7,28,3,0,4,28,2,0,6,28,4,0,13,28,5,0,3,28,1,0,7,28,3,0,12,1,28,0,1,64,1,65,5,0,1,1,15,0,2,63,19,0,1,63,10,0,1,1,17,0,1,28,13,0,1,28,16,0,5,28,59,0,13,63,4,0,1,63,3,0,12,63,17,0,1,28,4,0,1,28,2,0,10,28,1,0,1,28,3,0,5,28,6,0,1,28,1,0,1,28,1,0,1,28,1,0,4,28,1,0,11,28,2,0,4,28,5,0,5,28,4,0,1,28,17,0,41,28,2679,0,47,28,1,0,47,28,1,0,16,28,1,0,13,28,2,0,101,28,27,0,38,28,10,0,54,28,9,0,1,28,16,0,23,28,9,0,7,28,1,0,7,28,1,0,7,28,1,0,7,28,1,0,7,28,1,0,7,28,1,0,7,28,1,0,7,28,1,0,32,63,47,0,1,28,464,0,1,1,4,0,3,28,25,0,9,28,6,63,1,0,5,28,2,0,5,28,4,0,86,28,2,0,2,63,2,0,3,28,1,0,90,28,1,0,4,28,5,0,41,28,3,0,94,28,17,0,24,28,56,0,16,28,512,0,6582,28,74,0,20932,28,60,0,1165,28,115,0,269,28,3,0,16,28,10,63,2,28,20,0,32,28,2,0,13,28,1,63,12,0,2,63,1,0,25,28,127,0,9,28,2,0,103,28,2,0,2,28,110,0,7,28,1,63,3,28,1,63,4,28,1,63,23,28,5,63,24,0,52,28,12,0,2,63,50,28,17,63,11,0,10,63,38,0,10,63,28,28,8,63,2,0,23,28,13,63,172,0,41,28,14,63,9,0,3,28,1,63,8,28,2,63,2,0,10,63,422,0,11172,28,92,0,2048,66,6400,0,302,28,2,0,59,28,5,0,106,28,38,0,7,28,12,0,5,28,5,0,1,28,1,63,10,28,1,0,13,28,1,0,5,28,1,0,1,28,1,0,2,28,1,0,2,28,1,0,108,28,33,0,363,28,18,0,64,28,2,0,54,28,40,0,12,28,4,0,16,63,16,0,7,63,12,0,2,63,24,0,3,63,32,0,5,28,1,0,135,28,2,0,1,1,16,0,10,63,7,0,26,28,4,0,1,63,1,0,26,28,11,0,89,28,3,0,6,28,2,0,6,28,2,0,6,28,2,0,3,28,35,0])
function rle_dec(a){var r=[],i,l,n,x,ll;for(i=0,l=a.length;i<l;i+=2){n=a[i];x=a[i+1];r.length=ll=r.length+n;for(;n;n--)r[ll-n]=x}return r}
T=[,778240,2899968,823296,5156864,950272,,2945024,3010560,9564160,9629696,7794688,8650752,,3598854,7282688,7446528,7467008,8695808,7610368,7696384,7725056,8404992,8572928,8630272,8622080,8626176,3444736,3063808,8802304,9687040,8765440,8876032,8994816,9097216,9232384,9302016,9375744,9478144,3526656,3620864,8577024,3665920,7852032,3715072,3887104,7901184,3969024,7983104,4022272,8036352,4075520,8089600,4128768,8142848,4182016,8196096,4235264,8249344,4280320,4341760,8294400,4386816,8339456,4505600,7237632,4550656,4595712,4648960,4694016,4718592,4784128,7188480,7090176,7064582,7035910,7168000,7147520,4763648,4841472,4861952,,,4902912,,5099520,5136384,5009408,5054464,,,5361664,5427200,5554176,5639174,6541312,6615040,6660096,6716422,6847494,6828032,6975488,5668864,5767168,5693440,5799936,5836800,5935104,,5959680,5967872,6037504,,,6283264,,6332416,6492160,6479872,6381568,6414336,,6429190,6447104,6467584,1052672,6107136,6123520,6238208,6135808,6172672,6189056,6205440,6275072,,,,,,,3334144,2846720,2756608,2771974,3275782,2829318,2718726,3234822,3133440,3354624,3226118,1089536,2072576,1175552,985606,995328,1019904,1007616,,,5708806,5741574,5774342,3103750,3484678,3550214,4434950,4455430,4807686,5295110,5340166,6982662,7113734,7212038,7429126,7400454,7560198,7580678,8383494,7773190,8842246,9071622,9157638,9198598,9272326,9448454,9501702,9542662,9759750,9785344,785414,786432,790528,601263,2394,802816,31919,15535,815104,601263,2394,695471,831488,601263,2394,634031,847872,601263,2394,,864256,601263,2394,876544,23727,2394,888832,601263,2394,,905216,601263,2394,,921600,601263,2394,11439,937984,601263,2394,,634031,961542,962560,,970752,601263,2394,634031,987136,621743,638127,642223,1003520,646319,1011712,642223,,1024000,650415,,,1040384,474287,515247,,,1060864,654511,654511,654511,654511,2394,,,1093632,625839,629935,,,,,,,,,,,,,,,,,1171456,646319,1182726,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2079750,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2719744,2723840,556207,580783,584879,2740224,2744320,556207,580783,584879,2760704,588975,597167,,,,2788358,2791942,2796550,,,,552111,,,,,,,,2842624,,2850816,560303,2859008,564399,560303,564399,568495,572591,,,,,,2907142,2908160,2912256,601263,2394,2924544,31919,15535,2936832,601263,2394,2949120,36015,40111,56495,60591,64687,68783,113839,117935,122031,126127,130223,134319,146607,150703,162991,,3021830,3022848,3026944,601263,2394,3039232,31919,15535,3051520,601263,2394,,670895,3072000,605359,2394,3087366,3088384,634031,609455,613551,,,,,,,3129344,646319,3140614,3141632,3145728,601263,2394,,3162112,3166208,605359,2394,580783,3182592,3186688,605359,2394,3198976,,3207168,3211264,601263,2394,617647,3227648,552111,3235840,3239936,556207,597167,593071,3256320,3260416,556207,597167,593071,,,,3292166,3295750,3300358,,,,3313664,576687,552111,,,,3338240,560303,564399,568495,572591,3361798,3362816,3366912,605359,2394,,3383296,3387392,605359,2394,580783,3403776,3407872,605359,2394,3420160,,3428352,3432448,605359,2394,617647,674991,3452928,605359,2394,3468294,3469312,634031,609455,613551,,,,,,,,,,3522560,646319,679087,3534848,601263,2394,609455,,,,,,,,,,3588096,646319,,3600384,3604480,,695471,167087,609455,175279,3632134,3633152,3637248,601263,2394,,3653632,601263,2394,175279,3673094,3674112,343215,3682304,601263,2394,183471,3698688,601263,2394,175279,187567,3722246,3723264,,3731456,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,195759,3898374,3899392,3903488,601263,2394,,3919872,601263,2394,175279,3936256,601263,2394,,3952640,601263,2394,175279,2394,203951,3980294,3981312,3985408,601263,2394,,,,4009984,601263,2394,203951,212143,4033542,4034560,4038656,601263,2394,,,,4063232,601263,2394,212143,220335,4086790,4087808,4091904,601263,2394,,4108288,,4116480,601263,2394,220335,228527,4140038,4141056,4145152,601263,2394,,4161536,,4169728,601263,2394,228527,236719,4193286,4194304,4198400,601263,2394,,4214784,,4222976,601263,2394,236719,249007,4246534,4247552,4251648,601263,2394,244911,4268032,601263,2394,249007,4287494,,,,,,,,,,,,,,,265391,4353030,4354048,4358144,601263,2394,257199,4374528,601263,2394,265391,4393990,,,,,,,,,687279,683183,,,,4448256,646319,,,,,,,,,,,,4501504,646319,273583,4516870,4517888,4521984,601263,2394,269487,4538368,601263,2394,273583,281775,4561926,4562944,4567040,601263,2394,277679,4583424,601263,2394,281775,4602886,4603904,,4612096,4616192,,,4628480,,4636672,4640768,,,289967,4660230,4661248,4665344,601263,2394,285871,4681728,601263,2394,289967,4698112,,,,4714496,,4722688,330927,294063,298159,302255,306351,310447,314543,318639,322735,326831,,4771840,601263,2394,289967,691375,4792320,601263,2394,289967,,,,,,,,4837376,646319,,4849664,601263,2394,289967,343215,4873222,4874240,4878336,605359,2394,4890624,335023,339119,2394,4910086,4911104,699567,4919296,601263,2394,4931584,375983,19631,4943872,4951046,4952064,4956160,601263,2394,359599,4972544,4976640,601263,2394,351407,4993024,4997120,601263,2394,355503,,5017600,601263,2394,5029888,363695,2394,5042176,601263,2394,,175279,5065734,5066752,5070848,601263,2394,,5087232,601263,2394,175279,,5107712,601263,2394,167087,5124096,601263,2394,,,5144576,601263,2394,638127,695471,5165056,601263,2394,5177344,634031,2394,5189632,601263,2394,,5206016,601263,2394,5218304,23727,2394,5230592,601263,2394,,5246976,601263,2394,,5263360,601263,2394,11439,5279744,601263,2394,,,,,,,,,,,5332992,646319,,,,,5357568,646319,5365760,703663,634031,421039,380079,392367,5390336,,5398528,601263,2394,167087,5414912,601263,2394,,5434374,5435392,,5443584,388271,2394,5455872,601263,2394,,5472256,,384175,5484544,601263,2394,,5500928,,384175,5513216,601263,2394,,5529600,388271,2394,5541888,601263,2394,,5558272,388271,2394,5570560,601263,2394,175279,5590022,5591040,5595136,601263,2394,,5611520,388271,2394,5623808,601263,2394,175279,5640192,5644288,601263,2394,,5660672,388271,2394,5672960,425135,429231,433327,470191,519343,5697536,662703,658607,,,,,,,5734400,646319,,,,,,5763072,646319,666799,,,,,,5795840,646319,5807110,5808128,437423,5816320,642223,5824512,457903,5832704,642223,5843974,5844992,441519,,5857280,445615,5865472,449711,2394,5877760,,5885952,445615,5894144,445615,5902336,449711,2394,5914624,441519,5922816,449711,2394,,5939200,,5947392,,5955584,445615,,453807,5975046,5976064,445615,5984256,445615,5992448,,6000640,445615,6008832,445615,6017024,,6025216,445615,6033408,445615,6044678,6048774,,,,6062080,654511,6070272,654511,6081542,,,,6094848,654511,6103040,654511,,523439,,548015,527535,6131712,531631,6142982,6146566,6148096,6152192,576687,,552111,535727,539823,474287,6180864,576687,552111,,6197248,543919,,6212614,6216198,6217728,6221824,576687,,552111,535727,6245382,6248966,6250496,6254592,576687,,552111,535727,539823,6279168,646319,6290438,6291456,461999,6299648,478383,461999,6311936,466095,6320128,482479,466095,,6339590,6343174,6344704,6348800,461999,474287,576687,552111,6369280,474287,490671,486575,6385664,494767,6393856,,6402048,445615,511151,515247,6418432,498863,502959,6430720,6434816,507055,576687,552111,6451200,498863,445615,,,,654511,654511,474287,580783,,6499334,6502918,6504448,6508544,466095,474287,576687,552111,6529024,474287,490671,486575,,6552582,6553600,6557696,601263,2394,396463,6574080,601263,2394,6586368,,2394,2394,6602752,601263,2394,,400559,6626310,6627328,6631424,601263,2394,,6647808,601263,2394,400559,6667270,6668288,412847,6676480,601263,2394,,6692864,601263,2394,175279,404655,408751,,,,,6733824,601263,2394,412847,6750208,601263,2394,,6766592,601263,2394,,6782976,601263,2394,,6799360,601263,2394,11439,6815744,601263,2394,,6832128,638127,470191,433327,,,,,6864896,601263,2394,412847,6881280,601263,2394,,6897664,601263,2394,416943,6914048,601263,2394,,6930432,601263,2394,,6946816,601263,2394,11439,6963200,601263,2394,,634031,,,,,,7004160,646319,,,,,,,,,,7049216,601263,2394,289967,,,,7077888,601263,2394,289967,707759,7098368,601263,2394,289967,,,,,,,,7143424,646319,,7155712,601263,2394,289967,,7176192,601263,2394,289967,711855,7196672,601263,2394,289967,,,,,,7233536,646319,7244806,,,,,,,,,,,715951,7290880,601263,2394,,7307264,601263,2394,167087,7323648,601263,2394,,7340032,601263,2394,31919,7359494,7360512,7364608,601263,2394,720047,7380992,601263,2394,31919,2394,,,,,,7421952,646319,,,,7442432,646319,7450624,72879,76975,81071,93359,724143,7475200,601263,2394,31919,7491584,601263,2394,728239,7507968,601263,2394,,7524352,601263,2394,167087,7540736,601263,2394,,609455,,,,7573504,646319,,,,,,,7606272,646319,732335,7618560,601263,2394,,7634944,85167,89263,683183,7651328,601263,2394,167087,7667712,601263,2394,,7684096,601263,2394,31919,7700480,601263,2394,343215,7716864,601263,2394,7729152,601263,2394,736431,7745536,601263,2394,48303,7761920,601263,2394,,,,,7790592,646319,634031,7805958,7806976,7811072,601263,2394,,7827456,,7835648,601263,2394,179375,2394,7859206,7860224,343215,7868416,601263,2394,183471,7884800,601263,2394,179375,191663,199855,7912454,7913472,7917568,601263,2394,,7933952,601263,2394,179375,7950336,601263,2394,,7966720,601263,2394,179375,2394,208047,7994374,7995392,7999488,601263,2394,,,,8024064,601263,2394,208047,216239,8047622,8048640,8052736,601263,2394,,,,8077312,601263,2394,216239,224431,8100870,8101888,8105984,601263,2394,,8122368,,8130560,601263,2394,224431,232623,8154118,8155136,8159232,601263,2394,,8175616,,8183808,601263,2394,232623,240815,8207366,8208384,8212480,601263,2394,,8228864,,8237056,601263,2394,240815,253103,8260614,8261632,8265728,601263,2394,244911,8282112,601263,2394,253103,265391,8305670,8306688,8310784,601263,2394,261295,8327168,601263,2394,265391,8346630,,,,,,,,,687279,,,,,8400896,646319,732335,8413184,601263,2394,,8429568,601263,2394,8441856,8445952,97455,101551,2394,8462336,601263,2394,,8478720,601263,2394,8491008,105647,2394,8503296,601263,2394,,8519680,601263,2394,8531968,109743,2394,8544256,601263,2394,,8560640,601263,2394,31919,171183,179375,8588294,8589312,8593408,601263,2394,,8609792,601263,2394,179375,167087,167087,736431,8638464,601263,2394,52399,48303,8662022,8663040,8667136,601263,2394,,8683520,601263,2394,48303,728239,8704000,601263,2394,,8720384,601263,2394,167087,8736768,601263,2394,,8753152,601263,2394,31919,634031,8773632,601263,2394,,8790016,601263,2394,31919,740527,8810496,605359,2394,8822784,613551,8830976,167087,609455,,,,,,,,8871936,646319,752815,8884224,601263,2394,,8900608,601263,2394,167087,8916992,601263,2394,,8933376,601263,2394,,8949760,138415,8961030,8962048,142511,8970240,138415,2394,8982528,601263,2394,,8998912,601263,2394,744623,9015296,601263,2394,167087,9031680,601263,2394,,9051142,9052160,9056256,601263,2394,31919,,,,,,9093120,646319,9101312,601263,2394,748719,9117696,601263,2394,,9137158,9138176,9142272,601263,2394,31919,,,,,,,,,9191424,646319,,,,,,,,9228288,646319,756911,9240576,605359,2394,9252864,613551,9261056,167087,609455,,,,,,,9297920,646319,769199,9310208,601263,2394,36015,9326592,601263,2394,9341958,9342976,154799,9351168,601263,2394,9363456,158895,2394,158895,761007,9383936,601263,2394,,9400320,601263,2394,634031,9416704,601263,2394,,9433088,601263,2394,36015,,,,,,,9474048,646319,765103,9486336,601263,2394,36015,,,,,,,,,9535488,646319,,,,,9560064,646319,736431,9572352,601263,2394,44207,9591814,9592832,9596928,601263,2394,,9613312,601263,2394,44207,609455,634031,9640966,9641984,9646080,601263,2394,,9662464,,9670656,601263,2394,175279,2394,773295,9695232,601263,2394,,9711616,601263,2394,167087,9728000,601263,2394,,9744384,601263,2394,31919,,,,,,9781248,646319,7343,9793536,]
M=rle_dec([1,,5,2392,1,,77,2392,1,,4,2392,2,,99,2392,1,811008,1,785414,1,798720,8,2392,1,827392,1,839680,2,2392,1,843776,1,856064,2,2392,1,860160,1,872448,2,2392,1,884736,2,2392,1,897024,2,2392,1,901120,1,913408,2,2392,1,917504,1,929792,2,2392,1,933888,1,946176,3,2392,1,954368,1,2392,1,961542,1,966656,1,978944,3,2392,1,991232,1,2393,1,2392,1,999424,1,2392,1,1003520,8,2392,1,1044480,1,2392,1,,1,1059846,1,2392,1,1064960,1,1069056,1,1073152,1,1077248,1,2392,2,,1,1169926,3,2392,4,,1,2392,4,,1,2392,5,,1,2392,1,2393,2,2392,8,,1,2392,7,,1,2392,4,,1,2392,4,,1,2392,5,,1,2392,5,,1,2392,6,,1,2392,4,,1,2392,6,,1,2392,7,,1,2392,5,,1,2392,5,,1,2392,4,,1,2392,10,,1,2392,6,,1,2392,9,,1,2392,3,,1,2392,4,,1,2392,6,,1,2392,7,,1,2392,7,,1,2392,9,,1,2392,6,,1,2392,5,,1,2392,6,,1,2392,5,,1,2392,12,,1,2392,6,,1,2392,9,,1,2392,8,,2,2392,5,,1,2392,4,,1,2392,5,,1,2392,8,,1,2392,8,,1,2392,7,,1,2392,6,,1,2392,2,,1,2392,4,,1,2392,7,,1,2392,3,,1,2392,8,,1,2392,2,,1,2392,10,,1,2392,2,,1,2392,3,,1,2392,6,,1,2392,6,,1,2392,4,,1,2392,5,,1,2392,3,,1,2392,6,,1,2392,3,,1,2392,4,,1,2392,5,,1,2392,4,,1,2392,1,2736128,4,2392,1,2740224,6,2392,1,2781184,2,,1,2812934,1,2788358,1,2805760,1,2393,2,,2,2392,3,,1,2838528,2,,1,2392,1,2842624,3,2392,1,2863104,4,2392,5,,1,2932736,1,2907142,1,2920448,24,2392,1,3014656,1,3047424,1,3021830,1,3035136,5,2392,1,3059712,3,2392,1,3067904,1,3080192,4,2392,1,3092480,2,2392,1,3127814,5,,1,2392,1,2393,2,2392,1,3153920,4,2392,1,3174400,4,2392,1,3197702,5,2392,1,3219456,4,2392,1,2393,1,2392,1,3252224,4,2392,1,3256320,3,2392,1,3284992,2,,1,3324934,1,3292166,1,3312134,1,2393,2,,1,3317760,1,2393,2,2392,2,,7,2392,1,3375104,4,2392,1,3395584,4,2392,1,3418886,5,2392,1,3440640,3,2392,1,3448832,1,3461120,4,2392,1,3473408,2,2392,1,3521030,8,,1,2392,1,2393,1,3530752,1,3543040,3,2392,1,3586566,8,,1,2392,1,2393,1,,1,3612672,1,2393,2,2392,1,3616768,1,2392,1,3624960,1,2392,1,3632134,1,3645440,2,2392,1,3649536,1,3661824,5,2392,1,3678208,1,3690496,2,2392,1,3694592,1,3706880,6,2392,1,3729926,1,2392,1,2393,1,2392,2,,1,2392,2,,1,2392,2,,1,2392,2,,1,2392,2,,1,2392,3,,1,2392,3,,1,2392,4,,1,2392,2,,1,2392,2,,1,2392,2,,1,3891200,2,2392,1,3911680,2,2392,1,3915776,1,3928064,2,2392,1,3932160,1,3944448,2,2392,1,3948544,1,3960832,4,2392,1,3973120,1,2392,1,3980294,1,3996678,2,2392,1,4005888,2,,1,4018176,3,2392,1,4026368,1,2392,1,4033542,1,4049926,2,2392,1,4059136,2,,1,4071424,3,2392,1,4079616,1,2392,1,4086790,1,4100096,2,2392,1,4106758,1,4112384,1,2393,1,4124672,3,2392,1,4132864,1,2392,1,4140038,1,4153344,2,2392,1,4160006,1,4165632,1,2393,1,4177920,3,2392,1,4186112,1,2392,1,4193286,1,4206592,2,2392,1,4213254,1,4218880,1,2393,1,4231168,3,2392,1,4239360,1,2392,1,4246534,1,4259840,2,2392,1,4263936,1,4276224,5,2392,3,,1,2392,3,,1,2392,2,,1,2392,2,,1,4345856,1,2392,1,4353030,1,4366336,2,2392,1,4370432,1,4382720,5,2392,2,,1,2392,2,,4,2392,1,4446726,2,,1,2392,1,2393,1,4499974,10,,1,2392,1,2393,1,4509696,1,2392,1,4516870,1,4530176,2,2392,1,4534272,1,4546560,3,2392,1,4554752,1,2392,1,4561926,1,4575232,2,2392,1,4579328,1,4591616,5,2392,1,4610566,1,2392,1,2393,3,2392,1,4635142,1,2392,1,2393,2,2392,1,4653056,1,2392,1,4660230,1,4673536,2,2392,1,4677632,1,4689920,3,2392,1,4712966,4,2392,1,2393,11,2392,1,4767744,1,4780032,3,2392,1,4788224,1,4800512,3,2392,1,4835846,6,,1,2392,1,2393,1,4845568,1,4857856,3,2392,1,4866048,2,2392,1,4886528,6,2392,1,4927488,1,4910086,1,4915200,3,2392,1,4939776,3,2392,1,4943872,1,2392,1,4964352,4,2392,1,4984832,4,2392,1,5005312,3,2392,1,5013504,1,5025792,2,2392,1,5038080,2,2392,1,5050368,3,2392,1,5058560,1,2392,1,5065734,1,5079040,2,2392,1,5083136,1,5095424,3,2392,1,5103616,1,5115904,2,2392,1,5120000,1,5132288,3,2392,1,5140480,1,5152768,3,2392,1,5160960,1,5173248,2,2392,1,5185536,2,2392,1,5197824,2,2392,1,5201920,1,5214208,2,2392,1,5226496,2,2392,1,5238784,2,2392,1,5242880,1,5255168,2,2392,1,5259264,1,5271552,2,2392,1,5275648,1,5287936,3,2392,1,5331462,8,,1,2392,1,2393,1,5356038,3,,1,2392,1,2393,7,2392,1,5394432,1,5406720,2,2392,1,5410816,1,5423104,5,2392,1,5439488,1,5451776,2,2392,1,5464064,4,2392,1,5476352,1,5480448,1,5492736,4,2392,1,5505024,1,5509120,1,5521408,2,2392,1,5525504,1,5537792,2,2392,1,5550080,3,2392,1,5566464,2,2392,1,5578752,2,2392,1,5582848,1,2392,1,5590022,1,5603328,2,2392,1,5607424,1,5619712,2,2392,1,5632000,3,2392,1,5656576,1,5652480,15,2392,1,5732870,5,,1,2392,1,2393,1,5761542,4,,1,2392,1,2393,1,2392,1,5794310,4,,1,2392,1,2393,2,2392,1,5814790,1,2392,1,2393,1,2392,1,5831174,1,2392,1,2393,2,2392,1,5849088,1,5853184,1,5861376,1,5857280,4,2392,1,5884934,1,5898240,1,5890048,1,2392,1,5894144,4,2392,1,5918720,3,2392,1,,3,2392,1,5951488,1,2392,1,5955584,1,5963776,3,2392,1,5980160,1,2392,1,5984256,1,2392,1,5999622,1,2392,1,6004736,1,2392,1,6008832,1,2392,1,6024198,1,2392,1,6029312,1,2392,1,6033408,2,2392,1,6061062,2,,1,2392,1,6066176,1,2392,1,6070272,1,2392,1,6093830,2,,1,2392,1,6098944,1,2392,1,6103040,1,6111232,1,6115328,1,6119424,1,2392,1,6127616,1,2392,1,6131712,2,2392,1,6160384,1,2393,5,2392,1,6179334,1,6184960,1,2393,1,2392,1,6193152,1,6201344,1,6197248,3,2392,1,6230016,1,2393,6,2392,1,6262784,1,2393,6,2392,1,6279168,2,2392,1,6295552,1,6303744,1,6299648,2,2392,1,6316032,1,6324224,1,6320128,1,2392,1,,2,2392,1,6361088,1,2393,5,2392,1,6373376,5,2392,1,6400518,1,2392,1,2393,5,2392,1,6443008,1,2393,7,2392,1,,1,6471680,1,6475776,1,2392,1,6483968,1,2392,1,,2,2392,1,6520832,1,2393,5,2392,1,6533120,2,2392,1,6545408,1,6598656,1,2392,1,6565888,2,2392,1,6569984,1,6582272,6,2392,1,6610944,3,2392,1,6619136,1,2392,1,6626310,1,6639616,2,2392,1,6643712,1,6656000,5,2392,1,6672384,1,6684672,2,2392,1,6688768,1,6701056,5,2392,1,6729728,3,,1,6742016,2,2392,1,6746112,1,6758400,2,2392,1,6762496,1,6774784,2,2392,1,6778880,1,6791168,2,2392,1,6795264,1,6807552,2,2392,1,6811648,1,6823936,7,2392,1,6860800,3,,1,6873088,2,2392,1,6877184,1,6889472,2,2392,1,6893568,1,6905856,2,2392,1,6909952,1,6922240,2,2392,1,6926336,1,6938624,2,2392,1,6942720,1,6955008,2,2392,1,6959104,1,6971392,4,2392,1,7002630,4,,1,2392,1,2393,6,,1,7045120,2,,1,7057408,3,2392,1,7073792,2,,1,7086080,3,2392,1,7094272,1,7106560,3,2392,1,7141894,6,,1,2392,1,2393,1,7151616,1,7163904,3,2392,1,7172096,1,7184384,3,2392,1,7192576,1,7204864,3,2392,1,7232006,4,,1,2392,1,2393,2,2392,2,,1,2392,3,,1,2392,2,,1,7286784,1,7299072,2,2392,1,7303168,1,7315456,2,2392,1,7319552,1,7331840,2,2392,1,7335936,1,7348224,2,2392,1,7352320,2,2392,1,7372800,2,2392,1,7376896,1,7389184,4,2392,1,7420422,4,,1,2392,1,2393,1,7440902,2,,1,2392,1,2393,5,2392,1,7471104,1,7483392,2,2392,1,7487488,1,7499776,2,2392,1,7503872,1,7516160,2,2392,1,7520256,1,7532544,2,2392,1,7536640,1,7548928,2,2392,1,7553024,1,2392,1,7571974,2,,1,2392,1,2393,1,7604742,5,,1,2392,1,2393,1,7614464,1,7626752,2,2392,1,7630848,1,7643136,2,2392,1,7647232,1,7659520,2,2392,1,7663616,1,7675904,2,2392,1,7680000,1,7692288,3,2392,1,7708672,2,2392,1,7712768,3,2392,1,7737344,2,2392,1,7741440,1,7753728,2,2392,1,7757824,3,2392,1,7789062,3,,1,2392,1,2393,1,7798784,2,2392,1,7819264,2,2392,1,7825926,1,7831552,1,2393,1,7843840,6,2392,1,7864320,1,7876608,2,2392,1,7880704,1,7892992,4,2392,1,7905280,2,2392,1,7925760,2,2392,1,7929856,1,7942144,2,2392,1,7946240,1,7958528,2,2392,1,7962624,1,7974912,4,2392,1,7987200,1,2392,1,7994374,1,8010758,2,2392,1,8019968,2,,1,8032256,3,2392,1,8040448,1,2392,1,8047622,1,8064006,2,2392,1,8073216,2,,1,8085504,3,2392,1,8093696,1,2392,1,8100870,1,8114176,2,2392,1,8120838,1,8126464,1,2393,1,8138752,3,2392,1,8146944,1,2392,1,8154118,1,8167424,2,2392,1,8174086,1,8179712,1,2393,1,8192000,3,2392,1,8200192,1,2392,1,8207366,1,8220672,2,2392,1,8227334,1,8232960,1,2393,1,8245248,3,2392,1,8253440,1,2392,1,8260614,1,8273920,2,2392,1,8278016,1,8290304,3,2392,1,8298496,1,2392,1,8305670,1,8318976,2,2392,1,8323072,1,8335360,5,2392,2,,1,2392,2,,3,2392,1,8399366,3,,1,2392,1,2393,1,8409088,1,8421376,2,2392,1,8425472,1,8437760,2,2392,1,8458240,4,2392,1,8470528,2,2392,1,8474624,1,8486912,2,2392,1,8499200,2,2392,1,8511488,2,2392,1,8515584,1,8527872,2,2392,1,8540160,2,2392,1,8552448,2,2392,1,8556544,1,8568832,4,2392,1,8581120,1,2392,1,8588294,1,8601600,2,2392,1,8605696,1,8617984,5,2392,1,8634368,1,8646656,3,2392,1,8654848,1,2392,1,8662022,1,8675328,2,2392,1,8679424,1,8691712,3,2392,1,8699904,1,8712192,2,2392,1,8716288,1,8728576,2,2392,1,8732672,1,8744960,2,2392,1,8749056,1,8761344,3,2392,1,8769536,1,8781824,2,2392,1,8785920,1,8798208,3,2392,1,8806400,1,8818688,5,2392,1,8835072,1,2392,1,8870406,6,,1,2392,1,2393,1,8880128,1,8892416,2,2392,1,8896512,1,8908800,2,2392,1,8912896,1,8925184,2,2392,1,8929280,1,8941568,2,2392,1,8945664,1,8953856,1,8949760,1,8978432,1,2392,1,8966144,1,2392,1,8970240,1,2392,1,8990720,3,2392,1,9007104,2,2392,1,9011200,1,9023488,2,2392,1,9027584,1,9039872,2,2392,1,9043968,1,2392,1,9051142,1,9064448,3,2392,1,9091590,4,,1,2392,1,2393,1,9109504,2,2392,1,9113600,1,9125888,2,2392,1,9129984,1,2392,1,9137158,1,9150464,3,2392,1,9189894,7,,1,2392,1,2393,1,9226758,6,,1,2392,1,2393,1,9236480,1,9248768,5,2392,1,9265152,1,2392,1,9296390,5,,1,2392,1,2393,1,9306112,1,9318400,2,2392,1,9322496,1,9334784,4,2392,1,9347072,1,9359360,6,2392,1,9379840,1,9392128,2,2392,1,9396224,1,9408512,2,2392,1,9412608,1,9424896,2,2392,1,9428992,1,9441280,3,2392,1,9472518,5,,1,2392,1,2393,1,9482240,1,9494528,3,2392,1,9533958,7,,1,2392,1,2393,1,9558534,3,,1,2392,1,2393,1,9568256,1,9580544,2,2392,1,9584640,1,9625600,1,9591814,1,9605120,2,2392,1,9609216,1,9621504,4,2392,1,9633792,2,2392,1,9654272,2,2392,1,9660934,1,9666560,1,2393,1,9678848,4,2392,1,9691136,1,9703424,2,2392,1,9707520,1,9719808,2,2392,1,9723904,1,9736192,2,2392,1,9740288,1,9752576,3,2392,1,9779718,4,,1,2392,1,2393,1,9789440,1,2392,1,2393])
F=rle_dec([1,,5,2393,1,,77,2393,1,,4,2393,2,,100,2393,1,2392,1,2393,1,794624,2,2393,1,806912,2,2393,1,819200,3,2393,1,835584,3,2393,1,851968,3,2393,1,868352,2,2393,1,880640,2,2393,1,892928,3,2393,1,909312,3,2393,1,925696,3,2393,1,942080,4,2393,1,2392,2,2393,1,974848,3,2393,1,2392,3,2393,1,2392,1,2393,1,1015808,2,2393,1,1028096,1,1032192,1,1039366,3,2393,1,,7,2393,2,,1,2393,1,1097728,1,1104902,1,1125382,4,,1,1145862,4,,1,2393,5,,1,2393,1,2392,1,2393,1,1219590,8,,1,1252358,7,,1,1272838,4,,1,1293318,4,,1,1317894,5,,1,1342470,5,,1,1371142,6,,1,1391622,4,,1,1420294,6,,1,1453062,7,,1,1477638,5,,1,1502214,5,,1,1522694,4,,1,1567750,10,,1,1596422,6,,1,1637382,9,,1,1653766,3,,1,1674246,4,,1,1702918,6,,1,1735686,7,,1,1768454,7,,1,1809414,9,,1,1838086,6,,1,1862662,5,,1,1891334,6,,1,1915910,5,,1,1969158,12,,1,1997830,6,,1,2038790,9,,1,2393,8,,1,2393,1,2104326,5,,1,2124806,4,,1,2149382,5,,1,2186246,8,,1,2223110,8,,1,2255878,7,,1,2284550,6,,1,2296838,2,,1,2317318,4,,1,2350086,7,,1,2366470,3,,1,2403334,8,,1,2415622,2,,1,2460678,10,,1,2472966,2,,1,2489350,3,,1,2518022,6,,1,2546694,6,,1,2567174,4,,1,2591750,5,,1,2608134,3,,1,2636806,6,,1,2653190,3,,1,2673670,4,,1,2698246,5,,1,2393,4,,2,2393,1,2727936,1,2732032,2,2393,1,2392,1,2748416,1,2752512,2,2393,1,2764800,2,2393,2,,1,2393,1,2392,1,2393,1,2392,2,,2,2393,3,,1,2393,2,,1,2393,1,2392,1,2393,1,2857990,1,2867200,2,2393,1,2871296,1,2875392,1,2393,5,,1,2393,1,2392,1,2393,1,2916352,2,2393,1,2928640,2,2393,1,2940928,2,2393,1,2953216,1,2957312,1,2961408,1,2965504,1,2969600,1,2973696,1,2977792,1,2981888,1,2985984,1,2990080,1,2994176,1,2998272,1,3002368,1,3006464,3,2393,1,2392,1,2393,1,3031040,2,2393,1,3043328,2,2393,1,3055616,4,2393,1,3076096,2,2393,1,3096576,4,2393,5,,1,2393,1,2392,1,2393,1,3161094,1,2393,1,3149824,2,2393,1,3181574,1,2393,1,3170304,2,2393,1,3206150,1,2393,1,3190784,5,2393,1,3215360,3,2393,1,2392,2,2393,1,3244032,1,3248128,2,2393,1,2392,1,3264512,1,3268608,2,2393,2,,1,2393,1,2392,1,2393,1,2392,2,,1,2393,1,2392,2,2393,2,,1,2393,1,3342336,1,3346432,1,3350528,2,2393,1,3382278,1,2393,1,3371008,2,2393,1,3402758,1,2393,1,3391488,2,2393,1,3427334,1,2393,1,3411968,5,2393,1,3436544,4,2393,1,3457024,2,2393,1,3477504,4,2393,8,,1,2393,1,2392,2,2393,1,3538944,3,2393,8,,1,2393,1,2392,1,,1,2393,1,2392,1,3608576,5,2393,1,2392,1,2393,1,3641344,3,2393,1,3657728,3,2393,1,3710976,2,2393,1,3686400,3,2393,1,3702784,4,2393,1,3738630,2,2393,1,2392,1,3750918,2,,1,3763206,2,,1,3775494,2,,1,3787782,2,,1,3800070,2,,1,3816454,3,,1,3832838,3,,1,3853318,4,,1,3865606,2,,1,3877894,2,,1,2393,2,,2,2393,1,3964928,1,2393,1,3907584,3,2393,1,3923968,3,2393,1,3940352,3,2393,1,3956736,5,2393,1,2392,1,2393,1,3989504,2,2393,2,,1,2393,1,4014080,4,2393,1,2392,1,2393,1,4042752,2,2393,2,,1,2393,1,4067328,4,2393,1,2392,1,2393,1,4096000,3,2393,1,2392,1,2393,1,4120576,4,2393,1,2392,1,2393,1,4149248,3,2393,1,2392,1,2393,1,4173824,4,2393,1,2392,1,2393,1,4202496,3,2393,1,2392,1,2393,1,4227072,4,2393,1,2392,1,2393,1,4255744,3,2393,1,4272128,3,2393,1,4303878,3,,1,4320262,3,,1,4332550,2,,1,2393,2,,2,2393,1,2392,1,2393,1,4362240,3,2393,1,4378624,3,2393,1,4406278,2,,1,4415488,2,,1,4419584,1,4423680,1,4427776,2,2393,2,,1,2393,1,2392,1,2393,10,,1,2393,1,2392,2,2393,1,2392,1,2393,1,4526080,3,2393,1,4542464,4,2393,1,2392,1,2393,1,4571136,3,2393,1,4587520,3,2393,1,4627462,2,2393,1,2392,1,4620288,4,2393,1,2392,1,4644864,3,2393,1,2392,1,2393,1,4669440,3,2393,1,4685824,3,2393,1,4702208,1,4706304,2,2393,1,2392,1,2393,1,4726784,1,4730880,1,4734976,1,4739072,1,4743168,1,4747264,1,4751360,1,4755456,1,4759552,3,2393,1,4775936,4,2393,1,4796416,3,2393,6,,1,2393,1,2392,2,2393,1,4853760,4,2393,1,4898816,1,2393,1,4882432,2,2393,1,4894720,3,2393,1,2392,2,2393,1,4923392,2,2393,1,4935680,2,2393,1,2392,1,4971526,1,2393,1,4960256,2,2393,1,4992006,1,2393,1,4980736,4,2393,1,5001216,4,2393,1,5021696,2,2393,1,5033984,2,2393,1,5046272,4,2393,1,2392,1,2393,1,5074944,3,2393,1,5091328,4,2393,1,5111808,3,2393,1,5128192,4,2393,1,5148672,4,2393,1,5169152,2,2393,1,5181440,2,2393,1,5193728,3,2393,1,5210112,2,2393,1,5222400,2,2393,1,5234688,3,2393,1,5251072,3,2393,1,5267456,3,2393,1,5283840,3,2393,8,,1,2393,1,2392,1,2393,3,,1,2393,1,2392,1,2393,1,5369856,1,5373952,1,5378048,1,5382144,1,5389318,3,2393,1,5402624,3,2393,1,5419008,3,2393,1,5471238,2,2393,1,5447680,2,2393,1,5459968,2,2393,1,5499910,3,2393,1,5488640,6,2393,1,5517312,3,2393,1,5533696,2,2393,1,5545984,3,2393,1,5562368,2,2393,1,5574656,3,2393,1,2392,1,2393,1,5599232,3,2393,1,5615616,2,2393,1,5627904,4,2393,1,5648384,3,2393,1,5664768,2,2393,1,5677056,1,5681152,1,5685248,1,5689344,2,2393,1,5701632,2,2393,5,,1,2393,1,2392,1,2393,4,,1,2393,1,2392,2,2393,4,,1,2393,1,2392,1,2393,1,5823494,2,2393,1,2392,3,2393,1,2392,1,2393,1,5876742,3,2393,1,2392,1,2393,1,5869568,1,2393,1,5913606,4,2393,1,2392,1,2393,1,5906432,4,2393,1,5926912,1,2393,1,,1,2393,1,5946374,3,2393,1,2392,3,2393,1,5991430,2,2393,1,2392,1,6016006,4,2393,1,2392,5,2393,1,2392,1,2393,1,6077446,1,2393,2,,3,2393,1,2392,2,2393,2,,3,2393,1,2392,6,2393,1,2392,1,2393,1,6164480,1,2393,1,2392,1,6156288,2,2393,1,6168576,3,2393,1,2392,3,2393,1,2392,2,2393,1,6234112,1,2393,1,2392,1,6225920,4,2393,1,6266880,1,2393,1,2392,1,6258688,2,2393,1,6270976,2,2393,1,2392,1,2393,1,6310918,2,2393,1,2392,4,2393,1,2392,1,2393,1,,1,2393,1,6368262,1,2393,1,2392,1,6352896,1,6356992,2,2393,1,6377472,4,2393,1,6392838,1,6406144,2,2393,1,2392,1,6410240,2,2393,1,6422528,2,2393,1,2392,1,6438912,3,2393,1,6455296,1,6459392,1,2393,1,,5,2393,1,,1,2393,1,6528006,1,2393,1,2392,1,6512640,1,6516736,2,2393,1,6537216,5,2393,1,6594560,1,2393,1,6561792,3,2393,1,6578176,2,2393,1,6590464,3,2393,1,6606848,4,2393,1,2392,1,2393,1,6635520,3,2393,1,6651904,3,2393,1,6705152,2,2393,1,6680576,3,2393,1,6696960,2,2393,1,6709248,2,2393,3,,1,2393,1,6737920,3,2393,1,6754304,3,2393,1,6770688,3,2393,1,6787072,3,2393,1,6803456,3,2393,1,6819840,3,2393,1,6836224,1,6840320,2,2393,3,,1,2393,1,6868992,3,2393,1,6885376,3,2393,1,6901760,3,2393,1,6918144,3,2393,1,6934528,3,2393,1,6950912,3,2393,1,6967296,4,2393,4,,1,2393,1,2392,6,,1,2393,2,,1,2393,1,7053312,3,2393,2,,1,2393,1,7081984,4,2393,1,7102464,3,2393,6,,1,2393,1,2392,2,2393,1,7159808,4,2393,1,7180288,4,2393,1,7200768,3,2393,4,,1,2393,1,2392,1,2393,1,7257094,2,,1,7273478,3,,1,2393,2,,2,2393,1,7294976,3,2393,1,7311360,3,2393,1,7327744,3,2393,1,7344128,3,2393,1,7393280,1,2393,1,7368704,3,2393,1,7385088,4,2393,4,,1,2393,1,2392,1,2393,2,,1,2393,1,2392,1,2393,1,7454720,1,7458816,1,7462912,3,2393,1,7479296,3,2393,1,7495680,3,2393,1,7512064,3,2393,1,7528448,3,2393,1,7544832,4,2393,2,,1,2393,1,2392,1,2393,5,,1,2393,1,2392,2,2393,1,7622656,3,2393,1,7639040,3,2393,1,7655424,3,2393,1,7671808,3,2393,1,7688192,3,2393,1,7704576,3,2393,1,7720960,2,2393,1,7733248,3,2393,1,7749632,3,2393,1,7766016,2,2393,3,,1,2393,1,2392,2,2393,1,7847936,1,2393,1,7815168,3,2393,1,2392,1,2393,1,7839744,4,2393,1,7897088,2,2393,1,7872512,3,2393,1,7888896,5,2393,1,7979008,1,2393,1,7921664,3,2393,1,7938048,3,2393,1,7954432,3,2393,1,7970816,5,2393,1,2392,1,2393,1,8003584,2,2393,2,,1,2393,1,8028160,4,2393,1,2392,1,2393,1,8056832,2,2393,2,,1,2393,1,8081408,4,2393,1,2392,1,2393,1,8110080,3,2393,1,2392,1,2393,1,8134656,4,2393,1,2392,1,2393,1,8163328,3,2393,1,2392,1,2393,1,8187904,4,2393,1,2392,1,2393,1,8216576,3,2393,1,2392,1,2393,1,8241152,4,2393,1,2392,1,2393,1,8269824,3,2393,1,8286208,4,2393,1,2392,1,2393,1,8314880,3,2393,1,8331264,3,2393,1,8358918,2,,1,8368128,2,,1,8372224,1,8376320,2,2393,3,,1,2393,1,2392,2,2393,1,8417280,3,2393,1,8433664,2,2393,1,8454144,1,8450048,3,2393,1,8466432,3,2393,1,8482816,2,2393,1,8495104,2,2393,1,8507392,3,2393,1,8523776,2,2393,1,8536064,2,2393,1,8548352,3,2393,1,8564736,5,2393,1,2392,1,2393,1,8597504,3,2393,1,8613888,6,2393,1,8642560,4,2393,1,2392,1,2393,1,8671232,3,2393,1,8687616,4,2393,1,8708096,3,2393,1,8724480,3,2393,1,8740864,3,2393,1,8757248,4,2393,1,8777728,3,2393,1,8794112,4,2393,1,8814592,2,2393,1,8829958,4,2393,6,,1,2393,1,2392,2,2393,1,8888320,3,2393,1,8904704,3,2393,1,8921088,3,2393,1,8937472,3,2393,1,2392,1,2393,1,8974336,2,2393,1,2392,2,2393,1,8986624,3,2393,1,9003008,3,2393,1,9019392,3,2393,1,9035776,3,2393,1,2392,1,2393,1,9060352,3,2393,4,,1,2393,1,2392,1,2393,1,9105408,3,2393,1,9121792,3,2393,1,2392,1,2393,1,9146368,3,2393,7,,1,2393,1,2392,1,2393,6,,1,2393,1,2392,2,2393,1,9244672,2,2393,1,9260038,4,2393,5,,1,2393,1,2392,2,2393,1,9314304,3,2393,1,9330688,2,2393,1,9371648,2,2393,1,9355264,2,2393,1,9367552,4,2393,1,9388032,3,2393,1,9404416,3,2393,1,9420800,3,2393,1,9437184,3,2393,5,,1,2393,1,2392,2,2393,1,9490432,3,2393,7,,1,2393,1,2392,1,2393,3,,1,2393,1,2392,2,2393,1,9576448,3,2393,1,2392,1,2393,1,9601024,3,2393,1,9617408,5,2393,1,9682944,1,2393,1,9650176,3,2393,1,2392,1,2393,1,9674752,5,2393,1,9699328,3,2393,1,9715712,3,2393,1,9732096,3,2393,1,9748480,3,2393,4,,1,2393,1,2392,2,2393,1,2392])
D=function(a,i,l,b){for(i=0,l=a.length,b=[];i<l;i++)b[i]=a[i]&&revive(a[i]);return b}([,,,,,,,,,,,,,[[[[21]]]],,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,[[[[13]]],[[[13]]]],[[[[15]]],[[[15]]]],,,,,,,,,,,,,,,,,,,,,,,,,,[[[[18,19]]]],,,,[[[[5]]]],[[[[9]]]],,[[[[31]]]],,,,,,[[[[5,9,31,36,40,47,50,52,54]]]],,,,,,,,,,,,,[[[[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65]]]],[[[[1]]]],[[[[2]]]],[[[[3]]]],[[[[64]]]],[[[[65]]]],,,,,,,,,,,,,,,,,,,[[[[26,27,28,29,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58]]]],[[[[18,19,26,27,35,36,37,38,39,40]]]],,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,[[[[10]]]],,,,,,,,,,[[[[11]]]],,,,[[[[59]]]],,,,,,,,[[[[61]]]],,,,[[[[14]]]],,,,,,,,,,,,,[[[[18,19,34,63]]]],,,[[[[6]]]],[[[[34]]]],,,,,[[[[53]]]],,,,,,,,,,,,[[[[47]]],[[[53]]],[[[45]]],[[[45]]]],,,,,[[[[52]]],[[[50]]],[[[53]]],[[[39]]]],,,,,[[[[40]]],[[[35]]],[[[45]]],[[[51]]],[[[39]]]],,,,,,,,,[[[[35]]],[[[36]]],[[[51]]],[[[52]]],[[[50]]],[[[35]]],[[[37]]],[[[52]]]],,,,,,,,,[[[[36]]],[[[48]]],[[[48]]],[[[45]]],[[[39]]],[[[35]]],[[[47]]]],,,,,,,,[[[[36]]],[[[57]]],[[[52]]],[[[39]]]],,,,,[[[[37]]],[[[42]]],[[[35]]],[[[50]]]],,,,,[[[[37]]],[[[45]]],[[[35]]],[[[51]]],[[[51]]]],,,,,,[[[[37]]],[[[48]]],[[[47]]],[[[51]]],[[[52]]]],,,,,,[[[[38]]],[[[48]]],[[[53]]],[[[36]]],[[[45]]],[[[39]]]],,,,,,,[[[[39]]],[[[47]]],[[[53]]],[[[46]]]],,,,,[[[[39]]],[[[56]]],[[[49]]],[[[48]]],[[[50]]],[[[52]]]],,,,,,,[[[[39]]],[[[56]]],[[[52]]],[[[39]]],[[[47]]],[[[38]]],[[[51]]]],,,,,,,,[[[[40]]],[[[43]]],[[[47]]],[[[35]]],[[[45]]]],,,,,,[[[[40]]],[[[45]]],[[[48]]],[[[35]]],[[[52]]]],,,,,,[[[[41]]],[[[48]]],[[[52]]],[[[48]]]],,,,,[[[[43]]],[[[46]]],[[[49]]],[[[45]]],[[[39]]],[[[46]]],[[[39]]],[[[47]]],[[[52]]],[[[51]]]],,,,,,,,,,,[[[[43]]],[[[46]]],[[[49]]],[[[48]]],[[[50]]],[[[52]]]],,,,,,,[[[[43]]],[[[47]]],[[[52]]],[[[39]]],[[[50]]],[[[40]]],[[[35]]],[[[37]]],[[[39]]]],,,,,,,,,,[[[[43]]],[[[47]]],[[[52]]]],,,,[[[[45]]],[[[48]]],[[[47]]],[[[41]]]],,,,,[[[[47]]],[[[35]]],[[[52]]],[[[43]]],[[[54]]],[[[39]]]],,,,,,,[[[[49]]],[[[35]]],[[[37]]],[[[44]]],[[[35]]],[[[41]]],[[[39]]]],,,,,,,,[[[[49]]],[[[50]]],[[[43]]],[[[54]]],[[[35]]],[[[52]]],[[[39]]]],,,,,,,,[[[[49]]],[[[50]]],[[[48]]],[[[52]]],[[[39]]],[[[37]]],[[[52]]],[[[39]]],[[[38]]]],,,,,,,,,,[[[[49]]],[[[53]]],[[[36]]],[[[45]]],[[[43]]],[[[37]]]],,,,,,,[[[[51]]],[[[42]]],[[[48]]],[[[50]]],[[[52]]]],,,,,,[[[[51]]],[[[52]]],[[[35]]],[[[52]]],[[[43]]],[[[37]]]],,,,,,,[[[[51]]],[[[53]]],[[[49]]],[[[39]]],[[[50]]]],,,,,,[[[[51]]],[[[57]]],[[[47]]],[[[37]]],[[[42]]],[[[50]]],[[[48]]],[[[47]]],[[[43]]],[[[58]]],[[[39]]],[[[38]]]],,,,,,,,,,,,,[[[[52]]],[[[42]]],[[[50]]],[[[48]]],[[[55]]],[[[51]]]],,,,,,,[[[[52]]],[[[50]]],[[[35]]],[[[47]]],[[[51]]],[[[43]]],[[[39]]],[[[47]]],[[[52]]]],,,,,,,,,,[[[[54]]],[[[48]]],[[[45]]],[[[35]]],[[[52]]],[[[43]]],[[[45]]],[[[39]]]],,,,,,,,,,[[[[36]]],[[[50]]],[[[39]]],[[[35]]],[[[44]]]],,,,,,[[[[37]]],[[[35]]],[[[51]]],[[[39]]]],,,,,[[[[37]]],[[[35]]],[[[52]]],[[[37]]],[[[42]]]],,,,,,[[[[37]]],[[[48]]],[[[47]]],[[[52]]],[[[43]]],[[[47]]],[[[53]]],[[[39]]]],,,,,,,,,[[[[38]]],[[[39]]],[[[36]]],[[[53]]],[[[41]]],[[[41]]],[[[39]]],[[[50]]]],,,,,,,,,[[[[38]]],[[[39]]],[[[40]]],[[[35]]],[[[53]]],[[[45]]],[[[52]]]],,,,,,,,[[[[38]]],[[[39]]],[[[45]]],[[[39]]],[[[52]]],[[[39]]]],,,,,,,[[[[38]]],[[[48]]]],,,[[[[39]]],[[[45]]],[[[51]]],[[[39]]]],,,,,[[[[40]]],[[[43]]],[[[47]]],[[[35]]],[[[45]]],[[[45]]],[[[57]]]],,,,,,,,[[[[40]]],[[[48]]],[[[50]]]],,,,[[[[40]]],[[[53]]],[[[47]]],[[[37]]],[[[52]]],[[[43]]],[[[48]]],[[[47]]]],,,,,,,,,[[[[43]]],[[[40]]]],,,[[[[43]]],[[[47]]],[[[51]]],[[[52]]],[[[35]]],[[[47]]],[[[37]]],[[[39]]],[[[48]]],[[[40]]]],,,,,,,,,,,[[[[43]]],[[[47]]]],,,[[[[47]]],[[[39]]],[[[55]]]],,,,[[[[50]]],[[[39]]],[[[52]]],[[[53]]],[[[50]]],[[[47]]]],,,,,,,[[[[51]]],[[[55]]],[[[43]]],[[[52]]],[[[37]]],[[[42]]]],,,,,,,[[[[52]]],[[[42]]],[[[43]]],[[[51]]]],,,,,[[[[52]]],[[[42]]],[[[50]]],[[[48]]],[[[55]]]],,,,,,[[[[52]]],[[[50]]],[[[57]]]],,,,[[[[52]]],[[[57]]],[[[49]]],[[[39]]],[[[48]]],[[[40]]]],,,,,,,[[[[54]]],[[[35]]],[[[50]]]],,,,[[[[54]]],[[[48]]],[[[43]]],[[[38]]]],,,,,[[[[55]]],[[[42]]],[[[43]]],[[[45]]],[[[39]]]],,,,,,[[[[55]]],[[[43]]],[[[52]]],[[[42]]]],,,,,,,,,,,,,,,,,,[[[[17]]],[[[12]]]],,,,,,[[[[12]]],[[[17]]]],,,,[[[[12]]],[[[17]]]],,,,[[[[17]]],[[[17]]]],,,,[[[[0,1,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63]]]],,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,[[[[59]]]],,,,,,,,,,,,[[[[61]]]],,,,,,,,,,[[[[36]]],[[[50]]],[[[39]]],[[[35]]],[[[44]]]],,,,,,,,,,,,,[[[[21]]]],,,,,,,,,,,[[[[61]]]],,,,,,,,,,,,,,,,,,[[[[17]]],[[[12]]]],,,,,,[[[[12]]],[[[17]]]],,,,,,[[[[12]]],[[[17]]]],,,,,,,,,,,,,[[[[21]]]],,,,,,,,,,,[[[[61]]]],,,,,,,,,,,,,,,[[[[37]]],[[[48]]],[[[47]]],[[[52]]],[[[43]]],[[[47]]],[[[53]]],[[[39]]]],,,,,,,,,,,,,,,,[[[[38]]],[[[39]]],[[[36]]],[[[53]]],[[[41]]],[[[41]]],[[[39]]],[[[50]]]],,,,,,,,,,,,,,[[[[59]]]],,,,,,,,,,[[[[14]]]],,,,,,,,,,,,,,,,,,,[[[[23]]]],,[[[[23]]]],[[[[12]]],[[[23]]]],,,[[[[17]]],[[[23]]]],,,[[[[7]]],[[[23]]]],,,[[[[13]]],[[[23]]]],,,[[[[15]]],[[[23]]]],,,[[[[22]]],[[[22]]],[[[23]]]],,,,[[[[24]]],[[[24]]],[[[23]]]],,,,[[[[24]]],[[[24]]],[[[24]]],[[[23]]]],,,,,[[[[8]]],[[[23]]]],,,[[[[33]]],[[[23]]]],,,[[[[60]]],[[[23]]]],,,,,,,,,[[[[25]]]],,,,,,,,[[[[20]]]],,,,,,,,,,,,[[[[60]]],[[[60]]]],,,,,,,,,,,,,[[[[8]]],[[[8]]]],,,,,,,,,,,,,[[[[60]]]],,[[[[23]]]],,,,,,,,,,,[[[[33]]]],,[[[[23]]]],,,,,,,,,,,[[[[8]]]],,[[[[23]]]],,,,,,,,,,,,,,,,,[[[[23]]],[[[23]]],[[[23]]]],,,,[[[[4]]],[[[23]]],[[[23]]]],,,,[[[[23]]],[[[23]]]],,,[[[[4]]],[[[23]]]],,,,,,,,,,,,,,,[[[[22]]],[[[23]]]],,,[[[[24]]],[[[23]]]],,,[[[[22]]]],[[[[24]]]],,,[[[[43]]],[[[47]]]],,,,,[[[[43]]],[[[47]]],[[[51]]],[[[52]]],[[[35]]],[[[47]]],[[[37]]],[[[39]]],[[[48]]],[[[40]]]],,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,[[[[13]]]],,,[[[[13]]]],[[[[23]]]],,[[[[15]]]],,,[[[[15]]]],[[[[23]]]],,,,,,,,,,,,,[[[[12]]]],[[[[17]]]],[[[[7]]]],,[[[[23]]]],,,,,,,,,,,,[[[[62]]]],,,,,,,,,,[[[[38]]],[[[39]]],[[[45]]],[[[39]]],[[[52]]],[[[39]]]],,,,,,,,,[[[[4]]]],,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,[[[[10]]]],,,,,,,,,,[[[[11]]]],,,,,,,[[[[14]]]],,,,,[[[[30]]]],,,,,,,,[[[[32]]]],[[[[16]]]],,,,,,,,,,,,,,,[[[[10]]]],,,,,,,,,,[[[[11]]]],,,,[[[[59]]]],,,,,,,,[[[[61]]]],[[[[40]]],[[[53]]],[[[47]]],[[[37]]],[[[52]]],[[[43]]],[[[48]]],[[[47]]]],,,,,,,,,,,[[[[47]]],[[[39]]],[[[55]]]],,,,,,,,,,,,,[[[[10]]]],,,,,,,,[[[[11]]]],,,[[[[30]]]],,,,,,,[[[[32]]]],,[[[[30]]]],,,,,[[[[32]]]],,[[[[30]]]],,,,,[[[[14]]]],,,,,,,[[[[32]]]],,,,,,,,,,,,,[[[[14]]]],,,,,,,,,,,,[[[[14]]]],,,,,,,,,,,,,[[[[40]]],[[[35]]],[[[45]]],[[[51]]],[[[39]]]],,,,,,,,[[[[52]]],[[[50]]],[[[53]]],[[[39]]]],,,,,,,,[[[[47]]],[[[53]]],[[[45]]],[[[45]]]],,,,,,,,,,,,,,,,,,,[[[[16]]]],,,,,,,[[[[16]]]],,,,,,,,,,,,,,,[[[[18]]]],,[[[[19]]]],,,[[[[27,39]]]],,,,,,,,[[[[13]]]],,,,,,[[[[15]]]],,,,,,,[[[[18]]],[[[56]]]],,,,,,,,[[[[18]]],[[[29]]]],,,,,,,[[[[17]]]],,[[[[17]]]],,,,,,,,,,[[[[17,30,31]]]],,,,,,,,[[[[30]]]],,,[[[[32]]]],,,,,,[[[[31,32]]]],,,,,,,,[[[[12,17,30,31]]]],,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,[[[[18]]]],,,,,,,,,,,,,,,,[[[[53,56]]]],,[[[[56]]]],,,,,,,,,,,,,,,,,,[[[[59]]]],,,,,,,,,,,[[[[14]]]],,,,,,[[[[61]]]],,,,,,,[[[[14]]]],,,,,,,,,,,[[[[20]]]],,,,,,,[[[[41]]],[[[39]]],[[[52]]]],,,,,,,,,,,[[[[10]]]],,,,[[[[11]]]],,,,[[[[59]]]],,,,,,,,[[[[61]]]],,,,,[[[[51]]],[[[39]]],[[[52]]]],,,,,,,,,,,[[[[10]]]],,,,,,,,[[[[11]]]],,,,[[[[59]]]],,,,,,,,[[[[61]]]],,[[[[52]]],[[[42]]],[[[43]]],[[[51]]]],,,,,,,,,,,,,[[[[15]]],[[[15]]]],,,,,,,[[[[13]]],[[[13]]]],,,,,,,,,,,,[[[[52]]],[[[57]]],[[[49]]],[[[39]]],[[[48]]],[[[40]]]],,,,,,,,,[[[[15]]]],,,,,[[[[13]]]],,,,,,,,,,[[[[54]]],[[[48]]],[[[43]]],[[[38]]]],,,,,,,,[[[[22]]],[[[22]]]],,,[[[[24]]],[[[24]]],[[[24]]]],,,,[[[[24]]],[[[24]]]],,,,,,,[[[[10]]]],,,,,,,,[[[[11]]]],,,,,,,,,,,,,,,,[[[[39]]],[[[45]]],[[[51]]],[[[39]]]],,,,,,,[[[[43]]],[[[40]]]],,,,,,,,,,,,,,,,,,,,,,[[[[10]]]],,,,,,,,[[[[11]]]],,[[[[38]]],[[[48]]]],,,,,[[[[55]]],[[[42]]],[[[43]]],[[[45]]],[[[39]]]],,,,,,,,,,,,[[[[10]]]],,,,,,,,,,,,[[[[11]]]],,,,,,,,,,,,,,,,,,,,,,,[[[[54]]],[[[35]]],[[[50]]]],,,,,,,,,,,,[[[[23]]]],,[[[[23]]]],,,,,,,,,,,,,,,,,,,,,,,,[[[[25]]]],,,,,,,,[[[[20]]]],,,,,,,,,,,,[[[[60]]],[[[60]]]],,,,,,,,,,,,,[[[[8]]],[[[8]]]],,,,,,,,,,,,,[[[[60]]]],,[[[[23]]]],,,,,,,,,,,[[[[33]]]],,[[[[23]]]],,,,,,,,,,,[[[[8]]]],,[[[[23]]]],,,,,,,,,,,,,,,,,,,,,,,,,,,,[[[[22]]],[[[23]]]],,,[[[[24]]],[[[23]]]],,,[[[[22]]]],[[[[24]]]],,[[[[40]]],[[[48]]],[[[50]]]],,,,,,,,,,[[[[10]]]],,,,,,,,,,,,[[[[21]]]],,,,,,,,,,[[[[21]]]],,,,,,,,,,[[[[11]]]],,,,,,,,,,,,[[[[14]]]],,,,,,,,,,,,,,,,,,[[[[14]]]],,,,,,,,,[[[[10]]]],,,,,,,,[[[[11]]]],,,,,,,,,[[[[20]]]],,,,,,,,,,,,,,[[[[50]]],[[[39]]],[[[52]]],[[[53]]],[[[50]]],[[[47]]]],,,,,,,,,,,,,[[[[10]]]],,,,,,,,[[[[11]]]],,,,[[[[59]]]],,,,,,,,,,,,[[[[61]]]],,,,,,,,,,,,[[[[20]]]],,,,,,,[[[[37]]],[[[35]]],[[[51]]],[[[39]]]],,,,,,,,,,,,,,[[[[20]]]],,,,,,,[[[[38]]],[[[39]]],[[[40]]],[[[35]]],[[[53]]],[[[45]]],[[[52]]]],,,,,,,,,,[[[[51]]],[[[55]]],[[[43]]],[[[52]]],[[[37]]],[[[42]]]],,,,,,,,,,,,,,,,,,[[[[52]]],[[[42]]],[[[50]]],[[[48]]],[[[55]]]],,,,,,,,,,,,,,,,,,,,,,,,,,,,,,[[[[10]]]],,,,,,,,[[[[11]]]],,,,,[[[[37]]],[[[35]]],[[[52]]],[[[37]]],[[[42]]]],,,,,,,,,,,,,[[[[40]]],[[[43]]],[[[47]]],[[[35]]],[[[45]]],[[[45]]],[[[57]]]],,,,,,,,,,[[[[52]]],[[[50]]],[[[57]]]],,,,,,,,,,,,,,,,[[[[14]]]],,,,,,,,,,,,[[[[23]]]],,[[[[23]]]],,,,,,,,,,[[[[10]]]],,,,,,,,[[[[11]]]],,,,,[[[[55]]],[[[43]]],[[[52]]],[[[42]]]],,,,,,,,,[[[[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65]]]]])
function revive(x){var i,l,state,j,l2,all=[],t,ts;if(!x)return;for(i=0,l=x.length;i<l;i++){state=x[i];ts=[];for(j=0,l2=state.length;j<l2;j++){t=state[j];if(t[1]==l) ts.push([t[0],true]);else ts.push([t[0],t[1]==undefined?i+1:t[1]])}all.push(ts)}return dfa(all)
function dfa(ss){var i,l_ss,st,l_s,t,l_t,a,d=[],j,k,l;for(i=0,l_ss=ss.length;i<l_ss;i++){st=ss[i];a=[];for(j=0,l_s=st.length;j<l_s;j++){t=st[j];for(k=0,l_t=t[0].length;k<l_t;k++){a[t[0][k]]=t[1]===true?l_ss:t[1]}}for(j=0,l=a.length;j<l;j++)if(a[j]==undefined)a[j]=l_ss+1;d[i]=a}
return function _dfa(st,i){var eq,pr;while(st<l_ss){eq=equiv[s.charCodeAt(i++)];st=d[pr=st][eq]}if(eq==undefined&&i>=s.length){ds=pr;dp=i-1;return}ds=0;dp=undefined;if(st==l_ss){pos=i;return true}return false}}}
if(typeof out=='string'){s=out;out=[];x=JSParser(function(m,x,y){if(m=='fail')out=[false,x,y,s];if(m=='tree segment')out=out.concat(x)});x('chunk',s);x('eof');return out[0]===false?out:[true,{names:exports.names,tree:out,input:s}]}
return function(m,x){if(failed){out('fail',pos,'parse already failed');return}
switch(m){
case 'chunk':s+=x;l=s.length;while(tbl.length<l+1)tbl.push([]);mainloop();break
case 'eof':eof=true;mainloop();break
default:throw new Error('unhandled message: '+m)}}
//mainloop
function mainloop(){for(;;){
if(dp==undefined&&(S>2432||S<2394))
t_block:{
if(S&4/*pushpos*/)posns.push(pos)
if(S&2/*t_bufferout*/){bufs.push(buf);buf=[]}
if(S&8/*t_emitstate*/){emps.push(emp);emp=pos;buf.push(S>>>12)}
if(S&1/*cache*/&&(x=tbl[pos-offset][S])!=undefined){if(x){R=true;pos=x[0];buf=x[1];if(emp<x[2])emp=x[2]}else{R=false}}
}
if(R==undefined){
if(D[S>>>12]){R=D[S>>>12](ds||0,dp||pos);if(R==undefined){if(eof){ds=dp=undefined;R=false}else{out('ready');return}}}
else{states.push(S);S=T[S>>>12]}
if(S==2394){R=true;S=states.pop()}}
while(R!=undefined){
if(S==774144){(R?emit:fail)();return}if(R){
if(S&1/*cache*/){tbl[posns[posns.length-1]][S]=[pos,buf,emp];buf=buf.slice()}
if(S&8/*t_emitstate*/){if(pos!=emp&&emp!=posns[posns.length-1]){buf.push(-1,pos-emp)}emp=emps.pop();if(emp!=posns[posns.length-1]){buf=[-1,posns[posns.length-1]-emp].concat(buf)}}
if(S&16/*m_emitstate*/)buf.push(S>>>12)
if(S&32/*m_emitclose*/)buf.push(-2)
if(S&128/*m_emitlength*/)buf.push(pos-posns[posns.length-1])
if(S&8/*t_emitstate*/){emp=pos}
if(S&256/*m_resetpos*/)pos=posns[posns.length-1]
if(S&4/*pushpos*/)posns.pop()
if(S&512/*m_tossbuf*/)buf=bufs.pop()
if(S&1024/*m_emitbuf*/){buf=bufs.pop().concat(buf);}
if(!bufs.length&&buf.length>64)emit()
S=M[S>>>12]}
else{
if(S&1/*cache*/)tbl[posns[posns.length-1]][S]=false
if(S&4/*pushpos*/)pos=posns.pop()
if(S&2048/*f_tossbuf*/)buf=bufs.pop()
if(S&8/*t_emitstate*/){emp=emps.pop()}
if(emp>pos){emp=pos}
S=F[S>>>12]}
if(S==2392){R=true;S=states.pop()}else if(S==2393){R=false;S=states.pop()}else R=undefined;}}}
function emit(){var x=bufs.length?bufs[0]:buf;if(x.length){out('tree segment',x);if(bufs.length)bufs[0]=[];else buf=[]}}
function fail(s){out('fail',pos,s);failed=1}}
})(typeof exports=='object'?exports:JSParser={});
</script>
<script type="text/javascript">
/* Utility functions on PanPG parse trees.
* PanPG version 0.0.10
* built on Thu, 18 Aug 2011 18:51:30 GMT
* http://boshi.inimino.org/3box/PanPG/about.html
* MIT Licensed
*/
;(function(exports){
// (event array (can be partial), [name array], [input string], [state]) → [ascii-art tree, state]
// -or-
// (complete event array, [name array], [input string]) → ascii-art
// if the event array doesn't describe a complete, finished tree, or if the state value argument is provided, then the ascii-art and the state value will be returned as an array
// this is for examining partial tree fragments as they are generated by a streaming parser
function showTree(res,opts,state){var names,str,a,i,l,indent,name,x,y,out=[],output_positions=[],node,out_pos,state_was_passed
if(!res[0])return showError(res)
res=res[1]
names=res.names
a=res.tree
str=res.input
opts=opts||{}
opts.elide=opts.elide||['anonymous']
opts.drop=opts.drop||[]
state_was_passed=!!state
state=state||{stack:[],indent:'',pos:0,drop_depth:0}
for(i=0,l=a.length;i<l;i++){x=a[i]
if(x>0){
if(names){
name=names[x]
if(!name) return err('no such rule index in name array: '+x)}
else name=''+x
output_positions[state.stack.length]=out.length
node={index:x,name:name,start:state.pos}
if(opts.drop.indexOf(name)>-1)state.drop_depth++
out.push(show(state,node))
state.indent+=' '
state.stack.push(node)}
else if(x==-1){
i++
if(i==l){i--;return}
node={name:'anonymous',start:state.pos,end:state.pos+a[i]}
state.pos=node.end
out.push(show(state,node))
}
else if(x==-2){
i++
if(i==l)return err('incomplete close event, expected length at position '+i+' but found end of input array')
y=state.stack.pop()
state.pos=y.end=y.start+a[i]
out_pos=output_positions[state.stack.length]
state.indent=state.indent.slice(0,-1)
if(out_pos!=undefined){
out[out_pos]=show(state,y)}
if(opts.drop.indexOf(y.name)>-1)state.drop_depth--}
else return err('invalid event '+x+' at position '+i)}
if(state_was_passed || state.stack.length) return [out.join(''),state]
else return out.join('')
function err(s){return ['showTree: '+s]}
function show(state,node){var text='',main,indent,l
if(opts.elide.indexOf(node.name)>-1)return ''
if(state.drop_depth)return ''
if(node.end!=undefined && str){
text=show_str(str.slice(node.start,node.end))}
main=state.indent+node.name+' '+node.start+'-'+(node.end==undefined?'?':node.end)
l=main.length
indent=Array(32*Math.ceil((l+2)/32)-l).join(' ')
return main+indent+text+'\n'}
function show_str(s){
return '»'+s.replace(/\n/g,'\\n').replace(/\r/g,'\\r').replace(/(.{16}).{8,}/,"$1…")+'«'}}
// inspired by: http://gist.github.com/312863
function showError(res){var line_number,col,lines,line,start,end,prefix,suffix,arrow,pos,msg,str
pos=res[1];msg=res[2];str=res[3]
msg=msg||'Parse error'
if(str==undefined)return msg+' at position '+pos
prefix=str.slice(0,pos)
suffix=str.slice(pos)
line_number=prefix.split('\n').length
start=prefix.lastIndexOf('\n')+1
end=suffix.indexOf('\n')
if(end==-1) end=str.length
else end=prefix.length+end
line=str.slice(start,end)
line=line.replace(/\t/g,' ')
col=pos-start
arrow=Array(col).join('-')+'^'
return msg+' at line '+line_number+' column '+col+'\n'+line+'\n'+arrow}
function showResult(r,opts){
if(r[0])return showTree(r,opts)
return showError(r)}
function treeWalker(dict,result){var p,any,anon,other,fail,except,index,cb=[],stack=[],frame,pos=0,i,l,x,retval,names,events,begin=[],match,target,msg
fail=dict.fail
except=dict.exception
if(!result[0]){
msg='parse failed: '+result[1]+' '+(result[2]||'')
if(fail)return fail(result)||msg
return err(msg)}
result=result[1]
names=result.names
events=result.tree
for(p in dict) if(dict.hasOwnProperty(p)){
if(p=='any'){any=dict[p];throw new Error('unimplemented, use `other` instead')}
if(p=='anonymous'||p=='anon'){anon=dict[p];continue}
if(p=='other'){other=dict[p];continue}
if(p=='fail'){fail=dict[p];continue}
if(p=='exception'){except=dict[p];continue}
if(p=='warn'){continue}
target=cb
if(match=/(.*) start/.exec(p)){p=m[1];target=begin}
index=names.indexOf(p)
if(index==-1)return err('rule not found in rule names: '+p)
target[index]=dict[p]}
frame={cn:[]}
for(i=0,l=events.length;i<l;i++){x=events[i]
if(x>0){ // named rule start
stack.push(frame)
frame={index:x,start:pos}
if(begin[x]){
try{retval=begin[x](pos)}
// here we call err() but continue iff `except` returns true
catch(e){if(!err('exception in '+names[x]+' start:'+e))return}}
if(cb[x]||any||other) frame.cn=[]}
else if(x==-1){ // anonymous node
i++
if(i==l)return err('incomplete anonymous node')
if(anon)anon(m(pos,pos+events[i]))
pos+=events[i]}
else if(x==-2){ // node close
i++
if(i==l)return err('incomplete rule close')
pos=frame.start+events[i]
x=frame.index
match=m(frame.start,pos)
try{
if(cb[x]) retval=cb[x](match,frame.cn)
else if(other)retval=cb[x](match,frame.cn,names[x])}
catch(e){return err('exception in '+names[x]+': '+e+' (on node at char '+match.start+'-'+match.end+')')}
frame=stack.pop() // the parent node
if(cb[x] && retval!==undefined)
if(frame.cn)frame.cn.push(retval)
else warn('ignored return value of '+names[x]+' in '+names[frame.index])}
else return err('invalid event stream (saw '+x+' at position '+i+')')}
if(frame.cn)return frame.cn[0]
function m(s,e){
return {start:s
,end:e
,text:function(){return result.input.slice(s,e)}}}
function err(s){
if(except)return except(s)
throw new Error('treeWalker: '+s)}
function warn(s){
if(dict.warn)dict.warn(s)}}
exports.showTree=showTree
exports.treeWalker=treeWalker
})(typeof exports=='object'?exports:PanPG_util={});
// AST PARSER
// produce an AST based on https://developer.mozilla.org/en/SpiderMonkey/Parser_API
// differences:
// - no 'loc' property on nodes (may add separate start, end integers later)
// - Function body is always BlockStatement, never Expression (which is moz-specific)
// - no generators (also moz-specific)
// - no multiple catch clauses (also moz-specific)
// - no 'meta' property on FunctionDeclaration or FunctionExpression
// - no "for each ... in" support (moz-specific)
// - formal parameters must be identifiers, not destructuring patterns (which again is moz-specific)
// - wherever Pattern would appear, Identifier is used instead
// - VariableStatement is used instead of VariableDeclaration (since VariableStatement is the name of the production used in the spec) -- XXX this is a bad name also because now we have a VariableStatement inside a ForInStatement as "for(var p in o)" ... though maybe that is semantically not so inaccurate after all...
// - There is no VariableDeclaration nodes in the output (though they are generated as an intermediate form)
// - VariableStatement (nee VariableDeclaration) lacks "kind" (let, var, or const)
// - the name VariableDeclaration is used for something else in the spec, perhaps it should be changed here.
// - added 'VariableDeclarator' type, as Spidermonkey does but does not document, on individual children of VariableStatement.
// - There is no separate object for UnaryOperator or BinaryOperator, with a "token" property carrying the actual payload, instead, the operator appears directly as a string where a UnaryOperator or BinaryOperator object would appear in the spidermonkey AST.
// - I think it is odd that there is a separate UpdateExpression type given that there is already a UnaryExpression (and it has a prefix Boolean property)
// - There is no 'prefix' property on the UnaryExpression, since in every case it is true.
// - no yield expressions
// - no generator expressions
// - no array comprehensions
// - no graph expressions (sharp variables, sharp expressions)
// - no guard on CatchClause; param is Identifier, not Pattern
// - it is odd that all literals map to the Literal type which has no 'kind' or other property to indicate type, necessitates type checking of the value
// - added a 'kind' : 'number' | 'string' | 'Boolean' | 'regexp' property to Literal
// - in CallExpression and MemberExpression, rather than [Expression], the arguments property is a Arguments node type with an elements property which is the list of Expressions (this just makes recursion into the AST easier, it's arguable whether it's actually worth it)
// - logical expressions use a LogicalExpression node type with an expressions property having all (not just two) sub-expressions and an operator property having either '&&' or '||', instead of using BinaryExpression, as was done previously, or using the Mozilla-AST's LogicalExpression which is defined as a separate type from the BinaryExpression node type but still only having left and right properties. This means that the non-observable distinction between "(a && b) && c" and "a && (b && c)" will not be preserved in the AST, which I consider a feature.
// - assignment expressions use the same BinaryExpression node type, with an assignment operator as the operator, rather than a separate AssignmentExpression node type.
// Comments can come anywhere in the grammar, and if a comment appears, it is attached literally as a 'comment' property on the AST node that follows it (actually somewhere "nearby"); on the Program node there can additionally be a commentAfter property
// Many of the places where Identifier is used could just have a string rather than an Identifier node in the AST (e.g. as the label of a LabelledStatement)
// It might be useful to have a 'literal' property on string literals to store the literal as it appeared in the source, which may differ from 'value' which would be the string value after unescaping
// The full [incomplete] list of node types returned in parse trees:
// N.B. there are other node types created below but which do not end up in the final tree, these have names with a leading underscore.
// Program, EmptyStatement, BlockStatement, ExpressionStatement, IfStatement, LabelledStatement, BreakStatement, ContinueStatement, WithStatement, SwitchStatement, ReturnStatement, ThrowStatement, TryStatement, DoWhileStatement, WhileStatement, ForStatement, ForInStatement, DebuggerStatement
var myDecARR = new Array();
var myFPARR = new Array();
var myIdentARR = new Array();
"use strict"
var PanPG_util // assigned to by PanPG_util.js
, JSParser
function js_ast(s){var dict,pending_comment
//return PanPG_util.showTree(JSParser.parse(s),{drop:['WhiteSpace','anonymous','IdentifierStart','IdentifierPart','FunctionTok','LineTerminatorSequence','SourceCharacter']})
function assert(x,m){if(!x)throw new Error('assertion failed: '+m)}
dict =
{ Program: function (m, cn) {
return { type: "Program", elements: cn }
}
, EmptyStatement: function (m, cn) {
return { type: "EmptyStatement" }
}
, Block: function (m, cn) {
return { type: "BlockStatement"
, body: cn
}
}
, Statement: function (m, cn) { return cn[0] }
, ExpressionStatement: function (m, cn) {
return { type: "ExpressionStatement"
, expression: cn[0]
}
}
, IfStatement: function (m, cn) {
assert(isExpression(cn[0]))
assert(isStatement(cn[1]))
assert(!cn[2] || isStatement(cn[2]))
return { type: "IfStatement"
, test: cn[0]
, consequent: cn[1]
, alternate: cn[2] || null
}
}
, LabelledStatement: function (m, cn) {
assert(cn[0].type == 'Identifier')
assert(isStatement(cn[1]))
return { type: "LabelledStatement"
, label: cn[0]
, body: cn[1]
}
}
, BreakStatement: function (m, cn) {
assert(!cn[0] || cn[0].type == "Identifier")
return { type: "BreakStatement"
, label: cn[0] || null
}
}
, ContinueStatement: function (m, cn) {
assert(!cn[0] || cn[0].type == "Identifier")
return { type: "ContinueStatement"
, label: cn[0] || null
}
}
, WithStatement: function (m, cn) {
assert(isExpression(cn[0]))
assert(isStatement(cn[1]))
return { type: "WithStatement"
, object: cn[0]
, body: cn[1]
}
}
, SwitchStatement: function (m, cn) {
assert(isExpression(cn[0]))
return { type: "SwitchStatement"
, test: cn[0]
, cases: cn.slice(1)
}
}
, ReturnStatement: function (m, cn) {
assert(!cn[0] || isExpression(cn[0]))
return { type: "ReturnStatement"
, argument: cn[0] || null
}
}
, ThrowStatement: function (m, cn) {
assert(!cn[0] || isExpression(cn[0]))
return { type: "ThrowStatement"
, argument: cn[0] || null
}
}
, TryStatement: function (m, cn) {
var block, handler, finalizer
assert(cn[0].type == "BlockStatement")
block = cn.shift()
assert(!cn[0] || cn[0].type == 'CatchClause'
|| cn[0].type == '_FinallyClause')
if (cn[0] && cn[0].type == 'CatchClause') handler = cn.shift()
if (cn[0] && cn[0].type == '_FinallyClause') finalizer = cn[0].body
return { type: "TryStatement"
, block: block
, handler: handler || null
, finalizer: finalizer || null
}
}
, Catch: function (m, cn) {
assert(cn[0].type == "Identifier")
assert(cn[1].type == 'BlockStatement')
return { type: "CatchClause"
, param: cn[0]
, body: cn[1]
}
}
, Finally: function (m, cn) {
return { type: "_FinallyClause"
, body: cn[0]
}
}
, IterationStatement: function (m, cn) { return cn[0] }
, WhileStatement: function (m, cn) {
assert(isExpression(cn[0]), "Expression")
assert(isStatement(cn[1]), "Statement")
return { type: "WhileStatement"
, test: cn[0]
, body: cn[1]
}
}
, DoWhileStatement: function (m, cn) {
assert(isStatement(cn[0]))
assert(isExpression(cn[1]))
return { type: "DoWhileStatement"
, body: cn[0]
, test: cn[1]
}
}
, ForStatement: function (m, cn) {
var init, test, update
assert(cn[0])
if (cn[0].type == '_ForInit') init = cn.shift().expression
if (cn[0].type == 'VariableDeclaration') init = cn.shift()
if (cn[0].type == '_ForTest') test = cn.shift().expression
if (cn[0].type == '_ForUpdate') update = cn.shift().expression
assert(isStatement(cn[0]))
return { type: "ForStatement"
, init: init || null
, test: test || null
, update: update || null
, body: cn[0]
}
}
, ForInit: function (m, cn) {
assert(!cn[0] || isExpression(cn[0]), "Expression")
return { type: "_ForInit"
, expression: cn[0] || null
}
}
, ForVarInit: function (m, cn) {
assert(cn[0].type == "VariableDeclaration")
return cn[0]
}
, VariableDeclarationListNoIn: function (m, cn) {
return { type: "VariableDeclaration"
, declarations: cn.map(cleanup_vardecl)
}
}
, ForTest: function (m, cn) {
assert(!cn[0] || isExpression(cn[0]))
return { type: "_ForTest"
, expression: cn[0] || null
}
}
, ForUpdate: function (m, cn) {
assert(!cn[0] || isExpression(cn[0]))
return { type: "_ForUpdate"
, expression: cn[0] || null
}
}
, ForInStatement: function (m, cn) {
var left
if (cn[0].type == '_ForInLeft') left = cn.shift().expression
if (cn[0].type == 'VariableDeclaration') left = cn.shift()
assert(isExpression(cn[0]))
assert(isStatement(cn[1]))
return { type: "ForInStatement"
, left: left
, right: cn[0]
, body: cn[1]
}
}
, ForInLeft: function (m, cn) {
assert(isExpression(cn[0]))
return { type: "_ForInLeft"
, expression: cn[0]
}
}
, ForInVarLeft: function (m, cn) {
assert(cn[0].type == "VariableDeclarator")
return { type: "VariableDeclaration"
, declarations: [cn[0]]
}
}
, DebuggerStatement: function (m, cn) {
return { type: "DebuggerStatement" }
}
, FunctionDeclaration: function (m, cn) {
var id, params, body
assert(cn[0].type == "Identifier", "name")
id = cn.shift()
if (cn.length == 2) { assert(cn[0].type == "_ParameterList"); params = cn.shift() }
assert(cn[0].type == "BlockStatement", "body")
for (var i = 0; i < params.elements.length; i++)
myFPARR.push(params.elements[i]);
return { type: "FunctionDeclaration"
, id: id
, params: params ? params.elements : null
, body: cn[0]
}
}
, VariableDeclaration: function (m, cn) {
assert(cn[0].type == "Identifier", "variable identifier")
assert(!cn[1] || isExpression(cn[1]), "variable value")
myDecARR.push(cn[0])
return { type: "VariableDeclarator"
, id: cn[0]
, init: cn[1] || null
}
}
, VariableStatement: function (m, cn) {
return { type: "VariableStatement"
, declarations: cn
}
}
, ThisTok: function (m, cn) {
return { type: "ThisExpression" }
}
, ArrayLiteral: function (m, cn) {
var elements = []
assert(!cn[0] || cn[0].type == '_ElementList')
if (cn[0]) elements = cn[0].elements
assert(!cn[1] || cn[1].type == '_ElementList')
if (cn[1]) elements = elements.concat(cn[1].elements)
return { type: "ArrayExpression"
, elements: elements
}
}
, ElementList: function (m, cn) {
var elements, x
elements = []
while (x = cn.shift()) {
if (x.type == '_ElementList') elements = elements.concat(x.elements)
else elements.push(x)
}
return { type: "_ElementList"
, elements: elements
}
}
, Elision: function (m, cn) {
var elements
assert(!cn[0] || cn[0].type == '_ElementList')
if (cn[0]) elements = cn[0].elements, elements.unshift(null)
else elements = [null]
return { type: "_ElementList"
, elements: elements
}
}
, ObjectLiteral: function (m, cn) {
assert(!cn[0] || cn[0].type == '_PropertyNameAndValueList')
return { type: "ObjectExpression"
, properties: cn[0] ? cn[0].properties : []
}
}
, PropertyNameAndValueList: function (m, cn) {
return { type: "_PropertyNameAndValueList"
, properties: cn
}
}
, PropertyAssignment: function (m, cn) {
var kind, key, value
if (cn[0].type == "_PropertyName") {
kind = "init"
key = cn[0].id
assert(isExpression(cn[1]))
value = cn[1]
}
if (cn[0].type == "_PropertyGetter") {
kind = 'get'
// XXX how is the function body represented?
key = cn[0].name
value = cn[0].body
}
if (cn[0].type == "_PropertySetter") {
kind = 'set'
key = cn[0].name
value = cn[0].body
}
assert(kind, 'kind'); assert(key, 'key'); assert(value, 'value')
return { key: key // N.B. no type here
, value: value
, kind: kind
}
}
, PropertyName: function (m, cn) {
// PropertyName ← IdentifierName / StringLiteral / NumericLiteral
return { type: "_PropertyName"
, id: cn[0]
}
}
, PropertyGetter: function (m, cn) {
assert(cn[0] && cn[0].type == "_PropertyName")
assert(isExpression(cn[0].id))
assert(cn[1].type == "BlockStatement")
return { type: "_PropertyGetter"
, name: cn[0].id
, body: cn[1]
}
}
, PropertySetter: function (m, cn) {
assert(cn[0] && cn[0].type == "_PropertyName")
assert(isExpression(cn[0].id))
assert(cn[1].type == "Identifier")
assert(cn[2].type == "BlockStatement")
return { type: "_PropertySetter"
, name: cn[0].id
, body: { type: "FunctionExpression"
, id: null
, params: [cn[1]]
, body: cn[2]
}
}
}
, PropertySetParameterList: function (m, cn) { return cn[0] }
, IdentifierName: function (m, cn) {
// note this is used only by PropertyName; Identifier doesn't use this
return { type: "Identifier"
, name: m.text()
}
}
, FunctionExpression: function (m, cn) {
var id, params = []
if (cn[0].type == "Identifier") id = cn.shift()
if (cn[0].type == "_ParameterList") params = cn.shift().elements
assert(cn[0].type == "BlockStatement")
return { type: "FunctionExpression"
, id: id || null
, params: params
, body: cn[0]
}
}
, FormalParameterList: function (m, cn) {
return { type: "_ParameterList"
, elements: cn
}
}
, FunctionBody: function (m, cn) {
return { type: "BlockStatement"
, body: cn
}
}
, Expression: function (m, cn) {
if (cn.length == 1) return cn[0]
return { type: "SequenceExpression"
, expressions: cn
}
}
, UnaryExpression: function (m, cn) {
return cn[0]
}
, DeleteExpression: function (m, cn) {
return { type: "UnaryExpression"
, operator: "delete"
, argument: cn[0]
}
}
, VoidExpression: function (m, cn) {
return { type: "UnaryExpression"
, operator: "void"
, argument: cn[0]
}
}
, TypeofExpression: function (m, cn) {
return { type: "UnaryExpression"
, operator: "typeof"
, argument: cn[0]
}
}
, PreIncrementExpression: function (m, cn) {
return { type: "UpdateExpression"
, operator: "++"
, prefix: true
, argument: cn[0]
}
}
, PreDecrementExpression: function (m, cn) {
return { type: "UpdateExpression"
, operator: "--"
, prefix: true
, argument: cn[0]
}
}
, UnaryPlusExpression: function (m, cn) {
return { type: "UnaryExpression"
, operator: "+"
, argument: cn[0]
}
}
, UnaryMinusExpression: function (m, cn) {
return { type: "UnaryExpression"
, operator: "-"
, argument: cn[0]
}
}
, BitwiseNotExpression: function (m, cn) {
return { type: "UnaryExpression"
, operator: "~"
, argument: cn[0]
}
}
, LogicalNotExpression: function (m, cn) {
return { type: "UnaryExpression"
, operator: "!"
, argument: cn[0]
}
}
, PostfixExpression: function (m, cn) {
assert(!cn[1] || cn[1].type == "_PostfixOp")
if (!cn[1]) return cn[0]
return { type: "UpdateExpression"
, operator: cn[1].operator
, argument: cn[0]
, prefix: false
}
}
, PostIncrementOp: function (m, cn) {
return { type: "_PostfixOp"
, operator: "++"
}
}
, PostDecrementOp: function (m, cn) {
return { type: "_PostfixOp"
, operator: "--"
}
}
, AssignmentExpression: function (m, cn) {
assert(cn.length == 1 || cn.length == 3)
if (!cn[1]) return cn[0]
assert(cn[1].type == '_AssignmentOperator')
return { type: "AssignmentExpression"
, operator: cn[1].operator
, left: cn[0]
, right: cn[2]
}
}
, AssignmentOperator: function (m, cn) {
return { type: "_AssignmentOperator"
, operator: m.text()
}
}
, ConditionalExpression: function (m, cn) {
assert(cn.length == 1 || cn.length == 3)
if (!cn[1]) return cn[0]
return { type: "ConditionalExpression"
, test: cn[0]
, consequent: cn[1]
, alternate: cn[2]
}
}
, LogicalOrExpression: function self(m, cn) {//var right
if (!cn[1]) return cn[0]
//if(cn.length>2) right=self(null,cn.slice(1))
//else right=cn[1]
return { type: "LogicalExpression"
, operator: "||"
, expressions: cn
}
}
, LogicalAndExpression: function (m, cn) {
if (!cn[1]) return cn[0]
return { type: "LogicalExpression"
, operator: "&&"
, expressions: cn
}
}
, BitwiseOrExpression: function self(m, cn) {
var left
if (!cn[1]) return cn[0]
if (cn.length > 2) left = self(null, cn.slice(0, -1))
else left = cn[0]
return { type: "BinaryExpression"
, operator: "|"
, left: left
, right: cn[cn.length - 1]
}
}
, BitwiseXOrExpression: function self(m, cn) {
var left
if (!cn[1]) return cn[0]
if (cn.length > 2) left = self(null, cn.slice(0, -1))
else left = cn[0]
return { type: "BinaryExpression"
, operator: "^"
, left: left
, right: cn[cn.length - 1]
}
}
, BitwiseAndExpression: function self(m, cn) {
var left
if (!cn[1]) return cn[0]
if (cn.length > 2) left = self(null, cn.slice(0, -1))
else left = cn[0]
return { type: "BinaryExpression"
, operator: "&"
, left: left
, right: cn[cn.length - 1]
}
}
, EqualityExpression: function self(m, cn) {
var left
assert(cn.length % 2, 'odd number of child nodes in equality expr')
if (!cn[1]) return cn[0]
assert(cn[1].type == '_EqualityOperator')
if (cn.length > 3) left = self(null, cn.slice(0, -2))
else left = cn[0]
return { type: "BinaryExpression"
, operator: cn[cn.length - 2].operator
, left: left
, right: cn[cn.length - 1]
}
}
, EqualityOp: function (m, cn) {
return { type: "_EqualityOperator"
, operator: m.text()
}
}
, RelationalExpression: function self(m, cn) {
var left
assert(cn.length % 2, 'odd number of children')
if (!cn[1]) return cn[0]
if (cn.length > 3) left = self(null, cn.slice(0, -2))
else left = cn[0]
assert(cn[cn.length - 2].type == '_RelationalOperator')
return { type: "BinaryExpression"
, operator: cn[cn.length - 2].operator
, left: left
, right: cn[cn.length - 1]
}
}
, RelationalOp: function (m, cn) {
return { type: "_RelationalOperator"
, operator: m.text()
}
}
, ShiftExpression: function self(m, cn) {
var left
assert(cn.length % 2, 'odd number of children')
if (!cn[1]) return cn[0]
if (cn.length > 3) left = self(null, cn.slice(0, -2))
else left = cn[0]
assert(cn[cn.length - 2].type == '_ShiftOperator')
return { type: "BinaryExpression"
, operator: cn[cn.length - 2].operator
, left: left
, right: cn[cn.length - 1]
}
}
, ShiftOp: function (m, cn) {
return { type: "_ShiftOperator"
, operator: m.text()
}
}
, AdditiveExpression: function loop(m, cn) {
var left, right, op
assert(cn.length % 2 == 1, "odd number of children")
if (cn.length == 1) return cn[0]
if (cn.length > 3) {
left = loop(null, cn.slice(0, -2))
}
else left = cn[0]
right = cn[cn.length - 1]
op = cn[cn.length - 2]
assert(cn[1].type == '_AdditiveOperator')
return { type: "BinaryExpression"
, operator: op.operator
, left: left
, right: right
}
}
, AdditiveOp: function (m, cn) {
return { type: "_AdditiveOperator"
, operator: m.text()
}
}
, MultiplicativeExpression: function loop(m, cn) {
var left, right, op
assert(cn.length % 2 == 1, "odd number of children")
if (cn.length == 1) return cn[0]
if (cn.length > 3) {
left = loop(null, cn.slice(0, -2))
}
else left = cn[0]
right = cn[cn.length - 1]
op = cn[cn.length - 2]
assert(cn[1].type == '_MultiplicativeOperator')
return { type: "BinaryExpression"
, operator: op.operator
, left: left
, right: right
}
}
, MultiplicativeOp: function (m, cn) {
return { type: "_MultiplicativeOperator"
, operator: m.text()
}
}
// LeftHandSideExpr ← (NewTok S?)* ( PrimaryExpr / FunctionExpr ) ( S? Arguments / S? BracketAccessor / S? DotAccessor )*
// see grammars/ECMAScript_5_streamable.peg
, LeftHandSideExpression: function (m, cn) {
var news, core, tail, property, args
news = []
while (cn[0].type == 'NewTok') news.push(cn.shift())
assert(isExpression(cn[0]), 'LHSExpr: found core expression (saw ' + pp(cn[0]) + ')')
core = cn.shift()
tail = cn
// now we have the innermost expression, the prefix string of zero or more 'new', and the suffix string of arguments and accessors, in core, news, and tail respectively.
// We start with the core and eat outwards through the prefixes and suffixes until the entire expression is built up according the correct precedence rules.
while (cn.length || news.length) {
// First, if there is an accessor, it is appended to create a MemberExpression
if (cn[0] && (cn[0].type == '_DotAccessor' || cn[0].type == '_BracketAccessor')) {
property = cn.shift()
core = { type: "MemberExpression"
, object: core
, property: property.property
, computed: property.type == '_BracketAccessor'
}
// if there was an accessor then there might be another one so we need to loop
continue
}
// Now, if there is any of the tail left, the first element is an Arguments node (parenthesized expression list)
// If there is an unconsumed prefixed `new` token, then this is a NewExpression, with arguments if cn[0].
assert(!cn[0] || cn[0].type == 'Arguments')
if (news.length) {
news.pop()
args = cn.shift()
core = { type: "NewExpression"
, constructor: core
, arguments: args ? args : null
}
// eating Arguments may have exposed a new accessor, so we need to go back to the top of the loop
continue
}
// Here news.length==0, and if there is a cn[0], it is an Arguments.
assert(!news.length)
assert(!cn[0] || cn[0].type == 'Arguments')
// If there is Arguments without "new", that makes a CallExpression, otherwise we are done
if (cn[0]) {
core = { type: "CallExpression"
, callee: core
, arguments: cn.shift()
}
}
}
assert(!news.length && !cn.length)
return core
}
, NewTok: function (m, cn) { return { type: "NewTok"} }
, PrimaryExpression: function (m, cn) { return cn[0] }
, DotAccessor: function (m, cn) {
return { type: "_DotAccessor"
, property: { type: "Identifier"
, name: m.text().slice(1)
}
}
}
, BracketAccessor: function (m, cn) {
return { type: "_BracketAccessor"
, property: cn[0]
}
}
, Arguments: function (m, cn) {
assert(!cn[0] || cn[0].type == '_ArgumentList')
return { type: "Arguments"
, elements: cn[0] ? cn[0].elements : null
}
}
, ArgumentList: function (m, cn) {
return { type: "_ArgumentList"
, elements: cn
}
}
, CaseClause: function (m, cn) {
assert(isExpression(cn[0]))
return { type: "SwitchCase"
, test: cn.shift()
, consequent: cn
}
}
, DefaultClause: function (m, cn) {
return { type: "SwitchCase"
, test: null
, consequent: cn
}
}
, Identifier: function (m, cn) {
myIdentARR.push(m.text());
return { type: "Identifier"
, name: m.text()
}
}
, Literal: function (m, cn) { return cn[0] }
, NullLiteral: function (m, cn) {
return { type: "Literal"
, kind: "null"
, value: null
}
}
, BooleanLiteral: function (m, cn) { return cn[0] }
, TrueTok: function (m, cn) {
return { type: "Literal"
, kind: "Boolean"
, value: true
}
}
, FalseTok: function (m, cn) {
return { type: "Literal"
, kind: "Boolean"
, value: false
}
}
, NumericLiteral: function (m, cn) {
return { type: "Literal"
, kind: "number"
, value: eval(m.text())
}
} // XXX cheating
, StringLiteral: function (m, cn) {
return { type: "Literal"
, kind: "string"
, value: eval(m.text())
}
} // XXX cheating again
, RegularExpressionLiteral: function (m, cn) {
return { type: "Literal"
, kind: "regexp"
, source: cn[0]
, flags: cn[1]
, value: new RegExp(cn[0], cn[1])
}
}
, RegularExpressionBody: function (m, cn) {
return m.text()
}
, RegularExpressionFlags: function (m, cn) {
return m.text()
}
// everything else we deal with functionally, passing return values up the tree, but for comments we use some mutable local state.
, SingleLineComment: function (m, cn) {
var x
x = pending_comment
pending_comment = { type: "Comment"
, multiline: false
, text: m.text()
}
if (x) pending_comment.comment = x
}
, MultiLineComment: function (m, cn) {
var x
x = pending_comment
pending_comment = { type: "Comment"
, multiline: true
, text: m.text()
, comment: pending_comment
}
if (x) pending_comment.comment = x
}
/*
,
/**/
}
;
['VariableDeclarationList'
,'VariableDeclaration'
,'Expression'
,'AssignmentExpression'
,'ConditionalExpression'
,'LogicalOrExpression'
,'LogicalAndExpression'
,'BitwiseOrExpression'
,'BitwiseXOrExpression'
,'BitwiseAndExpression'
,'EqualityExpression'
,'RelationalExpression'
,'RelationalOp'
].forEach(function(x){
if(x in dict) dict[x+'NoIn']=dict[x]})
for(var rule in dict) dict[rule] = handle_comment(dict[rule])
for(var rule in dict) dict[rule] = handle_location(dict[rule])
// adds comment handling to one of the plain callbacks as they appear above
// this is actually pretty broken, some comments will be dropped (based on what it ends up attached to)
function handle_comment(f){
return function(m,cn){var retval
retval=f(m,cn)
//if(pending_comment && retval){retval.comment=pending_comment;pending_comment=undefined}
return retval}}
function handle_location(f){
return function(m,cn){var retval
retval=f(m,cn)
if(typeof retval!='object')return retval
retval.loc=
{start:m.start
,end:m.end}
return retval}}
function isExpression(x){
return x&&x.type
&& ( x.type.slice(-10)=="Expression"
|| x.type.slice(-14)=="ExpressionNoIn"
|| x.type=="Literal"
|| x.type=="Identifier" )}
function isStatement(x){return x&&x.type&&x.type.slice(-9)=="Statement"}
function cleanup_vardecl(decl){return {type:'VariableDeclarator',id:decl.id,init:decl.init}}
var warnings=[]
dict.warn=function(x){warnings.push(x)}
var parse_result=JSParser.parse(s)
if(!parse_result[0]) return {type:"ParseError"
,error:PanPG_util.showTree(parse_result)}
var result = PanPG_util.treeWalker(dict,parse_result)
//if(pending_comment) result.commentAfter=pending_comment // XXX won't ever happen (Program node will always be visited after any Comment it contains)
if(warnings.length)return warnings.join('\n')
return result}
// Equality on AST nodes
// js_ast_eq :: (AST,AST) → Boolean
function js_ast_eq(a,b){var i,l,p
if(a==null && b==null)return true
if(typeof a != typeof b)return false
if(a==b)return true
if(typeof a == 'number' && isNaN(a) && isNaN(b))return true
if(a instanceof RegExp){
if(!(b instanceof RegExp))return false
return a.toString() == b.toString()} // regex equivalence (hopefully)
if(typeof a != 'object')return false
if(a instanceof Array){
if(!(b instanceof Array))return false
if(a.length!=b.length)return false
for(i=0,l=a.length;i<l;i++)if(!js_ast_eq(a[i],b[i]))return false
return true}
for(p in a)if(!js_ast_eq(a[p],b[p]))return false
for(p in b)if(!p in a)return false
return true}
// AST diff
// js_ast_diff(a,b) returns null when a and b do not differ.
// Otherwise it returns an AST diff object which is sufficient to recreate either of `a` or `b` given the other.
// A diff object is either a simple diff or a path.
// A diff between two primitives, or between a primitive and an object, is a simple diff.
// A simple diff is represented as an array with `a` and `b` as the array elements.
// A diff between two objects which differ in some properties but not others can be a path.
// A path is an object containing properties corresponding to each property which differs between `a` and `b`.
// If a property name P exists in both `a` and `b` but differs in value, then the diff contains a property with that name containing the diff between a[P] and b[P].
// If a property name P exists in one of `a` or `b` but not the other, the property in the diff will be an array with the value that exists and the special value js_ast_diff.NONE in the other position.
js_ast_diff.NONE={}
function js_ast_diff(a,b){var p,diff,subdiff,differs
if(a==null && b==null)return null
if(a===b)return null
if(typeof a != typeof b)return[a,b]
if(a==null || b==null)return[a,b] //
if(a==js_ast_diff.NONE || b==js_ast_diff.NONE)return[a,b]
if(typeof a == 'number' && isNaN(a) && isNaN(b))return null
if(typeof a == 'string')return[a,b]
if(a instanceof RegExp){
if(a.toString() != b.toString())return[a,b]
return null}
diff={}
differs=false
for(p in a) if(subdiff=js_ast_diff(lookup(a,p),lookup(b,p))){
differs=true
diff[p]=subdiff}
for(p in b) if(!(p in a)){
differs=true
diff[p]=[a[p],js_ast_diff.NONE]}
return differs?diff:null
function lookup(o,p){
if(Object.prototype.hasOwnProperty.call(o,p))return o[p]
return js_ast_diff.NONE}}
// To apply a diff D to an input object In:
// If D is a simple diff, return the second element of D.
// (If a diff is being applied in reverse, then return the first element instead.)
// Otherwise D is a path, and In must be an object, otherwise it is an error.
// Let Out be a new empty object.
// For each property of In with a corresponding property in D, apply the diff in D to the value in In and set the corresponding property of Out to the result.
// All other properties are copied directly.
</script>
<style type="text/css">
body
{
background:#B7D4E2;
font-family:Arial;
margin:0;
padding:0;
}
h1
{
background:#475272;
color:#FFF;
padding:5px;
}
#input
{
width:80%;
height:300px;
background:#D0EDFD;
margin:0 auto 0 auto;
display:block;
border:solid 2px #475272;
}
</style>
</head>
<body>
<h1>Javascript Code</h1>
<textarea id="input"></textarea>
<h1>Declared Variables (<span id="varCount"></span>)</h1>
<span id="varOut"></span>
<h1>Function Parameters (<span id="paramCount"></span>)</h1>
<span id="funParams"></span>
<h1>Variable Reference Identifiers (<span id="identCount"></span>)</h1>
<span id="identOut"></span>
<h1>Abstract Syntax Tree</h1>
<pre><code id="ast"></code></pre>
<script>
var input_el = byId('input')
, output_el = byId('ast')
, examples_el = byId('examples')
, examples
, previous_input
, permalink = byId('permalink')
handleTextChange(input_el, handle_typing, 250);
function handle_typing() {
if (input_el.value == previous_input) return
location.hash = ''
update_output()
}
function genList(listARR, nameField) {
/* var output = '<ul>';
for (var i = 0; i < listARR.length; i++)
output += '<li>' + ((nameField) ? listARR[i].name : listARR[i]) + '</li>';
return output + '</ul>';
*/
var output = '';
for (var i = 0; i < listARR.length; i++)
output += ((nameField) ? listARR[i].name : listARR[i]) + ', ';
return output;
}
function update_output() {
myDecARR = new Array();
myFPARR = new Array();
myIdentARR = new Array();
var s, d1, d2, ast
s = input_el.value
if (previous_input == s) return
d1 = new Date
ast = js_ast(s)
d2 = new Date
output_el.textContent = 'generated in ' + (d2 - d1) + 'ms\n\n' + pp(ast)
previous_input = s
document.getElementById("varOut").innerHTML = genList(myDecARR, true);
document.getElementById("varCount").innerHTML = myDecARR.length;
document.getElementById("funParams").innerHTML = genList(myFPARR, true);
document.getElementById("paramCount").innerHTML = myFPARR.length;
document.getElementById("identOut").innerHTML = genList(myIdentARR, false);
document.getElementById("identCount").innerHTML = myIdentARR.length;
}
var hashchangesupport = 'onhashchange' in window
onhashchange = function () {
var m
if (m = /#?s=(.*)/.exec(location.hash)) {
input_el.value = decodeURIComponent(m[1])
}
update_output()
input_el.focus()
}
onhashchange()
update_output()
input_el.focus()
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment