Package com.lastcalc.parsers

Source Code of com.lastcalc.parsers.PreParser

/*******************************************************************************
* LastCalc - The last calculator you'll ever need
* Copyright (C) 2011, 2012 Uprizer Labs LLC
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE.  See the GNU Affero General Public License for more
* details.
******************************************************************************/
package com.lastcalc.parsers;

import java.io.PrintStream;
import java.io.Serializable;
import java.util.*;

import com.google.common.collect.*;

import com.lastcalc.TokenList;
import com.lastcalc.parsers.Parser.ParseResult;


public class PreParser extends Parser {
  public static PreParser singleton = new PreParser();

  private static final long serialVersionUID = 3705611710430408505L;

  private static TokenList template;

  public static Set<String> open = Sets.newHashSet("(", "{", "[");

  public static Set<String> close = Sets.newHashSet(")", "}", "]");

  public static Set<String> reserved = Sets.newHashSet(",", ":", "...", "ans");

  static {
    reserved.addAll(open);
    reserved.addAll(close);
    final ArrayList<Object> tpl = Lists.newArrayList();
    tpl.add(Lists.<Object> newArrayList(close));
    template = new TokenList.SimpleTokenList(tpl);
  }

  public static TokenList flatten(final TokenList input) {
    boolean willFlatten = false;
    for (final Object o : input) {
      if (o instanceof TokenList) {
        willFlatten = true;
        break;
      }
      if (o instanceof List) {
        willFlatten = true;
        break;
      }
      if (o instanceof Map) {
        willFlatten = true;
        break;
      }
      if (o instanceof ListWithTail || o instanceof MapWithTail) {
        willFlatten = true;
        break;
      }
    }
    if (!willFlatten)
      return input;

    final List<Object> ret = Lists.newArrayListWithCapacity(input.size() * 4);

    flattenTo(input, ret);

    return TokenList.create(ret);
  }

  private static void flattenTo(final Object obj, final List<Object> output) {
    if (obj instanceof TokenList) {
      final TokenList sts = (TokenList) obj;
      if (sts.size() == 1) {
        flattenTo(sts.get(0), output);
      } else {
        for (final Object o : sts) {
          flattenTo(o, output);
        }
      }
    } else if (obj instanceof List) {
      final List<Object> list = (List<Object>) obj;

      output.add("[");
      for (final Object lo : list) {
        flattenTo(lo, output);
        output.add(",");
      }
      if (list.isEmpty()) {
        output.add("]");
      } else {
        // Overwrite last ","
        output.set(output.size() - 1, "]");
      }
    } else if (obj instanceof Map) {
      final Map<Object, Object> map = (Map<Object, Object>) obj;

      output.add("{");
      for (final Map.Entry<Object, Object> e : map.entrySet()) {
        flattenTo(e.getKey(), output);
        output.add(":");
        flattenTo(e.getValue(), output);
        output.add(",");
      }
      if (map.isEmpty()) {
        output.add("}");
      } else {
        output.set(output.size() - 1, "}");
      }
    } else if (obj instanceof ListWithTail) {
      final ListWithTail lwt = (ListWithTail) obj;
      output.add("[");
      for (final Object lo : lwt.list) {
        flattenTo(lo, output);
        output.add(",");
      }
      output.set(output.size() - 1, "...");
      flattenTo(lwt.tail, output);
      output.add("]");
    } else if (obj instanceof MapWithTail) {
      final MapWithTail mwt = (MapWithTail) obj;

      output.add("{");
      for (final Map.Entry<Object, Object> e : mwt.map.entrySet()) {
        flattenTo(e.getKey(), output);
        output.add(":");
        flattenTo(e.getValue(), output);
        output.add(",");
      }
      output.set(output.size() - 1, "...");
      flattenTo(mwt.tail, output);
      output.add("}");
    } else {
      output.add(obj);
    }
  }

