1

言語 c-- の語彙アナライザーを実装する割り当てがあります。c_code を一連のトークンに変換する必要があります。これは、操作が容易になるため、内部で整数として表されます。言語の字句上の慣例として、double、else、if、int、return、void、while などのキーワードがあります。+ - * / < <= > >= == != = のような特殊記号も。、 。( ) [ ] { } /* */ //. 識別子は、任意の文字またはアンダースコアで始まり、その後に文字、数字、およびアンダースコアの任意の組み合わせが続きます。空白はトークンを区切り、無視されます。数値は整数または小数にすることができ、コメント行とブロックを使用できます。

import java.io.*;
public class Lex {

    public static boolean contains(char[] a, char b){
        for (int i = 0; i < a.length; i++) {
            if(b == a[i])
                return true;
        }
        return false;
    } 
    public static void main(String args[]) throws FileNotFoundException, IOException{

        //Declaring token values as constant integers.
        final int T_DOUBLE = 0; 
        final int T_ELSE = 1;
        final int T_IF = 2; 
        final int T_INT = 3;
        final int T_RETURN = 4; 
        final int T_VOID = 5;
        final int T_WHILE = 6; 
        final int T_PLUS = 7;
        final int T_MINUS = 8; 
        final int T_MULTIPLICATION = 9;
        final int T_DIVISION = 10; 
        final int T_LESS = 11;
        final int T_LESSEQUAL = 12; 
        final int T_GREATER = 13;
        final int T_GREATEREQUAL = 14; 
        final int T_EQUAL = 16;
        final int T_NOTEQUAL = 17;
        final int T_ASSIGNOP = 18; 
        final int T_SMEICOLON = 19;
        final int T_PERIOD = 20; 
        final int T_LEFTPAREN = 21;
        final int T_RIGHTPAREN = 22; 
        final int T_LEFTBRACKET = 23;
        final int T_RIGHTBRACKET = 24; 
        final int T_LEFTBRACE = 25;
        final int T_RIGHTBRACE = 26; 
        final int T_ID = 27;
        final int T_NUM = 28;
        char[] letters_ = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','A','B','C','D',
            'E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','_'};
        char[] numbers = {'0','1','2','3','4','5','6','7','8','9'};
        char[] symbols = {'+','-','*','/','<','>','!','=',':',',','.','(',')','[',']','{','}'};
        FileInputStream fstream = new FileInputStream("src\\testCode.txt");
        DataInputStream in = new DataInputStream(fstream);
        BufferedReader br = new BufferedReader(new InputStreamReader(in));
        BufferedWriter bw1 = new BufferedWriter(new FileWriter(new File("src\\output.txt"), true));
        BufferedWriter bw2 = new BufferedWriter(new FileWriter(new File("src\\output2.txt"), true));
        String scanner;String temp = "";
        int n = 0;
        while((scanner = br.readLine()) != null){
            for (int i = 0; i < scanner.length(); i++) {
                for (int j = 0; j < scanner.length(); j++) {
                    if(contains(letters_,scanner.charAt(i)) || contains(numbers,scanner.charAt(i)) || contains(symbols,scanner.charAt(i))){
                        j++;
                        n++;
                        if(scanner.charAt(j) == ' ' || scanner.charAt(j) == '\n' || scanner.charAt(j) == '\t'){

                        }
                    }

                }

            }
        }

        in.close();


    }

}

これは私たちのテストコードです:

int fact(int x) {
// recursive factorial function 
   if (x>1) 
      return x * fact(x-1);
   else return 1;
}

void main(void) {
/* CS 311 project 2
A lexical analyzer */
   int x, y, z;
   double _funny;
   x = get_integer();
   _Funny = get_double();
   if (x>0) 
      print_line(fact(x));
   else if (_funny != 3.14) 
      print_line(x*_funny);
}

これが出力になるはずです

3 27 21 3 27 22 25 2 21 27 13 28 22 4 27 9 27 21 27 8 28 22 18 1 4 28 18 26 5 27 21 5 22 25 3 27 19 27 19 27 18 0 27 18 27 817 27 17 27 21 22 18 2 21 27 13 28 22 27 21 27 21 27 22 22 18 1 2 21 27 12 28 22 27 21 27 9 27 22 18 26

