OSDN Git Service

保存コミット
authorhikarupsp <hikarupsp@users.sourceforge.jp>
Thu, 17 Oct 2013 18:12:09 +0000 (03:12 +0900)
committerhikarupsp <hikarupsp@users.sourceforge.jp>
Thu, 17 Oct 2013 18:12:09 +0000 (03:12 +0900)
aiext.js
elcc.js
test.elc

index dddfb12..a8bfdc8 100644 (file)
--- a/aiext.js
+++ b/aiext.js
@@ -153,6 +153,8 @@ String.prototype.compareLeftHand = function (search){
 String.prototype.splitByArray = function(separatorList){
        //リスト中の文字列それぞれで分割された配列を返す。
        //separatorはそれ以前の文字列の末尾に追加された状態で含まれる。
+       //"abcdefg".splitByArray(["a", "e", "g"]);
+       //      = ["a", "bcde", "fg"]
        var retArray = new Array();
        retArray[0] = this;
        
@@ -183,6 +185,8 @@ String.prototype.splitByArray = function(separatorList){
 String.prototype.splitByArraySeparatorSeparated = function(separatorList){
        //リスト中の文字列それぞれで分割された配列を返す。
        //separatorも分割された状態で含まれる。
+       //"abcdefg".splitByArraySeparatorSeparated(["a", "e", "g"]);
+       //      = ["a", "bcd", "e", "f", "g"]
        var retArray = new Array();
        retArray[0] = this;
        
@@ -208,6 +212,53 @@ String.prototype.splitByArraySeparatorSeparated = function(separatorList){
        return retArray;
 }
 
+String.prototype.splitByArraySeparatorSeparatedLong = function(separatorList){
+       //リスト中の文字列それぞれで分割された配列を返す。
+       //separatorも分割された状態で含まれる。
+       //separatorListの前の方にあるseparatorは、後方のseparatorによって分割されない。
+       //"abcdefgcdefg".splitByArraySeparatorSeparatedLong(["bcde", "cd", "f"]);
+       //      = ["a", "bcde", "f", "g", "cd", "e", "f", "g"]
+       //"for (i = 0; i != 15; i++) {".splitByArraySeparatorSeparatedLong(["!=", "(", ")", "="]);
+       //      = ["for ", "(", "i ", "=", " 0; i ", "!=", " 15; i++", ")", " {"]
+       var retArray = new Array();
+       var checkArray = new Array();
+       retArray[0] = this;
+       checkArray[0] = false;
+       
+       for(var i = 0; i < separatorList.length; i++){
+               var tmpArray = new Array();
+               var tmpCheckArray = new Array();
+               for(var k = 0; k < retArray.length; k++){
+                       if(!checkArray[k]){
+                               var tmpArraySub = retArray[k].split(separatorList[i]);
+                               tmpArray[k] = new Array();
+                               tmpCheckArray[k] = new Array();
+                               for(var m = 0, mLen = tmpArraySub.length - 1; m < mLen; m++){
+                                       if(tmpArraySub[m] != ""){
+                                               tmpArray[k].push(tmpArraySub[m]);
+                                               tmpCheckArray[k].push(false);
+                                       }
+                                       tmpArray[k].push(separatorList[i]);
+                                       tmpCheckArray[k].push(true);
+                               }
+                               if(tmpArraySub[tmpArraySub.length - 1] != ""){
+                                       tmpArray[k].push(tmpArraySub[m]);
+                                       tmpCheckArray[k].push(false);
+                               }
+                       } else{
+                               tmpArray.push([retArray[k]]);
+                               tmpCheckArray.push([true]);
+                       }
+               }
+               retArray = new Array();
+               checkArray = new Array();
+               retArray = retArray.concat.apply(retArray, tmpArray);
+               checkArray = checkArray.concat.apply(checkArray, tmpCheckArray);
+       }
+       
+       return retArray;
+}
+
 String.prototype.trim = function(str){
        return this.replace(/^[       ]+|[          ]+$/g, "").replace(/\n$/g, "");
 }
diff --git a/elcc.js b/elcc.js
index c2719f3..3142fd4 100644 (file)
--- a/elcc.js
+++ b/elcc.js
@@ -3,12 +3,31 @@
 function ELCHNOSCompiler(env){
        this.env = env;
        
+       this.line = null;
+       this.separated = null;
+       
        this.structure = new Array();
        this.currentStructure = this.structure;
        this.structureStack = new Array();
+       
+       //0はエントリポイント(main)用に予約
+       this.nextLabelID = 1;
 }
 ELCHNOSCompiler.prototype = {
        keyWordList: [
+               "@asm",
+               "@end",
+               "//",
+               "/*",
+               "*/",
+               "!=",
+               "==",
+               "+=",
+               "-=",
+               "*=",
+               "/=",
+               "++",
+               "--",
                "\n",
                "\t",
                " ",
@@ -17,9 +36,6 @@ ELCHNOSCompiler.prototype = {
                "(",
                ")",
                ";",
-               "//",
-               "/*",
-               "*/",
                ",",
                "[",
                "]",
@@ -32,79 +48,34 @@ ELCHNOSCompiler.prototype = {
        errorMessageList: [
                "Trap.",
                "Incompatible value attribute.",
-               "Unexpected identifier."
+               "Unexpected identifier.",
+               "Unknown assembly language type.",
+               "Invalid expression of OSECPU Binary."
        ],
        
        Flag_Sign_Signed                        : 0x00000001,
        Flag_Sign_Unsigned                      : 0x00000002,
        
        compile: function(str){
-               var line = str.split("\n");
-               var separated = str.splitByArraySeparatorSeparated(this.keyWordList);
-               
-               //コメント削除
-               var commentLineStartIndex = -1;
-               var commentBlockStartIndex = -1;
-               var commentBlockCount = 0;
-               var linesInCommentBlock = 0;
-               for(var i = 0, iLen = separated.length; i < iLen; i++){
-                       var s = separated[i];
-                       if(commentLineStartIndex == -1){
-                               if(s == "//"){
-                                       //行コメント開始
-                                       commentLineStartIndex = i;
-                               }
-                       } else{
-                               if(s == "\n"){
-                                       //行コメント終了
-                                       var len = i - commentLineStartIndex;
-                                       separated.splice(commentLineStartIndex, len);
-                                       iLen -= len;
-                                       i -= len;
-                                       commentLineStartIndex = -1;
-                               }
-                       }
-                       if(s == "/*"){
-                               //ブロックコメント開始
-                               if(commentBlockCount == 0){
-                                       commentBlockStartIndex = i;
-                               }
-                               commentBlockCount++;
-                       } else if(s == "*/"){
-                               //ブロックコメント終了
-                               commentBlockCount--;
-                               if(commentBlockCount == 0){
-                                       var len = i - commentBlockStartIndex + 1;
-                                       var padding = new Array();
-                                       padding.push(commentBlockStartIndex);
-                                       padding.push(len);
-                                       for(var j = 0, jLen = linesInCommentBlock; j < jLen; j++){
-                                               padding.push("\n");
-                                       }
-                                       separated.splice.apply(separated, padding);
-                                       i -= len;
-                                       iLen -= len;
-                                       linesInCommentBlock = 0;
-                               } else if(commentBlockCount < 0){
-                                       this.env.debug("Too many block comment closure [].\n");
-                                       return;
-                               }
-                       } else if(commentBlockCount < 0 && s == "\n"){
-                               linesInCommentBlock++;
-                       }
-               }
+               this.line = str.split("\n");
+               //分割
+               this.separated = str.splitByArraySeparatorSeparatedLong(this.keyWordList);
+               this.compile_removeComment();
                
                //不要な文字を削除
-               separated.removeAllObject("\t");
-               separated.removeAllObject(" ");
+               this.separated.removeAllObject("\t");
+               this.separated.removeAllObject(" ");
+               
+               console.log(this.separated);
                
+               //メイン処理
                var currentExpression = null;
                var numValSignFlag = 0;
                var numValBits = 0;
                var pointerCount = 0;
                var lineCount = 1;
                var blockLevel = 0;
-               var DestinationOperand = null;
+               //var DestinationOperand = null;
                var mode = 0;
                var unexpected = false;
                var errno = 2;
@@ -124,18 +95,18 @@ ELCHNOSCompiler.prototype = {
                        //18: 初期化式の区切りまたは終了括弧
                        //19: 終端記号
                        //
-                       //50: 関数名
+                       //50: 関数名または関数属性
                        //51: 引数開始括弧
                        //52: 引数or引数終了括弧
                        //53: 引数区切りor引数終了括弧
                        //54: 関数内部開始括弧
                        //
-                       //60: è­\98å\88¥å­\90ã\81«å¯¾ã\81\99ã\82\8bä½\95ã\82\89ã\81\8bã\81®æ\93\8dä½\9cã\81®é\96\8bå§\8b
+                       //60: è©\95価å¼\8fã\81®å\86\85容ã\81¾ã\81\9fã\81¯çµ\82端è¨\98å\8f·
                        //
-                       //71: 評価式の内容または終端記号
-                       
-               for(var i = 0, iLen = separated.length; i < iLen; i++){
-                       var s = separated[i].toLowerCase();
+                       //70: OSECPUアセンブリ直接記述モード
+                       //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"){
@@ -161,15 +132,19 @@ ELCHNOSCompiler.prototype = {
                                        unexpected = true;
                                        errno = 1;
                                }
-                       } else if(s == "char"  && (mode == 0 || mode == 10 || mode == 11)){
+                       } else if(s == "char"  && (mode == 0 || mode == 10 || mode == 11 || mode == 52)){
                                //char 8bit符号あり
                                numValBits = 8;
-                               mode = 11;
-                       } else if(s == "int" && (mode == 0 || mode == 10 || mode == 11)){
-                               //int 8bit符号あり
+                               if(mode == 0 || mode == 10 || mode == 11){
+                                       mode = 11;
+                               }
+                       } else if(s == "int" && (mode == 0 || mode == 10 || mode == 11 || mode == 52)){
+                               //int 32bit符号あり
                                numValBits = 32;
-                               mode = 11;
-                       } else if(s == ";" && (mode == 0 || mode == 12 || mode == 13 || mode == 19 || mode == 71)){
+                               if(mode == 0 || mode == 10 || mode == 11){
+                                       mode = 11;
+                               }
+                       } else if(s == ";" && (mode == 0 || mode == 12 || mode == 13 || mode == 19 || mode == 60 || mode == 71)){
                                if(mode == 12 || mode == 13 || mode == 19){
                                        //変数または定数の定義終了
                                        numValBits = 0;
@@ -177,44 +152,41 @@ ELCHNOSCompiler.prototype = {
                                        console.log(currentExpression);
                                        currentExpression = null;
                                        mode = 0;
-                               } else if(mode == 71){
+                               } else if(mode == 60 || mode == 71){
                                        //評価式終端
                                        console.log(currentExpression);
                                        currentExpression = null;
-                                       mode = 0;
+                                       if(mode == 60){
+                                               mode = 0;
+                                       } else if(mode == 71){
+                                               mode = 70;
+                                       }
                                } else{
                                        unexpected = true;
                                }
-                       } else if(s == "=" && (mode == 13 || mode == 60)){
+                       } else if(s == "=" && (mode == 13)){
                                if(mode == 13){
                                        //変数・定数初期化式開始
                                        mode = 16;
-                               } else if(mode == 60 && DestinationOperand){
-                                       //代入操作追加
-                                       var f = new ELCHNOSCompiler_ExpressionStructure_Expression(this.env);
-                                       f.pushOperand(DestinationOperand);
-                                       f.pushOperator(s);
-                                       
-                                       this.currentStructure.push(f);
-                                       currentExpression = f;
-                                       
-                                       DestinationOperand = null;
-                                       mode = 71;
                                } else{
                                        unexpected = true;
                                }
                        } else if(s == "*" && (mode == 11)){
                                //ポインタ属性の付加
                                pointerCount++;
-                       } else if(s == "," && (mode == 18 || mode == 12 || mode == 13)){
+                       } else if(s == "," && (mode == 18 || mode == 12 || mode == 13 || mode == 53)){
                                if(mode == 18){
                                        //初期化式の区切り
                                        mode = 17;
-                               } else if(mode == 12 || mode == 13){
+                               } else if(mode == 12 || mode == 13 || mode == 53){
                                        //連続した変数宣言の区切り
+                                       if(mode == 12 || mode == 13){
+                                               mode = 11;
+                                       } else if(mode == 53){
+                                               mode = 52;
+                                       }
                                        console.log(currentExpression);
                                        currentExpression = null;
-                                       mode = 11;
                                } else{
                                        unexpected = true;
                                }
@@ -243,7 +215,7 @@ ELCHNOSCompiler.prototype = {
                                } else if(mode == 0){
                                        if(this.structureStack.length > 0){
                                                console.log(this.currentStructure);
-                                               this.restoreCurrentStructure;
+                                               this.restoreCurrentStructure();
                                        } else{
                                                unexpected = true;
                                        }
@@ -254,22 +226,284 @@ ELCHNOSCompiler.prototype = {
                        } else if(s == ")" && (mode == 52 || mode == 53)){
                                //52: 引数or引数終了括弧
                                //53: 引数区切りor引数終了括弧
+                               console.log(currentExpression);
+                               currentExpression = null;
+                               for(var j = 0, jLen = this.currentStructure.length; j < jLen; j++){
+                                       //引数番号を付与
+                                       this.currentStructure[j].argumentIndex = j;
+                               }
                                mode = 54;
+                       } else if(s == "@asm" && (mode == 0)){
+                               i++;
+                               s = this.separated[i].toLowerCase();
+                               if(s == "osecpu"){
+                                       mode = 70;
+                               } else{
+                                       unexpected = true;
+                                       errno = 3;
+                               }
+                       } else if(s == "@end" && (mode == 70)){
+                               mode = 0;
                        //リストにない予約語
                        } else if(s == "procedure" && (mode == 0)){
                                //関数宣言
-                               var f = new ELCHNOSCompiler_ExpressionStructure_Function();
-                               this.changeCurrentStructure(f.structure)
+                               var f = new ELCHNOSCompiler_ExpressionStructure_Function(this.env);
+                               this.currentStructure.push(f);
+                               this.changeCurrentStructure(f.structure);
                                currentExpression = f;
                                
                                mode = 50;
+                       } else if(s == "inline" && (mode == 50)){
+                               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.env);
+                                       this.currentStructure.push(f);
+                                       this.changeCurrentStructure(f.structure);
+                                       currentExpression = f;
+                                       //初期化式
+                                       f.initializer = new ELCHNOSCompiler_ExpressionStructure_Expression(this.env);
+                                       for(i++; ; i++){
+                                               s = this.separated[i];
+                                               if(s == ";"){
+                                                       break;
+                                               }
+                                               if(this.isOperator(s)){
+                                                       f.initializer.pushOperator(s);
+                                               } else{
+                                                       //大文字小文字を区別
+                                                       s = this.separated[i];
+                                                       o = this.searchIdentifier(s);
+                                                       if(o){
+                                                               f.initializer.pushOperand(o);
+                                                       } else if(!isNaN(s)){
+                                                               f.initializer.pushOperand(s);
+                                                       } else{
+                                                               unexpected = true;
+                                                               break;
+                                                       }
+                                               }
+                                       }
+                                       console.log(f.initializer);
+                                       //条件評価式
+                                       if(!unexpected){
+                                               f.conditonalExpression = new ELCHNOSCompiler_ExpressionStructure_Expression(this.env);
+                                               for(i++; ; i++){
+                                                       s = this.separated[i];
+                                                       if(s == ";"){
+                                                               break;
+                                                       }
+                                                       if(this.isOperator(s)){
+                                                               f.conditonalExpression.pushOperator(s);
+                                                       } else{
+                                                               //大文字小文字を区別
+                                                               s = this.separated[i];
+                                                               o = this.searchIdentifier(s);
+                                                               if(o){
+                                                                       f.conditonalExpression.pushOperand(o);
+                                                               } else if(!isNaN(s)){
+                                                                       f.conditonalExpression.pushOperand(s);
+                                                               } else{
+                                                                       unexpected = true;
+                                                                       break;
+                                                               }
+                                                       }
+                                               }
+                                               console.log(f.conditonalExpression);
+                                       }
+                                       //更新式
+                                       if(!unexpected){
+                                               f.incrementalExpression = new ELCHNOSCompiler_ExpressionStructure_Expression(this.env);
+                                               for(i++; ; i++){
+                                                       s = this.separated[i];
+                                                       if(s == ")"){
+                                                               break;
+                                                       }
+                                                       if(this.isOperator(s)){
+                                                               f.incrementalExpression.pushOperator(s);
+                                                       } else{
+                                                               //大文字小文字を区別
+                                                               s = this.separated[i];
+                                                               o = this.searchIdentifier(s);
+                                                               if(o){
+                                                                       f.incrementalExpression.pushOperand(o);
+                                                               } else if(!isNaN(s)){
+                                                                       f.incrementalExpression.pushOperand(s);
+                                                               } else{
+                                                                       unexpected = true;
+                                                                       break;
+                                                               }
+                                                       }
+                                               }
+                                               console.log(f.incrementalExpression);
+                                       }
+                                       //開始括弧
+                                       if(!unexpected){
+                                               i++;
+                                               if(this.separated[i] != "{"){
+                                                       unexpected = true;
+                                               }
+                                               currentExpression = null;
+                                       }
+                               } else{
+                                       unexpected = true;
+                               }
+                       } else if(s == "if" && (mode == 0)){
+                               //if文
+                               //条件評価式-?>L2
+                               //実行部分
+                               //(break->L2)
+                               //L2:
+                               i++;
+                               s = this.separated[i];
+                               if(s == "("){
+                                       var f = new ELCHNOSCompiler_ExpressionStructure_if(this.env);
+                                       this.currentStructure.push(f);
+                                       this.changeCurrentStructure(f.structure);
+                                       currentExpression = f;
+                                       //条件評価式
+                                       f.conditonalExpression = new ELCHNOSCompiler_ExpressionStructure_Expression(this.env);
+                                       for(i++; ; i++){
+                                               s = this.separated[i];
+                                               if(s == ")"){
+                                                       break;
+                                               }
+                                               if(this.isOperator(s)){
+                                                       f.conditonalExpression.pushOperator(s);
+                                               } else{
+                                                       //大文字小文字を区別
+                                                       s = this.separated[i];
+                                                       o = this.searchIdentifier(s);
+                                                       if(o){
+                                                               f.conditonalExpression.pushOperand(o);
+                                                       } else if(!isNaN(s)){
+                                                               f.conditonalExpression.pushOperand(s);
+                                                       } else{
+                                                               unexpected = true;
+                                                               break;
+                                                       }
+                                               }
+                                       }
+                                       console.log(f.conditonalExpression);
+                                       //開始括弧
+                                       if(!unexpected){
+                                               i++;
+                                               if(this.separated[i] != "{"){
+                                                       unexpected = true;
+                                               }
+                                               currentExpression = null;
+                                       }
+                               } else{
+                                       unexpected = true;
+                               }
+                       //OSECPUアセンブリ
+                       } else if(s == "remark" && (mode == 70)){
+                               //超手抜き
+                               var b = new ELCHNOSCompiler_ExpressionStructure_OSECPUBinary(this.env);
+                               this.currentStructure.push(b);
+                               //len
+                               i++;
+                               s = this.separated[i];
+                               if(s.length == 2){
+                                       var len = parseInt(s, 16);
+                                       b.bin.push(len);
+                               } else{
+                                       unexpected = true;
+                                       errno = 4;
+                               }
+                               //data
+                               if(!unexpected){
+                                       i++;
+                                       s = this.separated[i];
+                                       if(s.length == len * 2){
+                                               for(var j = 0; j < len; j++){
+                                                       b.bin.push(parseInt(s.substr(j * 2, 2), 16));
+                                               }
+                                       } else{
+                                               unexpected = true;
+                                               errno = 4;
+                                       }
+                               }
+                               
+                               if(!unexpected){
+                                       i++;
+                                       if(this.separated[i] != ";"){
+                                               unexpected = true;
+                                       } else{
+                                               //この命令は定数のみで構成されているのでコンパイル済みとマークする
+                                               b.isCompiled = true;
+                                               b = null;
+                                       }
+                               }
+                       } else if(s == "call" && (mode == 70)){
+                               //超手抜き
+                               var b = new ELCHNOSCompiler_ExpressionStructure_OSECPUBinary(this.env);
+                               this.currentStructure.push(b);
+                               
+                               //第二引数が何か確認する
+                               i++;
+                               s = this.separated[i].toLowerCase();
+                               if((s.indexOf("p") == 0) && s.length == 3){
+                                       //ポインタレジスタをcall
+                                       //新しいラベル番号をもらう
+                                       var labelID = this.allocateLabelID();
+                                       //PLIMM(P30, labelID)
+                                               //03    reg0    imm32
+                                       b.bin.push(0x03);
+                                       b.bin.push(0x30);
+                                       b.bin.push((labelID >> 24) & 0xFF);
+                                       b.bin.push((labelID >> 16) & 0xFF);
+                                       b.bin.push((labelID >> 8) & 0xFF);
+                                       b.bin.push(labelID & 0xFF);
+                                       //PCP(P3F, Pxx)
+                                               //1E    reg0P   reg1P
+                                       b.bin.push(0x1e);
+                                       b.bin.push(0x3f);
+                                       b.bin.push(parseInt(s.substr(1),16));
+                                       //LB(1, labelID)
+                                               //02    opt     imm32
+                                       b.bin.push(0x02);
+                                       b.bin.push(0x01);
+                                       b.bin.push((labelID >> 24) & 0xFF);
+                                       b.bin.push((labelID >> 16) & 0xFF);
+                                       b.bin.push((labelID >> 8) & 0xFF);
+                                       b.bin.push(labelID & 0xFF);
+                                       //[FE] [01] [00]
+                                       b.bin.push(0xfe);
+                                       b.bin.push(0x01);
+                                       b.bin.push(0x00);
+                                       //終端記号
+                                       i++;
+                                       if(this.separated[i] != ";"){
+                                               unexpected = true;
+                                       } else{
+                                               //この命令は定数のみで構成されているのでコンパイル済みとマークする
+                                               b.isCompiled = true;
+                                               b = null;
+                                       }
+                               } else{
+                                       unexpected = true;
+                                       errno = 0;
+                               }
                        //予約語以外
-                       } else if(mode == 11){
+                       } else if(mode == 11 || mode == 52){
                                //変数または定数の宣言
-                               var v = new ELCHNOSCompiler_ExpressionStructure_Variable();
+                               //52: 引数名
+                               var v = new ELCHNOSCompiler_ExpressionStructure_Variable(this.env);
                                v.bits = numValBits;
                                v.isSigned = (numValSignFlag == 0) ? false : (0 != (numValSignFlag & this.Flag_Sign_Signed));
-                               s = separated[i];
+                               s = this.separated[i];
                                v.isPointer = (pointerCount != 0) ? true : false;
                                pointerCount = 0;
                                if(s.length > 0){
@@ -278,7 +512,9 @@ ELCHNOSCompiler.prototype = {
                                        this.currentStructure.push(v);
                                        currentExpression = v;
                                        
-                                       mode = 12;
+                                       //mode:11->12
+                                       //mode:52->53
+                                       mode++;
                                } else{
                                        unexpected = true;
                                }
@@ -290,31 +526,64 @@ ELCHNOSCompiler.prototype = {
                                currentExpression.initValue.push(parseInt(s));
                                mode = 18;
                        } else if(mode == 50){
-                               currentExpression.identifier = s;
+                               //関数名
+                               //大文字小文字を区別
+                               currentExpression.identifier = this.separated[i];
                                mode = 51;
                        } else{
                                //現在のスコープを検索
-                               o = this.currentStructure.isIncluded(s, function(aryobj, obj){ return (aryobj.identifier == obj) });
-                               if(!o){
-                                       //グローバルスコープを検索
-                                       o = this.structure.isIncluded(s, function(aryobj, obj){ return (aryobj.identifier == obj) });
-                               }
-                               if(mode == 0){
-                                       //DestinationOperandから操作式は始まる
+                               //大文字小文字を区別
+                               s = this.separated[i];
+                               o = this.searchIdentifier(s);
+                               if(mode == 0 || mode == 70){
+                                       //最初の左辺
                                        if(o){
-                                               DestinationOperand = o;
-                                               mode = 60;
+                                               var f = new ELCHNOSCompiler_ExpressionStructure_Expression(this.env);
+                                               f.pushOperand(o);
+                                               this.currentStructure.push(f);
+                                               currentExpression = f;
+                                               if(mode == 0){
+                                                       mode = 60;
+                                               } else if(mode == 70){
+                                                       mode = 71;
+                                               }
                                        } else{
-                                               unexpected = true;
+                                               if(mode == 70){
+                                                       //レジスタ名かもしれない
+                                                       s = this.separated[i].toLowerCase();
+                                                       if((s.indexOf("r") == 0 || s.indexOf("p") == 0) && s.length == 3){
+                                                               var f = new ELCHNOSCompiler_ExpressionStructure_Expression(this.env);
+                                                               f.pushOperand(s);
+                                                               this.currentStructure.push(f);
+                                                               currentExpression = f;
+                                                               mode = 71;
+                                                       } else{
+                                                               unexpected = true;
+                                                       }
+                                               } else{
+                                                       unexpected = true;
+                                               }
                                        }
-                               } else if(mode == 71){
+                               } else if(mode == 60 || mode == 71){
                                        //評価式オペランド
-                                       if(o){
-                                               currentExpression.pushOperand(o);
-                                       } else if(!isNaN(s)){
-                                               currentExpression.pushOperand(s);
+                                       if(this.isOperator(s)){
+                                               currentExpression.pushOperator(s);
                                        } else{
-                                               unexpected = true;
+                                               if(o){
+                                                       currentExpression.pushOperand(o);
+                                               } else if(!isNaN(s)){
+                                                       currentExpression.pushOperand(s);
+                                               } else{
+                                                       unexpected = true;
+                                               }
+                                       }
+                                       if(unexpected && mode == 71){
+                                               //レジスタ名かもしれない
+                                               s = this.separated[i].toLowerCase();
+                                               if((s.indexOf("r") == 0 || s.indexOf("p") == 0) && s.length == 3){
+                                                       unexpected = false;
+                                                       currentExpression.pushOperand(s);
+                                               }
                                        }
                                } else{
                                        unexpected = true;
@@ -322,10 +591,67 @@ ELCHNOSCompiler.prototype = {
                        }
                        if(unexpected){
                                //期待されていない値
-                               this.raiseError(2, lineCount, [s, mode]);
+                               s = this.separated[i];
+                               this.raiseError(errno, lineCount, [s, mode]);
+                               console.log(this.structure);
                                return;
                        }
                }
+               console.log(this.structure);
+       },
+       compile_removeComment: function(){
+               //コメント削除
+               var commentLineStartIndex = -1;
+               var commentBlockStartIndex = -1;
+               var commentBlockCount = 0;
+               var linesInCommentBlock = 0;
+               
+               for(var i = 0, iLen = this.separated.length; i < iLen; i++){
+                       var s = this.separated[i];
+                       if(commentLineStartIndex == -1){
+                               if(s == "//"){
+                                       //行コメント開始
+                                       commentLineStartIndex = i;
+                               }
+                       } else{
+                               if(s == "\n"){
+                                       //行コメント終了
+                                       var len = i - commentLineStartIndex;
+                                       this.separated.splice(commentLineStartIndex, len);
+                                       iLen -= len;
+                                       i -= len;
+                                       commentLineStartIndex = -1;
+                               }
+                       }
+                       if(s == "/*"){
+                               //ブロックコメント開始
+                               if(commentBlockCount == 0){
+                                       commentBlockStartIndex = i;
+                               }
+                               commentBlockCount++;
+                       } else if(s == "*/"){
+                               //ブロックコメント終了
+                               commentBlockCount--;
+                               if(commentBlockCount == 0){
+                                       var len = i - commentBlockStartIndex + 1;
+                                       var padding = new Array();
+                                       padding.push(commentBlockStartIndex);
+                                       padding.push(len);
+                                       for(var j = 0, jLen = linesInCommentBlock; j < jLen; j++){
+                                               padding.push("\n");
+                                       }
+                                       this.separated.splice.apply(this.separated, padding);
+                                       i -= len - linesInCommentBlock;
+                                       iLen -= len - linesInCommentBlock;
+                                       linesInCommentBlock = 0;
+                               } else if(commentBlockCount < 0){
+                                       this.env.debug("Too many block comment closure [].\n");
+                                       return;
+                               }
+                       } else if(commentBlockCount > 0 && s == "\n"){
+                               linesInCommentBlock++;
+                       }
+               }
        },
        raiseError: function(errno, lineCount, infoArray){
                if(errno < 0 || this.errorMessageList.length <= errno){
@@ -334,7 +660,7 @@ ELCHNOSCompiler.prototype = {
                        this.env.debug(lineCount + ":Error" + errno.toString().toUpperCase() + ":" + this.errorMessageList[errno] + "\n");
                }
                if(infoArray){
-                       this.env.debug("  ErrorInfo:" + infoArray.toString() + "\n");
+                       this.env.debug("  >" + infoArray.toString() + "\n");
                }
        },
        changeCurrentStructure: function(newstructure){
@@ -343,22 +669,60 @@ ELCHNOSCompiler.prototype = {
        },
        restoreCurrentStructure: function(){
                this.currentStructure = this.structureStack.pop();
-       }
+       },
+       searchIdentifier: function(identifier){
+               var o;
+               var cf = function(aryobj, obj){ return (aryobj.identifier == obj) };
+               
+               o = this.currentStructure.isIncluded(identifier, cf);
+               if(!o){
+                       for(var i = this.structureStack.length - 1; i >= 0; i--){
+                               o = this.structureStack[i].isIncluded(identifier, cf);
+                               if(o){
+                                       break;
+                               }
+                       }
+               }
+               return o;
+       },
+       isOperator: function(s){
+               return (
+                       s == "=" ||
+                       s == "+" ||
+                       s == "-" ||
+                       s == "*" ||
+                       s == "/" ||
+                       s == "!=" ||
+                       s == "++" ||
+                       s == "<" ||
+                       //s == "(" ||
+                       //s == ")"||
+                       false
+               );
+       },
+       allocateLabelID: function(){
+               this.nextLabelID++;
+               return this.nextLabelID - 1;
+       },
 }
 
-function ELCHNOSCompiler_ExpressionStructure_Variable(){
+function ELCHNOSCompiler_ExpressionStructure_Variable(env){
+       this.env = env;
        this.bits = 0;
        this.length = 0;
        this.isSigned = false;
        this.isPointer = false;
        this.identifier = null;
        this.initValue = new Array();
+       //引数として渡されるものであれば、引数の左から数えて何番目かが入る。
+       this.argumentIndex = -1;
 }
 ELCHNOSCompiler_ExpressionStructure_Variable.prototype = {
 
 }
 
-function ELCHNOSCompiler_ExpressionStructure_Function(){
+function ELCHNOSCompiler_ExpressionStructure_Function(env){
+       this.env = env;
        this.structure = new Array();
        this.identifier = null;
 }
@@ -366,13 +730,40 @@ ELCHNOSCompiler_ExpressionStructure_Function.prototype = {
 
 }
 
+function ELCHNOSCompiler_ExpressionStructure_Loop_for(env){
+       this.env = env;
+       this.structure = new Array();
+       this.initializer = null;
+       this.conditonalExpression = null;
+       this.incrementalExpression = null;
+       this.isInline = false;
+}
+ELCHNOSCompiler_ExpressionStructure_Loop_for.prototype = {
+
+}
+
+function ELCHNOSCompiler_ExpressionStructure_if(env){
+       this.env = env;
+       this.structure = new Array();
+       this.conditonalExpression = null;
+}
+ELCHNOSCompiler_ExpressionStructure_if.prototype = {
+
+}
+
 function ELCHNOSCompiler_ExpressionStructure_Expression(env){
        this.env = env;
        this.evalStack = new Array();
        this.evalOperatorStack = new Array();
        this.lastOperatorPriority = ELCHNOSCompiler_ExpressionStructure_Expression.prototype.operatorPriorityList.length;
+       this.startBracketIndexStack = new Array();
 }
 ELCHNOSCompiler_ExpressionStructure_Expression.prototype = {
+       //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);
+       //->    f g 1 4 2 3 - * + () 4 2 * 1 + ()
+       
        operatorPriorityList: [
                "/",
                "*",
@@ -387,6 +778,12 @@ ELCHNOSCompiler_ExpressionStructure_Expression.prototype = {
                this.evalStack.push(identifier);
        },
        pushOperator: function(operator){
+       /*
+               if(operator == "("){
+                       //開き括弧を記憶
+                       if(this.evalStack[])
+               }
+               */
                var p = this.getOperatorPriority(operator);
                if(this.lastOperatorPriority >= p){
                        //とりあえずとっておく
@@ -414,4 +811,13 @@ ELCHNOSCompiler_ExpressionStructure_Expression.prototype = {
                }
                return i;
        },
+}
+
+function ELCHNOSCompiler_ExpressionStructure_OSECPUBinary(env){
+       this.env = env;
+       this.bin = new Array();
+       this.isCompiled = false;
+}
+ELCHNOSCompiler_ExpressionStructure_OSECPUBinary.prototype = {
+
 }
\ No newline at end of file
index a3eaa3b..e6f2bf8 100644 (file)
--- a/test.elc
+++ b/test.elc
@@ -7,6 +7,21 @@ unsigned char table[32] = {
        129, 191, 164, 171, 187, 139, 196, 100,
 };
 
+procedure inline drawLine(int mode, x0, y0, x1, y1, col){
+       @asm OSECPU
+       REMARK 05 0100000003;
+       R30 = 0xff45;
+       R31 = mode;
+       R32 = x0;
+       R33 = y0;
+       R34 = x1;
+       R35 = y1;
+       R36 = col;
+       CALL P28;
+       REMARK 01 00;
+       @end
+}
+
 procedure main()
 {
        int x0, y0, x1, y1, col, i, j;
@@ -15,9 +30,9 @@ procedure main()
        p = table;
        for (i = 0; i != 15; i++) {
                x0 = *p;
-               p++
+               p++;
                y0 = *p;
-               p++
+               p++;
                
                q = table;
                for (j = -8; j != 8; j++) {
@@ -30,7 +45,7 @@ procedure main()
                                col = 1 - col;
                        }
                        if (col <= 7) {
-                               junkApi_drawLine(1 + 4, x0, y0, x1, y1, col);
+                               drawLine(1 + 4, x0, y0, x1, y1, col);
                        }
                }
        }