MiniBasicの実行

■MiniBasicの実行

1. 導出木の探索

2. ハッシュによる実現

3. Interpreterの実装

4. Mainの実装


■CAI演習課題6


■参考資料・リンク集

■質問・相談用掲示板

←目次へ戻る

2005年10月5日 6:48 更新

 

1. 導出木の探索

5章 MiniBasicの文法と解析 において、MiniBasicの文法を定義し、いくつかのプログラム例における構文解析について確認した。

ここでは、MiniBasicのプログラムの実行、すなわち、あるプログラム(命令列)に対する導出木が与えられた場合、この導出木を何らかの方法で探索し、数値演算や変数への値の代入、プログラム制御(条件実行文、繰り返し文)、ならびに組み込み関数機能の実現などを、逐次翻訳・実行するための方法について説明する。

1.1 逐次実行
1.2 条件実行文


1.1 逐次実行

文法 5.2 において、以下のプログラム例1が入力列として与えられた際、生成された導出木を図6.1に示す。この例は、変数への代入 → 変数値を5倍して表示 という2ステップを逐次実行するものである。

プログラム例1:代入と表示(乗算結果の表示)

I := 3
PRINT I * 5

 

図6.1: プログラム例1の導出木

ここでは、非終端記号の各ノード(Statements, Assignment, Expression, Valueなど)は、導出木内で、各々 Statements1, Statements1, Assignment1, Expression1, Expression2, ..., Value3 といった様にインスタンス名が与えられていると考えている。

4.四則演算式の実行 の場合では、各ノードでの値を評価するタイミングを検討したのだった。今回の命令列の実行では、特に各ノードでの「評価」については、[A]数値演算式の評価、[B]変数への代入、[C]組み込み関数の実施 という3つに大別される。

[A] 数値演算式の評価

図6.1 において、「値を評価すべき」タイミングは、以下の3カ所である。特に、(2)において、変数の値を評価していることに注意せよ(変数の値の取得方法については、後述)

  1. Value1 の葉(leaf)として、整数リテラル Number の値を評価した後、結果(整数値 3)を Value1 の結果とする。
  2. Value2 の葉(leaf)として、変数 Identifier:I の値を評価した後、結果(変数名 I の値)を Value2 の結果とする。
  3. Value3 の葉(leaf)として、整数リテラル Number の値を評価した後、結果(整数値 5)を Value3 の結果とする。

一方、図6.1 において、「数値演算を実行すべき」タイミングは、以下の2カ所である。

  1. Expression1 において、Value1以下の部分木の結果を得た後、これをそのまま、Expression1 以下の部分木の計算結果とする。
  2. Expression2 において、Value2以下の部分木の結果(left)と、Value3以下の部分木の結果(right)を得た後、これを乗算(left * right)し、結果を Expression2 以下の部分木の計算結果とする。

[B] 変数への代入

図6.1 において、「変数へ値を代入すべき」タイミングは、以下の1カ所である。

  1. Assignment1 の葉(leaf)として、代入する先の変数名(Identifier:I)を取得する。次に、整数値(Expression1)の値を評価した後、結果(整数値 3)を 変数名Iへの代入値としてセットする(変数へ値をセットする方法については、後述)。

[C] 組み込み関数の実施

図6.1 において、「組み込み関数を実施すべき」タイミングは、以下の1カ所である。

  1. PrintExp1 の葉(leaf)として、出力する整数値 Expression2 を評価する。評価した後、結果(ここでは、変数Iの値を5倍した値)を「表示」する。。

 


1.2 条件実行文

文法 4.2 において、以下のプログラム例2が入力列として与えられた際、生成された導出木を図6.2に示す。この例は、変数への読み込み → 変数値を絶対値変換して表示(正負の条件実行文)という2ステップを逐次実行するものである。

プログラム例2:数値読み込みと条件実行文(絶対値の表示)

