OSDN Git Service

ELCHNOS=PSECPU:バイナリ変換を途中まで実装。
authorhikarupsp <hikarupsp@users.sourceforge.jp>
Sat, 19 Oct 2013 13:01:37 +0000 (22:01 +0900)
committerhikarupsp <hikarupsp@users.sourceforge.jp>
Sat, 19 Oct 2013 13:01:37 +0000 (22:01 +0900)
aiext.js
elcc.js

index a8bfdc8..aa40dd3 100644 (file)
--- a/aiext.js
+++ b/aiext.js
@@ -135,6 +135,15 @@ Array.prototype.splitByArray = function(separatorList){
        return retArray;
 }
 
+Array.prototype.logAsHexByte = function(separatorList){
+       //十六進バイト列としてデバッグ出力する。
+       var ds = "";
+       for(var i = 0, iLen = this.length; i < iLen; i++){
+               ds += ("00" + this[i].toString(16).toUpperCase()).slice(-2);
+       }
+       console.log(ds);
+}
+
 //文字列関連
 String.prototype.replaceAll = function(org, dest){
        //String中にある文字列orgを文字列destにすべて置換する。
diff --git a/elcc.js b/elcc.js
index e38b84a..834bad6 100644 (file)
--- a/elcc.js
+++ b/elcc.js
@@ -1,10 +1,20 @@
 // ELCHNOSCompiler for AI004
 
+//手順:
+//トークン分割
+//構造解析・式の逆ポーランド化
+//中間バイナリ化
+
 function ELCHNOSCompiler(env){
        this.env = env;
        
+       this.unexpected = false;
+       this.errno = 0;
+       this.errLine = 0;
+       
        this.line = null;
        this.separated = null;
+       this.bin = new Array();
        
        this.structure = new Array();
        this.currentStructure = this.structure;
@@ -12,6 +22,8 @@ function ELCHNOSCompiler(env){
        
        //0はエントリポイント(main)用に予約
        this.nextLabelID = 1;
+       this.integerRegisterAllocationTable = new Array();
+       this.pointerRegisterAllocationTable = new Array();
 }
 ELCHNOSCompiler.prototype = {
        keyWordList: [
@@ -50,7 +62,8 @@ ELCHNOSCompiler.prototype = {
                "Incompatible value attribute.",
                "Unexpected identifier.",
                "Unknown assembly language type.",
-               "Invalid expression of OSECPU Binary."
+               "Invalid expression of OSECPU Binary.",
+               "Binary translation error.",
        ],
        
        Flag_Sign_Signed                        : 0x00000001,
@@ -70,16 +83,13 @@ ELCHNOSCompiler.prototype = {
                console.log(this.separated);
                
                //メイン処理
+               this.errno = 2;
                var currentExpression = null;
                var numValSignFlag = 0;
                var numValBits = 0;
                var pointerCount = 0;
                var lineCount = 1;
-               var blockLevel = 0;
-               //var DestinationOperand = null;
                var mode = 0;
-               var unexpected = false;
-               var errno = 2;
                var o;
                var f;
                        //次に期待する値を示す。
@@ -108,7 +118,6 @@ ELCHNOSCompiler.prototype = {
                        //71: OSECPUアセンブリ評価式の内容または終端記号
                for(var i = 0, iLen = this.separated.length; i < iLen; i++){
                        var s = this.separated[i].toLowerCase();
-                       //this.env.debug((i + 1) + ":" + s + "\n");
                        
                        if(s == "\n"){
                                //デバッグ用行数カウント
@@ -121,8 +130,8 @@ ELCHNOSCompiler.prototype = {
                                        numValSignFlag |= this.Flag_Sign_Signed;
                                        mode = 10;
                                } else{
-                                       unexpected = true;
-                                       errno = 1;
+                                       this.unexpected = true;
+                                       this.errno = 1;
                                }
                        } else if(s == "unsigned" && (mode == 0 || mode == 10)){
                                //符号なし
@@ -130,8 +139,8 @@ ELCHNOSCompiler.prototype = {
                                        numValSignFlag |= this.Flag_Sign_Unsigned;
                                        mode = 10;
                                } else{
-                                       unexpected = true;
-                                       errno = 1;
+                                       this.unexpected = true;
+                                       this.errno = 1;
                                }
                        } else if(s == "char"  && (mode == 0 || mode == 10 || mode == 11 || mode == 52)){
                                //char 8bit符号あり
@@ -150,12 +159,12 @@ ELCHNOSCompiler.prototype = {
                                        //変数または定数の定義終了
                                        numValBits = 0;
                                        numValSignFlag = 0;
-                                       console.log(currentExpression);
+                                       //console.log(currentExpression);
                                        currentExpression = null;
                                        mode = 0;
                                } else if(mode == 60 || mode == 71){
                                        //評価式終端
-                                       console.log(currentExpression);
+                                       //console.log(currentExpression);
                                        currentExpression = null;
                                        if(mode == 60){
                                                mode = 0;
@@ -163,14 +172,14 @@ ELCHNOSCompiler.prototype = {
                                                mode = 70;
                                        }
                                } else{
-                                       unexpected = true;
+                                       this.unexpected = true;
                                }
                        } else if(s == "=" && (mode == 13)){
                                if(mode == 13){
                                        //変数・定数初期化式開始
                                        mode = 16;
                                } else{
-                                       unexpected = true;
+                                       this.unexpected = true;
                                }
                        } else if(s == "*" && (mode == 11)){
                                //ポインタ属性の付加
@@ -186,10 +195,10 @@ ELCHNOSCompiler.prototype = {
                                        } else if(mode == 53){
                                                mode = 52;
                                        }
-                                       console.log(currentExpression);
+                                       //console.log(currentExpression);
                                        currentExpression = null;
                                } else{
-                                       unexpected = true;
+                                       this.unexpected = true;
                                }
                        //括弧系
                        } else if(s == "[" && (mode == 12)){
@@ -207,7 +216,7 @@ ELCHNOSCompiler.prototype = {
                                        currentExpression = null;
                                        mode = 0;
                                } else{
-                                       unexpected = true;
+                                       this.unexpected = true;
                                }
                        } else if(s == "}" && (mode == 17 || mode == 18 || mode == 0)){
                                if(mode == 17 || mode == 18){
@@ -215,10 +224,10 @@ ELCHNOSCompiler.prototype = {
                                        mode = 19;
                                } else if(mode == 0){
                                        if(this.structureStack.length > 0){
-                                               console.log(this.currentStructure);
+                                               //console.log(this.currentStructure);
                                                this.restoreCurrentStructure();
                                        } else{
-                                               unexpected = true;
+                                               this.unexpected = true;
                                        }
                                }
                        } else if(s == "(" && (mode == 51)){
@@ -227,7 +236,7 @@ ELCHNOSCompiler.prototype = {
                        } else if(s == ")" && (mode == 52 || mode == 53)){
                                //52: 引数or引数終了括弧
                                //53: 引数区切りor引数終了括弧
-                               console.log(currentExpression);
+                               //console.log(currentExpression);
                                currentExpression = null;
                                for(var j = 0, jLen = this.currentStructure.length; j < jLen; j++){
                                        //引数番号を付与
@@ -240,15 +249,15 @@ ELCHNOSCompiler.prototype = {
                                if(s == "osecpu"){
                                        mode = 70;
                                } else{
-                                       unexpected = true;
-                                       errno = 3;
+                                       this.unexpected = true;
+                                       this.errno = 3;
                                }
                        } else if(s == "@end" && (mode == 70)){
                                mode = 0;
                        //リストにない予約語
                        } else if(s == "procedure" && (mode == 0)){
                                //関数宣言
-                               var f = new ELCHNOSCompiler_ExpressionStructure_Function(this);
+                               var f = new ELCHNOSCompiler_ExpressionStructure_Function(this, lineCount);
                                this.currentStructure.push(f);
                                this.changeCurrentStructure(f.structure);
                                currentExpression = f;
@@ -258,74 +267,36 @@ ELCHNOSCompiler.prototype = {
                                currentExpression.isInline = true;
                        } else if(s == "for" && (mode == 0)){
                                //forループ
-                               //
-                               //初期化式
-                               //L1:
-                               //条件評価式-?>L2
-                               //実行部分
-                               //(break->L2)
-                               //更新式->L1
-                               //L2:
                                i++;
                                s = this.separated[i];
                                if(s == "("){
-                                       var f = new ELCHNOSCompiler_ExpressionStructure_Loop_for(this);
+                                       var f = new ELCHNOSCompiler_ExpressionStructure_Loop_for(this, lineCount);
                                        this.currentStructure.push(f);
                                        this.changeCurrentStructure(f.structure);
                                        currentExpression = f;
                                        //初期化式
-                                       f.initializer = new ELCHNOSCompiler_ExpressionStructure_Expression(this);
-                                       for(i++; ; i++){
-                                               s = this.separated[i];
-                                               if(s == ";"){
-                                                       break;
-                                               }
-                                               f.initializer.pushIdentifier(s);
-                                               if(unexpected){
-                                                       break;
-                                               }
-                                       }
-                                       console.log(f.initializer);
+                                       f.initializer = new ELCHNOSCompiler_ExpressionStructure_Expression(this, lineCount);
+                                       i = f.initializer.readExpressionToTerminator(i, ";");
                                        //条件評価式
-                                       if(!unexpected){
-                                               f.conditonalExpression = new ELCHNOSCompiler_ExpressionStructure_Expression(this);
-                                               for(i++; ; i++){
-                                                       s = this.separated[i];
-                                                       if(s == ";"){
-                                                               break;
-                                                       }
-                                                       f.conditonalExpression.pushIdentifier(s);
-                                                       if(unexpected){
-                                                               break;
-                                                       }
-                                               }
-                                               console.log(f.conditonalExpression);
+                                       if(!this.unexpected){
+                                               f.conditonalExpression = new ELCHNOSCompiler_ExpressionStructure_Expression(this, lineCount);
+                                               i = f.conditonalExpression.readExpressionToTerminator(i, ";");
                                        }
                                        //更新式
-                                       if(!unexpected){
-                                               f.incrementalExpression = new ELCHNOSCompiler_ExpressionStructure_Expression(this);
-                                               for(i++; ; i++){
-                                                       s = this.separated[i];
-                                                       if(s == ")"){
-                                                               break;
-                                                       }
-                                                       f.incrementalExpression.pushIdentifier(s);
-                                                       if(unexpected){
-                                                               break;
-                                                       }
-                                               }
-                                               console.log(f.incrementalExpression);
+                                       if(!this.unexpected){
+                                               f.incrementalExpression = new ELCHNOSCompiler_ExpressionStructure_Expression(this, lineCount);
+                                               i = f.incrementalExpression.readExpressionToTerminator(i, ")");
                                        }
                                        //開始括弧
-                                       if(!unexpected){
+                                       if(!this.unexpected){
                                                i++;
                                                if(this.separated[i] != "{"){
-                                                       unexpected = true;
+                                                       this.unexpected = true;
                                                }
                                                currentExpression = null;
                                        }
                                } else{
-                                       unexpected = true;
+                                       this.unexpected = true;
                                }
                        } else if(s == "if" && (mode == 0)){
                                //if文
@@ -336,38 +307,28 @@ ELCHNOSCompiler.prototype = {
                                i++;
                                s = this.separated[i];
                                if(s == "("){
-                                       var f = new ELCHNOSCompiler_ExpressionStructure_if(this);
+                                       var f = new ELCHNOSCompiler_ExpressionStructure_if(this, lineCount);
                                        this.currentStructure.push(f);
                                        this.changeCurrentStructure(f.structure);
                                        currentExpression = f;
                                        //条件評価式
-                                       f.conditonalExpression = new ELCHNOSCompiler_ExpressionStructure_Expression(this);
-                                       for(i++; ; i++){
-                                               s = this.separated[i];
-                                               if(s == ")"){
-                                                       break;
-                                               }
-                                               f.conditonalExpression.pushIdentifier(s);
-                                               if(unexpected){
-                                                       break;
-                                               }
-                                       }
-                                       console.log(f.conditonalExpression);
+                                       f.conditonalExpression = new ELCHNOSCompiler_ExpressionStructure_Expression(this, lineCount);
+                                       i = f.conditonalExpression.readExpressionToTerminator(i, ")");
                                        //開始括弧
-                                       if(!unexpected){
+                                       if(!this.unexpected){
                                                i++;
                                                if(this.separated[i] != "{"){
-                                                       unexpected = true;
+                                                       this.unexpected = true;
                                                }
                                                currentExpression = null;
                                        }
                                } else{
-                                       unexpected = true;
+                                       this.unexpected = true;
                                }
                        //OSECPUアセンブリ
                        } else if(s == "remark" && (mode == 70)){
                                //超手抜き
-                               var b = new ELCHNOSCompiler_ExpressionStructure_OSECPUBinary(this);
+                               var b = new ELCHNOSCompiler_ExpressionStructure_OSECPUBinary(this, lineCount);
                                this.currentStructure.push(b);
                                //FE    len     ...
                                b.bin.push(0xfe);
@@ -378,11 +339,11 @@ ELCHNOSCompiler.prototype = {
                                        var len = parseInt(s, 16);
                                        b.bin.push(len);
                                } else{
-                                       unexpected = true;
-                                       errno = 4;
+                                       this.unexpected = true;
+                                       this.errno = 4;
                                }
                                //data
-                               if(!unexpected){
+                               if(!this.unexpected){
                                        i++;
                                        s = this.separated[i];
                                        if(s.length == len * 2){
@@ -390,15 +351,15 @@ ELCHNOSCompiler.prototype = {
                                                        b.bin.push(parseInt(s.substr(j * 2, 2), 16));
                                                }
                                        } else{
-                                               unexpected = true;
-                                               errno = 4;
+                                               this.unexpected = true;
+                                               this.errno = 4;
                                        }
                                }
                                
-                               if(!unexpected){
+                               if(!this.unexpected){
                                        i++;
                                        if(this.separated[i] != ";"){
-                                               unexpected = true;
+                                               this.unexpected = true;
                                        } else{
                                                //この命令は定数のみで構成されているのでコンパイル済みとマークする
                                                b.isCompiled = true;
@@ -407,7 +368,7 @@ ELCHNOSCompiler.prototype = {
                                }
                        } else if(s == "call" && (mode == 70)){
                                //超手抜き
-                               var b = new ELCHNOSCompiler_ExpressionStructure_OSECPUBinary(this);
+                               var b = new ELCHNOSCompiler_ExpressionStructure_OSECPUBinary(this, lineCount);
                                this.currentStructure.push(b);
                                
                                //第二引数が何か確認する
@@ -445,21 +406,21 @@ ELCHNOSCompiler.prototype = {
                                        //終端記号
                                        i++;
                                        if(this.separated[i] != ";"){
-                                               unexpected = true;
+                                               this.unexpected = true;
                                        } else{
                                                //この命令は定数のみで構成されているのでコンパイル済みとマークする
                                                b.isCompiled = true;
                                                b = null;
                                        }
                                } else{
-                                       unexpected = true;
-                                       errno = 0;
+                                       this.unexpected = true;
+                                       this.errno = 0;
                                }
                        //予約語以外
                        } else if(mode == 11 || mode == 52){
                                //変数または定数の宣言
                                //52: 引数名
-                               var v = new ELCHNOSCompiler_ExpressionStructure_Variable(this);
+                               var v = new ELCHNOSCompiler_ExpressionStructure_Variable(this, lineCount);
                                v.bits = numValBits;
                                v.isSigned = (numValSignFlag == 0) ? false : (0 != (numValSignFlag & this.Flag_Sign_Signed));
                                s = this.separated[i];
@@ -475,7 +436,7 @@ ELCHNOSCompiler.prototype = {
                                        //mode:52->53
                                        mode++;
                                } else{
-                                       unexpected = true;
+                                       this.unexpected = true;
                                }
                        } else if(mode == 14){
                                currentExpression.length = parseInt(s);
@@ -495,12 +456,12 @@ ELCHNOSCompiler.prototype = {
                                        s = this.separated[i];
                                        if(mode == 0 || mode == 70){
                                                //最初の左辺だったら追加処理
-                                               var f = new ELCHNOSCompiler_ExpressionStructure_Expression(this);
+                                               var f = new ELCHNOSCompiler_ExpressionStructure_Expression(this, lineCount);
                                                this.currentStructure.push(f);
                                                currentExpression = f;
                                        }
                                        currentExpression.pushIdentifier(s);
-                                       if(!unexpected){
+                                       if(!this.unexpected){
                                                if(mode == 0){
                                                        mode = 60;
                                                } else if(mode == 70){
@@ -509,15 +470,42 @@ ELCHNOSCompiler.prototype = {
                                        }
                                }
                        }
-                       if(unexpected){
+                       if(this.unexpected){
                                //期待されていない値
                                s = this.separated[i];
-                               this.raiseError(errno, lineCount, [s, mode]);
+                               this.raiseError(this.errno, lineCount, [s, mode]);
                                console.log(this.structure);
                                return;
                        }
                }
                console.log(this.structure);
+               
+               //中間バイナリ生成
+               //バックエンドコードの中間表現を出力。
+               //0x00-0xff: そのまま使えるバイナリ
+               //0x10000000-0x1fffffff: 未決定の仮想整数レジスタ番号
+               //0x20000000-0x2fffffff: 未決定の仮想ポインタレジスタ番号
+               this.errno = 5;
+               
+               //OSECPUフロントエンドコードヘッダ
+               this.bin.push(0x05, 0xe1, 0x00);
+               
+               for(var i = 0, iLen = this.structure.length; i < iLen; i++){
+                       var b = this.structure[i].createBinary();
+                       if(b !== undefined){
+                               this.bin.push(b);
+                       }
+                       if(this.unexpected){
+                               if(!this.errLine){
+                                       this.errLine = this.structure[i].lineCount;
+                               }
+                               this.raiseError(this.errno, this.errLine, null);
+                               console.log(this.bin);
+                               return;
+                       }
+               }
+               
+               console.log(this.bin);
        },
        compile_removeComment: function(){
                //コメント削除
@@ -625,11 +613,150 @@ ELCHNOSCompiler.prototype = {
                this.nextLabelID++;
                return this.nextLabelID - 1;
        },
+       virtualIntegerRegisterOffset: 0x10000000,
+       allocateIntegerRegister: function(owner){
+               //レジスタテーブルは先頭から番号の小さい順につめて格納する。
+               //[regID, owner]
+               //0x10000000-0x1fffffff: 未決定の仮想整数レジスタ番号
+               var freeRegID = 0;
+               for(var i = 0, iLen = this.integerRegisterAllocationTable.length; i < iLen; i++){
+                       if(this.integerRegisterAllocationTable[i][0] != i + this.virtualIntegerRegisterOffset){
+                               //空いているレジスタ番号を見つけた
+                               if(i > 0x20){
+                                       this.integerRegisterAllocationTable.splice(i, 0, [i + this.virtualIntegerRegisterOffset, owner]);
+                               }
+                       }
+               }
+               if(i == iLen){
+                       //途中に空いているレジスタはなかったので追加
+                       this.integerRegisterAllocationTable.push([i + this.virtualIntegerRegisterOffset, owner]);
+               }
+               return i + this.virtualIntegerRegisterOffset;
+       },
+       freeIntegerRegister: function(regID, owner){
+               for(var i = 0, iLen = this.integerRegisterAllocationTable.length; i < iLen; i++){
+                       if(this.integerRegisterAllocationTable[i][0] == regID){
+                               //レジスタ番号を見つけた
+                               //オーナーが一致するか確認
+                               if(this.integerRegisterAllocationTable[i][1] == owner){
+                                       //一致したので解放する
+                                       this.integerRegisterAllocationTable.splice(i, 1);
+                               }
+                               break;
+                       }
+               }
+               if(i == iLen){
+                       console.log("register free error.");
+               }
+       },
+       virtualPointerRegisterOffset: 0x20000000,
+       allocatePointerRegister: function(owner){
+               //レジスタテーブルは先頭から番号の小さい順につめて格納する。
+               //[regID, owner]
+               //0x20000000-0x2fffffff: 未決定の仮想ポインタレジスタ番号
+               var freeRegID = 0;
+               for(var i = 0, iLen = this.pointerRegisterAllocationTable.length; i < iLen; i++){
+                       if(this.pointerRegisterAllocationTable[i][0] != i + this.virtualPointerRegisterOffset){
+                               //空いているレジスタ番号を見つけた
+                               this.pointerRegisterAllocationTable.splice(i, 0, [i + this.virtualPointerRegisterOffset, owner]);
+                       }
+               }
+               if(i == iLen){
+                       //途中に空いているレジスタはなかったので追加
+                       this.pointerRegisterAllocationTable.push([i + this.virtualPointerRegisterOffset, owner]);
+               }
+               return i + this.virtualPointerRegisterOffset;
+       },
+       freePointerRegister: function(regID, owner){
+               for(var i = 0, iLen = this.pointerRegisterAllocationTable.length; i < iLen; i++){
+                       if(this.pointerRegisterAllocationTable[i][0] == regID){
+                               //レジスタ番号を見つけた
+                               //オーナーが一致するか確認
+                               if(this.pointerRegisterAllocationTable[i][1] == owner){
+                                       //一致したので解放する
+                                       this.pointerRegisterAllocationTable.splice(i, 1);
+                               }
+                               break;
+                       }
+               }
+               if(i == iLen){
+                       console.log("register free error.");
+               }
+       },
+       freeAllRegisterOfOwner: function(owner){
+               //ownerが確保しているレジスタをすべて解放する
+               //IntegerRegister
+               for(var i = 0, iLen = this.integerRegisterAllocationTable.length; i < iLen; i++){
+                       if(this.integerRegisterAllocationTable[i][1] == owner){
+                               //見つけた
+                               this.integerRegisterAllocationTable.splice(i, 1);
+                       }
+               }
+               //PointerRegister
+               for(var i = 0, iLen = this.pointerRegisterAllocationTable.length; i < iLen; i++){
+                       if(this.pointerRegisterAllocationTable[i][1] == owner){
+                               //見つけた
+                               this.pointerRegisterAllocationTable.splice(i, 1);
+                       }
+               }
+       },
 }
 
-function ELCHNOSCompiler_ExpressionStructure_Variable(compiler){
+//
+// 文法構造クラス
+//
+
+function ELCHNOSCompiler_ExpressionStructure(compiler, lineCount){
+       //共通部分
        this.compiler = compiler;
+       this.lineCount = lineCount;
+       this.bin = new Array();
+}
+ELCHNOSCompiler_ExpressionStructure.prototype = {
+       T_VPtr          :0x01,
+       T_SINT8         :0x02,  //8bitの符号付き, いわゆる signed char.
+       T_UINT8         :0x03,
+       T_SINT16        :0x04,  //16bitの符号付き, いわゆる short.
+       T_UINT16        :0x05,
+       T_SINT32        :0x06,
+       T_UINT32        :0x07,
+       T_SINT4         :0x08,
+       T_UINT4         :0x09,
+       T_SINT2         :0x0a,
+       T_UINT2         :0x0b,
+       T_SINT1         :0x0c,  //代入できるのは0か-1のみ.
+       T_UINT1         :0x0d,
+       T_SINT12        :0x0e,
+       T_UINT12        :0x0f,
+       T_SINT20        :0x10,
+       T_UINT20        :0x11,
+       T_SINT24        :0x12,
+       T_UINT24        :0x13,
+       T_SINT28        :0x14,
+       T_UINT28        :0x15,
+       createBinary: function(){
+               this.compiler.unexpected = true;
+               return undefined;
+       },
+       appendInstruction_LB: function(opt, labelID){
+               this.bin.push(0x02, opt);
+               this.appendInstruction_UINT32BE(labelID);
+       },
+       appendInstruction_UINT32BE: function(data){
+               this.bin.push((data >> 24) & 0xFF);
+               this.bin.push((data >> 16) & 0xFF);
+               this.bin.push((data >> 8) & 0xFF);
+               this.bin.push(data & 0xFF);
+       },
+}
+
+var ELCHNOSCompiler_ExpressionStructure_Variable = function(compiler, lineCount){
+       // if(!isPointer && labelID != 0):DATA命令によるデータ(ラベル番号の代わり)
+       // if(isPointer && labelID == 0):ポインタ変数
+       // if(!isPointer && labelID == 0):一般変数
+       ELCHNOSCompiler_ExpressionStructure_Variable.base.apply(this, arguments);
        this.bits = 0;
+       //配列でなければ0が入る
        this.length = 0;
        this.isSigned = false;
        this.isPointer = false;
@@ -637,49 +764,144 @@ function ELCHNOSCompiler_ExpressionStructure_Variable(compiler){
        this.initValue = new Array();
        //引数として渡されるものであれば、引数の左から数えて何番目かが入る。
        this.argumentIndex = -1;
-}
-ELCHNOSCompiler_ExpressionStructure_Variable.prototype = {
-
-}
+       //dataをポインタとして持つ場合はlabelIDが利用される。
+       //それ以外の場合はレジスタIDを利用する。
+       this.labelID = 0;
+       this.registerID = 0xff;
+}.extend(ELCHNOSCompiler_ExpressionStructure, {
+       createBinary: function(){
+               //配列であればデータ命令のバイナリを作成して返す。
+               if(this.length > 0){
+                       //LB(opt:0x1, 0x0);
+                       this.labelID = this.compiler.allocateLabelID();
+                       this.appendInstruction_LB(0x01, this.labelID);
+                       //34    typ32   len32   data... 
+                       this.bin.push(0x34);
+                       if(this.bits == 8 && this.isSigned == false){
+                               //T_UINT8               :0x03,
+                               this.bin.push(0x00, 0x00, 0x00, 0x03);
+                       } else{
+                               this.compiler.unexpected = true;
+                               return undefined;
+                       }
+                       this.appendInstruction_UINT32BE(this.length);
+                       if(this.bits == 8 && this.isSigned == false){
+                               //T_UINT8               :0x03,
+                               for(var i = 0, iLen = this.initValue.length; i < iLen; i++){
+                                       this.bin.push(this.initValue[i] & 0xFF);
+                               }
+                               if(i > this.length){
+                                       this.compiler.unexpected = true;
+                                       return undefined;
+                               } else{
+                                       for(iLen = this.length; i < iLen; i++){
+                                               this.bin.push(0x00);
+                                       }
+                               }
+                       }
+                       return this.bin;
+               } else{
+                       return undefined;
+               }
+       },
+       allocateRegisterID: function(owner){
+               if(this.isPointer){
+                       this.registerID = this.compiler.allocatePointerRegister(owner);
+               } else{
+                       this.registerID = this.compiler.allocateIntegerRegister(owner);
+               }
+       }
+});
 
-function ELCHNOSCompiler_ExpressionStructure_Function(compiler){
-       this.compiler = compiler;
+var ELCHNOSCompiler_ExpressionStructure_Function = function(compiler, lineCount){
+       ELCHNOSCompiler_ExpressionStructure_Function.base.apply(this, arguments);
        this.structure = new Array();
        this.identifier = null;
-}
-ELCHNOSCompiler_ExpressionStructure_Function.prototype = {
-
-}
+       this.isInline = false;
+       this.labelID = 0;
+}.extend(ELCHNOSCompiler_ExpressionStructure, {
+       createBinary: function(){
+               if(this.isInline){
+                       //インライン関数はその場で展開されるのでバイナリはここでは生成しない
+                       return undefined;
+               } else{
+                       //optを変更できるようにするべき(grobal指定)
+                       //LB(opt:0x0, this.labelID);
+                       
+                       this.labelID = this.compiler.allocateLabelID();
+                       this.appendInstruction_LB(0x00, this.labelID);
+                       //内部
+                       for(var i = 0, iLen = this.structure.length; i < iLen; i++){
+                               if(this.structure[i] instanceof ELCHNOSCompiler_ExpressionStructure_Variable){
+                                       this.structure[i].allocateRegisterID(this);
+                               } else{
+                                       var b = this.structure[i].createBinary();
+                                       if(b !== undefined){
+                                               this.bin.push(b);
+                                       }
+                               }
+                               if(this.compiler.unexpected){
+                                       if(!this.compiler.errLine){
+                                               this.compiler.errLine = this.structure[i].lineCount;
+                                       }
+                                       console.log(this);
+                                       return undefined;
+                               }
+                       }
+                       this.compiler.freeAllRegisterOfOwner(this);
+                       return this.bin;
+               }
+       },
+});
 
-function ELCHNOSCompiler_ExpressionStructure_Loop_for(compiler){
-       this.compiler = compiler;
+var ELCHNOSCompiler_ExpressionStructure_Loop_for = function(compiler, lineCount){
+       ELCHNOSCompiler_ExpressionStructure_Loop_for.base.apply(this, arguments);
        this.structure = new Array();
        this.initializer = null;
        this.conditonalExpression = null;
        this.incrementalExpression = null;
-       this.isInline = false;
-}
-ELCHNOSCompiler_ExpressionStructure_Loop_for.prototype = {
-
-}
+       this.loopLabelID = 0;
+       this.endLabelID = 0;
+}.extend(ELCHNOSCompiler_ExpressionStructure, {
+       createBinary: function(){
+               //initializer
+               //loopLabelID:
+               //conditonalExpression-?>endLabelID
+               //実行部分
+               //(break->endLabelID)
+               //incrementalExpression->loopLabelID
+               //endLabelID:
+               
+               //initializer
+               this.bin.push(this.initializer.createBinary());
+               if(this.compiler.unexpected){
+                       return this.bin;
+               }
+               //loopLabelID:
+               this.loopLabelID = this.compiler.allocateLabelID();
+               this.appendInstruction_LB(0x00, this.loopLabelID);
+               
+               //conditonalExpression
+               
+               return this.bin;
+       },
+});
 
-function ELCHNOSCompiler_ExpressionStructure_if(compiler){
-       this.compiler = compiler;
+var ELCHNOSCompiler_ExpressionStructure_if = function(compiler, lineCount){
+       ELCHNOSCompiler_ExpressionStructure_if.base.apply(this, arguments);
        this.structure = new Array();
        this.conditonalExpression = null;
-}
-ELCHNOSCompiler_ExpressionStructure_if.prototype = {
+}.extend(ELCHNOSCompiler_ExpressionStructure, {
 
-}
+});
 
-function ELCHNOSCompiler_ExpressionStructure_Expression(compiler){
-       this.compiler = compiler;
+var ELCHNOSCompiler_ExpressionStructure_Expression = function(compiler, lineCount){
+       ELCHNOSCompiler_ExpressionStructure_Expression.base.apply(this, arguments);
        this.evalStack = new Array();
        this.evalOperatorStack = new Array();
        this.lastOperatorPriority = ELCHNOSCompiler_ExpressionStructure_Expression.prototype.operatorPriorityList.length;
        this.startBracketIndexStack = new Array();
-}
-ELCHNOSCompiler_ExpressionStructure_Expression.prototype = {
+}.extend(ELCHNOSCompiler_ExpressionStructure, {
        //drawLine(1 + 4, x0, y0, x1, y1, col);
        //->    drawLine 1 4 + x0 y0 x1 y1 col ()
        //f(g(1 + 4 * (2 - 3)), 4 * 2 + 1);
@@ -774,7 +996,7 @@ ELCHNOSCompiler_ExpressionStructure_Expression.prototype = {
                //識別子を式に追加する。
                //自動的にオペランドか演算子かを判別し、適切にプッシュする。
                //識別子は大文字小文字を区別できる状態で渡すようにする
-               //レジスタ直接指定もできる
+               //レジスタ直接指定もできる。Rxx, Pxx, 大文字小文字の区別なし。xxは16進。
                
                if(this.isOperator(identifier)){
                        //演算子
@@ -790,7 +1012,7 @@ ELCHNOSCompiler_ExpressionStructure_Expression.prototype = {
                        } else{
                                //レジスタ名である可能性を確認
                                var s = identifier.toLowerCase();
-                               if((s.indexOf("r") == 0 || s.indexOf("p") == 0) && s.length == 3){
+                               if(this.isRegisterName(s)){
                                        //レジスタ名指定
                                        this.pushOperand(s);
                                } else{
@@ -799,6 +1021,28 @@ ELCHNOSCompiler_ExpressionStructure_Expression.prototype = {
                        }
                }
        },
+       readExpressionToTerminator: function(startIndex, terminalCharacter){
+               //startIndexの次の文字から、terminalCharacterまでの識別子を式に追加する。
+               //括弧の対応関係はきちんと数えているので、terminalCharacterに閉じ括弧を指定しても問題ない。
+               //戻り値は、最後に追加した識別子の次の文字のseparatedにおけるインデックスで、
+               //正常に読み込まれた場合はterminalCharacterを指す。
+               var i = startIndex;
+               for(i++; ; i++){
+                       var s = this.compiler.separated[i];
+                       if(s == undefined){
+                               this.compiler.unexpected = true;
+                               break;
+                       }
+                       if(this.startBracketIndexStack.length == 0 && s == terminalCharacter){
+                               break;
+                       }
+                       this.pushIdentifier(s);
+                       if(this.compiler.unexpected){
+                               break;
+                       }
+               }
+               return i;
+       },
        getOperatorPriority: function(operator){
                for(var i = 0, iLen = this.operatorPriorityList.length; i < iLen; i++){
                        if(this.operatorPriorityList[i] == operator){
@@ -820,16 +1064,76 @@ ELCHNOSCompiler_ExpressionStructure_Expression.prototype = {
                        s == "(" ||
                        s == ")"||
                        s == "," ||
+                       s == "()" ||
                        false
                );
        },
-}
+       isRegisterName: function(s){
+               s = s.toLowerCase();
+               return (s.indexOf("r") == 0 || s.indexOf("p") == 0) && !isNaN(s.substring(1));
+       },
+       createBinary: function(){
+               //まずスタックを処理しやすいように詰め直す
+               var stack = new Array();
+               var dataStack = new Array();
+               var op00;
+               var op01;
+               var op02;
+               //残っている演算子から
+               for(var i = 0, iLen = this.evalOperatorStack.length; i < iLen; i++){
+                       stack.push(this.evalOperatorStack.pop());
+               }
+               for(var i = 0, iLen = this.evalStack.length; i < iLen; i++){
+                       stack.push(this.evalStack.pop());
+               }
+               console.log(stack);
+               for(var i = 0, iLen = stack.length; i < iLen; i++){
+                       var o = stack.pop();
+                       if(this.isOperator(o)){
+                               if(o == "="){
+                                       //2:代入
+                                       op01 = dataStack.pop();
+                                       op00 = dataStack.pop();
+                                       if(op00 instanceof ELCHNOSCompiler_ExpressionStructure_Variable){
+                                               //変数への代入
+                                               if(op00.isPointer && op00.labelID == 0){
+                                                       //ポインタレジスタに対する代入
+                                                       if(op01 instanceof ELCHNOSCompiler_ExpressionStructure_Variable){
+                                                               //変数からの代入
+                                                               if(!op01.isPointer && op01.labelID != 0){
+                                                                       //ラベル番号からの代入
+                                                                       //PLIMM
+                                                                       //03    reg0    imm32
+                                                                       this.bin.push(0x03, op00.registerID);
+                                                                       this.appendInstruction_UINT32BE(this.labelID);
+                                                               } else{
+                                                                       this.compiler.unexpected = true;
+                                                                       break;
+                                                               }
+                                                       } else{
+                                                               this.compiler.unexpected = true;
+                                                               break;
+                                                       }
+                                               } else{
+                                                       this.compiler.unexpected = true;
+                                                       break;
+                                               }
+                                       }
+                               } else{
+                                       this.compiler.unexpected = true;
+                                       break;
+                               }
+                       } else{
+                               dataStack.push(o);
+                       }
+               }
+               return this.bin;
+       },
+});
 
-function ELCHNOSCompiler_ExpressionStructure_OSECPUBinary(compiler){
-       this.compiler = compiler;
-       this.bin = new Array();
+var ELCHNOSCompiler_ExpressionStructure_OSECPUBinary = function(compiler, lineCount){
+       ELCHNOSCompiler_ExpressionStructure_OSECPUBinary.base.apply(this, arguments);
        this.isCompiled = false;
-}
-ELCHNOSCompiler_ExpressionStructure_OSECPUBinary.prototype = {
-
-}
\ No newline at end of file
+}.extend(ELCHNOSCompiler_ExpressionStructure, {
+       
+});
\ No newline at end of file