| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312 | start = methodPattern/* * expression pattern parsing */expressionPattern = temps? statements*/* * method pattern parsing */methodPattern   = unaryPattern / binaryPattern / keywordPatternunaryPattern  = ws key:identifier ws body:methodBody ws  {      return smalltalk.methodNode({	  selector: [key],	  children: [body]      });  }binaryPattern  = ws key:binary separator param:identifier ws body:methodBody ws  {      return smalltalk.methodNode({	  selector: [key],           params:    [smalltalk.valueNode({value: param})], 	  children: [body]      });  }keywordPattern  = ws pairs:(keywordPair)+ ws body:methodBody ws  {      var keywords = [];      var params = [];      for(var i=0;i<pairs.length;i++){          keywords.push(pairs[i].key);      }      for(var i=0;i<pairs.length;i++){          params.push(pairs[i].arg);      }      return smalltalk.methodNode({          selector: keywords,           params:   params,           children: [body]      });  }methodBody  = ws temps:temps? ws stats:statementList? ws    {        return smalltalk.sequenceNode({            temps:    temps || [],            children: stats || []        });    }/* * Method parsing */temps  = "|" vars:(ws v:variable ws{return v})* "|" {return vars}variable  = value:identifier   {      return smalltalk.variableNode({value: value});  }statementList  = ret:ret [.]*  {      return [ret]  }  / stats:statements ws [.]+ ws ret:ret [.]*  {      var statements = stats;      statements.push(ret);      return statements  }  / stats:statements? [.]*  {      return stats  }  statements  = first:(ws stat:statement {return stat}) others:(ws "." ws stat:statement ws {return stat})*  {    var statements = [];    var others = others || [];    statements.push(first);    for(var i=0; i<others.length;i++) {        statements.push(others[i]);    }    return statements  }ret  = ws "^" ws stat:statement  {      return smalltalk.returnNode({          children: [stat]      });  }statement  = jsStatement / assignment / cascade / keywordSend / binarySendjsStatement  = [<] val:(("<<" {return "<"} / [^<])*) [>]  {	return smalltalk.jsStatementNode({source: source})  }assignment  = ws left:reference ws ":=" ws right:statement ws  {      return smalltalk.assignmentNode({          left:  left,          right: right      });  }cascade  = ws send:(keywordSend / binarySend) messages:(ws ";" ws mess:message ws {return mess})+   {      var cascade = [];      cascade.push(send);      for(var i=0;i<messages.length;i++) {          cascade.push(messages[i]);      }      return smalltalk.cascadeNode({          receiver: send.receiver,          children: cascade      })  }unarySend  = rec:operand ws tail:unaryTail?  {      if(tail) {          smalltalk.setReceiver(tail,rec);          return tail;      }      else {          return rec      }  }unaryTail  = message:unaryTailMessage ws tail:unaryTail? ws  {      if(tail) {          smalltalk.setReceiver(tail, message);          return tail;      }      else {          return message      }  }unaryTailMessage  = key:identifier ![:]  {      return smalltalk.sendNode({          selector: [key]      });  }keywordSend  = rec:binarySend ws pairs:keywordPair+  {        var keywords = [];        var args = [];        for(var i=0;i<pairs.length;i++){            keywords.push(pairs[i].key);        }        for(var i=0;i<pairs.length;i++){            args.push(pairs[i].arg);        }        return smalltalk.sendNode({            receiver: rec,            selector: keywords,            args: args        });  }binarySend  = rec:unarySend ws tail:binaryTail?  {      if(tail) {          smalltalk.setReceiver(tail, rec);          return tail;      }             else {          return rec      }        }binaryTail  = ws rec:binaryTailMessage ws tail:binaryTail?  {	if(tail) {		 smalltalk.setReceiver(tail, rec);		 return tail	}	else {	     return rec	}  }binaryTailMessage  = ws key:binary ws arg:unarySend  {return smalltalk.sendNode({selector:[key], args: [arg]})}send  //= binarySend / unarySend / keywordSend  = keywordSend / binarySendmessage  = binaryMessage / unaryMessage / keywordMessagebinaryMessage  = key:binary ws arg:(unarySend / operand)  {return smalltalk.sendNode({selector: [binary], args: [arg]});}unaryMessage  = key:identifier ![:]  {return smalltalk.sendNode({selector: [key]});}keywordMessage  = pairs:keywordPair+   {      var selector = [];      var args = [];      for(var i=0;i<pairs.length;i++) {          selector.push(pairs[i].key);          args.push(pairs[i].arg);      }      return smalltalk.sendNode({selector: selector, args: args});  }operand  = literal / reference / subexpressionsubexpression  = "(" stat:statement ")" {return stat}block  = ws "[" ws params:blockParams? ws temps:temps? ws stats:statementList? ws "]" ws  {      return smalltalk.blockNode({          params: params,           children: [smalltalk.blockSequenceNode({temps: temps, children: stats})]      });  }blockParams  = params:((ws ":" ws param:identifier {return param})+) ws "|" ws  {return params}/* * common tokens */separator = [ \t\v\f\u00A0\uFEFF\n\r\u2028\u2029]+comments = (["][^"]*["])+ws = (separator / comments)*alphabetic =identifier = first:[a-z] others:[a-zA-Z0-9]* {return first + others.join("")}//literalsnumber = float / integerfloat = neg:[-]?int:integer "." dec:integer {return parseFloat((neg+int+"."+dec), 10)}integer = neg:[-]?digits:[0-9]+ {return (parseInt(neg+digits, 10))}string = ['] val:(("''" {return "'"} / [^'])*) ['] {        return '"' + val.join("").replace(/\"/ig, '\\"') + '"'}jsString = ['] val:(("''" {return "'"} / [^'])*) ['] {        return val.join("")}char = "$" val:. {return val}symbol = "#"val:[^ ] {return val}literalArray = "#(" ws lits:(lit:literal ws {return lit})* ws ")" {return "[" + lits + "]"}literal = number / literalArray /string / symbol / char /  blockkeyword = first:identifier last:[:] {return first + last}binary = bin:[+*/=><,@%~|&-]+ {return bin.join("")}variable = v:identifier {return smalltalk.variableNode({value: v});}global = first:[A-Z] others:[a-zA-Z0-9]* {return first + others.join("")}classRef = ref:global {return smalltalk.classRefNode({value: ref})}reference = variable / classRefkeywordPair = key:keyword ws arg:binarySend ws {return {key:key, arg: arg}}
 |