陳鍾誠

Version 1.0

編譯器

範例 – 編譯數學運算式為中間碼

PS D:\ccc\book\aijs\code\07-language> node compileExp '3+2'
"3+2"
 T0=3
 T1=2
 T2=T0+T1
PS D:\ccc\book\aijs\code\07-language> node compileExp '5*4/2'
"5*4/2"
 T0=5
 T1=4
 T2=2
 T3=T1/T2
 T4=T0*T3
PS D:\ccc\book\aijs\code\07-language> node compileExp '3+(5*4)-2'
"3+(5*4)-2"
 T0=3
 T1=5
 T2=4
 T3=T1*T2
 T4=2
 T5=T3-T4
 T6=T0+T5

原始碼 : compileExp.js

/* 運算式編譯器:

語法: E = T ([+-/*] E)*
      T = N | (E)

範例:3+(5*4)-2 */
var c = console;

var tagMap={
  N : ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"],
  OP: ["+", "-", "*", "/"]
};

var wi = 0;

function isNext(tag) {
  if (words[wi] === tag) return true;
  var tagWords=tagMap[tag];
  if (typeof tagWords === "undefined") 
    return false;
  else
    return (tagWords.indexOf(words[wi])>=0);
}

function next(tag) {
  // c.log("tag="+tag+" word="+words[wi]);
  if (isNext(tag)) {
    return words[wi++];
  }
  throw Error("Error !");
}

var tempIdx = 0;
var getTemp=function() {
  return tempIdx++;
}
// E = T ([+-/*] E)*
function E() {
  var t = T();
  while (isNext("OP")) {
    var op = next("OP");
    var e = E();
    var result = getTemp();
    console.log(" T%d=T%d%sT%d", result, t, op, e);
    t = result;
  }
  return t;
}

// T = N | (E)
function T() {
  if (isNext("N")) {
    var t = getTemp();
    var number = next("N");
    console.log(" T%d=%d", t, number);
    return t;
  } else {
    next("(");
    var e = E();
    next(")");
    return e;
  }
}

if (process.argv.length != 3) {
  c.log("參數數量錯誤,請嘗試以下範例:\n\nnode compileExp '3+(5*4)-2'\n")
  process.exit(1)
}
let words = process.argv[2]
c.log("%j", words);
E(words);