Package com.lastcalc

Source Code of com.lastcalc.SequentialParser

/*******************************************************************************
* 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;

import java.io.*;
import java.util.*;
import java.util.logging.Logger;

import com.google.common.collect.*;

import org.jscience.mathematics.number.Number;
import org.jscience.physics.amount.Amount;

import com.google.appengine.api.utils.SystemProperty;
import com.lastcalc.bootstrap.Bootstrap;
import com.lastcalc.engines.*;
import com.lastcalc.parsers.*;
import com.lastcalc.parsers.UserDefinedParserParser.UserDefinedParser;
import com.lastcalc.parsers.bool.IfThenElse;

public class SequentialParser implements Serializable {
  private static final Logger log = Logger.getLogger(Bootstrap.class.getName());

  public static final Set<String> recognizedWords = Sets.newHashSet();
  public static ParserPickerFactory globalParserPickerFactory;
  private static final FixedOrderParserPickerFactory priorityParsers = new FixedOrderParserPickerFactory();
  private static final FixedOrderParserPickerFactory lowPriorityParsers = new FixedOrderParserPickerFactory();

  static {
    final LinkedList<Parser> allParsers = Lists.newLinkedList();
    com.lastcalc.parsers.Parser.getAll(allParsers);
    for (final Parser p : allParsers) {
      for (final Object i : p.getTemplate()) {
        if (i instanceof String) {
          recognizedWords.add((String) i);
        }
      }
    }
    recognizedWords.add("ans");
    // globalParserPickerFactory = new
    // RecentFirstParserPickerFactory(allParsers);
    globalParserPickerFactory = new KeywordParserPickerFactory(allParsers);

    // Recompute worksheet
    // The first thing we do is parse any datastructures like lists or maps
    priorityParsers.addParser(new PreParser());
    priorityParsers.addParser(new IfThenElse());
    priorityParsers.addParser(new UserDefinedParserParser());

    lowPriorityParsers.addParser(new ToLowerCase());

    try {
      final BufferedReader br = new BufferedReader(new InputStreamReader(
          Bootstrap.class.getResourceAsStream("bootstrap.txt")));
      final SequentialParser parser = SequentialParser.create();
      int lineNo = 1;
      while (true) {
        String next = br.readLine();
        if (next == null) {
          break;
        }
        next = next.trim();
        if (next.length() == 0 || next.startsWith("#")) {
          continue;
        }
        final TokenList parsed = parser.parseNext(next);
        if (parsed.size() != 1 || !(parsed.get(0) instanceof UserDefinedParser)) {
          log.warning("Failed to parse line " + lineNo + " as UserDefinedParserParser (" + next + " -> "
              + parsed + ")");
        } else {
          globalParserPickerFactory.addParser((UserDefinedParser) parsed.get(0));
        }
        lineNo++;
      }
      br.close();

    } catch (final Exception e) {
      log.warning("Exception while loading boostrap parsers: " + e);
      e.printStackTrace();
    }
  }

  public static SequentialParser create() {
    final long timeout = SystemProperty.environment.value() == SystemProperty.Environment.Value.Production ? 2000
        : 2000;
    return new SequentialParser(priorityParsers, globalParserPickerFactory, lowPriorityParsers, timeout);
  }

  public static SequentialParser create(final ParserContext pc) {
    final long timeout = SystemProperty.environment.value() == SystemProperty.Environment.Value.Production ? 2000
        : 2000;
    return new SequentialParser(priorityParsers, globalParserPickerFactory, lowPriorityParsers, timeout, pc);
  }

  private static final long serialVersionUID = 3602019924032548636L;
  private final KeywordParserPickerFactory userDefinedParsers;
  private final BacktrackingParseEngine parseEngine;
  private final ParserContext context;
  private final Map<String, Integer> userDefinedKeywords = Maps.newConcurrentMap();
  private int pos;

  private TokenList previousAnswer = null;

  private int lastParseStepCount;

  public SequentialParser(final ParserPickerFactory priorityParsers, final ParserPickerFactory allParsers,
      final ParserPickerFactory lowPriorityParsers,
      final long timeout) {
    userDefinedParsers = new KeywordParserPickerFactory();
    final CombinedParserPickerFactory ppf = new CombinedParserPickerFactory(priorityParsers, userDefinedParsers,
        allParsers, lowPriorityParsers);
    parseEngine = new BacktrackingParseEngine(ppf);
    context = new ParserContext(parseEngine, timeout);
  }

  public SequentialParser(final ParserPickerFactory priorityParsers, final ParserPickerFactory allParsers,
      final ParserPickerFactory lowPriorityParsers,
      final long timeout, final ParserContext context) {

    userDefinedParsers = new KeywordParserPickerFactory();
    final CombinedParserPickerFactory ppf = new CombinedParserPickerFactory(priorityParsers, userDefinedParsers,
        allParsers, lowPriorityParsers);
    parseEngine = new BacktrackingParseEngine(ppf);
    this.context = context;
  }

  public TokenList parseNext(final String question) {
    return parseNext(Tokenizer.tokenize(question));
  }

  public TokenList parseNext(TokenList question) {
    TokenList answer = null;
   
    if(previousAnswer!=null){
      for(int i=0;i<question.size();i++){
        if(question.get(i).equals("ans")){
          question=question.replaceWithTokenList(i, i+1, previousAnswer);
        }
      }
    }
   
    if (previousAnswer != null && previousAnswer.size() == 1 && (previousAnswer.get(0) instanceof Amount || previousAnswer.get(0) instanceof Number)) {
      final TokenList questionWithPrevious = new TokenList.CompositeTokenList(previousAnswer, question);
      answer = parseEngine.parseAndGetLastStep(question, context, questionWithPrevious);
    } else {
      answer = parseEngine.parseAndGetLastStep(question, context);
    }
    lastParseStepCount = parseEngine.getLastParseStepCount();
    processNextAnswer(answer);

    return answer;
  }

  public TokenList stripUDF(final TokenList answer) {
    if (answer.size() == 1 && answer.get(0) instanceof UserDefinedParser) {
      final UserDefinedParser udf = (UserDefinedParser) answer.get(0);
      if (udf.variables.isEmpty()) {
        final TokenList parsedResult = parseEngine.parseAndGetLastStep(udf.after, context);
        if (parsedResult.size() == 1)
          return parsedResult;
      }
    }
    return answer;
  }

  // Parse a question without changing SequentialParser state
  public TokenList quietParse(final TokenList question) {
    return parseEngine.parseAndGetLastStep(question, context);
  }

  public void processNextAnswer(final TokenList answer) {
    if (answer.size() == 1 && answer.get(0) instanceof UserDefinedParser) {
      final UserDefinedParser udp = (UserDefinedParser) answer.get(0);

      if (udp.getTemplate().size() == 1 && udp.getTemplate().get(0) instanceof String) {
        final String keyword = (String) udp.getTemplate().get(0);
        if (!PreParser.reserved.contains(keyword) && !userDefinedKeywords.containsKey(keyword)) {
          userDefinedKeywords.put(keyword, pos + 1);
        }
      }
      userDefinedParsers.addParser(udp);
    }

    // We can also get a list of UDFs, for example from an import
    if (answer.size() == 1 && answer.get(0) instanceof Collection && ((Collection) answer.get(0)).size() > 0) {
      final List<UserDefinedParser> udfs = Lists.newArrayListWithCapacity(((Collection) answer.get(0)).size());
      // We do it this way to ensure that all items in the list are really
      // UserDefinedParsers
      for (final Object o : ((Collection<?>) answer.get(0))) {
        if (! (o instanceof UserDefinedParser)) {
          udfs.clear();
          break;
        } else {
          udfs.add((UserDefinedParser) o);
        }
      }
      for (final UserDefinedParser udf : udfs) {
        userDefinedParsers.addParser(udf);
      }
    }

    pos++;
    previousAnswer = answer;
  }

  public Map<String, Integer> getUserDefinedKeywordMap() {
    return userDefinedKeywords;
  }

  public void setDumpSteps(final boolean d) {
    parseEngine.setDumpSteps(d);
  }

  public int getLastParseStepCount() {
    return lastParseStepCount;
  }

  public ParserPickerFactory getUserDefinedParsers() {
    return userDefinedParsers;
  }
}
TOP

Related Classes of com.lastcalc.SequentialParser

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.