1 // ELCHNOSCompiler for AI004
3 function ELCHNOSCompiler(env){
9 this.structure = new Array();
10 this.currentStructure = this.structure;
11 this.structureStack = new Array();
13 //0はエントリポイント(main)用に予約
16 ELCHNOSCompiler.prototype = {
50 "Incompatible value attribute.",
51 "Unexpected identifier.",
52 "Unknown assembly language type.",
53 "Invalid expression of OSECPU Binary."
56 Flag_Sign_Signed : 0x00000001,
57 Flag_Sign_Unsigned : 0x00000002,
59 compile: function(str){
60 this.line = str.split("\n");
62 this.separated = str.splitByArraySeparatorSeparatedLong(this.keyWordList);
63 this.compile_removeComment();
66 this.separated.removeAllObject("\t");
67 this.separated.removeAllObject(" ");
69 console.log(this.separated);
72 var currentExpression = null;
73 var numValSignFlag = 0;
78 //var DestinationOperand = null;
80 var unexpected = false;
87 //10: 変数・定数の前置属性・型・または識別子
88 //11: 変数・定数の識別子またはポインタ属性
89 //12: 変数・定数の後置属性・初期化式または終端記号、もしくは連続した変数宣言の区切り
90 //13: 変数・定数の初期化式または終端記号、もしくは連続した変数宣言の区切り
106 //70: OSECPUアセンブリ直接記述モード
107 //71: OSECPUアセンブリ評価式の内容または終端記号
108 for(var i = 0, iLen = this.separated.length; i < iLen; i++){
109 var s = this.separated[i].toLowerCase();
110 //this.env.debug((i + 1) + ":" + s + "\n");
117 } else if(s == "signed" && (mode == 0 || mode == 10)){
119 if(numValSignFlag == 0){
120 numValSignFlag |= this.Flag_Sign_Signed;
126 } else if(s == "unsigned" && (mode == 0 || mode == 10)){
128 if(numValSignFlag == 0){
129 numValSignFlag |= this.Flag_Sign_Unsigned;
135 } else if(s == "char" && (mode == 0 || mode == 10 || mode == 11 || mode == 52)){
138 if(mode == 0 || mode == 10 || mode == 11){
141 } else if(s == "int" && (mode == 0 || mode == 10 || mode == 11 || mode == 52)){
144 if(mode == 0 || mode == 10 || mode == 11){
147 } else if(s == ";" && (mode == 0 || mode == 12 || mode == 13 || mode == 19 || mode == 60 || mode == 71)){
148 if(mode == 12 || mode == 13 || mode == 19){
152 console.log(currentExpression);
153 currentExpression = null;
155 } else if(mode == 60 || mode == 71){
157 console.log(currentExpression);
158 currentExpression = null;
161 } else if(mode == 71){
167 } else if(s == "=" && (mode == 13)){
174 } else if(s == "*" && (mode == 11)){
177 } else if(s == "," && (mode == 18 || mode == 12 || mode == 13 || mode == 53)){
181 } else if(mode == 12 || mode == 13 || mode == 53){
183 if(mode == 12 || mode == 13){
185 } else if(mode == 53){
188 console.log(currentExpression);
189 currentExpression = null;
194 } else if(s == "[" && (mode == 12)){
197 } else if(s == "]" && (mode == 15)){
200 } else if(s == "{" && (mode == 16 || mode == 54)){
204 } else if(mode == 54){
206 currentExpression = null;
211 } else if(s == "}" && (mode == 17 || mode == 18 || mode == 0)){
212 if(mode == 17 || mode == 18){
215 } else if(mode == 0){
216 if(this.structureStack.length > 0){
217 console.log(this.currentStructure);
218 this.restoreCurrentStructure();
223 } else if(s == "(" && (mode == 51)){
226 } else if(s == ")" && (mode == 52 || mode == 53)){
229 console.log(currentExpression);
230 currentExpression = null;
231 for(var j = 0, jLen = this.currentStructure.length; j < jLen; j++){
233 this.currentStructure[j].argumentIndex = j;
236 } else if(s == "@asm" && (mode == 0)){
238 s = this.separated[i].toLowerCase();
245 } else if(s == "@end" && (mode == 70)){
248 } else if(s == "procedure" && (mode == 0)){
250 var f = new ELCHNOSCompiler_ExpressionStructure_Function(this.env);
251 this.currentStructure.push(f);
252 this.changeCurrentStructure(f.structure);
253 currentExpression = f;
256 } else if(s == "inline" && (mode == 50)){
257 currentExpression.isInline = true;
258 } else if(s == "for" && (mode == 0)){
269 s = this.separated[i];
271 var f = new ELCHNOSCompiler_ExpressionStructure_Loop_for(this.env);
272 this.currentStructure.push(f);
273 this.changeCurrentStructure(f.structure);
274 currentExpression = f;
276 f.initializer = new ELCHNOSCompiler_ExpressionStructure_Expression(this.env);
278 s = this.separated[i];
282 if(this.isOperator(s)){
283 f.initializer.pushOperator(s);
286 s = this.separated[i];
287 o = this.searchIdentifier(s);
289 f.initializer.pushOperand(o);
290 } else if(!isNaN(s)){
291 f.initializer.pushOperand(s);
298 console.log(f.initializer);
301 f.conditonalExpression = new ELCHNOSCompiler_ExpressionStructure_Expression(this.env);
303 s = this.separated[i];
307 if(this.isOperator(s)){
308 f.conditonalExpression.pushOperator(s);
311 s = this.separated[i];
312 o = this.searchIdentifier(s);
314 f.conditonalExpression.pushOperand(o);
315 } else if(!isNaN(s)){
316 f.conditonalExpression.pushOperand(s);
323 console.log(f.conditonalExpression);
327 f.incrementalExpression = new ELCHNOSCompiler_ExpressionStructure_Expression(this.env);
329 s = this.separated[i];
333 if(this.isOperator(s)){
334 f.incrementalExpression.pushOperator(s);
337 s = this.separated[i];
338 o = this.searchIdentifier(s);
340 f.incrementalExpression.pushOperand(o);
341 } else if(!isNaN(s)){
342 f.incrementalExpression.pushOperand(s);
349 console.log(f.incrementalExpression);
354 if(this.separated[i] != "{"){
357 currentExpression = null;
362 } else if(s == "if" && (mode == 0)){
369 s = this.separated[i];
371 var f = new ELCHNOSCompiler_ExpressionStructure_if(this.env);
372 this.currentStructure.push(f);
373 this.changeCurrentStructure(f.structure);
374 currentExpression = f;
376 f.conditonalExpression = new ELCHNOSCompiler_ExpressionStructure_Expression(this.env);
378 s = this.separated[i];
382 if(this.isOperator(s)){
383 f.conditonalExpression.pushOperator(s);
386 s = this.separated[i];
387 o = this.searchIdentifier(s);
389 f.conditonalExpression.pushOperand(o);
390 } else if(!isNaN(s)){
391 f.conditonalExpression.pushOperand(s);
398 console.log(f.conditonalExpression);
402 if(this.separated[i] != "{"){
405 currentExpression = null;
411 } else if(s == "remark" && (mode == 70)){
413 var b = new ELCHNOSCompiler_ExpressionStructure_OSECPUBinary(this.env);
414 this.currentStructure.push(b);
417 s = this.separated[i];
419 var len = parseInt(s, 16);
428 s = this.separated[i];
429 if(s.length == len * 2){
430 for(var j = 0; j < len; j++){
431 b.bin.push(parseInt(s.substr(j * 2, 2), 16));
441 if(this.separated[i] != ";"){
444 //この命令は定数のみで構成されているのでコンパイル済みとマークする
449 } else if(s == "call" && (mode == 70)){
451 var b = new ELCHNOSCompiler_ExpressionStructure_OSECPUBinary(this.env);
452 this.currentStructure.push(b);
456 s = this.separated[i].toLowerCase();
457 if((s.indexOf("p") == 0) && s.length == 3){
460 var labelID = this.allocateLabelID();
461 //PLIMM(P30, labelID)
465 b.bin.push((labelID >> 24) & 0xFF);
466 b.bin.push((labelID >> 16) & 0xFF);
467 b.bin.push((labelID >> 8) & 0xFF);
468 b.bin.push(labelID & 0xFF);
473 b.bin.push(parseInt(s.substr(1),16));
478 b.bin.push((labelID >> 24) & 0xFF);
479 b.bin.push((labelID >> 16) & 0xFF);
480 b.bin.push((labelID >> 8) & 0xFF);
481 b.bin.push(labelID & 0xFF);
488 if(this.separated[i] != ";"){
491 //この命令は定数のみで構成されているのでコンパイル済みとマークする
500 } else if(mode == 11 || mode == 52){
503 var v = new ELCHNOSCompiler_ExpressionStructure_Variable(this.env);
505 v.isSigned = (numValSignFlag == 0) ? false : (0 != (numValSignFlag & this.Flag_Sign_Signed));
506 s = this.separated[i];
507 v.isPointer = (pointerCount != 0) ? true : false;
512 this.currentStructure.push(v);
513 currentExpression = v;
521 } else if(mode == 14){
522 currentExpression.length = parseInt(s);
524 } else if(mode == 17){
526 currentExpression.initValue.push(parseInt(s));
528 } else if(mode == 50){
531 currentExpression.identifier = this.separated[i];
536 s = this.separated[i];
537 o = this.searchIdentifier(s);
538 if(mode == 0 || mode == 70){
541 var f = new ELCHNOSCompiler_ExpressionStructure_Expression(this.env);
543 this.currentStructure.push(f);
544 currentExpression = f;
547 } else if(mode == 70){
553 s = this.separated[i].toLowerCase();
554 if((s.indexOf("r") == 0 || s.indexOf("p") == 0) && s.length == 3){
555 var f = new ELCHNOSCompiler_ExpressionStructure_Expression(this.env);
557 this.currentStructure.push(f);
558 currentExpression = f;
567 } else if(mode == 60 || mode == 71){
569 if(this.isOperator(s)){
570 currentExpression.pushOperator(s);
573 currentExpression.pushOperand(o);
574 } else if(!isNaN(s)){
575 currentExpression.pushOperand(s);
580 if(unexpected && mode == 71){
582 s = this.separated[i].toLowerCase();
583 if((s.indexOf("r") == 0 || s.indexOf("p") == 0) && s.length == 3){
585 currentExpression.pushOperand(s);
594 s = this.separated[i];
595 this.raiseError(errno, lineCount, [s, mode]);
596 console.log(this.structure);
600 console.log(this.structure);
602 compile_removeComment: function(){
604 var commentLineStartIndex = -1;
605 var commentBlockStartIndex = -1;
606 var commentBlockCount = 0;
607 var linesInCommentBlock = 0;
609 for(var i = 0, iLen = this.separated.length; i < iLen; i++){
610 var s = this.separated[i];
611 if(commentLineStartIndex == -1){
614 commentLineStartIndex = i;
619 var len = i - commentLineStartIndex;
620 this.separated.splice(commentLineStartIndex, len);
623 commentLineStartIndex = -1;
628 if(commentBlockCount == 0){
629 commentBlockStartIndex = i;
632 } else if(s == "*/"){
635 if(commentBlockCount == 0){
636 var len = i - commentBlockStartIndex + 1;
637 var padding = new Array();
638 padding.push(commentBlockStartIndex);
640 for(var j = 0, jLen = linesInCommentBlock; j < jLen; j++){
643 this.separated.splice.apply(this.separated, padding);
644 i -= len - linesInCommentBlock;
645 iLen -= len - linesInCommentBlock;
646 linesInCommentBlock = 0;
647 } else if(commentBlockCount < 0){
648 this.env.debug("Too many block comment closure [].\n");
651 } else if(commentBlockCount > 0 && s == "\n"){
652 linesInCommentBlock++;
656 raiseError: function(errno, lineCount, infoArray){
657 if(errno < 0 || this.errorMessageList.length <= errno){
658 this.env.debug(lineCount + ":Error" + errno.toString().toUpperCase() + ":Unknown\n");
660 this.env.debug(lineCount + ":Error" + errno.toString().toUpperCase() + ":" + this.errorMessageList[errno] + "\n");
663 this.env.debug(" >" + infoArray.toString() + "\n");
666 changeCurrentStructure: function(newstructure){
667 this.structureStack.push(this.currentStructure);
668 this.currentStructure = newstructure;
670 restoreCurrentStructure: function(){
671 this.currentStructure = this.structureStack.pop();
673 searchIdentifier: function(identifier){
675 var cf = function(aryobj, obj){ return (aryobj.identifier == obj) };
677 o = this.currentStructure.isIncluded(identifier, cf);
679 for(var i = this.structureStack.length - 1; i >= 0; i--){
680 o = this.structureStack[i].isIncluded(identifier, cf);
688 isOperator: function(s){
703 allocateLabelID: function(){
705 return this.nextLabelID - 1;
709 function ELCHNOSCompiler_ExpressionStructure_Variable(env){
713 this.isSigned = false;
714 this.isPointer = false;
715 this.identifier = null;
716 this.initValue = new Array();
717 //引数として渡されるものであれば、引数の左から数えて何番目かが入る。
718 this.argumentIndex = -1;
720 ELCHNOSCompiler_ExpressionStructure_Variable.prototype = {
724 function ELCHNOSCompiler_ExpressionStructure_Function(env){
726 this.structure = new Array();
727 this.identifier = null;
729 ELCHNOSCompiler_ExpressionStructure_Function.prototype = {
733 function ELCHNOSCompiler_ExpressionStructure_Loop_for(env){
735 this.structure = new Array();
736 this.initializer = null;
737 this.conditonalExpression = null;
738 this.incrementalExpression = null;
739 this.isInline = false;
741 ELCHNOSCompiler_ExpressionStructure_Loop_for.prototype = {
745 function ELCHNOSCompiler_ExpressionStructure_if(env){
747 this.structure = new Array();
748 this.conditonalExpression = null;
750 ELCHNOSCompiler_ExpressionStructure_if.prototype = {
754 function ELCHNOSCompiler_ExpressionStructure_Expression(env){
756 this.evalStack = new Array();
757 this.evalOperatorStack = new Array();
758 this.lastOperatorPriority = ELCHNOSCompiler_ExpressionStructure_Expression.prototype.operatorPriorityList.length;
759 this.startBracketIndexStack = new Array();
761 ELCHNOSCompiler_ExpressionStructure_Expression.prototype = {
762 //drawLine(1 + 4, x0, y0, x1, y1, col);
763 //-> drawLine 1 4 + x0 y0 x1 y1 col ()
764 //f(g(1 + 4 * (2 - 3)), 4 * 2 + 1);
765 //-> f g 1 4 2 3 - * + () 4 2 * 1 + ()
767 operatorPriorityList: [
777 pushOperand: function(identifier){
778 this.evalStack.push(identifier);
780 pushOperator: function(operator){
787 var p = this.getOperatorPriority(operator);
788 if(this.lastOperatorPriority >= p){
790 this.evalOperatorStack.push(operator);
792 //優先順位がより高い演算子を先に積んでおき、そのあと自分をとっておく
793 for(var i = 0, iLen = this.evalOperatorStack.length; i < iLen; i++){
794 var o = this.evalOperatorStack.pop();
795 if(this.getOperatorPriority(o) < p){
796 this.evalStack.push(o);
798 this.evalOperatorStack.push(o);
802 this.evalOperatorStack.push(operator);
804 this.lastOperatorPriority = p;
806 getOperatorPriority: function(operator){
807 for(var i = 0, iLen = this.operatorPriorityList.length; i < iLen; i++){
808 if(this.operatorPriorityList[i] == operator){
816 function ELCHNOSCompiler_ExpressionStructure_OSECPUBinary(env){
818 this.bin = new Array();
819 this.isCompiled = false;
821 ELCHNOSCompiler_ExpressionStructure_OSECPUBinary.prototype = {