All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.twineworks.tweakflow.lang.parse.builders.MatchPatternBuilder Maven / Gradle / Ivy

/*
 * The MIT License (MIT)
 *
 * Copyright (c) 2017 Twineworks GmbH
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

package com.twineworks.tweakflow.lang.parse.builders;

import com.twineworks.tweakflow.grammar.TweakFlowParser;
import com.twineworks.tweakflow.grammar.TweakFlowParserBaseVisitor;
import com.twineworks.tweakflow.lang.ast.expressions.StringNode;
import com.twineworks.tweakflow.lang.ast.structure.match.*;
import com.twineworks.tweakflow.lang.errors.LangError;
import com.twineworks.tweakflow.lang.errors.LangException;
import com.twineworks.tweakflow.lang.parse.units.ParseUnit;
import com.twineworks.tweakflow.lang.types.Types;
import org.antlr.v4.runtime.tree.ParseTree;

import java.util.ArrayList;
import java.util.List;

import static com.twineworks.tweakflow.lang.parse.util.CodeParseHelper.identifier;
import static com.twineworks.tweakflow.lang.parse.util.CodeParseHelper.srcOf;

public class MatchPatternBuilder extends TweakFlowParserBaseVisitor{

  private final ParseUnit parseUnit;

  public MatchPatternBuilder(ParseUnit parseUnit) {
    this.parseUnit = parseUnit;
  }

  @Override
  public MatchPatternNode visitExpPattern(TweakFlowParser.ExpPatternContext ctx) {
    ExpressionPatternNode patternNode = new ExpressionPatternNode();
    patternNode.setSourceInfo(srcOf(parseUnit, ctx));
    patternNode.setExpression(new ExpressionBuilder(parseUnit).visit(ctx.expression()));

    if (ctx.varCapture() != null){
      patternNode.setCapture(visitVarCapture(ctx.varCapture()));
    }

    return patternNode;
  }

  @Override
  public MatchPatternNode visitDataTypePattern(TweakFlowParser.DataTypePatternContext ctx) {
    DataTypePatternNode patternNode = new DataTypePatternNode();
    patternNode.setSourceInfo(srcOf(parseUnit, ctx));
    patternNode.setType(Types.byName(ctx.dataType().getText()));
    if (ctx.varCapture() != null){
      patternNode.setCapture(visitVarCapture(ctx.varCapture()));
    }
    return patternNode;
  }

  @Override
  public CapturePatternNode visitVarCapture(TweakFlowParser.VarCaptureContext ctx) {
    CapturePatternNode capturePatternNode = new CapturePatternNode();
    capturePatternNode.setSourceInfo(srcOf(parseUnit, ctx));
    if (ctx.identifier() != null){
      capturePatternNode.setSymbolName(identifier(ctx.identifier().getText()));
    }
    return capturePatternNode;
  }

  @Override
  public CapturePatternNode visitCapturePattern(TweakFlowParser.CapturePatternContext ctx) {
    CapturePatternNode capturePatternNode = new CapturePatternNode();
    capturePatternNode.setSourceInfo(srcOf(parseUnit, ctx));
    if (ctx.varCapture().identifier() != null){
      capturePatternNode.setSymbolName(identifier(ctx.varCapture().identifier().getText()));
    }
    return capturePatternNode;
  }

  @Override
  public CapturePatternNode visitSplatCapture(TweakFlowParser.SplatCaptureContext ctx) {
    CapturePatternNode capturePatternNode = new CapturePatternNode();
    capturePatternNode.setSourceInfo(srcOf(parseUnit, ctx));
    if (ctx.identifier() != null){
      capturePatternNode.setSymbolName(identifier(ctx.identifier().getText()));
    }
    return capturePatternNode;
  }

  @Override
  public MatchPatternNode visitListPattern(TweakFlowParser.ListPatternContext ctx) {
    ListPatternNode node = new ListPatternNode();
    node.setSourceInfo(srcOf(parseUnit, ctx));

    for (TweakFlowParser.MatchPatternContext pattern : ctx.matchPattern()) {
      node.getElements().add(visit(pattern));
    }

    if (ctx.varCapture() != null){
      node.setCapture(visitVarCapture(ctx.varCapture()));
    }

    return node;
  }

  @Override
  public MatchPatternNode visitHeadTailListPattern(TweakFlowParser.HeadTailListPatternContext ctx) {

    HeadTailListPatternNode node = new HeadTailListPatternNode();
    node.setSourceInfo(srcOf(parseUnit, ctx));

    for (TweakFlowParser.MatchPatternContext pattern : ctx.matchPattern()) {
      node.getElements().add(visit(pattern));
    }

    node.setTailCapture(visitSplatCapture(ctx.splatCapture()));

    if (ctx.varCapture() != null){
      node.setCapture(visitVarCapture(ctx.varCapture()));
    }

    return node;
  }

  @Override
  public MatchPatternNode visitInitLastListPattern(TweakFlowParser.InitLastListPatternContext ctx) {

    InitLastListPatternNode node = new InitLastListPatternNode();
    node.setSourceInfo(srcOf(parseUnit, ctx));

    for (TweakFlowParser.MatchPatternContext pattern : ctx.matchPattern()) {
      node.getElements().add(visit(pattern));
    }

    node.setInitCapture(visitSplatCapture(ctx.splatCapture()));

    if (ctx.varCapture() != null){
      node.setCapture(visitVarCapture(ctx.varCapture()));
    }

    return node;
  }

  @Override
  public MatchPatternNode visitMidListPattern(TweakFlowParser.MidListPatternContext ctx) {

    MidListPatternNode node = new MidListPatternNode();
    node.setSourceInfo(srcOf(parseUnit, ctx));

    ArrayList elements = node.getHeadElements();
    for (ParseTree child : ctx.children) {
      if (child instanceof TweakFlowParser.MatchPatternContext){
        elements.add(visit(child));
      }
      else if (child instanceof TweakFlowParser.SplatCaptureContext){
        node.setMidCapture(visitSplatCapture((TweakFlowParser.SplatCaptureContext) child));
        elements = node.getLastElements();
      }
    }

    if (ctx.varCapture() != null){
      node.setCapture(visitVarCapture(ctx.varCapture()));
    }

    return node;
  }

  @Override
  public MatchPatternNode visitOpenDictPattern(TweakFlowParser.OpenDictPatternContext ctx) {

    OpenDictPatternNode node = new OpenDictPatternNode();
    node.setSourceInfo(srcOf(parseUnit, ctx));
    ExpressionBuilder expressionBuilder = new ExpressionBuilder(parseUnit);

    List matchPattern = ctx.matchPattern();
    List keys = ctx.stringConstant();

    for (int i = 0; i < matchPattern.size(); i++) {
      TweakFlowParser.MatchPatternContext pattern = matchPattern.get(i);

      StringNode keyNode = (StringNode) expressionBuilder.visit(keys.get(i));
      String key = keyNode.getStringVal();
      if (node.getElements().containsKey(key)){
        throw new LangException(LangError.ALREADY_DEFINED, srcOf(parseUnit, keys.get(i)));
      }
      node.getElements().put(key, visit(pattern));
    }

    // exactly one rest capture allowed
    if (ctx.splatCapture().size() != 1){
      throw new LangException(LangError.ALREADY_DEFINED, srcOf(parseUnit, ctx.splatCapture(1)));
    }
    node.setRestCapture(visitSplatCapture(ctx.splatCapture(0)));


    if (ctx.varCapture() != null){
      node.setCapture(visitVarCapture(ctx.varCapture()));
    }

    return node;

  }

  @Override
  public MatchPatternNode visitDictPattern(TweakFlowParser.DictPatternContext ctx) {

    DictPatternNode node = new DictPatternNode();
    node.setSourceInfo(srcOf(parseUnit, ctx));
    ExpressionBuilder expressionBuilder = new ExpressionBuilder(parseUnit);

    List matchPattern = ctx.matchPattern();
    List keys = ctx.stringConstant();

    for (int i = 0; i < matchPattern.size(); i++) {
      TweakFlowParser.MatchPatternContext pattern = matchPattern.get(i);

      StringNode keyNode = (StringNode) expressionBuilder.visit(keys.get(i));
      String key = keyNode.getStringVal();

      if (node.getElements().containsKey(key)){
        throw new LangException(LangError.ALREADY_DEFINED, srcOf(parseUnit, keys.get(i)));
      }
      node.getElements().put(key, visit(pattern));
    }

    if (ctx.varCapture() != null){
      node.setCapture(visitVarCapture(ctx.varCapture()));
    }

    return node;
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy