Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package com.viffx.CodingLanguage.Compiler.Automata;
- import com.viffx.CodingLanguage.Compiler.Grammar;
- import com.viffx.CodingLanguage.Compiler.Symbols.NonTerminal;
- import com.viffx.CodingLanguage.Compiler.Symbols.Symbol;
- import com.viffx.CodingLanguage.Compiler.Symbols.Terminal;
- import java.util.*;
- import java.util.function.BiConsumer;
- import java.util.function.Consumer;
- public class LALR1 {
- private final Grammar G;
- public LALR1(Grammar g) {
- G = g;
- }
- private Set<Terminal> FIRST(List<Symbol> symbols) {
- Symbol first = symbols.getFirst();
- if (first == null) return new HashSet<>();
- if (first instanceof Terminal t) return Set.of(t);
- Set<Item> items = CLOSURE(G.station((NonTerminal) first));
- Set<Terminal> terminals = new HashSet<>();
- for (Item i : items) {
- Symbol symbol = G.symbol(i);
- if (symbol == null) continue;
- if (symbol instanceof Terminal t) {
- terminals.add(t);
- }
- }
- return terminals;
- }
- /*
- * Set<Item> CLOSURE(Set<Item> I)*/
- private Set<Item> CLOSURE (Set<Item> I) {
- Set<Item> J = new HashSet<>(I);
- Queue<Item> worklist = new LinkedList<>(J);
- while (!worklist.isEmpty()) {
- Item A = worklist.poll();
- Symbol symbol = G.symbol(A);
- if (symbol == null) continue;
- if (symbol instanceof NonTerminal nt) {
- int index = G.NT_index(nt);
- if (index < 0) throw new RuntimeException(nt + " is undefined in the given grammar.");
- int count = Math.max(0, G.NT_count(nt));
- for (int i = index; i - index < count; i++) {
- Item newItem = new Item(i,0);
- if (J.add(newItem)) worklist.add(newItem);
- }
- }
- }
- return J;
- }
- private Set<Item> GOTO(Set<Item> I, Symbol x) {
- Set<Item> advanced = new HashSet<>();
- for (Item item : I) {
- Symbol symbol = G.symbol(item);
- if (symbol == null || !G.symbol(item).equals(x)) continue;
- advanced.add(item.advance(G));
- }
- return CLOSURE(advanced);
- }
- private HashSet<Set<Item>> LR0ITEMS(Set<Item> START) {
- HashSet<Set<Item>> C = new HashSet<>(Set.of(START));
- Queue<Set<Item>> worklist = new LinkedList<>(C);
- while (!worklist.isEmpty()) {
- Set<Item> I = worklist.poll();
- for (Symbol X : G.symbols()) {
- Set<Item> GOTO = GOTO(I,X);
- if (GOTO.isEmpty()) continue;
- if (C.add(GOTO)) worklist.add(GOTO);
- }
- }
- return C;
- }
- /* Gets the start item.
- * Throws an exception if there is more than one production for the start item
- * Throws an exception if that the production is not a single non-terminal
- * */
- private Set<Item> startItem(int index) {
- List<List<Symbol>> START = G.productions(NonTerminal.START);
- if (START.isEmpty()) throw new RuntimeException("Start is undefined in the given grammar.");
- List<Symbol> START_PRODUCTION = new ArrayList<>(START.getFirst());
- if (START.size() != 1 || START_PRODUCTION.size() != 1 || START_PRODUCTION.getFirst() instanceof Terminal) throw new RuntimeException("Start must be defined as \"START > {Non terminal}\"");
- return Set.of(new Item(index,0, Set.of(Terminal.TEST)));
- }
- public Set<Item> KERNEL(Set<Item> LR0STATE, int index) {
- Set<Item> kernel = new HashSet<>();
- for (Item LR0ITEM : LR0STATE) {
- if (LR0ITEM.dot() > 0 || LR0ITEM.production() == index) {
- kernel.add(LR0ITEM);
- }
- }
- return kernel;
- }
- public Set<Set<Item>> LALR1ITEMS() {
- int index = G.NT_index(NonTerminal.START);
- Set<Item> START = CLOSURE(startItem(index));
- // [CALCULATE_KERNELS]
- HashSet<Set<Item>> kernels = new HashSet<>();
- HashSet<Set<Item>> LR0ITEMS = LR0ITEMS(START);
- // KERNEL(LR0ITEMS.getFirst(),index).forEach(item -> System.out.println("\t" + item.toReadable(G)));
- int count = 0;
- for (Set<Item> state : LR0ITEMS) {
- System.out.println("I" + count++ + ":");
- state.forEach(item -> System.out.println("\t" + item.toReadable(G)));
- System.out.println();
- }
- for (Set<Item> LR0STATE : LR0ITEMS) kernels.add(KERNEL(LR0STATE,index));
- count = 0;
- for (Set<Item> state : kernels) {
- System.out.println("I" + count++ + ":");
- state.forEach(item -> System.out.println("\t" + item.toReadable(G)));
- System.out.println();
- }
- HashMap<Item,Set<Channel>> channelsMap = new HashMap<>();
- // // [CALCULATE_LOOKAHEADS]
- for (Set<Item> I : kernels) {
- for (Item A : I) {
- for (Symbol X : G.symbols()) {
- if (!A.atEnd(G) && G.symbol(A).equals(X)) {
- // Step 1: Closure with dummy lookahead
- Item A_with_hash = new Item(A.production(), A.dot(), Set.of(Terminal.TEST));
- Set<Item> closure = CLOSURE(Set.of(A_with_hash));
- // Step 2: GOTO over symbol X
- Set<Item> gotoSet = GOTO(closure, X);
- for (Item B : gotoSet) {
- if (B.atEnd(G)) continue;
- if (!G.symbol(B).equals(X)) continue;
- if (B.lookahead().contains(Terminal.TEST)) {
- // Propagation from A to B
- channelsMap.computeIfAbsent(A, _ -> new HashSet<>())
- .add(new Propagated(B));
- } else {
- // Spontaneous generation for B
- // Set<Terminal> lookahead = FIRST(B); // or FIRST(B.β a)
- channelsMap.computeIfAbsent(B, _ -> new HashSet<>())
- .add(new Spontaneous(null));
- }
- }
- }
- }
- }
- }
- channelsMap.forEach((item, channel) -> {
- System.out.println(item + " -> " + channel);
- });
- System.out.println("Hi");
- //
- // // [INITIALIZE_LOOKAHEAD_TABLE]
- // Map<Integer,Set<Terminal>> lookaheads = new HashMap<>();
- // Map<Integer,Set<Integer>> propagatingChannels = new HashMap<>();
- // channelsMap.forEach((item, channels) -> {
- // for (Channel channel : channels) {
- // if (channel instanceof Spontaneous spontaneous) {
- // lookaheads.computeIfAbsent(item.hashCode(), _ -> new HashSet<>()).addAll(spontaneous.terminals());
- // continue;
- // }
- // propagatingChannels.computeIfAbsent(item.hashCode(), _ -> new HashSet<>()).add(((Propagated) channel).item().hashCode());
- // System.out.println(item.hashCode() + " -> " + ((Propagated) channel).item().hashCode());
- // }
- // //0,32,1,33,156,157,94,95
- // });
- // System.out.println("Hi");
- //
- // // [PUMP_LOOKAHEADS]
- // boolean change;
- // do {
- // change = false;
- // for (Map.Entry<Integer,Set<Integer>> entry : propagatingChannels.entrySet()) {
- // Integer from = entry.getKey();
- // for (Integer target : entry.getValue()) {
- // System.out.println(lookaheads.containsKey(from));
- // if (!lookaheads.containsKey(from)) continue;
- // Set<Terminal> fromLookahead = lookaheads.get(from);
- // change |= lookaheads.computeIfAbsent(target, _ -> new HashSet<>()).addAll(fromLookahead);
- // }
- // }
- // } while (change);
- //
- // lookaheads.forEach((item, terminals) -> {System.out.println(item + "->" + terminals);});
- return null; // STFU
- }
- private sealed interface Channel permits Propagated, Spontaneous {}
- private record Propagated(Item item) implements Channel {
- @Override
- public String toString() {
- return "Propagated{" +
- "item=" + item +
- '}';
- }
- }
- private record Spontaneous(Set<Terminal> terminals) implements Channel {
- @Override
- public String toString() {
- return "Spontaneous{" +
- "terminals=" + terminals +
- '}';
- }
- }
- // I.forEach(item1 -> {System.out.println(item1.toReadable(G));});
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement