Package ru.bmstu.datalog.algo

Source Code of ru.bmstu.datalog.algo.DatalogParser

package ru.bmstu.datalog.algo;

import java.io.BufferedReader;
import java.io.FileReader;
import java.util.ArrayList;

import ru.bmstu.datalog.data.Argument;
import ru.bmstu.datalog.data.DatalogData;
import ru.bmstu.datalog.data.Fact;
import ru.bmstu.datalog.data.Predicate;
import ru.bmstu.datalog.data.Request;
import ru.bmstu.datalog.data.Rule;

/**
* Datalog parser based on the recursive descent.
* @author art-vybor
*/
public class DatalogParser {
  private static int currentSymbol;
  private static String   stringForParse;


  /**
   * Parsing datalog program from file.
   * @param filename
   * @return {@link DatalogData}
   * @throws Exception
   */
  public static DatalogData parseDatalogFromFile(String filename) {
    StringBuilder strBuilder = new StringBuilder();
    try {
      @SuppressWarnings("resource")
      BufferedReader in = new BufferedReader(new FileReader(filename));
      String str;
     
      while ((str = in.readLine()) != null) {
        str = str.replaceAll("[ \t\n]", "");
       
        if (str.length() >= 2 && str.charAt(0) == '/' && str.charAt(1) == '/') continue; //comments
          strBuilder.append(str);
      }
    } catch (Exception e) {
      e.printStackTrace();
    }   
   
    return parseDatalogFromString(strBuilder.toString());
  }
 
  //TODO написать удаление комментариев в любом случае
 
  /**
   * Parsing datalog program presented as a string.
   * @param datalogProgram
   * @return {@link DatalogData}
   * @throws Exception
   */
  public static DatalogData parseDatalogFromString(String datalogProgram) {
    currentSymbol = 0;
    stringForParse = datalogProgram.replaceAll("[ \t\n]", "");
   
    DatalogData answer = new DatalogData();
    try {
      answer = parseProgram();
    } catch (Exception e) {
      e.printStackTrace();
    }
    return answer;
  }
 


  /**
   * Program ::= (Request | Rule | Fact)*
   * @return {@link DatalogData}
   * @throws Exception
   */
  private static DatalogData parseProgram() throws Exception {   
    DatalogData data = new DatalogData();
   
    while (currentSymbol < stringForParse.length()-1) {
     
      int cur = currentSymbol;     
      try {       
        data.addRequest(parseQuery());
       
      } catch (Exception eQuery) {       
        currentSymbol = cur;       
        try {
          data.addRule(parseRule());
         
        } catch (Exception eRulle) {
          currentSymbol = cur;         
          data.addFact(parseFact());
        }
      }
    }
   
    return data;   
  }
 
  /**
   * Rule ::= Predicate :- Predicate (',' Predicate)*
   * @return {@link Rule}
   * @throws Exception
   */
  private static Rule parseRule() throws Exception {   
    Rule rule = new Rule();
    rule.setHead(parsePredicate());
   
    parseString(":-");
   
    rule.addToBody(parsePredicate());
   
    while (skipSymbol(','))
      rule.addToBody(parsePredicate());
   
    parseSymbol('.');
   
    return rule;
  }
 
  /**
   * Request ::= '?' ':-' Predicate .
   * @return {@link Request}
   * @throws Exception
   */
  private static Request parseQuery() throws Exception {   
    parseSymbol('?');   
    parseString(":-");   
    Request request = new Request(parsePredicate());   
    parseSymbol('.');
   
    return request;   
  }

  /**
   * Fact ::= Predicate '.'
   * @return {@link Fact}
   * @throws Exception
   */
  private static Fact parseFact() throws Exception {   
    Fact fact = new Fact(parsePredicate());   
    parseSymbol('.');
       
    return fact;   
  }
 
  /**
   * Predicate ::= Name '(' Arguments ')'
   * @return {@link Predicate}
   * @throws Exception
   */
  private static Predicate parsePredicate() throws Exception {
    String name = parseName();   
    parseSymbol('(');   
    ArrayList<Argument> arguments = parseArguments();
    parseSymbol(')');
   
    return new Predicate(name, arguments);
  }

  /**
   * Arguments ::= Term | Arguments ',' Term
   * @return {@link ArrayList<Argument>}
   * @throws Exception
   */
  private static ArrayList<Argument> parseArguments() throws Exception {
    ArrayList<Argument> answer = new ArrayList<Argument>();
   
    int cur = currentSymbol;
    try {
      answer.add(parseTerm());
     
    } catch(Exception e) {
      currentSymbol = cur;
      return answer;
    }
   
    while(skipSymbol(','))
      answer.add(parseTerm());
   
    return answer;
  }

  /**
   * Term ::= Number | Name | '_'
   * @return {@link Argument}
   * @throws Exception
   */
  private static Argument parseTerm() throws Exception {
    Argument answer;
   
    int cur = currentSymbol;
    try {
      answer = new Argument(parseNumber());
     
    } catch(Exception e) {
      currentSymbol = cur;
     
      if (curSymbol() == '_') {
        answer = new Argument("_", -1);
        next();
      } else {
        boolean isConstant = Character.isLowerCase(curSymbol());
        if (isConstant) {
          answer = new Argument(parseName());
        } else {
          answer = new Argument(parseName(), -1);
        }
      }
    }
   
    return answer;
  }
 
  /**
   * Name ::= Letter ArbitaryString
   * @return {@link String}
   * @throws Exception
   */
  private static String parseName() throws Exception {
    if (!Character.isLetter(curSymbol())) throw new Exception("Incorrect predicate name (name is empty)");
    char firstChar = curSymbol();
    next();   
   
    return firstChar + parseArbitraryString();
  }
 
  /**
   * Number ::= Digit Digit*
   * @return {@link String}
   * @throws Exception
   */
  private static String parseNumber() throws Exception {
    StringBuilder strBuilder = new StringBuilder();
   
    if (!Character.isDigit(curSymbol())) throw new Exception("Incorrect number (number is empty)");
    strBuilder.append(curSymbol());
    next();      
   
    while (Character.isDigit(curSymbol())) {
      strBuilder.append(curSymbol());
      next();
    }
   
    return strBuilder.toString();
  }
 
  /**
   * ArbitraryString ::= (Letter | Digit)*
   * @return {@link String}
   */
  private static String parseArbitraryString() {
    StringBuilder strBuilder = new StringBuilder();
   
    while (Character.isLetterOrDigit(curSymbol())) {
      strBuilder.append(curSymbol());
      next();
    }
   
    return strBuilder.toString();   
  }
 
  /**
   * Support functions
   */
 
  private static char curSymbol() {
    return stringForParse.charAt(currentSymbol);
  }
 
  private static boolean skipSymbol(char symbol) {
    if (curSymbol() != symbol)
      return false;
   
    next();
    return true;
  }
 
  private static boolean skipString(String str) {   
    for (int i = 0; i < str.length(); ++i) {
      if (!skipSymbol(str.charAt(i)));
    }
    return true;
  }
 
  private static void parseSymbol(char symbol) throws Exception {
    if (!skipSymbol(symbol)) throw new Exception("No symbol: '" + symbol + "'");
  }
 
  private static void parseString(String str) throws Exception {
    if (!skipString(str)) throw new Exception("No string: '" + str + "'");
  }
 
  private static void next() {
    currentSymbol++;
  }
}
TOP

Related Classes of ru.bmstu.datalog.algo.DatalogParser

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.