parser.pegjs 7.1 KB

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