package ktak.parseley;

import ktak.immutablejava.Function;
import ktak.parseley.RuleType.End;
import ktak.parseley.RuleType.NonTerminal;
import ktak.parseley.RuleType.Terminal;

abstract class RuleOperation<NT,T,R,Type extends RuleType<NT,T,R,?>> {
    
    protected abstract <X> X match(
            Function<NonTerminalOperation<NT,T,R,?>,X> nonTerminalCase,
            Function<TerminalOperation<NT,T,R,?>,X> terminalCase,
            Function<EndOperation<NT,T,R>,X> endCase);
    
    protected static class NonTerminalOperation<NT,T,R,Next extends RuleType<NT,T,R,?>>
    extends RuleOperation<NT,T,R,NonTerminal<NT,T,R,Next>> {
        
        protected final Function<R,RuleOperation<NT,T,R,Next>> operation;
        
        protected NonTerminalOperation(Function<R,RuleOperation<NT,T,R,Next>> operation) {
            this.operation = operation;
        }
        
        @Override
        protected <X> X match(
                Function<NonTerminalOperation<NT,T,R,?>,X> nonTerminalCase,
                Function<TerminalOperation<NT,T,R,?>,X> terminalCase,
                Function<EndOperation<NT,T,R>,X> endCase) {
            return nonTerminalCase.apply(this);
        }
        
    }
    
    protected static class TerminalOperation<NT,T,R,Next extends RuleType<NT,T,R,?>>
    extends RuleOperation<NT,T,R,Terminal<NT,T,R,Next>> {
        
        protected final Function<T,RuleOperation<NT,T,R,Next>> operation;
        
        protected TerminalOperation(Function<T,RuleOperation<NT,T,R,Next>> operation) {
            this.operation = operation;
        }
        
        @Override
        protected <X> X match(
                Function<NonTerminalOperation<NT,T,R,?>,X> nonTerminalCase,
                Function<TerminalOperation<NT,T,R,?>,X> terminalCase,
                Function<EndOperation<NT,T,R>,X> endCase) {
            return terminalCase.apply(this);
        }
        
    }
    
    protected static class EndOperation<NT,T,R> extends RuleOperation<NT,T,R,End<NT,T,R>> {
        
        protected final R result;
        
        protected EndOperation(R result) {
            this.result = result;
        }
        
        @Override
        protected <X> X match(
                Function<NonTerminalOperation<NT,T,R,?>,X> nonTerminalCase,
                Function<TerminalOperation<NT,T,R,?>,X> terminalCase,
                Function<EndOperation<NT,T,R>,X> endCase) {
            return endCase.apply(this);
        }
        
    }
    
}

@@ -172,16 +172,23 @@
 minal;%0A%0A
+public 
 abstract
@@ -246,24 +246,24 @@
 T,T,R,?%3E%3E %7B%0A
-
     %0A    pro
@@ -490,32 +490,29 @@
 ;%0A    %0A    p
-rotected
+ublic
  static clas
@@ -736,24 +736,21 @@
        p
-rotected
+ublic
  NonTerm
@@ -1208,32 +1208,29 @@
 %7D%0A    %0A    p
-rotected
+ublic
  static clas
@@ -1448,24 +1448,21 @@
        p
-rotected
+ublic
  Termina
@@ -1918,24 +1918,21 @@
   %0A    p
-rotected
+ublic
  static 
@@ -2063,24 +2063,21 @@
        p
-rotected
+ublic
  EndOper

make rule operation classes public