/media/sda-magnetic/david/Dok-15-2023-11-27/fernuni-hagen/cs-i-ii/old-cs-2-01/java-fernuni-hagen-2021-10-28/Arithmetic.java


public class Arithmetic {
    /*
    Expression ::= Expression + Term | Term
    Term ::= Term * Factor | Factor
    Factor ::= Const | '(' Expression ')'
    */
    
    /*
    Expression ::= Term Expression2
    Expression2 ::= '+' Term Expression2 | End
    Term ::= Factor Term2
    Term2 ::= '*' Factor Term2 | End
    Factor ::= Const | '(' Expression ')'
    */
    
    public static Lexer lex;
    
    public static void main (String [] argv) {
        lex = new Lexer (argv [0]);
        
        System.out.println (argv [0]);
        
        Expr expr = new Expr ();
        expr.print (" ");
        System.out.println (expr.parse ());
    }
    
    public static class Lexer {
        String ToParse;
        int i;
        int undoi;
        
        Lexer (String ToParse) {
            this.ToParse = ToParse;
            i = 0;
        }
        
        public void undo () {
            i = undoi;
        }
        
        String lexer () {
            char ch;
            String ret = "";
            if (i >= ToParse.length ()) {
                ret = "END";
            }
            else if ((ch = (ToParse.charAt (i))) == '+') {
                undoi = i;
                i++;
                ret = "+";
            }
            else if (ch == '*') {
                undoi = i;
                i++;
                ret = "*";
            }
            else if (ch == '(') {
                undoi = i;
                i++;
                ret = "(";
            }
            else if (ch == ')') {
                undoi = i;
                i++;
                ret = ")";
            }
            else if ((ch >= '0') && (ch <= '9')) {
                undoi = i;
                ret = "";
                while (((ch = ToParse.charAt (i)) >= '0') && (ToParse.charAt (i) <= '9')) {
                    ret = ret + ch;
                    i++;
                    if (i >= ToParse.length ())
                        break;
                }
            }
            return ret;
        }
    
    }
    
    public static class Tree {
        Tree l;
        Tree r;
        String v;
        
        public Tree () {
            this.v = null;
            this.l = null;
            this.r = null;
        }
        
        public void print (String str) {
            if (this != null) {
                System.out.println (str + this.v);
                if (this.l != null)
                    this.l.print (str + "  ");
                if (this.r != null)
                    this.r.print (str + "  ");
            }
        }
        
        public int parse () {
            if (this.v == "+") {
                if ((this.l == null) || (this.r == null)) {
                    System.out.println ("Syntax error");
                    System.exit (1);
                }
                return this.l.parse () + this.r.parse ();
            }
            if (this.v == "*") {
                if ((this.l == null) || (this.r == null)) {
                    System.out.println ("Syntax error");
                    System.exit (1);
                }
                return this.l.parse () * this.r.parse ();
            }
            else if (this.v == null) {
                if (this.l == null) {
                    System.out.println ("Syntax error");
                    System.exit (1);
                }
                return 0 + this.l.parse ();
            }
            else if ((this.v.charAt (0) >= '0') && (this.v.charAt (0) <= '9')) {
                return Integer.parseInt (v);
            }
            return 0;
        }
    }
    
    
    public static class Expr extends Tree {
        
        public Expr () {
            this.l = new Term ();
            this.r = new Expr2 ();
            this.v = "+";
        }
    
    }
    
    public static class Expr2 extends Tree  {
        public Expr2 () {
            if (lex.lexer () == "+") {
                this.v = "+";
                this.l = new Term ();
                this.r = new Expr2 ();
            }
            else {
                lex.undo ();
                this.v = "0";
                this.l = null;
                this.r = null;
            }
        }
    }
    
    public static class Term extends Tree  {
        public Term () {
            this.l = new Factor ();
            this.r = new Term2 ();
            this.v = "*";
        }
    }
    
    public static class Term2 extends Tree  {
        public Term2 () {
            if (lex.lexer () == "*") {
                this.v = "*";
                this.l = new Factor ();
                this.r = new Term2 ();
            }
            else {
                lex.undo ();
                this.v = "1";
                this.l = null;
                this.r = null;
            }
        }    
    }
    
    public static class Factor extends Tree  {
        String ch;
        public Factor () {
            String val;
            if ((val = lex.lexer ()) == "(") {
                this.l = new Expr ();
                this.r = null;
                if (lex.lexer () != ")") {
                    System.out.println ("Syntax error");
                    System.exit (1);
                }
            }
            else if (val != "END") {
                this.v = val;
                this.l = null;
                this.r = null;
            }
        
        }
    
    }

}