Advertisement
Guest User

Untitled

a guest
Jun 17th, 2016
107
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
J 10.27 KB | None | 0 0
  1. package Syntax;
  2.  
  3. import BreakMyFuckingSky.Lexi;
  4. import BreakMyFuckingSky.Token;
  5. import sun.nio.cs.Surrogate;
  6.  
  7. import java.io.*;
  8. import java.util.*;
  9.  
  10. public class Earley {
  11.  
  12.     private ArrayList<TreeSet<State>> states =new ArrayList<>();//TODO создать I списков
  13.  
  14.     private ArrayList<Token> tokens = new ArrayList<Token>();
  15.  
  16.  
  17.     class State implements Comparable<State>{
  18.         String left;
  19.         ArrayList<String> rule = new ArrayList<>();
  20.         int pointer;
  21.         int ind;
  22.         TreeSet<State> parents = new TreeSet<>();
  23.  
  24.         public State(String l, ArrayList<String> r, int p, int i, State parent) {
  25.             left = l;
  26.             rule.addAll(r);
  27.             pointer = p;
  28.             ind = i;
  29.             if(parent!=null)
  30.                 parents.add(parent);
  31.         }
  32.  
  33.         public State(State s) {
  34.             left = s.left;
  35.             rule.addAll(s.rule);
  36.             pointer = s.pointer;
  37.             ind = s.ind;
  38.             parents.addAll(s.parents);
  39.         }
  40.  
  41.  
  42.         @Override
  43.         public int compareTo(State s) {
  44.             int res;
  45.             if(left.equals(s.left)) res =0;
  46.             else if(left.length()<=s.left.length()) res=-1;
  47.             else res = 1;
  48.             if(res!=0) return res;
  49.             if(rule.size()==s.rule.size()) {
  50.                 for (int i = 0; i < rule.size(); ++i) {
  51.                     if (!rule.get(i).equals(s.rule.get(i))) {
  52.                         res =-1;
  53.                         break;
  54.                     }
  55.                 }
  56.                 res =0;
  57.             }
  58.             else if(rule.size()<s.rule.size()) res = -1;
  59.             else res=1;
  60.             if(res!=0) return res;
  61.             res = Integer.compare(pointer,s.pointer);
  62.             if(res!=0) return res;
  63.             res = Integer.compare(ind,s.ind);
  64.             if(res!=0) return res;
  65.             return res;
  66.         }
  67.     }
  68.  
  69.     private HashMap<String, ArrayList<ArrayList<String>>> rules = new HashMap<>();
  70.  
  71.     /**
  72.      * Считывает грамматику из файла
  73.      * @param grammar файл с грамматикой
  74.      */
  75.     private void readGrammar(File grammar) {
  76.         try (BufferedReader rd = new BufferedReader(new FileReader(grammar))) {
  77.             String key;
  78.             String line;
  79.             while ((line = rd.readLine()) != null) {
  80.                 key = line.substring(0, (line.indexOf("::=")));
  81.                 line = line.substring(line.indexOf('=') + 1);
  82.                 StringTokenizer ExtenderRules = new StringTokenizer(line.trim(), "|");
  83.                 ArrayList<ArrayList<String>> arr = new ArrayList<>();
  84.                 while (ExtenderRules.hasMoreTokens()) {
  85.                     String token = ExtenderRules.nextToken();
  86.                     ArrayList<String> Rule = new ArrayList<>();
  87.                     StringTokenizer ExtenderWords = new StringTokenizer(token, " ");
  88.                     while (ExtenderWords.hasMoreTokens()) {
  89.                         Rule.add(ExtenderWords.nextToken());
  90.                     }
  91.                     arr.add(Rule);
  92.                 }
  93.                 rules.put(key, arr);
  94.             }
  95.         } catch (IOException exc) {
  96.             System.out.println("Error");
  97.         }
  98.     }
  99.  
  100.     /**
  101.      * Алгоритм Эрли. Запускает считыватель, предсказатель или завершатель по мере необходимости в зависимости
  102.      * от того, где находится указатель
  103.      * @return true - если грамматика порождает строку, false - если нет
  104.      */
  105.     private boolean earley() {
  106.  
  107.         ArrayList<String> startRule = new ArrayList<>();
  108.         startRule.add("S");
  109.  
  110.         for (int i = 0; i <= tokens.size(); i++) states.add(new TreeSet<State>());
  111.  
  112.         State BEGINING_STATE = new State("S'", startRule, 0, 0, null);
  113.         State ENDING_STATE = new State("S'", startRule, 1, 0, null);
  114.  
  115.         states.get(0).add(BEGINING_STATE);
  116.         for (int i = 0; i < tokens.size(); ++i) {
  117.             ArrayDeque<State> que = new ArrayDeque<>(states.get(i));
  118.             while (!que.isEmpty()) {
  119.                 State viewedState = que.pollFirst();
  120.                 int pointer = viewedState.pointer;
  121.                 if (pointer == viewedState.rule.size()) complete(viewedState, i, que);
  122.                 else {
  123.                     String elem = viewedState.rule.get(pointer);
  124.                     // проверка на то, что элемент либо тэг (класс Tag), либо класс токена
  125.                     if (elem.matches("\\p{Digit}+")) scan(viewedState, i);
  126.                     else predict(viewedState, i, que);
  127.                 }
  128.             }
  129.         }
  130.         int end = tokens.size();
  131.         ArrayDeque<State> que = new ArrayDeque<>(states.get(end));
  132.         while (!que.isEmpty() && !states.get(end).contains(ENDING_STATE)) {
  133.             State viewedState = que.pollFirst();
  134.             lastComplete(viewedState, end, que);
  135.         }
  136.         return states.get(end).contains(ENDING_STATE);
  137.     }
  138.  
  139.     /**
  140.      * Функция считыватель для Эрли. Если i символ входной строки совпадает с i символом в i множестве событий,
  141.      * то указатель сдвигается и новое правило добавляется в следуещее множнество
  142.      * @param viewedState правило, где указатель перед терминалом
  143.      * @param i индекс нужного множество
  144.      */
  145.     private void scan(State viewedState, int i) {
  146.         //выбирается терминал перед которым стоит точка
  147.         int pointed = new Integer(viewedState.rule.get(viewedState.pointer));
  148.         if(tokens.get(i).getTag() == pointed){
  149.             State newState = new State(viewedState);
  150.             newState.pointer++;
  151.             states.get(i+1).add(newState);
  152.         }
  153.         // TODO Синтаксическая ошибка
  154.         //else
  155.     }
  156.  
  157.     /**
  158.      * Завершатель для Эрли. Берет индекс входного State (поле ind) и по нему выбирает множество M.
  159.      * Далее выбираются из М все State у которых индекс совпадает с ранее выбранным индексом и указатель на символ стоит
  160.      * в начале (поле pointed)
  161.      * @param viewedState правило, где указатель в конце
  162.      * @param i индекс множества, в котором содержится viewedState
  163.      */
  164.     private void complete(State viewedState, int i, ArrayDeque<State> que) {
  165.         int ind = viewedState.ind;
  166.         TreeSet<State> M = states.get(ind);
  167.         for(State state: M){
  168.             if(state.pointer==0 && state.ind==ind) {
  169.                 for (State parent : state.parents) {
  170.                     State newState = new State(parent);
  171.                     newState.pointer++;
  172.                     if(!states.get(i).contains(newState)) {
  173.                         states.get(i).add(newState);
  174.                         que.addLast(newState);
  175.                     }
  176.                     else
  177.                         // TODO опасная зона на неправильный возврат значений
  178.                         states.get(i).ceiling(newState).parents.add(viewedState);
  179.                 }
  180.             }
  181.         }
  182.     }
  183.  
  184.  
  185.     private void lastComplete(State viewedState, int i, ArrayDeque<State> que) {
  186.         int ind = viewedState.ind;
  187.         TreeSet<State> M = states.get(ind);
  188.         for(State state: M){
  189.             if(state.pointer==0 && state.ind==ind) {
  190.                 for (State parent : state.parents) {
  191.                     State newState = new State(parent);
  192.                     if(++newState.pointer==newState.rule.size()) {
  193.                         states.get(i).add(newState);
  194.                         que.addLast(newState);
  195.                     }
  196.                 }
  197.             }
  198.         }
  199.     }
  200.     /**
  201.      * Предикт для Эрли. Добавляет все порождения входного правила
  202.      * @param viewedState правило, где указатель перед нетерминалом
  203.      * @param i индекс нужного множество
  204.      */
  205.     private void predict(State viewedState, int i, ArrayDeque<State> que) {
  206.         //выбирается нетерминал перед которым стоит точка
  207.         String pointed = viewedState.rule.get(viewedState.pointer);
  208.         // Можно ли упростить? тут проверка на существование этого нетерминала в грамматике(Кстати, тут можно выдать
  209.         // синтаксическую ошибку)
  210.         if (rules.containsKey(pointed)) {
  211.             //добавление порождений
  212.             for (ArrayList<String> r : rules.get(pointed)) {
  213.                 State newState=new State(pointed, r, 0, i, viewedState);
  214.                 if(!states.get(i).contains(newState)) {
  215.                     states.get(i).add(newState);
  216.                     que.addLast(newState);
  217.                 }
  218.                 else
  219.                 // TODO опасная зона на неправильный возврат значений
  220.                     states.get(i).ceiling(newState).parents.add(viewedState);
  221.             }
  222.         }
  223.     }
  224.  
  225.  
  226.  
  227.     public Earley(ArrayList<Token> tokens, File grammFile) {
  228.         this.tokens = tokens;
  229.         readGrammar(grammFile);
  230.     }
  231.  
  232.     public static void main(String[] args) {
  233.         Lexi lexi=null;
  234.         try {
  235.             lexi = new Lexi(new File("src\\main\\resources\\PROG1.txt"));
  236.         } catch (Exception e) {
  237.             System.out.println("Файл не найден");
  238.         }
  239.         Earley solution = new Earley(lexi.tokens, new File("src\\main\\resources\\test.txt"));
  240.         System.out.println(solution.earley());
  241.         //Surrogate.Generator generator = new Surrogate.Generator(lexi.tokens, "src\\outputCode.asm");
  242.        // generator.generate();
  243.     }
  244. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement