IoT何をいまさら(122) 泥縄で思い出す。インタプリタもどきの文法をEBNF化

Joseph Halfmoon

前回からだいぶ間が空いてしまいました。マイコンに載せてチョイとした用途に使うつもりのインタプリタもどきをGtestを活用?して作っていましたが、ソース以外にドキュメント無。自前とは言え仕様は忘却の彼方デス。作業再開にあたってソースを読みながら文法をEBNF化(いい加減だけれども。)後付け、泥縄、いつものことか。

※「IoT何をいまさら」投稿順Indexはこちら

EBNF

Extended Backus-Naur Formは、その名のとおりBNFの拡張記法です。BNFは、文法など定義するのに時々お目にかかるあれです。BNF素人がブツブツ言っていてもショウガない(ノージンジャー)なので、テキトーなドキュメントを引用させていただきます。

第2回 XML勧告読解に必須のEBNF

普通は、先にBNFなり、EBNFなりで文法を記述してから、それにそってコンパイラなり、インタプリタなり実装するってもんでしょうが、今回は逆です。途中まで「仕掛かかっている」インタプリタもどきのソースを読みながらこれをEBNFに「起こす」ことで記憶をよみがえらせようと。

しかし、ただEBNF化しても面白くないので、1個機能を追加することにいたしました。以下のように let 変数名、その値(式使ってよし)などとしたら値(いまのところ16進整数値のみですが)を変数に格納できるようにしたいと思います。

let X 3+5

まずは、EBNF化した仕様から。最初の1行が追加分。残りは前回までのもの。EBNF_0EC

 

ソース変更

まずはヘッダファイル undertest.hppの追加部分。

bool setdU32(uint32_t id, uint32_t val);
bool defVU32(char *buf);

関数を2個追加します。IDに対して値を格納するsetdU32と、今回追加のdefvariableの処理実体である defVU32です。

本体undertest.cppのdefVU32の定義が以下に。

//<defvariable> --> let <ident> <exp>
bool defVU32(char *buf) {
  if (strncmp(&buf[currentIndex], "let", 3)) {
    return false;
  }
  currentIndex += 3;
  nextCh();
  uint32_t id;
  if (toIdU32(buf, &id)) {
    nextCh();
    uint32_t v = expU32(buf);
    if (errFlag) {
      return false;
    }
    return setdU32(id, v);
  }
  return false;
}そ

そして値をセットするためのsetdU32が以下に。

bool setdU32(uint32_t id, uint32_t val) {
  int idx=0;
  while (idx < MAXID) {
    if (id == idtable[idx][0]) {
      idtable[idx][1] = val;
      return true; 
    } else if (0 == idtable[idx][0]) {
      idtable[idx][0] = id;
      idtable[idx][1] = val;
      return true; 
    }
    idx++;
  }
  return false;
}

そして、Google-Testで上記をテストするための testrunner.cpp への追加が以下に。

TEST(testrunner, defVU32) {
   strcpy(buf, "let X 3+5");
   currentIndex = 0;
   lastIndex = strlen(buf);
   errFlag = false;
   errNumber = 0;
   EXPECT_TRUE(defVU32(buf));
   EXPECT_EQ(currentIndex, 9);
   strcpy(buf, "X");
   currentIndex = 0;
   lastIndex = strlen(buf);
   errFlag = false;
   errNumber = 0;
   EXPECT_EQ(expU32(buf), 3+5);
   EXPECT_EQ(currentIndex, 1);
}
Google-Test結果

Test結果が長いので末尾のみ。testResults

まあ、少なくとも

let X 3+5

などと書くと3+5は8で、8を変数Xに代入してくれているみたい。これで変数の書き込み、読み出しはできたので、今度は関数か?

IoT何をいまさら(121)インタプリタもどき、Google-testその2 へ戻る

IoT何をいまさら(123) 38kHz IR receiver,赤外リモコンの波形を取得 へ進む