EDIT: Полный код с интерактивностью: http://jsfiddle.net/LDEGe/2/Проблемы с Шунтированием Yard Алгоритм
Я вводный CS студентом в средней школе, а также в качестве побочного проекта, не связанного с классом, я пытаюсь создать простой математического анализатора с использованием алгоритма Шунтин-Ярд. Я понимаю pseudocode здесь, но у меня возникли проблемы с преобразованием его в код 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);
};
}
Для начала, я только с помощью простых математических операторов, + - */^
и tokenizing строки, помещая пространство вокруг каждый оператора, а затем разделив его, и преобразование каждого лексем в объект, с типом, старшинства и ассоциативности, как этот
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;
}
Наконец, у меня есть алгоритм шунтирование, который, как я думал, что вслед за псевдокод здесь
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", "("]
. Может ли кто-нибудь указать мне, где находятся ошибки в алгоритме, и дать мне несколько советов о том, как его решить? Я просматривал это несколько раз, но я не вижу, где ошибка при обработке круглых скобок.
Благодаря
Где указано str_replace Я думаю, что это может быть одна из проблем – megawac
@megawac oops, забыли упомянуть, я использую phpjs – scrblnrd3
Я думаю, что первым шагом в разрешении этого было бы заменить str_replace из phpjs чистым JS код. Вы знаете, как использовать регулярные выражения? – Chandranshu