編集: インタラクティブな完全なコード: http://jsfiddle.net/LDEGe/2/
私は高校の CS 入門生で、クラスとは関係のないサイド プロジェクトとして、Shunting-Yard Algorithm を使用して簡単な数式パーサーを作成しようとしています。ここの疑似コードは理解できますが、Javascript コードに変換するのに問題があります。ここにスタックとキュー オブジェクトを作成しました
function Queue(){
this.stack=new Array();
this.dequeue=function(){
return this.stack.pop();
};
this.enqueue=function(addition){
this.stack.unshift(addition);
};
}
function Stack(){
this.stack=new Array();
this.pop=function(){
return this.stack.pop();
};
this.push=function(item){
this.stack.push(item);
};
this.peek=function(){
return this.stack[this.stack.length-1];
};
this.empty=function(){
return (this.stack.length<1);
};
}
まず、単純な数学演算子 を使用し、+ - * / ^
各演算子の前後にスペースを入れて文字列をトークン化し、それを分割し、各トークンを次のように型、優先順位、結合性を備えたオブジェクトに変換します。
function tokenize(input){
input=str_replace(["+","-","*","/","^","(",")"],[" + "," - "," * "," / "," ^ "," ( "," ) "],input).replace(/\s{2,}/g, ' ').trim().split(" ");
for(var i in input){
input[i]=new operator(input[i]);
}
return input;
}
オブジェクトに変換するには、この関数を実行します。この関数は、入力が何であるかを確認し、優先順位、結合性、名前、および型を割り当てます。
function operator(name){
this.name=name;
this.associativity="left";
this.type="operator";
this.precedence=1;
if(isNumeric(name)){
this.type="numeric";
}
else if(name=="("){
this.type="open";
}else if(name==")"){
this.type="close";
}else if(name=="^"){
this.precedence=10;
this.associativity="right";
}else if(name=="*" || name=="/"){
this.precedence=5;
}else if(name=="+" || name=="-"){
this.precedence=1;
}
var op={
"name":this.name,
"type":this.type,
"associativity":this.associativity,
"precedence":this.precedence
};
return op;
}
最後に、シャント アルゴリズムがあります。これは、疑似コード here に従っていると思われます。
function shunt(input){
var operators=new Stack();
var output=new Queue();
for(var i in input){
var token=input[i];
console.log(token.name);
if(token.type=="operator"){
// console.log(token);
while(!operators.empty() && operators.peek().type=="operator"){
if((token.associativity=="left" && token.precedence==operators.peek()) || (token.precedence<operators.peek().precedence)){
output.enqueue(operators.pop().name);
}
}
operators.push(token);
}else if(token.type=="open"){
console.log(token);
operators.push(token);
}else if(token.type=="close"){
while (!operators.empty() && !operators.peek().type=="open") {
output.enqueue(operators.pop().name);
}
operators.pop();
}else{
output.enqueue(token.name);
}
}
while(!operators.empty()){
output.enqueue(operators.pop().name);
}
output.stack.reverse();
return output.stack;
}
のような単純なものをトークン化してシャントすると1+1
、期待される が返され1 1 +
ます。しかし、 を与えると1+1+1
、無限ループに陥ります。また、閉じ括弧の認識に問題があり、すべての括弧トークンを削除するわけではありません。たとえば、 と入力すると(1+1)
、 が出力され["1", "1", "("]
ます。誰かがアルゴリズムのどこにエラーがあるかを教えてくれますか?それを解決する方法についてのヒントを教えてください。何度か見直したのですが、括弧の扱いのどこが間違っているのかわかりません。
ありがとう