  public static int findEdgeOrObjectBackwards(final TokenList orig, final int startPos, final Object obj) {
    int depth = 0;
    for (int x = startPos-1;; x--) {
      if (x == -1)
        return 0;
      final Object tx = orig.get(x);
      if (depth == 0 && tx.equals(obj))
        return x;
      else if (close.contains(tx)) {
        depth++;
      } else if (open.contains(tx)) {
        if (depth == 0)
          return x+1;
        else {
          depth--;
        }
      } else if (reserved.contains(tx) && depth == 0)
        return x+1;
    }
  }

  public static int findEdgeOrObjectForwards(final TokenList orig, final int startPos, final Object obj) {
    int depth = 0;
    for (int x = startPos + 1;; x++) {
      if (x >= orig.size())
        return orig.size() - 1;
      final Object tx = orig.get(x);
      if (depth == 0 && tx.equals(obj))
        return x;
      else if (open.contains(tx)) {
        depth++;
      } else if (close.contains(tx)) {
        if (depth == 0)
          return x - 1;
        else {
          depth--;
        }
      } else if (reserved.contains(tx) && depth == 0)
        return x - 1;
    }
  }

  public static TokenList enclosedByStructure(final TokenList orig, final int pos) {
    int startPos;
    for (startPos = pos; startPos > -1 && !reserved.contains(orig.get(startPos)); startPos--) {

    }
    startPos++;
    int endPos;
    for (endPos = pos; endPos < orig.size() && !reserved.contains(orig.get(endPos)); endPos++) {

    }
    return orig.subList(startPos, endPos);
  }

  @Override
  public TokenList getTemplate() {
    return template;
  }

  @Override
  public ParseResult parse(final TokenList tokens, final int templatePos, final ParserContext context) {
    if (tokens.get(templatePos).equals(")")) {
      if (tokens.get(templatePos - 2).equals("(") && !reserved.contains(tokens.get(templatePos - 1)))
        return ParseResult.success(tokens.replaceWithTokens(templatePos - 2, templatePos + 1,
            tokens.get(templatePos - 1)));
      else
        return ParseResult.fail();
    } else if (tokens.get(templatePos).equals("]")) {
      // Is there a tail
      int pos = templatePos;
      Object tail = null;
      if (tokens.get(templatePos - 1).equals("[")) {
        pos--;
      } else if (tokens.get(templatePos - 2).equals("...")) {
        tail = tokens.get(templatePos - 1);
        pos -= 2;
      }
      final LinkedList<Object> list = Lists.newLinkedList();
      while (true) {
        final Object posToken = tokens.get(pos);
        if (posToken.equals("[")) {
          break;
        }
        if (!posToken.equals(",") && !posToken.equals("...") && !posToken.equals("]"))
          return ParseResult.fail();
        if (reserved.contains(tokens.get(pos - 1)))
          return ParseResult.fail();
        list.addFirst(tokens.get(pos - 1));
        pos -= 2;
      }
      if (tail == null)
        return ParseResult.success(tokens.replaceWithTokens(pos, templatePos + 1, list));
      else if (tail instanceof Collection) {
        list.addAll((Collection<Object>) tail);
        return ParseResult.success(tokens.replaceWithTokens(pos, templatePos + 1, list));
      } else
        return ParseResult
            .success(tokens.replaceWithTokens(pos, templatePos + 1, new ListWithTail(list, tail)));
    } else if (tokens.get(templatePos).equals("}")) {
      // find start of map declaration
      int startBracket = templatePos - 1;
      while (true) {
        final Object tokenPos = tokens.get(startBracket);
        if (tokenPos.equals("{")) {
          break;
        }
        if (startBracket == 0)
          return ParseResult.fail();
        if (tokenPos.equals("{") || tokenPos.equals("[") || tokenPos.equals("]"))
          return ParseResult.fail();

        startBracket--;
      }

      int pos = startBracket;

      final Map<Object, Object> map = Maps.newLinkedHashMap();
      Object tail = null;
      if (startBracket < templatePos - 1) { // Handle empty map ie. {}
        while (pos < templatePos) {
          final Object posToken = tokens.get(pos);
          if (posToken.equals("{") || posToken.equals(",")) {
            final Object key = tokens.get(pos + 1);
            if (key instanceof String && reserved.contains(key))
              return ParseResult.fail();
            if (!tokens.get(pos + 2).equals(":"))
              return ParseResult.fail();
            final Object value = tokens.get(pos + 3);
            if (value instanceof String && reserved.contains(value))
              return ParseResult.fail();
            map.put(key, value);
          } else if (posToken.equals("...") && pos == templatePos - 2) {
            tail = tokens.get(pos + 1);
          } else
            return ParseResult.fail();
          pos += 4;
        }
      }
      if (tail == null)
        return ParseResult.success(tokens.replaceWithTokens(startBracket, templatePos + 1, map));
      else if (tail instanceof Map) {
        map.putAll((Map<Object, Object>) tail);
        return ParseResult.success(tokens.replaceWithTokens(startBracket, templatePos + 1, map));
      } else
        return ParseResult.success(tokens.replaceWithTokens(startBracket, templatePos + 1, new MapWithTail(map,
            tail)));

    }
    else if(tokens.get(templatePos).equals("ans"))
    {
      return ParseResult.success(tokens.replaceWithTokens(templatePos, templatePos, new Integer(1)));
    }
    return ParseResult.fail();
  }