READ I
IF I < 0 THEN
  PRINT 0 - I
ELSE
  PRINT I
ENDIF

 

図6.2: プログラム例2の導出木

条件実行文の命令列の実行では、条件文(論理演算式)の評価値が真か偽かによって、THEN以下の命令列を実行するか、ELSE以下の命令列を実行するかを判断する必要がある。

図6.2の場合について、具体的には、条件実行文の命令列:IfStatement1の実行では、条件文:LessThanCondition1の論理演算式の評価値が真か偽かによって、THEN以下の命令列(Statement2)を実行するか、ELSE以下の命令列(Statement3)を実行するか、という様態になっている。

特に論理演算を行うノード LessThanCondition1 での「評価」については、以下に述べる。

[D] 論理演算式の評価

図6.2:ノード LessThanCondition1 において、「値を評価すべき」タイミングは、以下の3カ所である。特に、(2)において、変数の値を評価していることに注意せよ(変数の値の取得方法については、後述)

  1. Value1 の葉(leaf)として、変数 Identifier:I の値を評価した後、結果(変数名 I の値)を Value1 の結果とする。
  2. Value2 の葉(leaf)として、整数リテラル Number の値を評価した後、結果(整数値 0)を Value2 の結果とする。

一方、図6.2:ノード LessThanCondition1 において、「論理演算の実行」タイミングは、以下の1カ所である。

  1. LessThanCondition1 において、Value1以下の部分木の結果(left)と、Value2以下の部分木の結果(right)を得た後、これを比較し(? left < right)し、結果(真偽値)を LessThanCondition1 以下の部分木の計算結果とする。

 

2. ハッシュによる実現

2.1 ハッシュ表を用いた評価値格納と変数管理
2.2 ハッシュ表を用いた評価の実際


2.1 ハッシュ表を用いた評価値格納と変数管理

MiniBasicの各ノードにおける数値/論理演算結果の格納、ならびに変数管理と代入/評価は、各々ハッシュ表を用意して行う。

ハッシュ表は、以下の2つを用意する。

・評価値管理表(values):key ノード名 --> value 整数値/論理値
・変数管理表(variables):key 変数名 --> value 数値

A. 評価値管理表(values)の操作

整数値、論理値操作向けに、各々2つの操作(書き込み/読み出し)を用意する。

整数値用
 書き込み:setIntValue (引数 Node名, セットする整数値)
 読み出し:getIntValue (引数 Node名) → 返り値:Nodeの評価値(整数)

論理値用
 書き込み:setBoolValue (引数 Node名, セットする論理値)
 読み出し:getBoolValue (引数 Node名) → 返り値:Nodeの評価値(論理値)

B. 変数管理表(variables)の操作

変数の管理/代入/評価値操作向けに、2つの操作(代入/読み出し)を用意する。

変数管理用
 代入操作:setVariable (引数 変数名, セットする整数値)
 読み出し:getVariable (引数 変数名) → 返り値:変数の値(整数)
      ※一度も代入されていない変数の評価値は、ゼロを返すようにしておく。

 


2.2 ハッシュ表を用いた評価の実際

プログラム例1:図6.1 の導出木において、DFS探索の各ステップにおけるハッシュ表の操作について、以下に示す。

