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

com.squarespace.template.TokenMatcher Maven / Gradle / Ivy

There is a newer version: 2.10.0
Show newest version
/**
 * Copyright (c) 2014 SQUARESPACE, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.squarespace.template;

import com.squarespace.compiler.match.Recognizers.Recognizer;


/**
 * Incremental pattern matcher.
 */
public class TokenMatcher {

  private final String raw;

  /** Start as set by region() */
  private int start = -1;

  /** Start of the most recent match. */
  private int matchStart = -1;

  /** End of the most recent match. */
  private int matchEnd = -1;

  /** Pointer to the character range of potential matches */
  private int pointer = -1;

  /** End of the character range of potential matches */
  private int end = -1;

  private boolean matched;

  public TokenMatcher(final String raw) {
    this.raw = raw;
    region(0, raw.length());
  }

  /**
   * Set the region of the potential matches.
   */
  public TokenMatcher region(int start, int end) {
    this.start = start;
    this.pointer = start;
    this.end = end;
    return this;
  }

  /**
   * Return a view of the remainder of the potential character range. Useful when
   * a match fails to report it, e.g. "expected FOO found 'BAR'".
   */
  public StringView remainder() {
    return new StringView(raw, pointer, end);
  }

  /**
   * Consume the matched range, returning a token containing all the characters matched.
   * Move the match pointer past the matched range.
   */
  public StringView consume() {
    StringView tok = new StringView(raw, matchStart, matchEnd);
    pointer = matchEnd;
    return tok;
  }

  /**
   * Skip a token rather than consume it.
   */
  public void skip() {
    pointer = matchEnd;
  }

  /**
   * Once we're done matching we can assert that we've consumed the entire input range.
   */
  public boolean finished() {
    return pointer == end;
  }

  /**
   * Index of the start of the most recent match.
   */
  public int matchStart() {
    return matchStart;
  }

  /**
   * Index of the end of the most recent match.
   */
  public int matchEnd() {
    return matchEnd;
  }

  /**
   * Index of the pointer to the next character in the remainder of the input range.
   */
  public int pointer() {
    return pointer;
  }

  public int start() {
    return start;
  }

  /**
   * Index of the end of the input range.
   */
  public int end() {
    return end;
  }

  public boolean arguments() {
    return match(Patterns.ARGUMENTS);
  }

  public boolean equalsign() {
    return match('=');
  }

  public boolean formatter() {
    return match(Patterns.FORMATTER);
  }

  public boolean keyword() {
    return match(Patterns.RESERVED_WORD);
  }

  public boolean localVariable() {
    return match(Patterns.VARIABLE_DEFINITION);
  }

  public boolean operator() {
    return match(Patterns.BOOLEAN_OP);
  }

  public boolean path() {
    return match(Patterns.PATH);
  }

  public boolean pipe() {
    return match('|');
  }

  public boolean predicate() {
    return match(Patterns.PREDICATE);
  }

  public boolean predicateArgs() {
    return match(Patterns.PREDICATE_ARGUMENTS);
  }

  public boolean space() {
    return match(' ');
  }

  public boolean variable() {
    return match(Patterns.VARIABLE_REF_DOTTED);
  }

  public boolean variablesDelimiter() {
    return match(Patterns.VARIABLES_DELIMITER);
  }

  public boolean whitespace() {
    return match(Patterns.WHITESPACE);
  }

  public boolean word() {
    return match(Patterns.WORD);
  }

  public boolean wordSection() {
    return match(Patterns.KEYWORD_SECTION);
  }

  public boolean wordWith() {
    return match(Patterns.KEYWORD_WITH);
  }

  public boolean peek(int skip, char ch) {
    int p = pointer + skip;
    return p < end ? raw.charAt(p) == ch : false;
  }

  public void seek(int n) {
    pointer += n;
  }

  /**
   * Perform a match using a Recognizer pattern and, if successful,
   * set the match range.
   */
  private boolean match(Recognizer pattern) {
    int pos = pattern.match(raw, pointer, end);
    if (pos > pointer) {
      matchStart = pointer;
      matchEnd = pos;
      return true;
    }
    return false;
  }

  /**
   * Perform a match of a single character and, if successful, set the match range.
   */
  private boolean match(char ch) {
    if (pointer == end) {
      return false;
    }
    matched = raw.charAt(pointer) == ch;
    if (matched) {
      matchStart = pointer;
      matchEnd = pointer + 1;
    }
    return matched;
  }


}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy