parser.pegjs 7.2 KB

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