[STEP #1] Statement1 --> Assignment1

[STEP #2] Identifier : I (変数名の取得)

[STEP #3] Token : assign ':='

[STEP #4] Value1:
      setIntValue ( Value1, Number:3 )

[STEP #5] Expression1:
      setIntValue ( Expression1, getIntValue ( Node1 ) )

[STEP #6] Assignment1:
      setVariable ( Identifier "I", getIntValue ( Expression1 ) )

※この時点で、変数用ハッシュ表:key "I" --> value 3 が格納されている。

[STEP #7] Statement2 --> PrintExp1

[STEP #8] Token : Print 'PRINT'

[STEP #9] Value2:
      setIntValue ( Value2, getVariable ( Identifier "I" ) )

[STEP#10] Token : Mult '*'

[STEP#11] Value3:
      setIntValue ( Value3, Number:5 )

[STEP#12] Expression2:
      left := getIntValue ( Value2 )
      right := getIntValue ( Value3 )
      setIntValue ( Expression2, left * right )

[STEP#13] getIntValue ( Expression2 ) --> I * 5 の値を表示

[STEP#14] Empty1 --> [EOF] 終了

 

3. Interpreterの実装

SableCCにて逐次翻訳・実行プログラム(インタープリター)を実装するため、まずDFS探索エンジン(DepthFirstAdapterクラス)への Visitor を実装する。

まず、探索時の各ノードの評価値ならびに変数値を管理するため、Hashtableオブジェクトを使用してハッシュ表を構成する。次に、各命令のノードについて、変数代入や各種演算、条件分岐処理、繰り返し処理などを行うためのVisitorを実装する。

Visitorは、Design Patternsの一つである。詳しくは参考文献を参照のこと。

3.1 ハッシュ表の実装
3.2 Acceptor/Visitorの例
3.3 Visitor (Interpreterクラス) の実装

 


3.1 ハッシュ表の実装

各ノードにおける数値/論理演算結果の格納、ならびに変数管理と代入/評価は、Hashtableオブジェクトを使用して、以下の2つを用意する。

・評価値管理表(values):key ノード名 --> value 整数値/論理値
・変数管理表(variables):key 変数名 --> value 数値

<評価値管理表(values)の実装>

    // -----------------------------------------------------------------
    // Hashtable to associate integer and boolean values
    // with expression and condition nodes

    Hashtable values = new Hashtable(); 

    // Routines to avoid typecasts
    void setIntValue(Node node, int value) 
    {
        values.put(node, new Integer(value)); 
    }

    int getIntValue(Node node) 
    {
        return ((Integer) values.get(node)).intValue(); 
    }

    void setBoolValue(Node node, boolean value) 
    {
        values.put(node, new Boolean(value)); 
    }

    boolean getBoolValue(Node node) 
    { 
        return ((Boolean) values.get(node)).booleanValue(); 
    }
      

<変数管理表(variables)の実装>

    // -----------------------------------------------------------------
    // Hashtable to hold variables and their values

    Hashtable variables = new Hashtable();

    // Routines to avoid typecasts
    void setVariable(String name, int value) 
    {
        variables.put(name.toUpperCase(), new Integer(value)); 
    }

    int getVariable(String name) 
    { 
        Integer variable = (Integer) variables.get(name.toUpperCase());

        // If the variable has already been assigned a value 
        if(variable != null)
            return variable.intValue(); // return the stored value
        else
            return 0; // else return 0
    }
      

 


3.2 Acceptor/Visitorの例

DepthFirstAdapterクラスのAcceptorのうち、caseAAssignmentStatementメソッド(変数への値代入)を例にしてVisitor側の実装について検討してみる。

A. Acceptor側

caseAAssignmentStatementメソッドは、AAssignmentStatement型のnodeオブジェクトを引数とする Acceptor である。caseAAssignmentStatementメソッド(Acceptor側)の抜粋を以下に示す。

DepthFirstAdapter :: caseAAssignmentStatement の抜粋

    public void caseAAssignmentStatement(AAssignmentStatement node)
    {
        inAAssignmentStatement(node);
        if(node.getIdentifier() != null)
        {
            node.getIdentifier().apply(this);
        }
        if(node.getAssign() != null)
        {
            node.getAssign().apply(this);
        }
        if(node.getExpression() != null)
        {
            node.getExpression().apply(this);
        }
        if(node.getNewLine() != null)
        {
            node.getNewLine().apply(this);
        }
        outAAssignmentStatement(node);
    }
      

これは、引数として渡された当該nodeオブジェクトについて(例えば図6.1における Assignment1 node)これの child(Identifier, Assign token, Expression) が NULL でなければ、各々のchild を探索( apply(this) )して評価する、という「探索動作のみ」を記述している。

B. Visitor側

今回は、Assignmentのchildについて、まず Expression 以下の部分木の評価値(整数値)を取得し、取得した値を、Identifier で指示されている「変数名」をキーとして、変数管理用ハッシュ表の内容を更新する、といった作業を caseAAssignmentStatement メソッドで行わせたい。

DepthFirstAdapterクラスを継承した Visitor側 Interpreter.java における、caseAAssignmentStatementメソッド(Visitor側)の抜粋を以下に示す。

Interpreter :: caseAAssignmentStatementの抜粋

    public void caseAAssignmentStatement(AAssignmentStatement node)
    {
        node.getExpression().apply(this); // Evaluate the expression
        
        setVariable( // Assign variable
            node.getIdentifier().getText(),
            getIntValue(node.getExpression())); 
    }
      

具体的には、ノードに到達した際、その 代入したい部分木の評価値を getExpression().apply(this) によって取得しておき、(その結果は、部分木の評価終了後、評価値管理用ハッシュ表に格納されているから)getIntValue(node.getExpression()) によってハッシュ表から取り出し、その値を、変数管理用ハッシュにおいて変数名(getIdentifier().getText())をキーにして、代入する。

 


3.3 Visitor (Interpreterクラス) の実装

ハッシュ表を利用して、逐次翻訳・実行動作を行うための、Visitor (Interpreterクラス) の、具体的な実装について、以下に説明する。

Interpreterクラス(ソースファイル)

InterpreterクラスのVisitor一覧

 

Interpreterクラス(ソースファイル)抜粋

     8  package minibasic;

    17  public class Interpreter extends DepthFirstAdapter
    18  {

            ...... ハッシュの実装(3.1節参照) ........

            ...... Visitor : 条件実行文(IF)の実装 .........

    71      /**
    72       * IF condition THEN statements [ELSE statements] ENDIF
    73       */
    74      public void caseAIfStatement(AIfStatement node)
    75      {
    76          node.getCondition().apply(this);  // Evaluate the condition
    77
    78          if(getBoolValue(node.getCondition()))
    79          {
    80              node.getStatements().apply(this); // Evaluate then
                                                         statements
    81          }
    82          else
    83          {  
    84              node.getOptionalElse().apply(this); // Evaluate else
                                                           statements
    85          }
    86      }

            ...... Visitor : 繰り返し実行(FOR)文の実装 .........

    88      /**
    89       * FOR identifier := from_exp TO to_exp statements NEXT
    90       */
    91      public void caseAForStatement(AForStatement node)
    92      {
    93          node.getFromExp().apply(this); // Evaluate the from
                         expression
    94          node.getToExp().apply(this);   // Evaluate the to expression
    95
    96          int from = getIntValue(node.getFromExp());
    97          int to   = getIntValue(node.getToExp());
    98
    99          for(int i = from; i <= to; i++)
   100          {
   101              setVariable(node.getIdentifier().getText(), i); 
                    // Assign the value to the loop variable
   102
   103              node.getStatements().apply(this); // Evaluate the
                                                         statements
   104          }
   105      }

            ...... Visitor : 組み込み関数(READ,PRINT)の実装 .........

   110      BufferedReader in = 
                       new BufferedReader(new InputStreamReader(System.in)); 
   111      PrintStream    out = System.out;

            ...... 中略 ......

   120      /**
   121       * READ identifier
   122       */
   123      public void caseAReadStatement(AReadStatement node)
   124      {
   125          System.out.print("? "); // Display a prompt
   126          try
   127          {
   128              String s = in.readLine(); // Read one line of text
   129              int value = Integer.parseInt(s); // parse the value
   130              setVariable(node.getIdentifier().getText(), value); 
                                                     // Set the variable
   131          }
   132          catch(IOException e) // I/O ERROR!!!
   133          {
                    ...... 例外処理(中略) ......
   139          }
   140      }
   141
   142      /**
   143       * PRINT expression
   144       */
   145      public void caseAPrintExpStatement(APrintExpStatement node)
   146      {
   147          node.getExpression().apply(this); // Evaluate the expression
   148
   149          out.print(getIntValue(node.getExpression())); // print it
   150      }
   151
   152      /**
   153       * PRINT "string"
   154       */
   155      public void caseAPrintStrStatement(APrintStrStatement node)
   156      {
   157          String s = node.getString().getText(); // get the string text
   158          out.print(s.substring(1, s.length() - 1)); // Don't print "
   159      }
   160
   161      /**
   162       * PRINTLN
   163       */
   164      public void caseAPrintlnStatement(APrintlnStatement node)
   165      {
   166          out.println(); // print a new line
   167      }

            ...... Visitor : 変数代入文の実装 .........

   172      /**
   173       * ASSIGNMENT identifier := expression
   174       */
   175      public void caseAAssignmentStatement(AAssignmentStatement node)
   176      {
   177          node.getExpression().apply(this); // Evaluate the expression
   178          
   179          setVariable( // Assign variable
   180              node.getIdentifier().getText(),
   181              getIntValue(node.getExpression())); 
   182      }

            ...... Visitor : 条件文(論理式)の評価 .........

   187      static final int LT = 0;
   188      static final int GT = 1;
   189      static final int EQ = 2;
   190
   191      boolean evalCondition(Node left, Node right, int operator)
   192      {
   193          left.apply(this);  // Evaluate the left expression
   194          right.apply(this); // Evaluate the right expression
   195
   196          switch(operator)
   197          {
   198          case LT: return getIntValue(left) < getIntValue(right);
   199          case GT: return getIntValue(left) > getIntValue(right);
   200          case EQ: return getIntValue(left) == getIntValue(right);
   201          default: throw new RuntimeException("Internal Error");
   202          }
   203      }
   204
   205      /**
   206       * CONDITION(LT) left < right
   207       */
   208      public void caseALessThanCondition(ALessThanCondition node)
   209      { 
   210          setBoolValue(node, evalCondition(node.getLeft(), 
                                                 node.getRight(), LT));
   211      }
   212
   213      /**
   214       * CONDITION(GT) left > right
   215       */
   216      public void caseAGreaterThanCondition(AGreaterThanCondition node)
   217      { 
   218          setBoolValue(node, evalCondition(node.getLeft(), 
                                                 node.getRight(), GT));
   219      }
   220
   221      /**
   222       * CONDITION(EQ) left = right
   223       */
   224      public void caseAEqualCondition(AEqualCondition node)
   225      { 
   226          setBoolValue(node, evalCondition(node.getLeft(), 
                                                 node.getRight(), EQ));
   227      }

            ...... Visitor : 数値演算式の評価 .........

   232      static final int PLUS  = 0;
   233      static final int MINUS = 1;
   234      static final int MULT  = 2;
   235      static final int DIV   = 3;
   236      static final int MOD   = 4;
   237
   238      int evalExpression(Node left, Node right, int operator)
   239      {
   240          left.apply(this);  // Evaluate the left expression
   241          right.apply(this); // Evaluate the right expression
   242
   243          switch(operator)
   244          {
   245          case PLUS:  return getIntValue(left) + getIntValue(right);
   246          case MINUS: return getIntValue(left) - getIntValue(right);
   247          case MULT:  return getIntValue(left) * getIntValue(right);
   248          case DIV:   return getIntValue(left) / getIntValue(right);
   249          case MOD:   return getIntValue(left) % getIntValue(right);
   250          default: throw new RuntimeException("Internal Error");
   251          }
   252      }
   253
   254      /**
   255       * GET value
   256       */
   257      public void caseAValueExpression(AValueExpression node)
   258      {
   259          node.getValue().apply(this); // Evaluate the expression
   260
   261          setIntValue(node, getIntValue(node.getValue()));
   262      }
   263
   264      /**
   265       * CALC(PLUS) left + right
   266       */
   267      public void caseAPlusExpression(APlusExpression node)
   268      {
   269          setIntValue(node, evalExpression(node.getLeft(), 
                                                 node.getRight(), PLUS));
   270      }
   271
   272      /**
   273       * CALC(MINUS) left - right
   274       */
   275      public void caseAMinusExpression(AMinusExpression node)
   276      {
   277          setIntValue(node, evalExpression(node.getLeft(), 
                                                 node.getRight(), MINUS));
   278      }
   279
   280      /**
   281       * CALC(MULT) left * right
   282       */
   283      public void caseAMultExpression(AMultExpression node)
   284      {
   285          setIntValue(node, evalExpression(node.getLeft(), 
                                                 node.getRight(), MULT));
   286      }
   287
   288      /**
   289       * CALC(DIV) left / right
   290       */
   291      public void caseADivExpression(ADivExpression node)
   292      {
   293          try
   294          {
   295              setIntValue(node, evalExpression(node.getLeft(), 
                                                     node.getRight(), DIV));
   296          }
   297          catch(ArithmeticException e) // DIVIDE BY ZERO ERROR
   298          {
   299              error("DIVIDE BY ZERO ERROR IN LINE " + 
                                                    node.getDiv().getLine());
   300          }
   301      }
   302
   303      /**
   304       * CALC(MOD) left MOD right
   305       */
   306      public void caseAModExpression(AModExpression node)
   307      {
   308          try
   309          {
   310              setIntValue(node, evalExpression(node.getLeft(), 
                                                     node.getRight(), MOD));
   311          }
   312          catch(ArithmeticException e) // MODULUS ZERO ERROR
   313          {
   314              error("MODULUS ZERO ERROR IN LINE " + 
                                                  node.getMod().getLine());
   315          }
   316      }

            ...... Visitor : リテラル、変数値の取得 .........

   321      /**
   322       * CONTSTANT value (integer format)
   323       */
   324      public void caseAConstantValue(AConstantValue node)
   325      {
   326          try
   327          {
   328              int value = Integer.parseInt(node.getNumber().getText());
   329              setIntValue(node, value);
   330          }
   331          catch(NumberFormatException e) // NUMBER FORMAT ERROR!!!
   332          {
   333              error("NUMBER FORMAT ERROR IN LINE " + 
                                                 node.getNumber().getLine());
   334          }
   335      }
   336
   337      /**
   338       * IDENT value (assigned variable)
   339       */
   340      public void caseAIdentifierValue(AIdentifierValue node)
   341      {
   342          setIntValue(node, getVariable(node.getIdentifier().getText()));
   343      }
   344
   345      /**
   346       * EXPRESSION value
   347       */
   348      public void caseAExpressionValue(AExpressionValue node)
   349      {
   350          node.getExpression().apply(this); // Evaluate the expression
   351
   352          setIntValue(node, getIntValue(node.getExpression()));
   353      }

   357  }
      

<説明>

17行目:Interpreterクラス宣言(DepthFirstAdapterクラスから継承)

71--86行目:条件実行文の実装

構文規則 IF condition THEN statements [ELSE statements] ENDIF に対応する、caseAIfStatement Visitor の実装である。

・論理式Conditionを評価(getCondition())
・評価値管理ハッシュを表引き
  評価値が真の場合 --> THEN以下Statement部分木を探索
  評価値が偽の場合 --> ELSE以下OptionalElse部分木を探索

88--105行目:繰り返し実行文の実装

構文規則 FOR identifier := from_exp TO to_exp statements NEXT に対応する、caseAForStatement Visitor の実装である。

・カウント用変数の開始値 FromExpを評価(getFromExp())--> from
・カウント用変数の終了値 ToExpを評価(getToExp())--> to
・from から to までの回数分、以下を繰り返し実行する
  カウント用変数について、現在のカウント値を代入
  Statements部分木を探索

110--167行目:組み込み関数(READ,PRINT,PRINTLN)の実装

標準入力からの読み込み、ならびに標準出力への表示についての実装である。

172--182行目:変数代入文の実装

3.2節 B.を参照のこと

187--227行目:論理演算式の評価の実装

IF条件実行文で用いられる論理式の評価についての実装である。

・leaf left を評価
・leaf right を評価
・evalCondition関数を用いて、left : right の関係の真偽を評価
・評価値管理ハッシュへ、当該ノードの評価値(論理値)をセット

232--316行目:数値演算式の評価の実装

・leaf left を評価
・leaf right を評価
・evalExpression関数を用いて、left ↑ right の演算を評価
・評価値管理ハッシュへ、当該ノードの評価値(整数値)をセット

321--353行目:リテラル・変数値の取得の実装

 

4. Mainの実装

SableCCにおいて、文法ファイルに基づいて生成された lexer/parser, ならびに先に実装した Visitor(Interpreterクラス)を駆動するため、Mainを実装する。最後に、実行プログラム全体をビルドし、入力命令列を与えてテストを行う。

4.1 Main.javaの実装
4.2 実行プログラムのビルドとテスト

 


4.1 Main.javaの実装

Lexer, Parser, 各ノードオブジェクト(node)のクラスパッケージを利用し、Visitor(Interpreterクラス)を利用してプログラム実行動作を駆動するための、Mainの具体的な実装について、以下に説明する。

Mainクラス(ソースファイル)

Mainクラスの実装(抜粋)

     8  package minibasic;

    11  import minibasic.node.*;
    12  import minibasic.lexer.*;
    13  import minibasic.parser.*;

    17  public class Main
    18  {
    19      public static void main(String[] arguments)
    20      {
    21
    22          try
    23          {
    24              Lexer l = new Lexer(
    25                  new PushbackReader(
    26                  new BufferedReader(
    27                  new FileReader(arguments[0])), 1024));
    28
    29              Parser p = new Parser(l);
    30
    31              Node tree = p.parse();
    32
    33              tree.apply(new Interpreter());
    34          }
    35          catch(Exception e)
    36          {
    37              System.out.println(e);
    38          }
    39      }
    40  }
      

<説明>

11-13行目

node, lexer, parserクラスパッケージの利用を宣言

24--27行目

ファイル入力ストリームから PushbackReader を使用して入力列を読み込み、Lexerコンストラクタによって字句解析器 Lexerオブジェクトのインスタンス l を得る。

29行目

Lexerのインスタンス l を引数として、Parserコンストラクタによって構文解析器 Parserオブジェクトのインスタンス p を得る。

31行目

Parserクラスの parseメソッドによって、導出木のインスタンス tree を得る。

33行目

Visitorクラスの Interpreter のインスタンス を new し、導出木treeに対してDFS探索を実行する。

 


4.2 実行プログラムのビルドとテスト

minibasicプロジェクトファイルはここからダウンロード
minibasic-src.tar.gz

実際に、MiniBasicプログラムのいくつかを、インタープリター実行プログラム(minibasic.jar)に入力した場合の実行結果を以下に示す。

<プログラム例1 test2.basic(絶対値の表示)>

PRINT "What is your number"
READ I
PRINT "ABS( "
PRINT I
PRINT " ) = "
IF I < 0 THEN
  PRINT ( 0 - I )
ELSE
  PRINT I
ENDIF
PRINTLN

<実行結果1:プログラム例1 test2.basic

$ java -jar minibasic.jar test2.basic 

What is your number? 9
ABS( 9 ) = 9


$ java -jar minibasic.jar test2.basic

What is your number? -9
ABS( -9 ) = 9

 

<プログラム例2 test3.basic(かけ算の表)>

PRINT "What is your number"
READ I
FOR X := 1 TO I
  FOR Y := 1 TO I
    PRINT X * Y
    PRINT " "
  NEXT
PRINTLN
NEXT
PRINTLN
      

<実行結果2:プログラム例2 test3.basic

$ java -jar minibasic.jar test3.basic

What is your number? 9
1 2 3 4 5 6 7 8 9 
2 4 6 8 10 12 14 16 18 
3 6 9 12 15 18 21 24 27 
4 8 12 16 20 24 28 32 36 
5 10 15 20 25 30 35 40 45 
6 12 18 24 30 36 42 48 54 
7 14 21 28 35 42 49 56 63 
8 16 24 32 40 48 56 64 72 
9 18 27 36 45 54 63 72 81 


$ java -jar minibasic.jar test3.basic

What is your number? 16
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 
2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 
3 6 9 12 15 18 21 24 27 30 33 36 39 42 45 48 
4 8 12 16 20 24 28 32 36 40 44 48 52 56 60 64 
5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80 
6 12 18 24 30 36 42 48 54 60 66 72 78 84 90 96 
7 14 21 28 35 42 49 56 63 70 77 84 91 98 105 112 
8 16 24 32 40 48 56 64 72 80 88 96 104 112 120 128 
9 18 27 36 45 54 63 72 81 90 99 108 117 126 135 144 
10 20 30 40 50 60 70 80 90 100 110 120 130 140 150 160 
11 22 33 44 55 66 77 88 99 110 121 132 143 154 165 176 
12 24 36 48 60 72 84 96 108 120 132 144 156 168 180 192 
13 26 39 52 65 78 91 104 117 130 143 156 169 182 195 208 
14 28 42 56 70 84 98 112 126 140 154 168 182 196 210 224 
15 30 45 60 75 90 105 120 135 150 165 180 195 210 225 240 
16 32 48 64 80 96 112 128 144 160 176 192 208 224 240 256 

 

<プログラム例3 test4.basic(Newton法による二乗根)>

PRINT "What is your number"
READ I
X := 3
FOR N := 1 TO 20
  X := ( X + ( ( I * 10000 ) / X ) ) / 2 
  PRINT "N="
  PRINT N
  PRINT ", X="
  PRINT X
  PRINTLN
NEXT
PRINT "SQRT ( "
PRINT I
PRINT " ) = "
PRINT ( X / 100 )
PRINT "."
PRINT ( X % 100 )
PRINTLN
      

<実行結果3:プログラム例3 test4.basic

$ java -jar minibasic.jar test4.basic

What is your number? 3
N=1, X=5001
N=2, X=2503
N=3, X=1257
N=4, X=640
N=5, X=343
N=6, X=215
N=7, X=177
N=8, X=173
N=9, X=173
N=10, X=173
N=11, X=173
N=12, X=173
N=13, X=173
N=14, X=173
N=15, X=173
N=16, X=173
N=17, X=173
N=18, X=173
N=19, X=173
N=20, X=173
SQRT ( 3 ) = 1.73


$ java -jar minibasic.jar test4.basic

What is your number? 4096
N=1, X=6826668
N=2, X=3413336
N=3, X=1706673
N=4, X=853348
N=5, X=426697
N=6, X=213396
N=7, X=106793
N=8, X=53588
N=9, X=27176
N=10, X=14341
N=11, X=8598
N=12, X=6680
N=13, X=6405
N=14, X=6400
N=15, X=6400
N=16, X=6400
N=17, X=6400
N=18, X=6400
N=19, X=6400
N=20, X=6400
SQRT ( 4096 ) = 64.0
      
 

 

信州大学インターネット大学院

wasaki@cs.shinshu-u.ac.jp
Copyright(c) 2006 Katsumi Wasaki. All rights reserved.