Сам себе интерпретатор. Часть 1
Сам себе интерпретатор.
Автор: Колесник Сергей aka John Frost
ICQ: 488-251
E-mail: john-frost@ya.ru
jf_calc_1.rar [69.82 Kb] (cкачиваний: 344)
Тебе никогда не приходило в голову узнать, как же все таки создаются языки программирования (ЯП). На них пишутся сложнейшие вычислительные системы, создаются операционные системы и виртуальные машины. На них создана программа, в которой вот и набран этот текст.
Мы с тобой не хуже всяких бородатых преподов в инсте, утверждающих, что создать свой ЯП чрезвычайно сложно, и не под силу обычному кодеру. И сейчас я расскажу, объясню и покажу, как можно легко и просто написать свой собственный язык, не имея никаких специализированных познаний в этой области. А в конце мы еще и накодим небольшую программку на своем собственном языке и с гордостью сможем показывать ее друзьям и удивленным учителям информатики. Так вперед же, вперед к запретным знаниям, вперед к кодингу проги, на которой, потом можно будет тоже кодить!
Кстати, чтобы не было недопонимания, целью этой статьи является написание интерпретатора, а не компилятора, во первых это легче и понятней, во вторых это даже, имхо, интересней. И еще, алгоритм создания этого интерпретатора я придумал сам, методом проб и ошибок, он не претендует на звание самого быстрого или алгоритмически правильного, я просто хочу показать как решил поставленную задачу. Поэтому, если есть какие-то претензии к функционалу конечного продукта – оставьте их при себе, если знаете как сделать лучше, то сделайте, с удовольствием выложу ваше творение на сайте. А это просто пример для обучения.
Первым делом анализаторы, но, а интерпретаторы потом.
Представим себе выражение вида «x2=((0-b)+D^(1/2))/(2*a);», вот примерно то, что дальше было бы разумно делать:
1)Вычислить выражение находящиеся справа от знака присваивания.
А) Заменить все переменные в выражении на их значения.
Б) Вычислить выражение в соответствие с приоритетам операций (скобки,умножение, деление и т.д.)
2) Присвоить полученное значение переменной слева.
Получается, что нам надо научить программу понимать и обрабатывать выражения записанные человеком, приводить их к виду понятному для компьютера. Что-то вроде упрощения.
Этим занимается часть кода, под названием синтаксический анализатор выражений. Отправной точкой в анализе является лексема. Все выражение, разбивается на множество лексем разных видов. Вот посмотрим на этот текст «IF a1==5 THEN x=3+7*5 ELSE x=(3-7)*2», подумаем, на какие лексемы его можно разбить: IF – команда, пробел – разделитель, а1 – переменная, == - логическое выражение, пробел – разделитель, THEN – команда, х –переменная, = - разделитель, 3 – число, + - разделитель и т.д. Давайте выясним какие типы лексем нам понадобятся:
1)Number – число, необходимо для каких-либо логических или алгебраических операций
2)Delimeter – разделитель, служит для разделения команд, чисел и переменных. К ним относятся +-*/()^:;<>!= и пробел.
3)Logic – логические типы, служат для выполнения каких-либо логических условий, к ним относятся равно ==, не равно !=, больше или равно >= и меньше или равно <=.
4)Variable – переменная. Можно записывать в нее значения и считывать, необходима для выполнения условий и математических операций.
5)Command – команда, такая как IF или GOTO. Позволяют менять логику выполнения программы, в зависимости от сложившихся условий. К тому же команды являются зарегистрированными словами, и их именами нельзя будет называть переменные.
Так, теперь мы обладаем нужной информацией для написания класса лексемы.
class Leksem//класс лексем
{
public static string[] CommandName ={ "IF", "THEN", "ELSE", "RETURN","GOTO","MSGBOX", "LABEL"};//ИМЕНА ЗАРЕГЕСТРИРОВАННЫХ СЛОВ
public enum LeksemType { Number, Delimeter, Variable,Command,Logic};//Типы лексем
public string name;//имя лексемы
public double value;//значение, если есть
public LeksemType Type;
public Leksem(string strname, LeksemType typess)//конструктор с именем и типом лексемы
{
name = strname;
Type = typess;
}
public Leksem(string strname, LeksemType typess, double val)//конструктор с именем. типом и значением лексемы
{
name = strname;
Type = typess;
value = val;
}
{
public static string[] CommandName ={ "IF", "THEN", "ELSE", "RETURN","GOTO","MSGBOX", "LABEL"};//ИМЕНА ЗАРЕГЕСТРИРОВАННЫХ СЛОВ
public enum LeksemType { Number, Delimeter, Variable,Command,Logic};//Типы лексем
public string name;//имя лексемы
public double value;//значение, если есть
public LeksemType Type;
public Leksem(string strname, LeksemType typess)//конструктор с именем и типом лексемы
{
name = strname;
Type = typess;
}
public Leksem(string strname, LeksemType typess, double val)//конструктор с именем. типом и значением лексемы
{
name = strname;
Type = typess;
value = val;
}
Как ты мог заметить, у нас будет 7 зарегестрированных слов, этого будет достаточно, чтобы реализовать, следование, условие и циклы – т.е. можно закодить в принципе любой алгоритм.
Так, мы создали уже описание лексемы, теперь давай напишем метод, который будет разбирать текст из входного потока в массив лексем. Это очень важная часть, т.к. все последующие операции будут проводится уже именно с лексемами.
public static ArrayList GetLeksemsFromString(string text)// выдает массив лексем из строки
{
double tmp;
ArrayList temp = new ArrayList();
int start = 0;
int end = 0;
string str = "";
for (int i = 0; i < text.Length; i++)
{
if (("+-/*%^=():;<>! ".IndexOf(text[i]) != -1))//если совпадает с вот этими символами то
{
end = i;
int length = end - start;
if(double.TryParse(text.Substring(start, length), out tmp))//если это число то записываем число до этого разделителя
temp.Add(new Leksem(text.Substring(start, length),Leksem.LeksemType.Number));
else if(char.IsLetter(text[start]))
{
if(vm.IsCommand(text.Substring(start, length)))
temp.Add(new Leksem(text.Substring(start, length), Leksem.LeksemType.Command));
else
temp.Add(new Leksem(text.Substring(start, length), Leksem.LeksemType.Variable));
}
switch (text[i])
{
case '<':
case '>':
case '!':
if (text[i + 1] == '=')
{
temp.Add(new Leksem(text.Substring(i, 2), Leksem.LeksemType.Logic));
i++;
}
else
{
temp.Add(new Leksem(text[i].ToString(), Leksem.LeksemType.Logic));
}
break;
case '=':
if (text[i + 1] == '=')
{
temp.Add(new Leksem(text.Substring(i, 2), Leksem.LeksemType.Logic));
i++;
}
else
temp.Add(new Leksem(text[i].ToString(), Leksem.LeksemType.Delimeter));
break;
default:
if (text[i].ToString() != ";" && text[i].ToString() != " ")
temp.Add(new Leksem(text[i].ToString(), Leksem.LeksemType.Delimeter));//записываем этот разделитель
break;
}
start = i+1;
}
}
return temp;
}
{
double tmp;
ArrayList temp = new ArrayList();
int start = 0;
int end = 0;
string str = "";
for (int i = 0; i < text.Length; i++)
{
if (("+-/*%^=():;<>! ".IndexOf(text[i]) != -1))//если совпадает с вот этими символами то
{
end = i;
int length = end - start;
if(double.TryParse(text.Substring(start, length), out tmp))//если это число то записываем число до этого разделителя
temp.Add(new Leksem(text.Substring(start, length),Leksem.LeksemType.Number));
else if(char.IsLetter(text[start]))
{
if(vm.IsCommand(text.Substring(start, length)))
temp.Add(new Leksem(text.Substring(start, length), Leksem.LeksemType.Command));
else
temp.Add(new Leksem(text.Substring(start, length), Leksem.LeksemType.Variable));
}
switch (text[i])
{
case '<':
case '>':
case '!':
if (text[i + 1] == '=')
{
temp.Add(new Leksem(text.Substring(i, 2), Leksem.LeksemType.Logic));
i++;
}
else
{
temp.Add(new Leksem(text[i].ToString(), Leksem.LeksemType.Logic));
}
break;
case '=':
if (text[i + 1] == '=')
{
temp.Add(new Leksem(text.Substring(i, 2), Leksem.LeksemType.Logic));
i++;
}
else
temp.Add(new Leksem(text[i].ToString(), Leksem.LeksemType.Delimeter));
break;
default:
if (text[i].ToString() != ";" && text[i].ToString() != " ")
temp.Add(new Leksem(text[i].ToString(), Leksem.LeksemType.Delimeter));//записываем этот разделитель
break;
}
start = i+1;
}
}
return temp;
}
Разберем теперь поподробней что же мы тут делаем. Наш метод принимает текст и возвращает ArrayList, в котором и будут все полученные лексемы. Перебираем посимвольно текст, если находим символ из разряда разделителя, то смотрим что у нас было, от найденного символа до прошлого разделителя, если это число, то добавляем в ArrayList лексему типа число и ее значение:
if(double.TryParse(text.Substring(start, length), out tmp))//если это число то записываем число до этого разделителя
temp.Add(new Leksem(text.Substring(start, length),Leksem.LeksemType.Number));
temp.Add(new Leksem(text.Substring(start, length),Leksem.LeksemType.Number));
Если это не число (начинается с символа, а не цифры), то проверяем является ли это переменной либо командой и заносим в результирующий массив:
else if(char.IsLetter(text[start])
{
if(vm.IsCommand(text.Substring(start, length)))
temp.Add(new Leksem(text.Substring(start, length), Leksem.LeksemType.Command))
else
temp.Add(new Leksem(text.Substring(start, length), Leksem.LeksemType.Variable));
}
{
if(vm.IsCommand(text.Substring(start, length)))
temp.Add(new Leksem(text.Substring(start, length), Leksem.LeksemType.Command))
else
temp.Add(new Leksem(text.Substring(start, length), Leksem.LeksemType.Variable));
}
Вот метод, который проверяет, является ли это слово командой, пока не задавайтесь вопросом, откуда он, он встроен в менеджер переменных, который мы чуть позже напишем.
public bool IsCommand(string name)//Является ли это зарегестрированным словом или нет
{
for (int i = 0; i < Leksem.CommandName.Length; i++)
{
if (Leksem.CommandName[i] == name)
return true;
}
return false;
}
{
for (int i = 0; i < Leksem.CommandName.Length; i++)
{
if (Leksem.CommandName[i] == name)
return true;
}
return false;
}
Далее, используя switch, мы проверяем, является ли это слово логическим выражение. Также мы определяем, является ли равно двойным, и если это так, значит это тоже логическое выражение, иначе это просто разделитель.
switch (text[i])
{
case '<':
case '>':
case '!':
if (text[i + 1] == '=')
{
temp.Add(new Leksem(text.Substring(i, 2), Leksem.LeksemType.Logic));
i++;
}
else
{
temp.Add(new Leksem(text[i].ToString(), Leksem.LeksemType.Logic));
}
break;
case '=':
if (text[i + 1] == '=')
{
temp.Add(new Leksem(text.Substring(i, 2), Leksem.LeksemType.Logic));
i++;
}
else
temp.Add(new Leksem(text[i].ToString(), Leksem.LeksemType.Delimeter));
break;
{
case '<':
case '>':
case '!':
if (text[i + 1] == '=')
{
temp.Add(new Leksem(text.Substring(i, 2), Leksem.LeksemType.Logic));
i++;
}
else
{
temp.Add(new Leksem(text[i].ToString(), Leksem.LeksemType.Logic));
}
break;
case '=':
if (text[i + 1] == '=')
{
temp.Add(new Leksem(text.Substring(i, 2), Leksem.LeksemType.Logic));
i++;
}
else
temp.Add(new Leksem(text[i].ToString(), Leksem.LeksemType.Delimeter));
break;
Затем мы записываем сам разделить в массив лексем, исключая при этом точку с запятой ; и пробел, т.к. они нам не нужны будут.
default:
if (text[i].ToString() != ";" && text[i].ToString() != " ")
temp.Add(new Leksem(text[i].ToString(), Leksem.LeksemType.Delimeter));//записываем этот разделитель
if (text[i].ToString() != ";" && text[i].ToString() != " ")
temp.Add(new Leksem(text[i].ToString(), Leksem.LeksemType.Delimeter));//записываем этот разделитель
Математика-шматематика
На лексемы мы уже разобрали, теперь напишем метод, который будет высчитывать простейшие арифметические операции, по их приоритету, но без скобок и переменных. Т.е. это будет самый нижний уровень упрощения, он будет вычислять уже то, что было упрощенно от скобок и переменных. Упрощению подлежат три лексемы, левый операнд, оператор и правый операнд. Например “3+7+9”, тут пять лексем, три числа и два разделителя. Сначала подлежат упрощению первые три, а именно “3+7”, результат будет 10, значит мы уже получим вот такую последовательность “10+9”, упростим ее и в конечном итоге останется всего лишь “19”.
Вырисовывается алгоритм упрощения:
1)Находим лексему-разделитель
2)Вычисляем выражение
3)Заносим результат в левый операнд, а лексему-разделитель и правый операнд удаляем из списка лексем.
В коде это выглядит так:
case "*":
((Leksem)leksems[i - 1]).name = ((double.Parse(((Leksem)leksems[i - 1]).name)) * (double.Parse(((Leksem)leksems[i + 1]).name))).ToString();
((Leksem)leksems[i - 1]).Type = Leksem.LeksemType.Number;
leksems.RemoveAt(i);
leksems.RemoveAt(i);
((Leksem)leksems[i - 1]).name = ((double.Parse(((Leksem)leksems[i - 1]).name)) * (double.Parse(((Leksem)leksems[i + 1]).name))).ToString();
((Leksem)leksems[i - 1]).Type = Leksem.LeksemType.Number;
leksems.RemoveAt(i);
leksems.RemoveAt(i);
Так, простые выражения анализировать и решать научились, теперь научимся разбирать выражения со скобками. Делается это в принципе легко – создаем объект типа stack, он может хранить в себе данные, по типу последним вошел, первым вышел. Зачем это нужно? Да вот зачем, нам нужно выделить выражение между скобками. Делается это элементарно, перебираем все лексемы, открывающиеся скобки заносим в стек, а если находим закрывающуюся скобку, то просто достаем последнюю найденную открывающуюся и вуаля – у нас в руках простое выражение, которое мы уже научились вычислять.
Единственное что я объясню позже – так это упрощение переменных, а пока просто не обращай внимание на эту строчку.
public static double GetExpressionFromBrackets(ArrayList leksems)//упрощаем скобки. оставляем одни выражения
{
leksems = vm.GetExpressionWithoutVariables(leksems); //убираем переменные
Stack openstack = new Stack();//стек для открывающихся скобок
double result; int tmp = 0;
for (int i = 0; i < leksems.Count; i++)//проходимся по всем лексемам
{
switch (((Leksem)leksems[i]).name)
{
case "("://если открывающаяся скобка
openstack.Push(new bracket(i));//запихиваем в стек скобку
break;
case ")"://если закрывающаяся скобку
if (openstack.Count >= 1)//если там есть хоть одна открывающаяся скобка
{
bracket tb = ((bracket)openstack.Pop());//вытаскиваем из стека скобку открывающаяся
ArrayList toResult = new ArrayList();//массиво лексем между скобками
leksems.RemoveAt(tb.start);//удаляем открывающуюся скобку
for (int j = tb.start; j < i - 1; j++)//заполняем массив лексемами между скобок и удаляем эти лексемы
{
toResult.Add(leksems[tb.start]);
leksems.RemoveAt(tb.start);
}
leksems[tb.start] = new Leksem(GetResult(toResult).ToString(), Leksem.LeksemType.Number);//вместо закрывающей скобки записываем вычесленное выражение в этих скобках
i = -1;//цикл начнем сначала
openstack.Clear();//очистим стек
}
else//СКОБКИ НЕ ПРАВИЛЬНО РАССТАВЛЕНЫ
{
MessageBox.Show("Неправильно расставлены скобки!", "Ошибка!");
return 0.0;
}
break;
}
}
return GetResult(leksems);//вычесляем уже упрощенное от скобок выражений
}
struct bracket//структура для скобок
{
public int start;
public bracket(int startnum)
{
start=startnum;
}
}
{
leksems = vm.GetExpressionWithoutVariables(leksems); //убираем переменные
Stack openstack = new Stack();//стек для открывающихся скобок
double result; int tmp = 0;
for (int i = 0; i < leksems.Count; i++)//проходимся по всем лексемам
{
switch (((Leksem)leksems[i]).name)
{
case "("://если открывающаяся скобка
openstack.Push(new bracket(i));//запихиваем в стек скобку
break;
case ")"://если закрывающаяся скобку
if (openstack.Count >= 1)//если там есть хоть одна открывающаяся скобка
{
bracket tb = ((bracket)openstack.Pop());//вытаскиваем из стека скобку открывающаяся
ArrayList toResult = new ArrayList();//массиво лексем между скобками
leksems.RemoveAt(tb.start);//удаляем открывающуюся скобку
for (int j = tb.start; j < i - 1; j++)//заполняем массив лексемами между скобок и удаляем эти лексемы
{
toResult.Add(leksems[tb.start]);
leksems.RemoveAt(tb.start);
}
leksems[tb.start] = new Leksem(GetResult(toResult).ToString(), Leksem.LeksemType.Number);//вместо закрывающей скобки записываем вычесленное выражение в этих скобках
i = -1;//цикл начнем сначала
openstack.Clear();//очистим стек
}
else//СКОБКИ НЕ ПРАВИЛЬНО РАССТАВЛЕНЫ
{
MessageBox.Show("Неправильно расставлены скобки!", "Ошибка!");
return 0.0;
}
break;
}
}
return GetResult(leksems);//вычесляем уже упрощенное от скобок выражений
}
struct bracket//структура для скобок
{
public int start;
public bracket(int startnum)
{
start=startnum;
}
}
Добавляем переменные
Настало время, объяснить то, о чем я еще в самом начале упоминал – о переменных. Переменные нуждаются в управлении, добавлении, получении значения и т.д. Поэтому мы напишем свой менеджер переменных, который и будет этим всем заниматься. Кстати, небольшое отступление, когда я начал интересоваться вопросом как добавить переменные в выражения, я наткнулся на пример Г. Шилдта, известного писателя книг по кодингу. У него было показано как добавить переменные только с именами от A до Z, т.е. всего 26 переменных, с фиксированными однобуквенными именами. Конечно, этого в принципе должно хватить и всё такое, но хочется, чтобы все было как-то “по взрослому”. И поэтому я решил поделиться с тобой информацией о том, как сделать возможным добавление любого кол-ва переменных, с любыми именами, и они будут использоваться сразу после того места, где вы впервые их заюзаете, т.е. объявлять не надо. Тип переменных по умолчанию double, но если у тебя будет желание – можешь добавить разные типы, просто ради компактности, и чтобы не забивать мозги, пока ввел только числовые переменные, хотя ввести текст будет делом 10 минут – ну пусть это будет твои домашним заданием
Я уже говорил, что написание такого менеджера просто? Так вот, это не правда. Написание такого менеджера чрезвычайно просто . Подумаем, из чего состоит переменная – из имени и значения. Какой же вывод? А вывод вот в чем – для хранения данных в формате ключ-значение подойдет объект hashtable. Теперь мы можем просто очень просто написать метод для добавления переменной:
Hashtable variables;
public void AddVariable(string name, double value)
{
if(variables[name]==null)
variables.Add(name, value);
}
public void AddVariable(string name, double value)
{
if(variables[name]==null)
variables.Add(name, value);
}
А методы для записи значения в переменную и чтения значения из него будут такими:
public void SetVariableValue(string name, double value)
{
AddVariable(name, value);
variables[name] = value;
}
public double GetVariableValue(string name)
{
if (variables[name] != null)
return ((double)variables[name]);
else
AddVariable(name, 0.0);
return 0.0;
}
{
AddVariable(name, value);
variables[name] = value;
}
public double GetVariableValue(string name)
{
if (variables[name] != null)
return ((double)variables[name]);
else
AddVariable(name, 0.0);
return 0.0;
}
Теперь же владея такими функциями, мы можем уже реализовать метод для замены всех переменных в выражениях на их значения:
public ArrayList GetExpressionWithoutVariables(ArrayList leksems)
{
for (int i = 0; i < leksems.Count; i++)//проходимся по всем лексемам, добавляем переменные, если их не добавили
{
if (((Leksem)leksems[i]).Type == Leksem.LeksemType.Variable)
this.AddVariable(((Leksem)leksems[i]).name, 0.0);
}
for (int i = 0; i < leksems.Count; i++)//проходимся по всем лексемам, заменяеи переменные на их значения
{
if (((Leksem)leksems[i]).Type == Leksem.LeksemType.Variable)
leksems[i] = new Leksem(this.GetVariableValue(((Leksem)leksems[i]).name).ToString(), Leksem.LeksemType.Number);
}
return leksems;
}
{
for (int i = 0; i < leksems.Count; i++)//проходимся по всем лексемам, добавляем переменные, если их не добавили
{
if (((Leksem)leksems[i]).Type == Leksem.LeksemType.Variable)
this.AddVariable(((Leksem)leksems[i]).name, 0.0);
}
for (int i = 0; i < leksems.Count; i++)//проходимся по всем лексемам, заменяеи переменные на их значения
{
if (((Leksem)leksems[i]).Type == Leksem.LeksemType.Variable)
leksems[i] = new Leksem(this.GetVariableValue(((Leksem)leksems[i]).name).ToString(), Leksem.LeksemType.Number);
}
return leksems;
}
Вот вообщем-то и все, вот таким простым способом мы создали функциональный менеджер переменных. Можно даже остановиться на текущем результате и получить клевый калькулятор с поддержкой переменных. Но мы пойдем до конца, и все-таки сделаем интерпретатор.
Продолжение здесь.
- Просмотров: 10631
Версия для печати
#1
Spatial |
Spatial | Супер статейка! Спасибо John Frost!
Дата публикации: 3 января 2009 13:58 | ICQ: --
цитировать
цитировать
#2
ak_featZima |
ak_featZima | А я предлагаю всё-таки довести проект до ума =) Обвесить интепритатор средой разработки, компиляции и распространения... Понаделать кучу либ и плагинов... В конце-концов просто завоевать мир ;) С Новым Годом!!!
Дата публикации: 4 января 2009 01:59 | ICQ: --
цитировать
цитировать
#3
John Frost |
John Frost | 
советую обратится у психоаналитику и захватить хотя бы свою комнату:)
С новым годом!
С новым годом!
Дата публикации: 4 января 2009 08:45 | ICQ: 488251
цитировать
цитировать
#4
Vanger |
Vanger | 
талмуд все ж монументальный
сразу в голову пришла идея, что нужно делать разделение таких статей на страницы.. чтобы не все сразу показывалось. ориентироваться сложно
сразу в голову пришла идея, что нужно делать разделение таких статей на страницы.. чтобы не все сразу показывалось. ориентироваться сложно
Дата публикации: 4 января 2009 13:18 | ICQ: --
цитировать
цитировать
#5
DimaVT |
DimaVT | 
А предпочел бы чтоб проект довели до ума и создали язык в котором сложнейшие программы делались лишь указанием цели програмы 
Дата публикации: 4 января 2009 20:02 | ICQ: --
цитировать
цитировать
#6
Vanger |
Vanger | 
DimaVT
сначала цель нужна. для чего нужен новый язык программирования ?
сначала цель нужна. для чего нужен новый язык программирования ?
Дата публикации: 4 января 2009 20:09 | ICQ: --
цитировать
цитировать
#7
ak_featZima |
ak_featZima | сначала цель нужна. для чего нужен новый язык программирования ?
Согласен!!! Готов на любой существующий... мне нужен интерпретатор с возможностью вызова функций в либах и с передачей произвольных параметров в них... а ещё чтобы работал быстро, и желательно без .NET...
Так что делайте ) Вы же, ёпт, программисты! Сделай те хоть раз до конца что либо рабочее...
Дата публикации: 5 января 2009 10:42 | ICQ: --
цитировать
цитировать
#8
Vanger |
Vanger | 
)))))
я через пару дней рабочее выложу
но оно узкоприкладное:)
я через пару дней рабочее выложу
но оно узкоприкладное:)
Дата публикации: 5 января 2009 22:59 | ICQ: --
цитировать
цитировать
#9
John Frost |
John Frost | 
Так что делайте ) Вы же, ёпт, программисты! Сделай те хоть раз до конца что либо рабочее...
Кстати, чтобы не было недопонимания, целью этой статьи является написание интерпретатора, а не компилятора, во первых это легче и понятней, во вторых это даже, имхо, интересней. И еще, алгоритм создания этого интерпретатора я придумал сам, методом проб и ошибок, он не претендует на звание самого быстрого или алгоритмически правильного, я просто хочу показать как решил поставленную задачу. Поэтому, если есть какие-то претензии к функционалу конечного продукта – оставьте их при себе, если знаете как сделать лучше, то сделайте, с удовольствием выложу ваше творение на сайте. А это просто пример для обучения.
Вот для кого я это писал???
Согласен!!! Готов на любой существующий... мне нужен интерпретатор с возможностью вызова функций в либах и с передачей произвольных параметров в них... а ещё чтобы работал быстро, и желательно без .NET...
Их целая куча, бери и юзай, не надо путать пример для обучения и реальные программы. Руби/Луа тебе в зубы и вперед!
Дата публикации: 5 января 2009 23:06 | ICQ: 488251
цитировать
цитировать
#10
featZima |
featZima | 
Их целая куча, бери и юзай
А можно с этого места поподробнее ?)
Дата публикации: 6 января 2009 13:26 | ICQ: 436090461
цитировать
цитировать
#11
John Frost |
John Frost | 
Lisp, Scheme, Python, Бейсик, PHP, Perl, Forth и т.д.
Дата публикации: 6 января 2009 16:32 | ICQ: 488251
цитировать
цитировать
#12
featZima |
featZima | 
И какой из этих интерпретаторов позволит мне вывести иконку в трее с сообщением?) 
Дата публикации: 6 января 2009 20:10 | ICQ: 436090461
цитировать
цитировать
#13
John Frost |
John Frost | 
А какой из этих лимузинов позволит мне дачу вскопать?
Бери бейзик и вызывай апи, и че хошь выводи. Только степень оценки полезности языков твоя меня поражает.
В этой статьей, еслиб ты правильно все прочел, ты бы увидел, что с помощью моего интерпретатора это легко делается и в трее мессадж вывести, и окнами потрясти....
Бери бейзик и вызывай апи, и че хошь выводи. Только степень оценки полезности языков твоя меня поражает.
В этой статьей, еслиб ты правильно все прочел, ты бы увидел, что с помощью моего интерпретатора это легко делается и в трее мессадж вывести, и окнами потрясти....
Дата публикации: 7 января 2009 10:52 | ICQ: 488251
цитировать
цитировать
#14
featZima |
featZima | 
Ладно.... сообщения я выведу, а если мне нужно полностью интерфей делать, то же на API ?)
Дата публикации: 7 января 2009 10:55 | ICQ: 436090461
цитировать
цитировать
#15
John Frost |
John Frost | 
Ты не поверишь, но сцуко, проги на винде работают через WinAPI. Даже если это C#-прога, она вызывает функции из фреймворка, а тот уже напрямую винапи. Я не пойму, чего ты хочешь? Тебя не устраивают существующие языки? Я показал небольшие основы - напиши свой.
Дата публикации: 7 января 2009 10:59 | ICQ: 488251
цитировать
цитировать
#16
ak_featZima |
ak_featZima | Я хочу интерпретатор, который позволит мне создавать формочки с кнопочками при этом не городя при этом кучу системных вызовов типа CreateWindows, RegisterClass...
Дата публикации: 7 января 2009 14:42 | ICQ: --
цитировать
цитировать
#17
Vanger |
Vanger | 
нехило вы тут нафлудили
а вообще при всем хорошем отношении к featZime, говорить "я хочу ...." неправильно без изучения того что сейчас УЖЕ создано
создавать новый язык (исполняемый или компилируемый, неважно) надо тоже с предварительным изучением существующих технологий
а вообще при всем хорошем отношении к featZime, говорить "я хочу ...." неправильно без изучения того что сейчас УЖЕ создано
создавать новый язык (исполняемый или компилируемый, неважно) надо тоже с предварительным изучением существующих технологий
Дата публикации: 7 января 2009 14:46 | ICQ: --
цитировать
цитировать
#18
John Frost |
John Frost | 
+1
"Я хочу" не имеет смысла. Ты сначала изучи созданные технологии, а то будет как здесь http://coderszone.info/forum/index.php?showtopic=401&pid=1061&st=0
"Я хочу" не имеет смысла. Ты сначала изучи созданные технологии, а то будет как здесь http://coderszone.info/forum/index.php?showtopic=401&pid=1061&st=0
Дата публикации: 7 января 2009 17:46 | ICQ: 488251
цитировать
цитировать
#19
ak_featZima |
ak_featZima | Учить все могут, а вот вы возьмите и сделайте!
Дата публикации: 8 января 2009 22:38 | ICQ: --
цитировать
цитировать
#20
John Frost |
John Frost | 
Пля.... опять за старое. А сделаю такой интерпретатор, а ты купи слона?
Дата публикации: 9 января 2009 09:46 | ICQ: 488251
цитировать
цитировать
#21
featZima |
featZima | 
Разве что игрушечного =) Но я согласен !
Дата публикации: 9 января 2009 13:49 | ICQ: 436090461
цитировать
цитировать
#22
John Frost |
John Frost | 
Ну вот игрушечный интерпретатор я тоже сделал:-) Обвесь его фишками какими нужны и будет настоящий
Дата публикации: 9 января 2009 13:51 | ICQ: 488251
цитировать
цитировать
#23
John Frost |
John Frost | 
ЧУВАКИ!!!! Кароче, тут нехватет еще куска статьи! Прикинь, статья не поместилась!!!! кашмар
Дата публикации: 10 января 2009 18:48 | ICQ: 488251
цитировать
цитировать
#25
Джон Фрост |
Джон Фрост | Не могу!!! Предел символов:(
Дата публикации: 13 января 2009 11:57 | ICQ: --
цитировать
цитировать
#26
Vanger |
Vanger | 
с пределом символов разберемся
может надо дополнение к движку сделать
p.s. нехило вы тут нафлудили (и я вместе с вами:D)
может надо дополнение к движку сделать
p.s. нехило вы тут нафлудили (и я вместе с вами:D)
Дата публикации: 13 января 2009 15:26 | ICQ: --
цитировать
цитировать
#27
DeXPeriX |
DeXPeriX | 
Эххх. Интерпретатор создавать не очень сложно. И в современности нужно редко. Я то свой уже написал (диалект LaTeX'a). Но это были чистые понты и желание попрактиковаться в С++. Не думаю, что он реально окажется кому-то полезным...
А вот про компилятор я б почитал статейку аля "Создаём свой компилятор за 200 строк кода" и т.п. Но там же реальные сложности будут, да и чтоб что-то хотябы такого уровня как в статье, только компилировалось в Windows-EXE - целые книги пишут :(
ЗЫ Имхо, писать интерпретатор в интерпретируемом языке - изврат ;) :) {ну, частично интерпретируемом :-P}
Кстати, почему система комментов не воспринимает человеческие смайлики? o_O
Опять же, имхо, смайл в 2 символа писать удобнее и привычнее ;)
А вот про компилятор я б почитал статейку аля "Создаём свой компилятор за 200 строк кода" и т.п. Но там же реальные сложности будут, да и чтоб что-то хотябы такого уровня как в статье, только компилировалось в Windows-EXE - целые книги пишут :(
ЗЫ Имхо, писать интерпретатор в интерпретируемом языке - изврат ;) :) {ну, частично интерпретируемом :-P}
Кстати, почему система комментов не воспринимает человеческие смайлики? o_O
Опять же, имхо, смайл в 2 символа писать удобнее и привычнее ;)
Дата публикации: 18 января 2009 23:48 | ICQ: 606986
цитировать
цитировать
#28
Джон Фрост |
Джон Фрост | Вот не понимаю я некоторых личностей:-) Ну я же показывал только как для обучения. А насчет современности, возьми любой большой продукт - MS OFFICE, 1С, да хоть mIRC. У них у всех встроенный язык, тоже интерпретируемый. Просто если вы способны написать ваш собственный язык, но при этом не знаете куда его деть и как использовать - то грош цена таким знаниям. Мой "изврат" используется в достаточно крупной промышленной программе. Ну нельзя было в моем случае компилировать в ехе. Интерпретаторы - это не покалеченный компилятор, это инструмент для других нужд.
А насчет того, о чем писать, так вот всяких статей о том как сделать троян или емэил-клиент дохренища, и каждый второй пишет, и ничего, все равно нужны.
А насчет того, о чем писать, так вот всяких статей о том как сделать троян или емэил-клиент дохренища, и каждый второй пишет, и ничего, все равно нужны.
Дата публикации: 19 января 2009 15:17 | ICQ: --
цитировать
цитировать
#29
DeXPeriX |
DeXPeriX | 
Ты б ещё PHP, Python etc вспомнил. Конечно, интерпретируемые языки активно используются. Но нормальные языки редко пишутся одним человеком и уж далеко не за несколько дней
>Просто если вы способны написать ваш собственный язык, но при этом не знаете куда его деть и как использовать - то грош цена таким знаниям.
Мне понадобился язык - я его написал. А так чтобы умышлено ещё один язык для чего-то делать, имхо, не нужно
>Мой "изврат" используется в достаточно крупной промышленной программе.
Чем lua не катит в твоём случае?
Статья полезная, не спорю. Меня только C# смущает. Религия не позволяет...
>Просто если вы способны написать ваш собственный язык, но при этом не знаете куда его деть и как использовать - то грош цена таким знаниям.
Мне понадобился язык - я его написал. А так чтобы умышлено ещё один язык для чего-то делать, имхо, не нужно
>Мой "изврат" используется в достаточно крупной промышленной программе.
Чем lua не катит в твоём случае?
Статья полезная, не спорю. Меня только C# смущает. Религия не позволяет...
Дата публикации: 19 января 2009 15:28 | ICQ: 606986
цитировать
цитировать
#30
Джон Фрост |
Джон Фрост | Мне понадобился язык - я его написал. А так чтобы умышлено ещё один язык для чего-то делать, имхо, не нужно
Вот это тафтология:-) Т.е. тебе понадобился язык просто так, и ты не умышленно его написал:) Я все пишу для какой-либо цели. Возникла проблема - решил. Но, не просто так, уже нет такой возможности:(
Чем lua не катит в твоём случае?
Я бы потратил столько-же или больше времени на освоение, внедрение и сопровождение. ЗАпросы слишком малы были, а Луа стоит юзать если цели грандиозны.
Статья полезная, не спорю. Меня только C# смущает. Религия не позволяет...
Ну так я планирую написать и улучшить версию для Явы :-) А Ява многорелигиозная:-)
Дата публикации: 19 января 2009 15:36 | ICQ: --
цитировать
цитировать