  @Override
  public String toString() {
    return "";
  }

  @Override
  public int hashCode() {
    return "BracketsParser".hashCode();
  }

  @Override
  public boolean equals(final Object obj) {
    return obj instanceof PreParser;
  }

  public static class ListWithTail implements Serializable {
    private static final long serialVersionUID = -529889868305161556L;

    public final List<Object> list;

    public final Object tail;

    public ListWithTail(final List<Object> list, final Object tail) {
      this.list = list;
      this.tail = tail;
    }

    @Override
    public String toString() {
      final StringBuilder builder = new StringBuilder();
      builder.append("ListWithTail [list=");
      builder.append(list);
      builder.append(", tail=");
      builder.append(tail);
      builder.append("]");
      return builder.toString();
    }

    @Override
    public int hashCode() {
      final int prime = 31;
      int result = 1;
      result = prime * result + ((list == null) ? 0 : list.hashCode());
      result = prime * result + ((tail == null) ? 0 : tail.hashCode());
      return result;
    }

    @Override
    public boolean equals(final Object obj) {
      if (this == obj)
        return true;
      if (obj == null)
        return false;
      if (!(obj instanceof ListWithTail))
        return false;
      final ListWithTail other = (ListWithTail) obj;
      if (list == null) {
        if (other.list != null)
          return false;
      } else if (!list.equals(other.list))
        return false;
      if (tail == null) {
        if (other.tail != null)
          return false;
      } else if (!tail.equals(other.tail))
        return false;
      return true;
    }

  }

  public static class MapWithTail implements Serializable {
    private static final long serialVersionUID = -3556614307132116724L;

    public final Map<Object, Object> map;

    public final Object tail;

    public MapWithTail(final Map<Object, Object> map, final Object tail) {
      this.map = map;
      this.tail = tail;
    }

    @Override
    public String toString() {
      final StringBuilder builder = new StringBuilder();
      builder.append("MapWithTail [map=");
      builder.append(map);
      builder.append(", tail=");
      builder.append(tail);
      builder.append("]");
      return builder.toString();
    }

    @Override
    public int hashCode() {
      final int prime = 31;
      int result = 1;
      result = prime * result + ((map == null) ? 0 : map.hashCode());
      result = prime * result + ((tail == null) ? 0 : tail.hashCode());
      return result;
    }

    @Override
    public boolean equals(final Object obj) {
      if (this == obj)
        return true;
      if (obj == null)
        return false;
      if (!(obj instanceof MapWithTail))
        return false;
      final MapWithTail other = (MapWithTail) obj;
      if (map == null) {
        if (other.map != null)
          return false;
      } else if (!map.equals(other.map))
        return false;
      if (tail == null) {
        if (other.tail != null)
          return false;
      } else if (!tail.equals(other.tail))
        return false;
      return true;
    }

  }
}
TOP

Related Classes of com.lastcalc.parsers.PreParser

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.