// 🧮 Nyash数式パーサー - Everything is Box哲学による実装
// 再帰下降構文解析 + デバッグ機能付き

print("🧮 === Nyash Calculator App ===")

// デバッグ機能初期化
DEBUG = new DebugBox()
DEBUG.startTracking()

// 🎯 トークンBox - すべてのトークンがBox
box Token<T> {
    init { type, value, position }
    
    Token(tokenType, tokenValue) {
        me.type = tokenType
        me.value = tokenValue
        me.position = 0
    }
    
    toString() {
        return "Token(" + me.type + ": " + me.value + ")"
    }
    
    isType(expectedType) {
        return me.type == expectedType
    }
}

// 🔢 数値トークン専用Box
box NumberToken from Token<IntegerBox> {
    init { numValue }
    
    NumberToken(value) {
        super("NUMBER", value)
        me.numValue = value
    }
    
    getValue() {
        return me.numValue
    }
}

// ➕ 演算子トークン専用Box
box OperatorToken from Token<StringBox> {
    init { operator, precedence }
    
    OperatorToken(op) {
        super("OPERATOR", op)
        me.operator = op
        
        // 演算子優先度設定
        if op == "+" || op == "-" {
            me.precedence = 1
        }
        if op == "*" || op == "/" {
            me.precedence = 2
        }
    }
    
    getPrecedence() {
        return me.precedence
    }
}

// 📝 字句解析器Box
box Tokenizer {
    init { input, position, tokens }
    
    Tokenizer(expression) {
        me.input = expression
        me.position = 0
        me.tokens = new ArrayBox()
    }
    
    // 次の文字を取得
    peek() {
        if me.position >= me.input.length() {
            return ""
        }
        return me.input.charAt(me.position)
    }
    
    // 文字を消費して進む
    advance() {
        me.position = me.position + 1
    }
    
    // 空白をスキップ
    skipWhitespace() {
        loop(me.position < me.input.length() && me.peek() == " ") {
            me.advance()
        }
    }
    
    // 数値を読み取り
    readNumber() {
        start = me.position
        
        loop(me.position < me.input.length()) {
            char = me.peek()
            if char >= "0" && char <= "9" {
                me.advance()
            } else {
                break
            }
        }
        
        numberStr = me.input.substring(start, me.position)
        return new NumberToken(numberStr.toInteger())
    }
    
    // トークン化実行
    tokenize() {
        loop(me.position < me.input.length()) {
            me.skipWhitespace()
            
            if me.position >= me.input.length() {
                break
            }
            
            char = me.peek()
            
            // 数値の場合
            if char >= "0" && char <= "9" {
                token = me.readNumber()
                me.tokens.push(token)
                DEBUG.trackBox(token, "number_token_" + me.tokens.length())
            }
            // 演算子の場合
            else if char == "+" || char == "-" || char == "*" || char == "/" {
                token = new OperatorToken(char)
                me.tokens.push(token)
                me.advance()
                DEBUG.trackBox(token, "operator_token_" + me.tokens.length())
            }
            // 括弧の場合
            else if char == "(" || char == ")" {
                token = new Token("PAREN", char)
                me.tokens.push(token)
                me.advance()
                DEBUG.trackBox(token, "paren_token_" + me.tokens.length())
            }
            else {
                print("❌ Unknown character: " + char)
                me.advance()
            }
        }
        
        // 終端トークン追加
        eofToken = new Token("EOF", "")
        me.tokens.push(eofToken)
        
        return me.tokens
    }
    
    printTokens() {
        print("🎯 Tokens:")
        i = 0
        loop(i < me.tokens.length()) {
            token = me.tokens.get(i)
            print("  " + i + ": " + token.toString())
            i = i + 1
        }
    }
}

