構文木をいじれるC言語風データ定義言語

2chにサンプルだけ書いたら変人扱いされたのですが、とにかくC言語風のデータ定義言語を考えています。仮にCEX(C like EXpression)と名づけました。

基本的な考え方

CEXのデータの基本形は

トークン[](){}

です。

各カッコ内は、";"でトークンを分割し、さらに","で分割します。その分割された中に入るデータはCEXが再帰的に入ることになります。

パーサーは、字句解析部でほぼ、D言語の字句解析に近いことを行い、そのトークンをCEXの考え方に基づいて構文木を作成します。

トークン、[]、()、{}は全て省略可能です。

例)

void main(){
  printf("hello world\n");
}

は、

void(){}
main(){
  printf[]("hello world\n"){};
}

の省略形と言った感じです。実際には括弧は存在する、存在しないのフラグを持つか、nullと長さ0のリストで判定することになると思います。

このデータを操作するオブジェクトの例を以下に示します。

public class CEX
{
  private char _k;
  private CEX _a;
  private CEX _p;
  private CEX _b;

  public char k() {return _k;}
  public void k(char str) {_k = k;}

  public CEX a() {return _a;}
  public CEX a(int semi) {return _a[semi];}
  public CEX a(int semi, int white){return _a[semi][white];}
  public CEX a(int semi, int white, int canma) {return _a[semi][white][canma];}
  public CEX a0(){return _a[0][0][0];}
  public CEX as(int semi){return _a[semi][0][0];}
  public CEX aw(int white){return _a[0][white][0];}
  public CEX ac(int canma){return _a[0][0][canma];}
  public CEX asw(int semi,int white){return _a[semi][white][0];}
  public CEX asc(int semi,int canma){return _a[semi][0][canma];}
  public CEX awc(int white,int canma){return _a[0][white][canma];}
  public char astr() {return "[" ~ str(_a) ~ "]";}

  public CEX p() {return _p;}
  public CEX p(int semi) {return _p[semi];}
  public CEX p(int semi, int white){return _p[semi][white];}
  public CEX p(int semi, int white, int canma) {return _p[semi][white][canma];}
  public CEX p0(){return _p[0][0][0];}
  public CEX ps(int semi){return _p[semi][0][0];}
  public CEX pw(int white){return _p[0][white][0];}
  public CEX pc(int canma){return _p[0][0][canma];}
  public CEX psw(int semi,int white){return _p[semi][white][0];}
  public CEX psc(int semi,int canma){return _p[semi][0][canma];}
  public CEX pwc(int white,int canma){return _p[0][white][canma];}
  public char pstr() {return "[" ~ str(_p) ~ "]";}

  public CEX b() {return _b;}
  public CEX b(int semi) {return _b[semi];}
  public CEX b(int semi, int white){return _b[semi][white];}
  public CEX b(int semi, int white, int canma) {return _b[semi][white][canma];}
  public CEX b0(){return _b[0][0][0];}
  public CEX bs(int semi){return _b[semi][0][0];}
  public CEX bw(int white){return _b[0][white][0];}
  public CEX bc(int canma){return _b[0][0][canma];}
  public CEX bsw(int semi,int white){return _b[semi][white][0];}
  public CEX bsc(int semi,int canma){return _b[semi][0][canma];}
  public CEX bwc(int white,int canma){return _b[0][white][canma];}
  public char bstr() {return "[" ~ str(_b) ~ "]";}
  public char toString() {
    k ~ " " ~ astr() ~ pstr() ~ bstr();
  }
  private static char str(CEX s){
    char str;
    for (int i = 0; i < s.length; i++) {
      for (int j = 0; j < s[i].length; j++) {
        for (int k = 0; k < s[i][j].length; k++) {
          str ~= s[i][j][k].toString() ~ " ";
        }
        str[str.length] = ",";
      }
      str[str.length] = ";";
    }
    return str[0 .. str.length - 1];
  }
}

public class CEXReader {
  static public CEX read(char str) {
    Token tokens = CEXTokenizer.tokens(str);
    CEX cex = new CEX();
    return cex;
  }
}

public class CEXWriter {
  static public char write(CEX cex) {
    char[] str;
    return str;
  }
}

長くなるので
a:[]
p:()
b:{}
s:';'
c:','
w:' '
と略しています。
この言語でプログラミング言語(仮にCXP C like eXpression Programing language)を作るとした場合のサンプルコードをいかに示します。

class[public;a;;] {

};
abstractClass[public;absc1;;] {

};
interface[public;b;;] {

};
/**
 * publicでaクラスを継承し、bインターフェイスを持つnameという名前をもつクラス
 */
class[public;name;a;b] {

  function[public; ret; name](var(int){a},var(int){b}) {
  };
  function[public,static; ret; name](var[inout](int){a}, var[out](int){b})) {
  };
};

struct[public;S1] {
  var[;int] a;
  var[;int] b;
  var[;int] c;
};

function[public; void; main]() {
   var[static](int) {a=12,b,c};
   a = 1 + 2 * 14; // (((a = 1)+2)*14)と解釈される。演算子による優先順位付けはなし。
   a = (1 + (2 * 14)); // とかかなくてはならない。
   let(a = 1 + 2 * 14);// a=(1+(2*14))と構文解析してくれる拡張構文。
   var[static](int[12]){d=(1,2,3,4,5,6,7,8,9,10,11,12)};
   var[static](S1){s={a=10,b=10,c=10}};
   var[static](int[char[ ] ]){d=["a"=1,"b"=2,"c"=3]};
   var(name){c1=name.new()};// new演算子はなくて、newメソッドを使う。
   c1.delete();// デリート
   if(a==b){
   }else{
   };
   // ローカルブロックはエラー ラベルを使うこと。
   var(function[public;void;]()){a=main};// 関数ポインタ
   for[c](var(int){i=0};i<10;i++) {//[c]はラベル
     break;
     continue;
     switch(a){
     case[1]{
       break[c];// forからbreak
     }
     case[2]{
       continue[c];// forをcontinue
     }
     case[3]{
       // 3,4を実行する。
     }
     case[4]{
       break;
     }
     // case[5]a++; エラー
     };
   };
   return[](){};
};

と言った感じになると思います。
このプログラム言語は構文ツリーそのものですので、構文を追加するようなことが比較的簡単であるはずで、そういう構文追加機能を考えていますが、LISPなどのプログラミング経験が少ないので、勉強中です。