parser.pegjs 11 KB

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