parser.pegjs 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  1. start = method
  2. separator =
  3. [ \t\v\f\u00A0\u1680\u2000-\u200A\u202F\u205F\u3000\uFEFF\n\r\u2028\u2029]+
  4. comments = ('"' [^"]* '"')+
  5. ws = (separator / comments)*
  6. maybeDotsWs = ('.' / separator / comments)*
  7. someDotsWs = ws '.' maybeDotsWs
  8. identifier = $([a-zA-Z] [a-zA-Z0-9]*)
  9. keyword = $(identifier ':')
  10. className = $([A-Z] [a-zA-Z0-9]*)
  11. string = val:rawString {
  12. return $globals.ValueNode._new()
  13. ._location_(location())
  14. ._source_(text())
  15. ._value_(val);
  16. }
  17. rawString = '\'' val:(('\'\'' {return '\'';} / [^'])*) '\'' {return val.join('');}
  18. character = '$' char:. {
  19. return $globals.ValueNode._new()
  20. ._location_(location())
  21. ._source_(text())
  22. ._value_(char);
  23. }
  24. symbol = '#' rest:bareSymbol {return rest;}
  25. bareSymbol = val:($(keyword+) / binarySelector / unarySelector / rawString) {
  26. return $globals.ValueNode._new()
  27. ._location_(location())
  28. ._source_(text())
  29. ._value_(val);
  30. }
  31. number = val:rawNumber {
  32. return $globals.ValueNode._new()
  33. ._location_(location())
  34. ._source_(text())
  35. ._value_(val);
  36. }
  37. rawNumber = numberExp / hex / float / integer
  38. numberExp = n:$((float / integer) 'e' integer) {return parseFloat(n);}
  39. hex = neg:'-'? '16r' num:$[0-9a-fA-F]+ {
  40. return parseInt(((neg || '') + num), 16);
  41. }
  42. float = n:$('-'? [0-9]+ '.' [0-9]+) {return parseFloat(n, 10);}
  43. integer = n:$('-'? [0-9]+) {return parseInt(n, 10);}
  44. literalArray = '#(' rest:wsLiteralArrayContents ws ')' {
  45. return rest
  46. ._location_(location())
  47. ._source_(text());
  48. }
  49. bareLiteralArray = '(' rest:wsLiteralArrayContents ws ')' {
  50. return rest
  51. ._location_(location())
  52. ._source_(text());
  53. }
  54. literalArrayElement = parseTimeLiteral / bareLiteralArray / bareSymbol
  55. wsLiteralArrayContents =
  56. lits:(ws lit:literalArrayElement {return lit._value();})* {
  57. return $globals.ValueNode._new()
  58. ._value_(lits);
  59. }
  60. dynamicArray = '{' expressions:wsExpressions? maybeDotsWs '}' {
  61. return $globals.DynamicArrayNode._new()
  62. ._location_(location())
  63. ._source_(text())
  64. ._dagChildren_(expressions || []);
  65. }
  66. dynamicDictionary = '#{' expressions:wsAssociations? maybeDotsWs '}' {
  67. return $globals.DynamicDictionaryNode._new()
  68. ._location_(location())
  69. ._source_(text())
  70. ._dagChildren_(expressions || []);
  71. }
  72. pseudoVariable = val:(
  73. 'true' {return true;} /
  74. 'false' {return false;} /
  75. 'nil' {return null;}
  76. ) {
  77. return $globals.ValueNode._new()
  78. ._location_(location())
  79. ._source_(text())
  80. ._value_(val);
  81. }
  82. parseTimeLiteral =
  83. pseudoVariable / number / literalArray / string / symbol / character
  84. runtimeLiteral = dynamicDictionary / dynamicArray / block
  85. literal = runtimeLiteral / parseTimeLiteral
  86. variable = identifier:identifier {
  87. return $globals.VariableNode._new()
  88. ._location_(location())
  89. ._source_(text())
  90. ._value_(identifier);
  91. }
  92. reference = variable
  93. binarySelector = $[\\+*/=><,@%~|&-]+
  94. unarySelector = identifier
  95. wsKeywordPattern =
  96. pairs:(ws key:keyword ws arg:identifier {return {key:key, arg:arg};})+ {
  97. var selector = '';
  98. var params = [];
  99. for(var i = 0; i < pairs.length; i++) {
  100. selector += pairs[i].key;
  101. params.push(pairs[i].arg);
  102. }
  103. return [selector, params];
  104. }
  105. wsBinaryPattern = ws selector:binarySelector ws arg:identifier {
  106. return [selector, [arg]];
  107. }
  108. wsUnaryPattern = ws selector:unarySelector {return [selector, []];}
  109. expression = assignment / cascade / keywordSend
  110. wsExpressionsRest = someDotsWs expression:expression {
  111. return expression;
  112. }
  113. wsExpressions = maybeDotsWs first:expression others:wsExpressionsRest* {
  114. return [first].concat(others);
  115. }
  116. wsUnaryPragmaMessage = ws selector:unarySelector !':' {
  117. return $globals.Message._selector_arguments_(selector, []);
  118. }
  119. wsKeywordPragmaMessage =
  120. pairs:(ws key:keyword ws arg:parseTimeLiteral {return {key:key, arg:arg};})+ {
  121. var selector = '';
  122. var args = [];
  123. for(var i = 0; i < pairs.length; i++) {
  124. selector += pairs[i].key;
  125. args.push(pairs[i].arg._value());
  126. }
  127. return $globals.Message._selector_arguments_(selector, args)
  128. }
  129. wsPragmaMessage = wsUnaryPragmaMessage / wsKeywordPragmaMessage
  130. wsPragmas = items:(ws '<' message:wsPragmaMessage ws '>' {return message;})*
  131. assignment = variable:variable ws ':=' ws expression:expression {
  132. return $globals.AssignmentNode._new()
  133. ._location_(location())
  134. ._source_(text())
  135. ._left_(variable)
  136. ._right_(expression);
  137. }
  138. ret = '^' ws expression:expression {
  139. return $globals.ReturnNode._new()
  140. ._location_(location())
  141. ._source_(text())
  142. ._dagChildren_([expression]);
  143. }
  144. temps = '|' vars:(ws variable:identifier {return variable;})* ws '|' {
  145. return vars;
  146. }
  147. wsBlockParamList =
  148. params:((ws ':' ws param:identifier {return param;})+) ws '|' {
  149. return params;
  150. }
  151. subexpression = '(' ws expression:expression ws ')' {
  152. return expression;
  153. }
  154. wsStatements =
  155. maybeDotsWs ret:ret {return [ret];} /
  156. exps:wsExpressions someDotsWs ret:ret {
  157. var expressions = exps;
  158. expressions.push(ret);
  159. return expressions;
  160. } /
  161. expressions:wsExpressions? {return expressions || [];}
  162. wsSequenceWs = aPragmas:wsPragmas? ws temps:temps? zPragmas:wsPragmas? statements:wsStatements? maybeDotsWs {
  163. return $globals.SequenceNode._new()
  164. ._location_(location())
  165. ._source_(text())
  166. ._temps_(temps || [])
  167. ._pragmas_((aPragmas || []).concat(zPragmas || []))
  168. ._dagChildren_(statements || []);
  169. }
  170. block = '[' params:wsBlockParamList? sequence:wsSequenceWs ']' {
  171. return $globals.BlockNode._new()
  172. ._location_(location())
  173. ._source_(text())
  174. ._parameters_(params || [])
  175. ._dagChildren_([sequence._asBlockSequenceNode()]);
  176. }
  177. operand = literal / reference / subexpression
  178. wsUnaryMessage = ws selector:unarySelector !':' {
  179. return $globals.SendNode._new()
  180. ._location_(location())
  181. ._source_(text())
  182. ._selector_(selector);
  183. }
  184. wsUnaryTail = wsUnaryMessage*
  185. unarySend = receiver:operand tail:wsUnaryTail {
  186. return receiver._withTail_(tail);
  187. }
  188. wsBinaryMessage = ws selector:binarySelector ws arg:unarySend {
  189. return $globals.SendNode._new()
  190. ._location_(location())
  191. ._source_(text())
  192. ._selector_(selector)
  193. ._arguments_([arg]);
  194. }
  195. wsBinaryTail = unarys:wsUnaryTail binarys:wsBinaryMessage* { return unarys.concat(binarys); }
  196. binarySend = receiver:operand tail:wsBinaryTail {
  197. return receiver._withTail_(tail);
  198. }
  199. wsKeywordMessage =
  200. pairs:(ws key:keyword ws arg:binarySend {return {key:key, arg:arg};})+ {
  201. var selector = '';
  202. var args = [];
  203. for(var i = 0; i < pairs.length; i++) {
  204. selector += pairs[i].key;
  205. args.push(pairs[i].arg);
  206. }
  207. return $globals.SendNode._new()
  208. ._location_(location())
  209. ._source_(text())
  210. ._selector_(selector)
  211. ._arguments_(args);
  212. }
  213. wsKeywordTail = binarys:wsBinaryTail final:wsKeywordMessage? {
  214. if (final) binarys.push(final);
  215. return binarys;
  216. }
  217. keywordSend = receiver:operand tail:wsKeywordTail {
  218. return receiver._withTail_(tail);
  219. }
  220. wsMessage = wsBinaryMessage / wsUnaryMessage / wsKeywordMessage
  221. cascade =
  222. receiver:operand tail:wsKeywordTail & {return tail.length > 0;}
  223. messages:(ws ';' mess:wsMessage {return mess;})+ {
  224. messages.unshift(receiver._withTail_(tail));
  225. return $globals.CascadeNode._new()
  226. ._location_(location())
  227. ._source_(text())
  228. ._dagChildren_(messages);
  229. }
  230. method =
  231. pattern:(wsKeywordPattern / wsBinaryPattern / wsUnaryPattern)
  232. sequence:wsSequenceWs {
  233. return $globals.MethodNode._new()
  234. ._location_(location())
  235. ._source_(text())
  236. ._selector_(pattern[0])
  237. ._arguments_(pattern[1])
  238. ._dagChildren_([sequence]);
  239. }
  240. associationSend =
  241. receiver:operand tail:wsBinaryTail
  242. & { return tail.length > 0 && tail[tail.length-1]._selector() === '->' } {
  243. var last = tail.pop();
  244. return [receiver._withTail_(tail), last._arguments()[0]];
  245. }
  246. wsAssociationsRest = someDotsWs expression:associationSend {
  247. return expression;
  248. }
  249. wsAssociations = maybeDotsWs first:associationSend others:wsAssociationsRest* {
  250. return first.concat.apply(first, others);
  251. }