Files
hakorune/examples/calculator_app.nyash

367 lines
9.2 KiB
Plaintext
Raw Normal View History

// 🧮 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!")