Если интересно, то у меня вот такой исходный код:
a1 +1 0 0 b1 -1 0 0 c1 -1 0 4 d1 +1 0 4 end c 255 : .+. 255 0 2 0 q a1 b1 c1 d1
Внутри интерпретатора имеет такой вид, как видно, просто линейно вызываются процедуры одна за другой:
id00000010 RunChilds (exec args) id00000000 pnt3Flt id00000001 "+1" id00000002 "0" id00000003 "0" id00000004 pnt3Flt id00000005 "-1" id00000006 "0" id00000007 "0" id00000008 pnt3Flt id00000009 "-1" id0000000A "0" id0000000B "4" id0000000C pnt3Flt id0000000D "+1" id0000000E "0" id0000000F "4" id00000014 .+. id00000015 "255" id00000016 "0" id00000013 : id00000014 ".+." id00000017 "2" id00000011 glColor id00000012 "255" id00000013 ":" id00000018 "0" id0000001A GL_QUADS id0000001B glVertex3fv id00000000 "pnt3Flt" id0000001C glVertex3fv id00000004 "pnt3Flt" id0000001D glVertex3fv id00000008 "pnt3Flt" id0000001E glVertex3fv id0000000C "pnt3Flt"
Распространения констант пока что нету.
как вариант, можно сделать текстовый конвертер.
Типа так!
свой язык + свои функции -> конвертируется в обычный исходный код Delphi или С++ и потом этот конечный код
компилировать в профессианально-отлаженной IDE типа Visual Studio или в другой аналогичной.
dige
> Типа так!
>
> свой язык + свои функции -> конвертируется в обычный исходный код Delphi или
> С++
Без разницы, - что в машинный код, что в исходный код какого-либо языка программирования... основная работа, - всё равно - распарсить исходный код (частично автоматизируется существующими инструментами) и составить дерево разбора (оно же в вырожденном состоянии - абстрактное синтаксическое дерево). Потом, используя это дерево, - применив к нему, при обходе узлов, 100500 проверок (определены ли используемые переменные/функции, совпадают ли типы присваиваемых значений - типам переменных, попадают ли числовые данные в свои диапазоны, итд, итп - можно собственно сгенерировать нужный нам код (либо бинарный, либо исходный другого языка). То же самое дерево разбора используется для подсветки синтаксиса в IDE,... только тут ещё нужна продвинутая система восстановления после ошибок.
Да это будет не просто текстовый редактор, а текстовый процессор !
Но зато в необходимости коммутации с компилятором нету!
Я однажды попробовал написать на ассемблере и С++ один и тот же код, одинаковые по "логике работы" и тестировал с помощью высокоточного таймера.
Visual Studio оптимизировал мой "чистый" С++ код в несколько раз лучше, чем то, что я написал на ассемблере.
Это были вставки, вот так
__asm
{
}
0iStalker
Мне, кстати, тоже наиболее удобным кажется COCO/R или PegGrammar.
COCO/R очень слабый. На LL(1) далеко не уедешь. Даже C# не разобрать.
PegGrammar (это как я понимаю ты про немерловый макрос) не смотря на то что разбирает намного более широкий класс языков чем COCO/R признан тупиковой веткой и больше развиваться не будет.
Вот будущее немерловых парсеров. Находится в активной разработке.
https://github.com/rampelstinskin/ParserGenerator/
Умеет левую (с небольшими ограничениями не существенными на практике) и правую рекурсию.
Поддерживает приоритеты и ассоциативность операторов.
Поддерживает неограниченное заглядывание вперед.
Умеет (!) менять грамматику во время разбора. Те встретил например "using XmlGrammar;" и добавил правила разбора XML’я. Область видимости закончилась правила разбора XML’я выгрузились.
>Без разницы, - что в машинный код, что в исходный код какого-либо языка программирования...
Это, мягко говоря, не совсем так.
В остальном согласен.
Кстати компиляторы в любом случае нужно писать на языках поддерживающих pattern matching. Очень сильно помогает делать те самые "100500 проверок".
а как насчёт первозданного дубового варианта - пусть язык будет с ограничениями и костылями, зато маленький и с IDE. То есть пусть будет Г(громоздко:), но зато не на основе чужого Г(громоздкого продукта:). Использование всех этих куку-коко тоже конечно дело хорошее, но для достижений несколько другого плана, решения более повседневных унылых задач.
tmtlib
> Использование всех этих куку-коко тоже конечно дело хорошее, но для достижений
> несколько другого плана, решения более повседневных унылых задач.
Поверь, с использованием этих ку-ку и ко-ко дубовое делается быстрее
ЗЫ.
Ах, да,... продолжаем, начатое в #4
Заготовки для постройки дерева разбора
ast.h
#ifndef __AST_H__ #define __AST_H__ #include <string> #include <vector> #include <iostream> class NodeAST { public: virtual ~NodeAST(){}; virtual void print( ) = 0; }; class IntNodeAST : public NodeAST { std::string val; public: IntNodeAST( std::string v):val( v){} void print( ) { std::cout<<val; } }; class VarNodeAST : public NodeAST { std::string var; public: VarNodeAST( std::string n):var( n){} void print( ) { std::cout<<var; } }; class BinOpNodeAST : public NodeAST { int op; NodeAST* lhs; NodeAST* rhs; public: BinOpNodeAST( int o, NodeAST* l, NodeAST* r): op( o), lhs( l), rhs( r){} void print( ) { std::cout<<"( "; lhs->print( ); switch( op) { case 1: std::cout<<"+"; break; case 2: std::cout<<"-"; break; case 3: std::cout<<"*"; break; case 4: std::cout<<"/"; break; } rhs->print( ); std::cout<<" )"; } }; class UnOpNodeAST : public NodeAST { int op; NodeAST* rhs; public: UnOpNodeAST( int o, NodeAST* r): op( 0), rhs( r){} void print( ) { switch( op) { case 1: std::cout<<"+"; break; case 2: std::cout<<"-"; break; } rhs->print( ); } }; class StmtNodeAST : public NodeAST { VarNodeAST* var; NodeAST* expr; public: StmtNodeAST( VarNodeAST* v, NodeAST* e):var( v), expr( e){} void print( ) { var->print( ); std::cout<<"="; expr->print( ); std::cout<<";"<<std::endl; } }; extern std::vector<NodeAST*> _stmts; #endif
#include <stdio.h> #include <string> #include <vector> #include "ast.h" typedef std::vector<std::string> strvec_t; typedef std::string stdstring_t; namespace BINOPS { enum BINOPS_ { AddOp=1, SubOp, MulOp, DivOp, ModOp, }; } COMPILER gmaker CHARACTERS letter="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_". digit="0123456789". cr="\r". lf="\n". tab="\t". ws=" ". TOKENS IDENT = letter {letter | digit}. INT = digit {digit}. COMMENTS FROM "#" TO cr lf IGNORE cr + lf + tab + ws PRODUCTIONS gmaker = {stmt} EOF. stmt (. VarNodeAST* var; NodeAST* e; .) = {Variable<var> "=" Expr<e> (. StmtNodeAST* s = new StmtNodeAST(var, e); _stmts.push_back(s); .) } ";" . Expr<NodeAST*& ef> (. int op; NodeAST* tf; NodeAST* ctf; .) = Term<tf> {AddOp<op> Term<ctf> (. NodeAST* tmp; tmp = new BinOpNodeAST(op, tf, ctf); tf = tmp; .) } (. ef = tf; .) . Term<NodeAST*& tf> (. int op; NodeAST* sf; NodeAST* bf; .) = Sfactor<sf> {MulOp<op> Factor<bf> (. NodeAST* tmp; tmp = new BinOpNodeAST(op, sf, bf); sf = tmp; .) } (. tf = sf; .) . Sfactor<NodeAST*& sf> (. int op; NodeAST* f; .) = (. op = -1; .) [AddOp<op>] Factor<f> (. if (op == -1) sf = new UnOpNodeAST(op, f); else sf = f; .) . Factor<NodeAST*& f> (. NodeAST* e; IntNodeAST* i; VarNodeAST* v; .) = Int<i> (. f = i; .) | Variable<v> (. f = v; .) | "(" Expr<e> ")" (. f = e; .) . Variable<VarNodeAST*& var> (. stdstring_t name; .) = IDENT (. char* v = coco_string_create_char(t->val); name = v; coco_string_delete(v); var = new VarNodeAST(name); .). Int<IntNodeAST*& res> (. stdstring_t val; .) = INT (. char* v = coco_string_create_char(t->val); val = v; res = new IntNodeAST(val); coco_string_delete(v); .) . AddOp<int& op> = (. op = -1; .) ( "+" (. op = BINOPS::AddOp; .) | "-" (. op = BINOPS::SubOp; .) ). MulOp<int& op> = (. op = -1; .) ( "*" (. op = BINOPS::MulOp; .) | "/" (. op = BINOPS::DivOp; .) | "%" (. op = BINOPS::ModOp; .) ). END gmaker.
эм... ну вот, этот парсер должен уметь разбирать выражения навроде
x = 1 + 2 * 3;
y = 1 * 2 + 3 * 4;
z = a+b*(c-d);
и распечатывать разобранное в консоль в виде исходного текста. Желающие могут, вместо метода print, - написать метод codegen
Правда, пока не разобрался почему не хочет хавать унарный оператор,,.. так что выражения вида
x = -2 + 3;
будут считываться, как
x = 2 + 3;
0iStalker
> Поверь, с использованием этих ку-ку и ко-ко дубовое делается быстрее
мде, с этим сложно поспорить.
0iStalker
> Правда, пока не разобрался почему не хочет хавать унарный оператор
сделать при разборе number токена учёт - ?
0iStalker
Ух ты ужОс какой.
Что называется почувствуйте разницу.
https://github.com/rampelstinskin/ParserGenerator/blob/master/Test/Main.n
chucheloid
> Что называется почувствуйте разницу.
а то же самое на lisp ?
innuendo
Думаешь на лиспе короче будет? Ошибаешься.
Тема в архиве.