blob: defd32a68f1463fba54a0301b9e2ccfce54ceccd [file] [log] [blame]
/*=============================================================================#
# Copyright (c) 2020 Stephan Wahlbrink and others.
#
# This program and the accompanying materials are made available under the
# terms of the Eclipse Public License 2.0 which is available at
# https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
# which is available at https://www.apache.org/licenses/LICENSE-2.0.
#
# SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
#
# Contributors:
# Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
#=============================================================================*/
package org.eclipse.statet.r.core.rsource.ast;
import static org.junit.jupiter.api.Assertions.assertEquals;
import java.util.List;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
import org.eclipse.statet.jcommons.collections.ImCollections;
import org.eclipse.statet.jcommons.lang.NonNullByDefault;
import org.eclipse.statet.jcommons.lang.Nullable;
import org.eclipse.statet.jcommons.text.core.input.StringParserInput;
import org.eclipse.statet.ltk.model.core.ModelManager;
import org.eclipse.statet.r.core.rlang.RTerminal;
@NonNullByDefault
public class RScannerBasicTest {
public static class NodeDescr {
final NodeType type;
final @Nullable RTerminal op0;
public NodeDescr(final NodeType type, final @Nullable RTerminal op) {
this.type= type;
this.op0= op;
}
@Override
public String toString() {
return this.type + " ยป " + ((this.op0 != null) ? this.op0.name() : "");
}
}
static final NodeDescr SYMBOL= new NodeDescr(NodeType.SYMBOL, null);
static final NodeDescr MULT_MULT= new NodeDescr(NodeType.MULT, RTerminal.MULT);
static final NodeDescr MULT_DIV= new NodeDescr(NodeType.MULT, RTerminal.DIV);
static final NodeDescr ADD_PLUS= new NodeDescr(NodeType.ADD, RTerminal.PLUS);
static final NodeDescr ADD_MINUS= new NodeDescr(NodeType.ADD, RTerminal.MINUS);
static List<NodeDescr> commonOps() {
return ImCollections.newList(
ADD_PLUS, ADD_MINUS,
MULT_MULT, MULT_DIV );
}
static final NodeDescr HELP_QUESTIONMARK= new NodeDescr(NodeType.HELP, RTerminal.QUESTIONMARK);
static final NodeDescr ASSIGN_LEFT_S= new NodeDescr(NodeType.A_LEFT, RTerminal.ARROW_LEFT_S);
static final NodeDescr ASSIGN_LEFT_D= new NodeDescr(NodeType.A_LEFT, RTerminal.ARROW_LEFT_D);
static final NodeDescr ASSIGN_RIGHT_S= new NodeDescr(NodeType.A_RIGHT, RTerminal.ARROW_RIGHT_S);
static final NodeDescr ASSIGN_RIGHT_D= new NodeDescr(NodeType.A_RIGHT, RTerminal.ARROW_RIGHT_D);
static final NodeDescr ASSIGN_EQUALS= new NodeDescr(NodeType.A_EQUALS, RTerminal.EQUAL);
static List<NodeDescr> assignOps() {
return ImCollections.newList(
ASSIGN_LEFT_S, ASSIGN_LEFT_D,
ASSIGN_RIGHT_S, ASSIGN_RIGHT_S,
ASSIGN_EQUALS );
}
private final RScanner scanner= new RScanner(ModelManager.MODEL_FILE);
private final StringParserInput input= new StringParserInput();
public RScannerBasicTest() {
}
@Test
public void ADD() {
RAstNode expr0;
expr0= assertExpr("x + y", 0, 5, ADD_PLUS);
assertNode(expr0, new int[] { 0 }, 0, 1, SYMBOL);
assertNode(expr0, new int[] { 1 }, 4, 5, SYMBOL);
expr0= assertExpr("x - y", 0, 5, ADD_MINUS);
assertNode(expr0, new int[] { 0 }, 0, 1, SYMBOL);
assertNode(expr0, new int[] { 1 }, 4, 5, SYMBOL);
expr0= assertExpr("x + y + z", 0, 9, ADD_PLUS);
assertNode(expr0, new int[] { 0 }, 0, 5, ADD_PLUS);
assertNode(expr0, new int[] { 0, 0 }, 0, 1, SYMBOL);
assertNode(expr0, new int[] { 0, 1 }, 4, 5, SYMBOL);
assertNode(expr0, new int[] { 1 }, 8, 9, SYMBOL);
expr0= assertExpr("x + y - z", 0, 9, ADD_MINUS);
assertNode(expr0, new int[] { 0 }, 0, 5, ADD_PLUS);
assertNode(expr0, new int[] { 0, 0 }, 0, 1, SYMBOL);
assertNode(expr0, new int[] { 0, 1 }, 4, 5, SYMBOL);
assertNode(expr0, new int[] { 1 }, 8, 9, SYMBOL);
expr0= assertExpr("x - y - z", 0, 9, ADD_MINUS);
assertNode(expr0, new int[] { 0 }, 0, 5, ADD_MINUS);
assertNode(expr0, new int[] { 0, 0 }, 0, 1, SYMBOL);
assertNode(expr0, new int[] { 0, 1 }, 4, 5, SYMBOL);
assertNode(expr0, new int[] { 1 }, 8, 9, SYMBOL);
expr0= assertExpr("x - y + z", 0, 9, ADD_PLUS);
assertNode(expr0, new int[] { 0 }, 0, 5, ADD_MINUS);
assertNode(expr0, new int[] { 0, 0 }, 0, 1, SYMBOL);
assertNode(expr0, new int[] { 0, 1 }, 4, 5, SYMBOL);
assertNode(expr0, new int[] { 1 }, 8, 9, SYMBOL);
assertTwoOps_differentPrio(ADD_PLUS, MULT_MULT);
assertTwoOps_differentPrio(ADD_PLUS, MULT_DIV);
assertTwoOps_differentPrio(ADD_MINUS, MULT_MULT);
assertTwoOps_differentPrio(ADD_MINUS, MULT_DIV);
}
@Test
public void HELP() {
RAstNode expr0;
expr0= assertExpr("? y", 0, 3, HELP_QUESTIONMARK);
assertEquals(1, expr0.getChildCount());
assertNode(expr0, new int[] { 0 }, 2, 3, SYMBOL);
expr0= assertExpr("? y + z", 0, 7, HELP_QUESTIONMARK);
assertEquals(1, expr0.getChildCount());
assertNode(expr0, new int[] { 0 }, 2, 7, ADD_PLUS);
assertNode(expr0, new int[] { 0, 0 }, 2, 3, SYMBOL);
assertNode(expr0, new int[] { 0, 1 }, 6, 7, SYMBOL);
expr0= assertExpr("x ? y", 0, 5, HELP_QUESTIONMARK);
assertEquals(2, expr0.getChildCount());
assertNode(expr0, new int[] { 0 }, 0, 1, SYMBOL);
assertNode(expr0, new int[] { 1 }, 4, 5, SYMBOL);
}
@ParameterizedTest
@MethodSource("commonOps")
public void HELP_commonOps(final NodeDescr opDescr) {
assertTwoOps_differentPrio(HELP_QUESTIONMARK, opDescr);
}
@ParameterizedTest
@MethodSource("assignOps")
public void HELP_assignOps(final NodeDescr opDescr) {
assertTwoOps_differentPrio(HELP_QUESTIONMARK, opDescr);
}
@ParameterizedTest
@MethodSource("commonOps")
public void ASSIGN_commonOps(final NodeDescr opDescr) {
assertTwoOps_differentPrio(ASSIGN_LEFT_S, opDescr);
assertTwoOps_differentPrio(ASSIGN_LEFT_D, opDescr);
assertTwoOps_differentPrio(ASSIGN_RIGHT_S, opDescr);
assertTwoOps_differentPrio(ASSIGN_RIGHT_D, opDescr);
assertTwoOps_differentPrio(ASSIGN_EQUALS, opDescr);
}
private void assertNode(final RAstNode node, final String nodeLabel,
final int startOffset, final int endOffset,
final NodeDescr nodeDescr) {
assertEquals(nodeDescr.type, node.getNodeType(), nodeLabel + ".nodeType");
assertEquals(startOffset, node.getStartOffset(), nodeLabel + ".startOffset");
assertEquals(endOffset, node.getEndOffset(), nodeLabel + ".endOffset");
assertEquals(nodeDescr.op0, node.getOperator(0), nodeLabel + ".operator[0]");
}
private RAstNode assertExpr(final String code,
final int startOffset, final int endOffset,
final NodeDescr node0Descr) {
final SourceComponent root= this.scanner.scanSourceRange(this.input.reset(code).init(),
null, false );
assertEquals(1, root.getChildCount());
assertEquals(startOffset, root.getStartOffset(), "root.startOffset");
assertEquals(endOffset, root.getEndOffset(), "root.endOffset");
final RAstNode expr0= root.getChild(0);
assertNode(expr0, "expr[0]", startOffset, endOffset, node0Descr);
return expr0;
}
private void assertTwoOps_differentPrio(final NodeDescr lowDescr, final NodeDescr highDescr) {
RAstNode expr0;
final String ls= lowDescr.op0.text;
final int ll= lowDescr.op0.text.length();
final String hs= highDescr.op0.text;
final int hl= highDescr.op0.text.length();
expr0= assertExpr("r " + ls + " x " + hs + " y",
0, 7 + ll + hl, lowDescr);
assertNode(expr0, new int[] { 0 }, 0, 1, SYMBOL);
assertNode(expr0, new int[] { 1 }, 3 + ll, 7 + ll + hl, highDescr);
assertNode(expr0, new int[] { 1, 0 }, 3 + ll, 4 + ll, SYMBOL);
assertNode(expr0, new int[] { 1, 1 }, 6 + ll + hl, 7 + ll + hl, SYMBOL);
expr0= assertExpr("r " + ls + " x " + hs + " y[z]",
0, 10 + ll + hl, lowDescr);
assertNode(expr0, new int[] { 0 }, 0, 1, SYMBOL);
assertNode(expr0, new int[] { 1 }, 3 + ll, 10 + ll + hl, highDescr);
expr0= assertExpr("r " + ls + " x[y] " + hs + " z",
0, 10 + ll + hl, lowDescr);
assertNode(expr0, new int[] { 0 }, 0, 1, SYMBOL);
assertNode(expr0, new int[] { 1 }, 3 + ll, 10 + ll + hl, highDescr);
expr0= assertExpr("r " + hs + " s " + ls + " x",
0, 7 + hl + ll, lowDescr);
assertNode(expr0, new int[] { 0 }, 0, 4 + hl, highDescr);
assertNode(expr0, new int[] { 0, 0 }, 0, 1, SYMBOL);
assertNode(expr0, new int[] { 0, 1 }, 3 + hl, 4 + hl, SYMBOL);
assertNode(expr0, new int[] { 1 }, 6 + hl + ll, 7 + hl + ll, SYMBOL);
expr0= assertExpr("r " + hs + " s[t] " + ls + " x",
0, 10 + hl + ll, lowDescr);
assertNode(expr0, new int[] { 0 }, 0, 7 + hl, highDescr);
assertNode(expr0, new int[] { 1 }, 9 + hl + ll, 10 + hl + ll, SYMBOL);
}
private void assertNode(final RAstNode expr0, final int[] nodeIndex,
final int startOffset, final int endOffset,
final NodeDescr nodeDescr) {
RAstNode node= expr0;
final StringBuilder sb= new StringBuilder("expr[0]");
for (int i= 0; i < nodeIndex.length; i++) {
node= node.getChild(nodeIndex[i]);
sb.append('[');
sb.append(nodeIndex[i]);
sb.append(']');
}
assertNode(node, sb.toString(), startOffset, endOffset, nodeDescr);
}
}