1
0

parser.pegjs 7.9 KB

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