parser.pegjs 7.3 KB

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