JSONParseTreeHandler.js 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. /* ***** BEGIN LICENSE BLOCK *****
  2. * Distributed under the BSD license:
  3. *
  4. * Copyright (c) 2010, Ajax.org B.V.
  5. * All rights reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions are met:
  9. * * Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * * Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. * * Neither the name of Ajax.org B.V. nor the
  15. * names of its contributors may be used to endorse or promote products
  16. * derived from this software without specific prior written permission.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  19. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  20. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  21. * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY
  22. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  23. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  24. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  25. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  26. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  27. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  28. *
  29. * ***** END LICENSE BLOCK ***** */
  30. define(function(require, exports, module){
  31. var JSONParseTreeHandler = exports.JSONParseTreeHandler = function(code) {
  32. //List of nodes that are not targeted by the parse tree size optimization.
  33. var list = [
  34. "OrExpr", "AndExpr", "ComparisonExpr", "StringConcatExpr", "RangeExpr"
  35. //, "AdditiveExpr", "MultiplicativeExpr"
  36. , "UnionExpr", "IntersectExceptExpr", "InstanceofExpr", "TreatExpr", "CastableExpr"
  37. , "CastExpr", "UnaryExpr", "ValueExpr", "FTContainsExpr", "SimpleMapExpr", "PathExpr", "RelativePathExpr"
  38. , "PostfixExpr", "StepExpr"
  39. ];
  40. var ast = null;
  41. var ptr = null;
  42. var remains = code;
  43. var cursor = 0;
  44. var lineCursor = 0;
  45. var line = 0;
  46. var col = 0;
  47. function createNode(name){
  48. return { name: name, children: [], getParent: null, pos: { sl: 0, sc: 0, el: 0, ec: 0 } };
  49. }
  50. function pushNode(name, begin){
  51. var node = createNode(name);
  52. if(ast === null) {
  53. ast = node;
  54. ptr = node;
  55. } else {
  56. node.getParent = ptr;
  57. ptr.children.push(node);
  58. ptr = ptr.children[ptr.children.length - 1];
  59. }
  60. }
  61. function popNode(){
  62. if(ptr.children.length > 0) {
  63. var s = ptr.children[0];
  64. var e = null;
  65. //We want to skip empty non terminals. For instance PredicateList:
  66. // [108] AxisStep ::= (ReverseStep | ForwardStep) PredicateList
  67. // [120] PredicateList ::= Predicate*
  68. for(var i= ptr.children.length - 1; i >= 0;i--) {
  69. e = ptr.children[i];
  70. if(e.pos.el !== 0 || e.pos.ec !== 0) {
  71. break;
  72. }
  73. }
  74. ptr.pos.sl = s.pos.sl;
  75. ptr.pos.sc = s.pos.sc;
  76. ptr.pos.el = e.pos.el;
  77. ptr.pos.ec = e.pos.ec;
  78. }
  79. //Normalize EQName && FunctionName
  80. if(ptr.name === "FunctionName") {
  81. ptr.name = "EQName";
  82. }
  83. if(ptr.name === "EQName" && ptr.value === undefined) {
  84. ptr.value = ptr.children[0].value;
  85. ptr.children.pop();
  86. }
  87. if(ptr.getParent !== null) {
  88. ptr = ptr.getParent;
  89. //for(var i in ptr.children) {
  90. //delete ptr.children[i].getParent;
  91. //}
  92. } else {
  93. //delete ptr.getParent;
  94. }
  95. //Parse tree size optimization
  96. if(ptr.children.length > 0) {
  97. var lastChild = ptr.children[ptr.children.length - 1];
  98. if(lastChild.children.length === 1 && list.indexOf(lastChild.name) !== -1) {
  99. ptr.children[ptr.children.length - 1] = lastChild.children[0];
  100. }
  101. }
  102. }
  103. this.closeParseTree = function() {
  104. while(ptr.getParent !== null) {
  105. popNode();
  106. }
  107. popNode();
  108. };
  109. this.peek = function() {
  110. return ptr;
  111. };
  112. this.getParseTree = function() {
  113. return ast;
  114. };
  115. this.reset = function(input) {};
  116. this.startNonterminal = function(name, begin) {
  117. pushNode(name, begin);
  118. };
  119. this.endNonterminal = function(name, end) {
  120. popNode();
  121. };
  122. this.terminal = function(name, begin, end) {
  123. name = (name.substring(0, 1) === "'" && name.substring(name.length - 1) === "'") ? "TOKEN" : name;
  124. pushNode(name, begin);
  125. setValue(ptr, begin, end);
  126. popNode();
  127. };
  128. this.whitespace = function(begin, end) {
  129. var name = "WS";
  130. pushNode(name, begin);
  131. setValue(ptr, begin, end);
  132. popNode();
  133. };
  134. function setValue(node, begin, end) {
  135. var e = end - cursor;
  136. ptr.value = remains.substring(0, e);
  137. remains = remains.substring(e);
  138. cursor = end;
  139. var sl = line;
  140. var sc = lineCursor;
  141. var el = sl + ptr.value.split("\n").length - 1;
  142. var lastIdx = ptr.value.lastIndexOf("\n");
  143. var ec = lastIdx === -1 ? sc + ptr.value.length : ptr.value.substring(lastIdx + 1).length;
  144. // ec = ec === 0 ? 0 : ec - 1;
  145. line = el;
  146. //lineCursor = ec === 0 ? 0 : ec;
  147. lineCursor = ec;
  148. ptr.pos.sl = sl;
  149. ptr.pos.sc = sc;
  150. ptr.pos.el = el;
  151. ptr.pos.ec = ec;
  152. }
  153. };
  154. });