parser.pegjs 7.0 KB

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