人気ブログランキング | 話題のタグを見る

変数つき1行電卓

パーサの記事も大分続いたので、テキストフィールドに入力した数式を計算する電卓のプログラムを紹介して最後にする。HTML edit E (http://www.mnet.ne.jp/~tnomura/javascript/edite.html) にコピペしてアンダースコア_ を消去すれば動作確認できる。perse.js は http://www.mnet.ne.jp/~tnomura/javascript/parse.js に置いた。テキストフィールドに数式を入力してリターンキーを入力すると結果が表示される。変数が使えるので、次のような計算もできる。

a = 1
b = 2
(a + b) * (a + b)

<!doctype html>
<html lang="ja">
<head>
<meta charset="utf-8">
<script src="parse.js"></script>
<script>

// Lexical Analysis

var spacing = P.pat( P.lex(/^\s*/), P.pop )
var num = function() {return P.lex(/^\d+/)() && spacing() }
var m = function() {return P.lex(/^[*/]/)() && spacing() }
var p = function() {return P.lex(/^[+-]/)() && spacing() }
var lpar = function() {return P.lex(/^[(]/)() && spacing() }
var rpar = function() {return P.lex(/^[)]/)() && spacing() }

// Syntactic Analysis

var mFact = P.pat( function() {return m() && fact() }, function() {
    var b = parseInt(P.pop()); op = P.pop(); a = parseInt(P.pop())
    if (op == "*") {
        P.push( "" + (a*b) )
    } else {
        P.push( "" + (a/b) )
    }
})
var term = function() {return fact() && P.many( mFact )() }
var pTerm = P.pat( function() {return p() && term()}, function() {
    var b = parseInt(P.pop()); op = P.pop(); var a = parseInt(P.pop())
    if (op == "+") {
        P.push( "" + (a+b) )
    } else {
        P.push( "" + (a-b) )
    }
})
var expr = function() {return term() && P.many( pTerm )() }
var paren = P.pat( function() {return lpar() && expr() && rpar() }, function() {
    P.pop(); var val = P.pop(); P.pop()
    P.push( val )
})
var fact = function() {return num() || evalvar() || paren() }

// Subscription

var variables = {}

var ident = function() {return P.lex(/^\w+/)() && spacing() }
var equal = function() {return P.lex(/^=/)() && spacing() }
var notequal = P.notPred( P.lex(/^=/) )
var subscribe = P.pat( function() {return ident() && equal() && expr() }, function() {
    var value = P.pop(); P.pop(); var identifier = P.pop()
    variables[identifier] = value
    P.push(value)
})
var evalvar = P.pat( function() {return ident() && notequal()}, function() {
    var id = P.pop()
    P.push( variables[id] )
})

var program = function() {return subscribe() || expr() }

function calculate() {
    var line = d_ocument.getElementById("line")
    P.setLine( line.value )
    program()
    line.value = P.pop()
}

</script>
</head>
<body>
<input type="text" id="line" o_nchange="calculate()">
</body>
</html>
by tnomura9 | 2016-02-27 22:10 | JavaScript | Comments(0)
<< 生成文法と分析文法 形式文法とは何か >>