All files / src/abap/2_statements result.ts

77.87% Statements 88/113
76.92% Branches 10/13
66.66% Functions 8/12
77.87% Lines 88/113

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 1141x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 652298x 652298x 652298x 652298x 652298x 652298x 652298x     652298x 1x 1x 573730x 573730x 573730x 573730x 573730x 1x 1x 9616918x 9616918x 1x 1x 24x 24x 1x 1x 573730x 573730x 1x 1x 545061x 545061x 545061x 545061x 786979x     786979x 786979x 786979x 786979x 786979x 545061x 545061x 545061x 545061x 545061x 545061x 1x 1x                 1x 1x 31194x 31194x 31194x 31194x 88621x     88621x 88621x 88621x 31194x 31194x 31194x 1x 1x               1x 1x     1x 1x     1x 1x 11089946x 11089946x 1x 1x  
import {AbstractToken} from "../1_lexer/tokens/abstract_token";
import {ExpressionNode} from "../nodes/expression_node";
import {TokenNode} from "../nodes/token_node";
 
type ResultNode = {
  readonly node: ExpressionNode | TokenNode,
  readonly previous: ResultNode | undefined,
};
 
export class Result {
  private readonly tokens: readonly AbstractToken[];
  private readonly tokenIndex: number;
  private nodes: ResultNode | undefined;
  private nodeCount: number;
 
  public constructor(tokens: readonly AbstractToken[], tokenIndex: number, nodes?: (ExpressionNode | TokenNode)[]) {
// tokens: all tokens, from the tokenIndex = not yet matched
// nodes: matched tokens
    this.tokens = tokens;
    this.tokenIndex = tokenIndex;
    this.nodeCount = 0;
 
    if (nodes !== undefined) {
      this.setNodes(nodes);
    }
  }
 
  private static fromChain(tokens: readonly AbstractToken[], tokenIndex: number, nodes: ResultNode | undefined, nodeCount: number): Result {
    const ret = new Result(tokens, tokenIndex);
    ret.nodes = nodes;
    ret.nodeCount = nodeCount;
    return ret;
  }
 
  public peek(): AbstractToken {
    return this.tokens[this.tokenIndex];
  }
 
  public peekAt(offset: number): AbstractToken | undefined {
    return this.tokens[this.tokenIndex + offset];
  }
 
  public shift(node: ExpressionNode | TokenNode): Result {
    return Result.fromChain(this.tokens, this.tokenIndex + 1, {node, previous: this.nodes}, this.nodeCount + 1);
  }
 
  public wrapConsumed(consumedTokens: number, node: ExpressionNode): Result {
    let current = this.nodes;
    let currentCount = this.nodeCount;
    const children: (ExpressionNode | TokenNode)[] = [];
    while (consumedTokens > 0) {
      if (current === undefined) {
        break;
      }
      children.push(current.node);
      consumedTokens = consumedTokens - current.node.countTokens();
      current = current.previous;
      currentCount--;
    }
 
    node.setChildren(children.reverse());
    this.nodes = {node, previous: current};
    this.nodeCount = currentCount + 1;
    return this;
  }
 
  public popNode(): ExpressionNode | TokenNode | undefined {
    if (this.nodes === undefined) {
      return undefined;
    }
    const ret = this.nodes.node;
    this.nodes = this.nodes.previous;
    this.nodeCount--;
    return ret;
  }
 
  public getNodes(): (ExpressionNode | TokenNode)[] {
    const ret = new Array<ExpressionNode | TokenNode>(this.nodeCount);
    let current = this.nodes;
 
    for (let index = this.nodeCount - 1; index >= 0; index--) {
      if (current === undefined) {
        break;
      }
      ret[index] = current.node;
      current = current.previous;
    }
 
    return ret;
  }
 
  public setNodes(n: (ExpressionNode | TokenNode)[]): void {
    this.nodes = undefined;
    this.nodeCount = 0;
    for (const node of n) {
      this.nodes = {node, previous: this.nodes};
      this.nodeCount++;
    }
  }
 
  public getTokens(): readonly AbstractToken[] {
    return this.tokens;
  }
 
  public getTokenIndex(): number {
    return this.tokenIndex;
  }
 
  public remainingLength(): number {
    return this.tokens.length - this.tokenIndex;
  }
 
}