text: import { addNoneTerminalToCst, addTerminalToCst, setNodeLocationFull, setNodeLocationOnlyOffset } from "../../cst/cst";
  import { has, isUndefined, keys, NOOP } from "../../../utils/utils";
  import { createBaseSemanticVisitorConstructor, createBaseVisitorConstructorWithDefaults } from "../../cst/cst_visitor";
  import { DEFAULT_PARSER_CONFIG } from "../parser";
  /**
   * This trait is responsible for the CST building logic.
   */
  var TreeBuilder = /** @class */ (function () {
      function TreeBuilder() {
      }
      TreeBuilder.prototype.initTreeBuilder = function (config) {
          this.CST_STACK = [];
          // outputCst is no longer exposed/defined in the pubic API
          this.outputCst = config.outputCst;
          this.nodeLocationTracking = has(config, "nodeLocationTracking")
              ? config.nodeLocationTracking
              : DEFAULT_PARSER_CONFIG.nodeLocationTracking;
          if (!this.outputCst) {
              this.cstInvocationStateUpdate = NOOP;
              this.cstFinallyStateUpdate = NOOP;
              this.cstPostTerminal = NOOP;
              this.cstPostNonTerminal = NOOP;
              this.cstPostRule = NOOP;
          }
          else {
              if (/full/i.test(this.nodeLocationTracking)) {
                  if (this.recoveryEnabled) {
                      this.setNodeLocationFromToken = setNodeLocationFull;
                      this.setNodeLocationFromNode = setNodeLocationFull;
                      this.cstPostRule = NOOP;
                      this.setInitialNodeLocation = this.setInitialNodeLocationFullRecovery;
                  }
                  else {
                      this.setNodeLocationFromToken = NOOP;
                      this.setNodeLocationFromNode = NOOP;
                      this.cstPostRule = this.cstPostRuleFull;
                      this.setInitialNodeLocation = this.setInitialNodeLocationFullRegular;
                  }
              }
              else if (/onlyOffset/i.test(this.nodeLocationTracking)) {
                  if (this.recoveryEnabled) {
                      this.setNodeLocationFromToken = setNodeLocationOnlyOffset;
                      this.setNodeLocationFromNode = setNodeLocationOnlyOffset;
                      this.cstPostRule = NOOP;
                      this.setInitialNodeLocation = this.setInitialNodeLocationOnlyOffsetRecovery;
                  }
                  else {
                      this.setNodeLocationFromToken = NOOP;
                      this.setNodeLocationFromNode = NOOP;
                      this.cstPostRule = this.cstPostRuleOnlyOffset;
                      this.setInitialNodeLocation = this.setInitialNodeLocationOnlyOffsetRegular;
                  }
              }
              else if (/none/i.test(this.nodeLocationTracking)) {
                  this.setNodeLocationFromToken = NOOP;
                  this.setNodeLocationFromNode = NOOP;
                  this.cstPostRule = NOOP;
                  this.setInitialNodeLocation = NOOP;
              }
              else {
                  throw Error("Invalid <nodeLocationTracking> config option: \"" + config.nodeLocationTracking + "\"");
              }
          }
      };
      TreeBuilder.prototype.setInitialNodeLocationOnlyOffsetRecovery = function (cstNode) {
          cstNode.location = {
              startOffset: NaN,
              endOffset: NaN
          };
      };
      TreeBuilder.prototype.setInitialNodeLocationOnlyOffsetRegular = function (cstNode) {
          cstNode.location = {
              // without error recovery the starting Location of a new CstNode is guaranteed
              // To be the next Token's startOffset (for valid inputs).
              // For invalid inputs there won't be any CSTOutput so this potential
              // inaccuracy does not matter
              startOffset: this.LA(1).startOffset,
              endOffset: NaN
          };
      };
      TreeBuilder.prototype.setInitialNodeLocationFullRecovery = function (cstNode) {
          cstNode.location = {
              startOffset: NaN,
              startLine: NaN,
              startColumn: NaN,
              endOffset: NaN,
              endLine: NaN,
              endColumn: NaN
          };
      };
      /**
         *  @see setInitialNodeLocationOnlyOffsetRegular for explanation why this work
    
         * @param cstNode
         */
      TreeBuilder.prototype.setInitialNodeLocationFullRegular = function (cstNode) {
          var nextToken = this.LA(1);
          cstNode.location = {
              startOffset: nextToken.startOffset,
              startLine: nextToken.startLine,
              startColumn: nextToken.startColumn,
              endOffset: NaN,
              endLine: NaN,
              endColumn: NaN
          };
      };
      TreeBuilder.prototype.cstInvocationStateUpdate = function (fullRuleName, shortName) {
          var cstNode = {
              name: fullRuleName,
              children: {}
          };
          this.setInitialNodeLocation(cstNode);
          this.CST_STACK.push(cstNode);
      };
      TreeBuilder.prototype.cstFinallyStateUpdate = function () {
          this.CST_STACK.pop();
      };
      TreeBuilder.prototype.cstPostRuleFull = function (ruleCstNode) {
          var prevToken = this.LA(0);
          var loc = ruleCstNode.location;
          // If this condition is true it means we consumed at least one Token
          // In this CstNode.
          if (loc.startOffset <= prevToken.startOffset === true) {
              loc.endOffset = prevToken.endOffset;
              loc.endLine = prevToken.endLine;
              loc.endColumn = prevToken.endColumn;
          }
          // "empty" CstNode edge case
          else {
              loc.startOffset = NaN;
              loc.startLine = NaN;
              loc.startColumn = NaN;
          }
      };
      TreeBuilder.prototype.cstPostRuleOnlyOffset = function (ruleCstNode) {
          var prevToken = this.LA(0);
          var loc = ruleCstNode.location;
          // If this condition is true it means we consumed at least one Token
          // In this CstNode.
          if (loc.startOffset <= prevToken.startOffset === true) {
              loc.endOffset = prevToken.endOffset;
          }
          // "empty" CstNode edge case
          else {
              loc.startOffset = NaN;
          }
      };
      TreeBuilder.prototype.cstPostTerminal = function (key, consumedToken) {
          var rootCst = this.CST_STACK[this.CST_STACK.length - 1];
          addTerminalToCst(rootCst, consumedToken, key);
          // This is only used when **both** error recovery and CST Output are enabled.
          this.setNodeLocationFromToken(rootCst.location, consumedToken);
      };
      TreeBuilder.prototype.cstPostNonTerminal = function (ruleCstResult, ruleName) {
          var preCstNode = this.CST_STACK[this.CST_STACK.length - 1];
          addNoneTerminalToCst(preCstNode, ruleName, ruleCstResult);
          // This is only used when **both** error recovery and CST Output are enabled.
          this.setNodeLocationFromNode(preCstNode.location, ruleCstResult.location);
      };
      TreeBuilder.prototype.getBaseCstVisitorConstructor = function () {
          if (isUndefined(this.baseCstVisitorConstructor)) {
              var newBaseCstVisitorConstructor = createBaseSemanticVisitorConstructor(this.className, keys(this.gastProductionsCache));
              this.baseCstVisitorConstructor = newBaseCstVisitorConstructor;
              return newBaseCstVisitorConstructor;
          }
          return this.baseCstVisitorConstructor;
      };
      TreeBuilder.prototype.getBaseCstVisitorConstructorWithDefaults = function () {
          if (isUndefined(this.baseCstVisitorWithDefaultsConstructor)) {
              var newConstructor = createBaseVisitorConstructorWithDefaults(this.className, keys(this.gastProductionsCache), this.getBaseCstVisitorConstructor());
              this.baseCstVisitorWithDefaultsConstructor = newConstructor;
              return newConstructor;
          }
          return this.baseCstVisitorWithDefaultsConstructor;
      };
      TreeBuilder.prototype.getLastExplicitRuleShortName = function () {
          var ruleStack = this.RULE_STACK;
          return ruleStack[ruleStack.length - 1];
      };
      TreeBuilder.prototype.getPreviousExplicitRuleShortName = function () {
          var ruleStack = this.RULE_STACK;
          return ruleStack[ruleStack.length - 2];
      };
      TreeBuilder.prototype.getLastExplicitRuleOccurrenceIndex = function () {
          var occurrenceStack = this.RULE_OCCURRENCE_STACK;
          return occurrenceStack[occurrenceStack.length - 1];
      };
      return TreeBuilder;
  }());
  export { TreeBuilder };
  //# sourceMappingURL=tree_builder.js.map