ФлеймФорумПрограммирование

А что если сделать свою мини-среду программирования с компилятором? (2 стр)

Страницы: 1 2 3 49 Следующая »
#15
13:13, 15 фев 2012

Если интересно, то у меня вот такой исходный код:

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"

Распространения констант пока что нету.

#16
14:48, 15 фев 2012

как вариант, можно сделать текстовый конвертер.
Типа так!

свой язык + свои функции -> конвертируется в обычный исходный код Delphi или С++ и потом этот конечный код
компилировать в профессианально-отлаженной IDE типа Visual Studio или в другой аналогичной.

#17
14:58, 15 фев 2012

dige
> Типа так!
>
> свой язык + свои функции -> конвертируется в обычный исходный код Delphi или
> С++

Без разницы, - что в машинный код, что в исходный код какого-либо языка программирования... основная работа, - всё равно - распарсить исходный код (частично автоматизируется существующими инструментами) и составить дерево разбора (оно же в вырожденном состоянии - абстрактное синтаксическое дерево). Потом, используя это дерево, - применив к нему, при обходе узлов, 100500 проверок (определены ли используемые переменные/функции, совпадают ли типы присваиваемых значений - типам переменных, попадают ли числовые данные в свои диапазоны, итд, итп - можно собственно сгенерировать нужный нам код (либо бинарный, либо исходный другого языка).  То же самое дерево разбора  используется для подсветки синтаксиса в IDE,... только тут ещё нужна продвинутая система восстановления после ошибок.

#18
15:04, 15 фев 2012

Да это будет не просто текстовый редактор, а текстовый процессор !

Но зато в необходимости коммутации с компилятором нету!

Я однажды попробовал написать на ассемблере и С++ один и тот же код, одинаковые по "логике работы" и тестировал с помощью высокоточного таймера.

Visual Studio оптимизировал мой "чистый" С++ код в несколько раз лучше, чем то, что я написал на ассемблере.
Это были вставки, вот так

__asm
{

}
#19
16:14, 15 фев 2012

0iStalker
Мне, кстати, тоже наиболее удобным кажется COCO/R или PegGrammar.

#20
14:04, 16 фев 2012

COCO/R очень слабый. На LL(1) далеко не уедешь. Даже C# не разобрать.
PegGrammar (это как я понимаю ты про немерловый макрос) не смотря на то что разбирает намного более широкий класс языков чем COCO/R  признан тупиковой веткой и больше развиваться не будет.

Вот будущее немерловых парсеров. Находится в активной разработке.
https://github.com/rampelstinskin/ParserGenerator/
Умеет левую (с небольшими ограничениями не существенными на практике) и правую рекурсию.
Поддерживает приоритеты и ассоциативность операторов.
Поддерживает неограниченное заглядывание вперед.
Умеет (!) менять грамматику во время разбора. Те встретил например "using XmlGrammar;" и добавил правила разбора XML’я. Область видимости закончилась правила разбора XML’я выгрузились.

>Без разницы, - что в машинный код, что в исходный код какого-либо языка программирования...
Это, мягко говоря, не совсем так.
В остальном согласен.

Кстати компиляторы в любом случае нужно писать на языках поддерживающих pattern matching. Очень сильно помогает делать те самые "100500 проверок".

#21
14:51, 16 фев 2012

а как насчёт первозданного дубового варианта - пусть язык будет с ограничениями и костылями, зато маленький и с IDE. То есть пусть будет Г(громоздко:), но зато не на основе чужого Г(громоздкого продукта:). Использование всех этих куку-коко тоже конечно дело хорошее, но для достижений несколько другого плана, решения более повседневных унылых задач.

#22
15:07, 16 фев 2012

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
#23
15:08, 16 фев 2012

#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

#24
15:15, 16 фев 2012

Правда, пока не разобрался почему не хочет хавать унарный оператор,,.. так что выражения вида

x = -2 + 3;

будут считываться, как

x = 2 + 3;

#25
15:17, 16 фев 2012

0iStalker
> Поверь, с использованием этих ку-ку и ко-ко дубовое делается быстрее
мде, с этим сложно поспорить.

#26
15:19, 16 фев 2012

0iStalker
> Правда, пока не разобрался почему не хочет хавать унарный оператор

сделать при разборе number токена учёт - ?

#27
15:22, 16 фев 2012

0iStalker
Ух ты ужОс какой.
Что называется почувствуйте разницу.
https://github.com/rampelstinskin/ParserGenerator/blob/master/Test/Main.n

#28
15:24, 16 фев 2012

chucheloid
> Что называется почувствуйте разницу.

а то же самое на lisp ?

#29
15:28, 16 фев 2012

innuendo
Думаешь на лиспе короче будет? Ошибаешься.

Страницы: 1 2 3 49 Следующая »
ФлеймФорумПрограммирование

Тема в архиве.