Для школьного проекта я и одноклассник пишем предметно-ориентированный язык в javascript (узел).Язык содержит операторы, которые требуют пользовательского ввода через соединение Websocket.
Когда оператор требует пользовательского ввода, интерпретатор должен прекратить выполнение и ждать события.
Обычно можно приостановить потоки дождаться получения пользовательского ввода, прежде чем продолжить поток, но мы не можем этого сделать, так как node.js является однопоточным и не предлагает опции сна без блокировки процессора.
Мы пробовали много способовобойти это, но не удалось.: - (
Ответом на этот вопрос может быть предложение о том, как сделать переводчика с паузой.
Ниже мы рассмотрим упрощение интерпретатора (с ошибками)
Мы строим абстрактное синтаксическое дерево с этими узлами
var Print = function( str ){
this.str = str;
}
var Block = function( stats ){
this.stats = stats;
}
var Delayed = function( stats ){
this.stats = stats;
}
var Loop = function( times, stats ){
this.times = times;
this.stats = stats;
}
- Печать - простое утверждение, которое никогда не нужно останавливать.
- Блок - последовательность операторов
- Задержка - последовательность операторов, которая будет выполнена через некоторое время.
- Цикл - несколько итераций последовательности операторов
Дерево выглядит так:
var ast = new Block([
new Delayed([
new Print("blah blah"),
new Delayed([])
]),
new Loop(3,[
new Delayed([
new Print("loop delayed")
])
])
]);
Интерпретатор использовал для оценки операторов. Обратите внимание, что этот код не работает должным образом. Он никогда не приостанавливает ожидание ввода.
var Interpreter = function( ast ){
this.ast = ast;
}
Interpreter.prototype.run = function(){
this.handle( this.ast );
}
Interpreter.prototype.handleAll = function( stats ){
for( var i = 0; i < stats.length; i++ ){
this.handle(stats[i]);
}
}
Interpreter.prototype.handle = function( stat ){
var t = this;
/*-----------------------------------------------*
* Simple statement - no need for pause here *
*-----------------------------------------------*/
if( stat instanceof Print ){
sys.puts(stat.str);
}
/*-----------------------------------------------------*
* Delayed - this might contain more delayed stats *
*-----------------------------------------------------*/
else if( stat instanceof Delayed ){
sys.debug("waiting for user input");
// this represents a user input with a string
setTimeout(function(str){
sys.debug("done waiting");
sys.puts(str);
// this might contain delayed stats
t.handleAll(stat.stats);
}, 2000, "some string");
}
// ============================================
// = Block - this might contain delayed stats =
// ============================================
else if( stat instanceof Block ){
sys.debug("doing a block - before");
this.handleAll(stat.stats);
sys.debug("doing a block - after");
}
// ===========================================
// = Loop - this might contain delayed stats =
// ===========================================
else if( stat instanceof Loop ){
sys.debug("before loop");
for( var i = 0; i < stat.times; i++ ){
sys.debug("inside loop[" + i + "] - begin");
// this will maybe contain delayed stats
this.handleAll(stat.stats);
sys.debug("inside loop[" + i + "] - end");
}
sys.debug("after loop");
}
else {
throw "error.. statement not recognized"
}
}
Интерпретатор должен останавливаться, когдаОператор "Delayed" встречается, а затем продолжается, когда задержка завершена.
Приведенный выше код никогда не останавливается. Когда встречается оператор "Delayed", подсостояния задерживаются, но другое состояниепосле задержки «Задержка».
Для не фрагментированной версии кода, se http://pastie.org/1317023