parser.pegjs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. start = method
  2. separator = [ \t\v\f\u00A0\uFEFF\n\r\u2028\u2029]+
  3. comments = (["][^"]*["])+
  4. ws = (separator / comments)*
  5. identifier = first:[a-zA-Z] others:[a-zA-Z0-9]* {return first + others.join("");}
  6. keyword = first:identifier last:[:] {return first + last;}
  7. selector = first:[a-zA-Z] others:[a-zA-Z0-9\:]* {return first + others.join("");}
  8. className = first:[A-Z] others:[a-zA-Z0-9]* {return first + others.join("");}
  9. string = ['] val:(("''" {return "'";} / [^'])*) ['] {
  10. return smalltalk.ValueNode._new()
  11. ._position_((line).__at(column))
  12. ._value_(val.join("").replace(/\"/ig, '"'));
  13. }
  14. symbol = "#" rest:bareSymbol {return rest;}
  15. bareSymbol = val:(selector / binarySelector / node:string {return node._value();})
  16. {
  17. return smalltalk.ValueNode._new()
  18. ._position_((line).__at(column))
  19. ._value_(val);
  20. }
  21. number = n:(numberExp / hex / float / integer) {
  22. return smalltalk.ValueNode._new()
  23. ._position_((line).__at(column))
  24. ._value_(n);
  25. }
  26. numberExp = n:((float / integer) "e" integer) {return parseFloat(n.join(""));}
  27. hex = neg:[-]? "16r" num:[0-9a-fA-F]+ {return parseInt((neg + num.join("")), 16);}
  28. float = neg:[-]?digits:[0-9]+ "." dec:[0-9]+ {return parseFloat((neg + digits.join("") + "." + dec.join("")), 10);}
  29. integer = neg:[-]?digits:[0-9]+ {return (parseInt(neg+digits.join(""), 10));}
  30. literalArray = "#(" rest:literalArrayRest {return rest;}
  31. bareLiteralArray = "(" rest:literalArrayRest {return rest;}
  32. literalArrayRest = ws lits:(lit:(parseTimeLiteral / bareLiteralArray / bareSymbol) ws {return lit._value();})* ws ")" {
  33. return smalltalk.ValueNode._new()
  34. ._position_((line).__at(column))
  35. ._value_(lits);
  36. }
  37. dynamicArray = "{" ws expressions:expressions? ws "."? "}" {
  38. return smalltalk.DynamicArrayNode._new()
  39. ._position_((line).__at(column))
  40. ._nodes_(expressions);
  41. }
  42. dynamicDictionary = "#{" ws expressions: expressions? ws "}" {
  43. return smalltalk.DynamicDictionaryNode._new()
  44. ._position_((line).__at(column))
  45. ._nodes_(expressions);
  46. }
  47. pseudoVariable = val:(
  48. 'true' {return true;}
  49. / 'false' {return false;}
  50. / 'nil' {return nil;}) {
  51. return smalltalk.ValueNode._new()
  52. ._position_((line).__at(column))
  53. ._value_(val);
  54. }
  55. parseTimeLiteral = pseudoVariable / number / literalArray / string / symbol
  56. runtimeLiteral = dynamicDictionary / dynamicArray / block
  57. literal = runtimeLiteral / parseTimeLiteral
  58. variable = identifier:identifier {
  59. return smalltalk.VariableNode._new()
  60. ._position_((line).__at(column))
  61. ._value_(identifier);
  62. }
  63. reference = variable
  64. keywordPair = key:keyword ws arg:binarySend ws {return {key:key, arg: arg};}
  65. binarySelector = bin:[\\+*/=><,@%~|&-]+ {return bin.join("");}
  66. unarySelector = identifier
  67. keywordPattern = pairs:(ws key:keyword ws arg:identifier {return {key:key, arg: arg};})+ {
  68. var keywords = [];
  69. var params = [];
  70. var i = 0;
  71. for(i = 0; i < pairs.length; i++){
  72. keywords.push(pairs[i].key);
  73. }
  74. for(i = 0; i < pairs.length; i++){
  75. params.push(pairs[i].arg);
  76. }
  77. return [keywords.join(""), params];
  78. }
  79. binaryPattern = ws selector:binarySelector ws arg:identifier {return [selector, [arg]];}
  80. unaryPattern = ws selector:unarySelector {return [selector, []];}
  81. expression = assignment / cascade / keywordSend / binarySend
  82. expressionList = ws "." ws expression:expression {return expression;}
  83. expressions = first:expression others:expressionList* {
  84. var result = [first];
  85. for(var i = 0; i < others.length; i++) {
  86. result.push(others[i]);
  87. }
  88. return result;
  89. }
  90. assignment = variable:variable ws ':=' ws expression:expression {
  91. return smalltalk.AssignmentNode._new()
  92. ._position_((line).__at(column))
  93. ._left_(variable)
  94. ._right_(expression);
  95. }
  96. ret = '^' ws expression:expression ws '.'? {
  97. return smalltalk.ReturnNode._new()
  98. ._position_((line).__at(column))
  99. ._nodes_([expression]);
  100. }
  101. temps = "|" vars:(ws variable:identifier ws {return variable;})* "|" {return vars;}
  102. blockParamList = params:((ws ":" ws param:identifier {return param;})+) ws "|" {return params;}
  103. subexpression = '(' ws expression:expression ws ')' {return expression;}
  104. statements = ret:ret [.]* {return [ret];}
  105. / exps:expressions ws [.]+ ws ret:ret [.]* {
  106. var expressions = exps;
  107. expressions.push(ret);
  108. return expressions;
  109. }
  110. / expressions:expressions? [.]* {
  111. return expressions || [];
  112. }
  113. sequence = jsSequence / stSequence
  114. stSequence = temps:temps? ws statements:statements? ws {
  115. return smalltalk.SequenceNode._new()
  116. ._position_((line).__at(column))
  117. ._temps_(temps || [])
  118. ._nodes_(statements || []);
  119. }
  120. jsSequence = jsStatement
  121. block = '[' ws params:blockParamList? ws sequence:sequence? ws ']' {
  122. return smalltalk.BlockNode._new()
  123. ._position_((line).__at(column))
  124. ._parameters_(params || [])
  125. ._nodes_([sequence._asBlockSequenceNode()]);
  126. }
  127. operand = literal / reference / subexpression
  128. unaryMessage = ws selector:unarySelector ![:] {
  129. return smalltalk.SendNode._new()
  130. ._position_((line).__at(column))
  131. ._selector_(selector);
  132. }
  133. unaryTail = message:unaryMessage ws tail:unaryTail? ws {
  134. if(tail) {
  135. return tail._valueForReceiver_(message);
  136. }
  137. else {
  138. return message;
  139. }
  140. }
  141. unarySend = receiver:operand ws tail:unaryTail? {
  142. if(tail) {
  143. return tail._valueForReceiver_(receiver);
  144. }
  145. else {
  146. return receiver;
  147. }
  148. }
  149. binaryMessage = ws selector:binarySelector ws arg:(unarySend / operand) {
  150. return smalltalk.SendNode._new()
  151. ._position_((line).__at(column))
  152. ._selector_(selector)
  153. ._arguments_([arg]);
  154. }
  155. binaryTail = message:binaryMessage tail:binaryTail? {
  156. if(tail) {
  157. return tail._valueForReceiver_(message);
  158. }
  159. else {
  160. return message;
  161. }
  162. }
  163. binarySend = receiver:unarySend tail:binaryTail? {
  164. if(tail) {
  165. return tail._valueForReceiver_(receiver);
  166. }
  167. else {
  168. return receiver;
  169. }
  170. }
  171. keywordMessage = ws pairs:(pair:keywordPair ws {return pair;})+ {
  172. var selector = [];
  173. var args = [];
  174. for(var i = 0; i < pairs.length; i++) {
  175. selector.push(pairs[i].key);
  176. args.push(pairs[i].arg);
  177. }
  178. return smalltalk.SendNode._new()
  179. ._position_((line).__at(column))
  180. ._selector_(selector.join(""))
  181. ._arguments_(args);
  182. }
  183. keywordSend = receiver:binarySend tail:keywordMessage {
  184. return tail._valueForReceiver_(receiver);
  185. }
  186. message = binaryMessage / unaryMessage / keywordMessage
  187. cascade = ws send:(keywordSend / binarySend) messages:(ws ";" ws mess:message ws {return mess;})+ {
  188. var cascade = [];
  189. cascade.push(send);
  190. for(var i = 0; i < messages.length; i++) {
  191. cascade.push(messages[i]);
  192. }
  193. return smalltalk.CascadeNode._new()
  194. ._position_((line).__at(column))
  195. ._receiver_(send._receiver())
  196. ._nodes_(cascade);
  197. }
  198. jsStatement = "<" val:((">>" {return ">";} / [^>])*) ">" {
  199. return smalltalk.JSStatementNode._new()
  200. ._position_((line).__at(column))
  201. ._source_(val.join(""));
  202. }
  203. method = ws pattern:(keywordPattern / binaryPattern / unaryPattern) ws sequence:sequence? ws {
  204. return smalltalk.MethodNode._new()
  205. ._position_((line).__at(column))
  206. ._selector_(pattern[0])
  207. ._arguments_(pattern[1])
  208. ._nodes_([sequence]);
  209. }