INT id leftparen INT id rightparen leftbrace IF leftparen id より大きい num rightparen RETURN id 乗算 id leftparen id マイナス num rightparen セミコロン ELSE RETURN num セミコロン rightbrace VOID id leftparen VOID rightparen leftbrace INT id コンマ id コンマ id セミコロン DOUBLE id セミコロン id assignop id leftparen rightparen セミコロンid assignop id leftparen rightparen セミコロン IF leftparen id greater num rightparen id leftparen id leftparen id rightparen rightparen セミコロン ELSE IF leftparen id notequal num rightparen id leftparen id 乗算 id rightparen セミコロン rightbrace

ユーザー John の提案に基づいてコードを書きました。これがどのように機能するかについてはまだ混乱しています。2番目のループを繰り返して空白またはシンボルを見つけると、シンボルのwsの前にどのタイプのトークンが来たかがわかります。スキップした文字を文字列に入れ、case ステートメントを使用してそれを判断しようとしましたが、ファイル全体が文字列に書き込まれるため、トークンが一致しないと思います。また、メソッドがコメントを見つけて安全に無視するにはどうすればよいでしょうか?

4

2 に答える 2

0

このプログラムにアプローチするには、いくつかの異なる方法があります。コードを書かずに、何をする必要があるかを説明しようとします。

あなたが提出した例から。

講師からプログラムの鍵が渡されました。彼はあなたに出力を与えたので、状態テーブルを作成できます。

出力を調べて手動でこれを実行して回答を確認するか、これを行う小さなプログラムを作成することができます。

これは、左側に州番号、右側に対応する単語を示した表です。

         3  int,  
         27 ID,
         21 leftparen, 
         22 right paren,
         25 left brace s, 
         2  if,
         13  greater, 

等々。


状態テーブルに対応する入力バッファー2 出力バッファー
2 ループ 1 つの外側ループと 1 つの内側ループ
1 ケース ステートメント を作成する必要があります。

入力バッファを通過するとき、外側のループを初期化します 内側のループを初期化します この最初の文字を比較して、有効な文字かどうかを判断しますか? そうでない場合は、有効な文字が見つかるまでループをインクリメントします

有効な文字が見つかったら、それがトークンの始まりです。次に、空白または特殊な記号を見つけて内側のループをインクリメントし、トークンの終わりを見つけます。次に、case ステートメントを使用して、1 つのバッファーに数値を出力し、2 番目のバッファーに対応する単語を出力します。

次に、数値バッファを出力します。次に、ワード バッファを出力します。

次に、外側のループを内側のループにインクリメントします + 1 内側のループを外側のループと等しくします

End of File が見つかるまで続行します。それらが教師の出力と一致する場合は、終了です。そうでない場合は、論理エラーがあります。次に、どの値が無効であるかを確認し、プログラムのその部分を調べます。

それは20歳の男です。

于 2012-05-10T08:13:56.097 に答える
0

私がLLKアナライザーを書いていたという事実を除けば、かなりおなじみの味です...あなたの場合、形式文法などの方法を調べてみてください-あなたのステップは、それらの文法による分析を実行する前にほとんど必須のステップです。lex && flex のような実用的なパーサー (オープンソース) が役立つかもしれません。

INHO、最も簡単な方法は、入力ファイルを文字単位で文字列に読み取り、この文字列が正規表現のいずれかと一致するかどうかを確認することです...一致する場合は、適切なコードを出力に書き込み、バッファとして使用している文字列をクリアします. この場合、2 つの問題があります。これは O(n*m) で機能します。ここで、n はテキストの長さ、m は使用する正規表現の数 (価値がある場合) であり、2 つ目 - 使用してはなりませんプレフィックス付きの式...プレフィックスとして別の式を使用する式を使用してはならないことを意味します(開始)。そうしないと、この式に到達できなくなります。

于 2012-05-10T11:30:25.790 に答える