[ create a new paste ] login | about

Link: http://codepad.org/bJ6EoLbs    [ raw code | fork ]

C, pasted on Jan 18:
/********************************************************
 * 再帰的下降型構文解析の例
 * E: expressionを加減算の結果とする
 * T: term  を乗除算の結果
 * F: factor 項(被演算子)とする
 * i: identifier 識別子(簡単のためアルファベット1文字)
 *
 * 構文規則(BNF)
 * <L>::= <E> '\n'
 * <E>::= <T> { {+|-} T}
 * <T>::= <F> { {*|/} <F> }
 * <F>::= i | ( <E> )
 *
 応用練習問題
  1)Pーマシン言語に翻訳する
  2)一桁の数字からなる式の計算する電卓プログラムに改造する。
  (2+8)/(7-4) * 5
   15
 ********************************************************/

#include <stdio.h>
void scan();
void error();
void E(); /* 非終端記号Eを解析する関数 */
void T(); /* 非終端記号Fを解析する関数 */
void F();  /* 非終端記号Tを解析する関数 */

char next; /*次のトークン*/

/*******************************************
 * <L>::= <E> 改行文字
 * lineは開始記号なので
 * プログラムを短くするためmainにしてしまう
 ******************************************/

int main (int argc, char* argv[])
{
  scan();
  printf("L--->E\n");
  E();
  if (next != '\n') error();
  printf("\n");
  exit(0);
}


/*****************************************************
 *  トークン(非終端記号)を読みこむ関数
 *  空白(タブはないものとして)を読み飛ばす
 *  字句解析はしばしばスキャナーと呼ばれるので、ここではscan()とする。
****************************************************/
void scan()
{

  while ( (next = getchar()) == ' ');

}
/******************************************************
 * 簡単のためエラー回復なし、で構文解析終了とする
 *****************************************************/
void error()
{
  printf("*********error**********\n");
  exit(1);
}


/*****************************************
 * <E>::= <T> { {+|-} T }
 * 
 * 解析プログラム E( ):
 *    最初のトークンは既に読まれている
 *    T();
 *    while(トークン == 加算演算子) {
 *      次のトークンを読む(); 
 *      T();
 *    }
 * 戻るときは次のトークンまで読んでいる 
 *****************************************/

void E() {
  printf("E--->T <E-rest> \n");
  T();
  if (next !='+' && next !='-') 
    printf("<E-rest>--->empty\n");
  while ( next=='+' || next == '-') {
    printf("<E-rest> --->%c T\n", next);
    scan(); 
    T();
    printf("ADDまたはSUB命令を生成\n");
  }
}

/***************************
 * <T>::=<F> { {*|/} <F> } 
 * 
 *解析プログラムT():
 *    最初のトークンは既に読まれている
 *    F();
 *    while(トークン == 乗除演算子) {
 *      次のトークンを読む(); 
 *      F();
 *    }
 * 戻るときは次のトークンまで読んでいる 
 ****************************/

void T() {
  printf("T--->F <F-rest>\n");
  F();
  if (next !='*' && next !='/') 
    printf("<F-rest>--->empty\n");
  while (next=='*' || next=='/') {
    printf("<F-rest>---> %c F\n", next);
    scan(); 
    F();
    printf("MULまたはDIV命令を生成\n");
  }
}

/********************************************
 * <F>::=  <a-zのアルファベット> 
 *           | ( <E> )
 *
 *解析プログラムF()
 *    if (トークン == 識別子) {
 *      次のトークンを読む(); 
 *	  }
 *    else if (トークン == 括弧開き) {
 *      次のトークンを読む(); 
 *      T();
 *      括弧閉じを確定
 *      次のトークンを読む(); 
 *    }
 * 戻るときは次のトークンまで読んでいる 
 ********************************************/

void F() {

  if ( next >='a' && next <= 'z' ) {
    printf("F--->id(%c)\n", next);
        printf("LOAD命令を生成\n");
    scan();  
  }
  else if (next == '('){
    printf("F --->( E )\n");
    scan();
    E();
    if (next == ')') {
      scan();
    } 
    else 
      error();
  }
}


Create a new paste based on this one


Comments: