smalltalk.pegjs 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. start = methodPattern
  2. /*
  3. * expression pattern parsing
  4. */
  5. expressionPattern = temps? statements*
  6. /*
  7. * method pattern parsing
  8. */
  9. methodPattern
  10. = unaryPattern / binaryPattern / keywordPattern
  11. unaryPattern
  12. = ws key:identifier ws body:methodBody ws
  13. {
  14. return smalltalk.methodNode({
  15. selector: [key],
  16. children: [body]
  17. });
  18. }
  19. binaryPattern
  20. = ws key:binary separator param:identifier ws body:methodBody ws
  21. {
  22. return smalltalk.methodNode({
  23. selector: [key],
  24. params: [smalltalk.valueNode({value: param})],
  25. children: [body]
  26. });
  27. }
  28. keywordPattern
  29. = ws pairs:(keywordPair)+ ws body:methodBody ws
  30. {
  31. var keywords = [];
  32. var params = [];
  33. for(var i=0;i<pairs.length;i++){
  34. keywords.push(pairs[i].key);
  35. }
  36. for(var i=0;i<pairs.length;i++){
  37. params.push(pairs[i].arg);
  38. }
  39. return smalltalk.methodNode({
  40. selector: keywords,
  41. params: params,
  42. children: [body]
  43. });
  44. }
  45. methodBody
  46. = ws temps:temps? ws stats:statementList? ws
  47. {
  48. return smalltalk.sequenceNode({
  49. temps: temps || [],
  50. children: stats || []
  51. });
  52. }
  53. /*
  54. * Method parsing
  55. */
  56. temps
  57. = "|" vars:(ws v:variable ws{return v})* "|" {return vars}
  58. variable
  59. = value:identifier
  60. {
  61. return smalltalk.variableNode({value: value});
  62. }
  63. statementList
  64. = ret:ret [.]*
  65. {
  66. return [ret]
  67. }
  68. / stats:statements ws [.]+ ws ret:ret [.]*
  69. {
  70. var statements = stats;
  71. statements.push(ret);
  72. return statements
  73. }
  74. / stats:statements? [.]*
  75. {
  76. return stats
  77. }
  78. statements
  79. = first:(ws stat:statement {return stat}) others:(ws "." ws stat:statement ws {return stat})*
  80. {
  81. var statements = [];
  82. var others = others || [];
  83. statements.push(first);
  84. for(var i=0; i<others.length;i++) {
  85. statements.push(others[i]);
  86. }
  87. return statements
  88. }
  89. ret
  90. = ws "^" ws stat:statement
  91. {
  92. return smalltalk.returnNode({
  93. children: [stat]
  94. });
  95. }
  96. statement
  97. = jsStatement / assignment / cascade / keywordSend / binarySend
  98. jsStatement
  99. = [<] val:(("<<" {return "<"} / [^<])*) [>]
  100. {
  101. return smalltalk.jsStatementNode({source: source})
  102. }
  103. assignment
  104. = ws left:reference ws ":=" ws right:statement ws
  105. {
  106. return smalltalk.assignmentNode({
  107. left: left,
  108. right: right
  109. });
  110. }
  111. cascade
  112. = ws send:(keywordSend / binarySend) messages:(ws ";" ws mess:message ws {return mess})+
  113. {
  114. var cascade = [];
  115. cascade.push(send);
  116. for(var i=0;i<messages.length;i++) {
  117. cascade.push(messages[i]);
  118. }
  119. return smalltalk.cascadeNode({
  120. receiver: send.receiver,
  121. children: cascade
  122. })
  123. }
  124. unarySend
  125. = rec:operand ws tail:unaryTail?
  126. {
  127. if(tail) {
  128. smalltalk.setReceiver(tail,rec);
  129. return tail;
  130. }
  131. else {
  132. return rec
  133. }
  134. }
  135. unaryTail
  136. = message:unaryTailMessage ws tail:unaryTail? ws
  137. {
  138. if(tail) {
  139. smalltalk.setReceiver(tail, message);
  140. return tail;
  141. }
  142. else {
  143. return message
  144. }
  145. }
  146. unaryTailMessage
  147. = key:identifier ![:]
  148. {
  149. return smalltalk.sendNode({
  150. selector: [key]
  151. });
  152. }
  153. keywordSend
  154. = rec:binarySend ws pairs:keywordPair+
  155. {
  156. var keywords = [];
  157. var args = [];
  158. for(var i=0;i<pairs.length;i++){
  159. keywords.push(pairs[i].key);
  160. }
  161. for(var i=0;i<pairs.length;i++){
  162. args.push(pairs[i].arg);
  163. }
  164. return smalltalk.sendNode({
  165. receiver: rec,
  166. selector: keywords,
  167. args: args
  168. });
  169. }
  170. binarySend
  171. = rec:unarySend ws tail:binaryTail?
  172. {
  173. if(tail) {
  174. smalltalk.setReceiver(tail, rec);
  175. return tail;
  176. }
  177. else {
  178. return rec
  179. }
  180. }
  181. binaryTail
  182. = ws rec:binaryTailMessage ws tail:binaryTail?
  183. {
  184. if(tail) {
  185. smalltalk.setReceiver(tail, rec);
  186. return tail
  187. }
  188. else {
  189. return rec
  190. }
  191. }
  192. binaryTailMessage
  193. = ws key:binary ws arg:unarySend
  194. {return smalltalk.sendNode({selector:[key], args: [arg]})}
  195. send
  196. //= binarySend / unarySend / keywordSend
  197. = keywordSend / binarySend
  198. message
  199. = binaryMessage / unaryMessage / keywordMessage
  200. binaryMessage
  201. = key:binary ws arg:(unarySend / operand)
  202. {return smalltalk.sendNode({selector: [binary], args: [arg]});}
  203. unaryMessage
  204. = key:identifier ![:]
  205. {return smalltalk.sendNode({selector: [key]});}
  206. keywordMessage
  207. = pairs:keywordPair+
  208. {
  209. var selector = [];
  210. var args = [];
  211. for(var i=0;i<pairs.length;i++) {
  212. selector.push(pairs[i].key);
  213. args.push(pairs[i].arg);
  214. }
  215. return smalltalk.sendNode({selector: selector, args: args});
  216. }
  217. operand
  218. = literal / reference / subexpression
  219. subexpression
  220. = "(" stat:statement ")" {return stat}
  221. block
  222. = ws "[" ws params:blockParams? ws temps:temps? ws stats:statementList? ws "]" ws
  223. {
  224. return smalltalk.blockNode({
  225. params: params,
  226. children: [smalltalk.blockSequenceNode({temps: temps, children: stats})]
  227. });
  228. }
  229. blockParams
  230. = params:((ws ":" ws param:identifier {return param})+) ws "|" ws
  231. {return params}
  232. /*
  233. * common tokens
  234. */
  235. separator = [ \t\v\f\u00A0\uFEFF\n\r\u2028\u2029]+
  236. comments = (["][^"]*["])+
  237. ws = (separator / comments)*
  238. alphabetic =
  239. identifier = first:[a-z] others:[a-zA-Z0-9]* {return first + others.join("")}
  240. //literals
  241. number = float / integer
  242. float = neg:[-]?int:integer "." dec:integer {return parseFloat((neg+int+"."+dec), 10)}
  243. integer = neg:[-]?digits:[0-9]+ {return (parseInt(neg+digits, 10))}
  244. string = ['] val:(("''" {return "'"} / [^'])*) ['] {
  245. return '"' + val.join("").replace(/\"/ig, '\\"') + '"'
  246. }
  247. jsString = ['] val:(("''" {return "'"} / [^'])*) ['] {
  248. return val.join("")
  249. }
  250. char = "$" val:. {return val}
  251. symbol = "#"val:[^ ] {return val}
  252. literalArray = "#(" ws lits:(lit:literal ws {return lit})* ws ")" {return "[" + lits + "]"}
  253. literal = number / literalArray /string / symbol / char / block
  254. keyword = first:identifier last:[:] {return first + last}
  255. binary = bin:[+*/=><,@%~|&-]+ {return bin.join("")}
  256. variable = v:identifier {return smalltalk.variableNode({value: v});}
  257. global = first:[A-Z] others:[a-zA-Z0-9]* {return first + others.join("")}
  258. classRef = ref:global {return smalltalk.classRefNode({value: ref})}
  259. reference = variable / classRef
  260. keywordPair = key:keyword ws arg:binarySend ws {return {key:key, arg: arg}}