parser.pegjs 12 KB

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