// 🔍 構文解析器Box - 再帰下降パーサー
box Parser {
    init { tokens, position }
    
    Parser(tokenList) {
        me.tokens = tokenList
        me.position = 0
    }
    
    // 現在のトークンを取得
    currentToken() {
        if me.position >= me.tokens.length() {
            return new Token("EOF", "")
        }
        return me.tokens.get(me.position)
    }
    
    // トークンを消費して進む
    consume() {
        me.position = me.position + 1
    }
    
    // 指定したタイプのトークンを期待して消費
    expect(expectedType) {
        token = me.currentToken()
        if token.isType(expectedType) {
            me.consume()
            return token
        }
        print("❌ Parse error: Expected " + expectedType + ", got " + token.type)
        return null
    }
    
    // 式の解析 (+ と -)
    parseExpression() {
        DEBUG.traceCall("parseExpression", "", "")
        
        result = me.parseTerm()
        
        loop(true) {
            token = me.currentToken()
            if token.isType("OPERATOR") {
                op = token.value
                if op == "+" || op == "-" {
                    me.consume()
                    right = me.parseTerm()
                    
                    if op == "+" {
                        result = result + right
                    } else {
                        result = result - right
                    }
                    
                    print("📊 " + op + " operation: result = " + result)
                } else {
                    break
                }
            } else {
                break
            }
        }
        
        return result
    }
    
    // 項の解析 (* と /)
    parseTerm() {
        DEBUG.traceCall("parseTerm", "", "")
        
        result = me.parseFactor()
        
        loop(true) {
            token = me.currentToken()
            if token.isType("OPERATOR") {
                op = token.value
                if op == "*" || op == "/" {
                    me.consume()
                    right = me.parseFactor()
                    
                    if op == "*" {
                        result = result * right
                    } else {
                        if right == 0 {
                            print("❌ Division by zero!")
                            return 0
                        }
                        result = result / right
                    }
                    
                    print("📊 " + op + " operation: result = " + result)
                } else {
                    break
                }
            } else {
                break
            }
        }
        
        return result
    }
    
    // 因子の解析 (数値と括弧)
    parseFactor() {
        DEBUG.traceCall("parseFactor", "", "")
        
        token = me.currentToken()
        
        // 数値
        if token.isType("NUMBER") {
            me.consume()
            value = token.value.toInteger()
            print("🔢 Number: " + value)
            return value
        }
        // 括弧
        else if token.isType("PAREN") && token.value == "(" {
            me.consume()  // consume '('
            result = me.parseExpression()
            me.expect("PAREN")  // expect ')'
            return result
        }
        // エラー
        else {
            print("❌ Parse error: Unexpected token " + token.toString())
            return 0
        }
    }
    
    // 構文解析実行
    parse() {
        print("🚀 Starting parse...")
        result = me.parseExpression()
        
        // 最後にEOFトークンがあることを確認
        if !me.currentToken().isType("EOF") {
            print("⚠️  Warning: Extra tokens after expression")
        }
        
        return result
    }
}

// 🧮 メイン計算機Box
box Calculator {
    init { name }
    
    Calculator() {
        me.name = "Nyash Calculator"
    }
    
    // 式を評価
    evaluate(expression) {
        print("\n📝 Evaluating: " + expression)
        
        // Step 1: トークン化
        tokenizer = new Tokenizer(expression)
        DEBUG.trackBox(tokenizer, "main_tokenizer")
        
        tokens = tokenizer.tokenize()
        tokenizer.printTokens()
        
        // Step 2: 構文解析・評価
        parser = new Parser(tokens)
        DEBUG.trackBox(parser, "main_parser")
        
        result = parser.parse()
        
        print("✅ Result: " + result)
        return result
    }
}

// 🚀 アプリケーション実行
print("🎯 Testing Nyash Calculator...")

calc = new Calculator()
DEBUG.trackBox(calc, "main_calculator")

// テスト式
testExpressions = new ArrayBox()
testExpressions.push("2 + 3")
testExpressions.push("5 * 4")  
testExpressions.push("10 - 6")
testExpressions.push("15 / 3")
testExpressions.push("2 + 3 * 4")
testExpressions.push("(2 + 3) * 4")

// すべてのテスト実行
i = 0
loop(i < testExpressions.length()) {
    expression = testExpressions.get(i)
    calc.evaluate(expression)
    i = i + 1
}

// デバッグ情報表示
print("\n📊 === Debug Report ===")
print(DEBUG.memoryReport())
print(DEBUG.showCallStack())

print("\n🎉 Calculator app completed!")