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

78.63% Statements 92/117
76.92% Branches 10/13
66.66% Functions 8/12
78.63% Lines 92/117

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 114 115 116 117 1181x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 2177581x 2177581x 2177581x 2177581x 2177581x 2177581x 2177581x     2177581x 1x 1x 1868803x 1868803x 1868803x 1868803x 1868803x 1x 1x 15464489x 15464489x 1x 1x 28x 28x 1x 1x 1868803x 1868803x 1x 1x 1446692x 1446692x 1446692x 1446692x 1446692x 2099964x     2099964x 2099964x 2099964x 2099964x 2099964x 2099964x 1446692x 1446692x 1446692x 1446692x 1446692x 1446692x 1x 1x                 1x 1x 162038x 162038x 162038x 162038x 384566x     384566x 384566x 384566x 162038x 162038x 162038x 1x 1x               1x 1x     1x 1x     1x 1x 19296471x 19296471x 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,
  // number of tokens covered by node, kept here so ExpressionNode does not have to store it
  readonly tokenCount: number,
  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: TokenNode): Result {
    return Result.fromChain(this.tokens, this.tokenIndex + 1, {node, tokenCount: 1, previous: this.nodes}, this.nodeCount + 1);
  }
 
  public wrapConsumed(consumedTokens: number, node: ExpressionNode): Result {
    let current = this.nodes;
    let currentCount = this.nodeCount;
    let tokenCount = 0;
    const children: (ExpressionNode | TokenNode)[] = [];
    while (consumedTokens > 0) {
      if (current === undefined) {
        break;
      }
      children.push(current.node);
      consumedTokens = consumedTokens - current.tokenCount;
      tokenCount = tokenCount + current.tokenCount;
      current = current.previous;
      currentCount--;
    }
 
    node.setChildren(children.reverse());
    this.nodes = {node, tokenCount, 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, tokenCount: node.countTokens(), 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;
  }
 
}