0

そこで、このプログラムを作成して、コードを含むファイルをトークン化し、各識別子、キーワード、数値、および記号を数値トークンに分離しました。私が抱えている問題は、各行の最初の単語に正しいトークンが割り当てられることです。後の行のすべてのトークンは識別子と見なされます。これが私のトークナイザー関数で、問題は次のとおりです。

    public class cmmLex {

    public static boolean isLetter(char b){        
        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','_'};
        for (int i = 0; i < letters_.length; i++) {
            if(b == letters_[i])
                return true;
        }
        return false;
    }

    public static boolean isNumber(char b){        
        char[] numbers = {'0','1','2','3','4','5','6','7','8','9'};
        for (int i = 0; i < numbers.length; i++) {
            if(b == numbers[i])
                return true;
        }
        return false;
    }

    public static boolean isKeyword(StringBuffer str){
        String[] keywords = {"int", "double", "if", "while","return","void","else"};
        for (int i = 0; i < keywords.length; i++) {
            if (keywords[i].equals(str.toString()))
                return true;
        }

        return false;
    }

    public static boolean isSymbol(char a){
        char[] symbols = {'+','-','*','/','<','>','!','=',',','.','(',')','[',']','{','}'};
        for (int i = 0; i < symbols.length; i++) {
            if(a == symbols[i])
                return true;
        }

        return false;
    }

    public static void lexMe(StringBuffer string)
    {   

        if(isKeyword(string)){
            switch(string.toString()){
                case "double":
                    System.out.print("0 ");
                    break;
                case "else":
                    System.out.print("1 ");
                    break;
                case "if":
                    System.out.print("2 ");
                    break;
                case "int":
                    System.out.print("3 ");
                    break;
                case "return":
                    System.out.print("4 ");
                    break;
                case "void":
                    System.out.print("5 ");
                    break;
                case "while":
                    System.out.print("6 ");
                    break;
            }  
        }else{
            System.out.print("27 ");
        }
    }


    public static void tokenize(String line){
        StringBuffer consumed = new StringBuffer();
        outerloop:
        for (int i = 0; i < line.length(); i++) {
            char ch = line.charAt(i);
            if(isLetter(ch) && consumed.length() == 0){
                consumed.append(line.charAt(i));
                for (int j = i+1; j < line.length(); j++) {
                    ch = line.charAt(j);
                    if(isLetter(ch) || isNumber(ch)){
                        consumed.append(ch);
                    }else{
                        //call lexme to tokenize string

                        lexMe(consumed);

                        //consumed.setLength(0);
                        i = j;
                    }

                }
            }else if(isNumber(ch) && consumed.length() == 0){
                consumed.append(line.charAt(i) );
                for (int j = i+1; j < line.length(); j++) {
                    ch = line.charAt(j);
                    if(isNumber(ch) || line.charAt(j) == '.'){
                        consumed.append(ch);
                    }else{
                        System.out.print("28 ");
                        i = j;
                    }
                }
            }else if (isSymbol(ch)){
                switch(ch){
                    case '+':
                        System.out.print("7 ");
                        break;
                    case '-':
                        System.out.print("8 ");
                        break;
                    case '*':
                        if(line.charAt(i-1) == '/'){
                            break outerloop;
                        }else{
                            System.out.println("9 ");
                        }                       
                        break;
                    case '/':
                        if(line.charAt(i+1) == '/')
                            break outerloop;
                        else if((ch = line.charAt(i+1)) == '*'){
                            consumed.append(ch);
                            for (int j = i; j < line.length(); j++) {
                                ch = line.charAt(j);
                                if(ch == '*'){
                                    if(ch == '/'){
                                        break outerloop;
                                    }
                                }else{
                                    consumed.append(ch);
                                }        

                            }
                        }else{
                            System.out.println("10 ");

                        } 
                        break;
                    case '<':
                        if(line.charAt(i+1) == '='){
                            System.out.print("12 ");
                            break;
                        }
                        System.out.print("11 ");
                        break;                 
                    case '>':
                        if(line.charAt(i+1) == '='){
                            System.out.print("14 ");
                            break;
                        }
                        System.out.print("13 ");
                        break;
                    case '!':
                        if(line.charAt(i+1) == '='){
                            System.out.print("16 ");
                            break;
                        }
                        break;
                    case '=':
                        System.out.print("15 ");
                        break;
                    case ';':
                        System.out.print("18 ");
                        break;
                    case ',':
                        System.out.print("19 ");
                        break;
                    case '.':
                        System.out.print("20 ");
                        break;
                    case '(':
                        System.out.print("21 ");
                        break;
                    case ')':
                        System.out.print("22 ");
                        break;
                    case '[':
                        System.out.print("23 ");
                        break;
                    case ']':
                        System.out.print("24 ");
                        break;
                    case '{':
                        System.out.print("25 ");
                        break;
                    case '}':
                        System.out.print("26 ");
                        break;
                }
            }
        }
        System.out.println("");
    }

    public static void main(String[] args) throws FileNotFoundException, IOException {
        File file = new File("src\\testCode.txt");
        String testCode;

        try {

            Scanner scanner = new Scanner(file);

            while (scanner.hasNextLine()) {
                String line = scanner.nextLine();
                tokenize(line);
            }
            scanner.close();
        }catch (FileNotFoundException e) {

        }

    }
}

また、私が抱えているもう1つの問題は、コメントブロックを無視して修正できないことです。「/」を消費してループを解除するときにコメントブロックのブールフラグを設定しようとしましたが、フラグはまだ設定されていますが、「/」が表示されるまで残りの行をスキャンしてから、フラグを次のように設定します。 false。しかし、これは機能しませんでした。何か案は?

これが私のファイルの最初の行です:

int fact(int x){

この行を印刷することになっています:

3 27 21 3 27 22 25

そしてこれが現在どのように出ているか:

3 27 27 27 27 27

多分私は空白を正しく処理していませんか?

4

3 に答える 3

1

メソッドlexMeのスイッチは、最初の単語を通過した後、必要以上に収集している文字列をチェックしています。

デバッガーを使用してそれを確認するか、その値のデバッグ印刷を行うと、問題が発生します。

その問題は、ラインが原因であるように見えます

  consumed.setLength(0);

投稿されたコードでコメントアウトされました。

それを元に戻すと、「fact」文字列を処理した直後に、実際にその条件を再チェックif(isLetter(ch) && consumed.length() == 0)する必要があるときに、チェックに基づいて条件内にあるforループが継続するため、まだ問題があります。

コードが現在何をしているかを理解するためにデバッガーを使用してから、いくつかの主要なリファクタリングを行うことをお勧めします。

ノート

私は今、他の答えを見てきました。それは、休憩を追加することによって、これらの問題を拾い上げて(実際には実行せずに)修正します。

breakただし、ループと条件をネストして使用すると、コードが非常に混乱するため、全体を再考することを強くお勧めします。

于 2012-05-13T20:25:39.237 に答える
1

tokenize()のループに問題があります。コードの修正バージョンは次のとおりです。

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Scanner;

public class cmmLex {

    public static boolean isLetter(char b){        
        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','_'};
        for (int i = 0; i < letters_.length; i++) {
            if(b == letters_[i])
                return true;
        }
        return false;
    }

    public static boolean isNumber(char b){        
        char[] numbers = {'0','1','2','3','4','5','6','7','8','9'};
        for (int i = 0; i < numbers.length; i++) {
            if(b == numbers[i])
                return true;
        }
        return false;
    }

    public static boolean isKeyword(StringBuffer str){
        String[] keywords = {"int", "double", "if", "while","return","void","else"};
        for (int i = 0; i < keywords.length; i++) {
            if (keywords[i].equals(str.toString()))
                return true;
        }

        return false;
    }

    public static boolean isSymbol(char a){
        char[] symbols = {'+','-','*','/','<','>','!','=',',','.','(',')','[',']','{','}'};
        for (int i = 0; i < symbols.length; i++) {
            if(a == symbols[i])
                return true;
        }

        return false;
    }

    public static void lexMe(StringBuffer string)
    {   

        if(isKeyword(string)){
            switch(string.toString()){
                case "double":
                    System.out.print("0 ");
                    break;
                case "else":
                    System.out.print("1 ");
                    break;
                case "if":
                    System.out.print("2 ");
                    break;
                case "int":
                    System.out.print("3 ");
                    break;
                case "return":
                    System.out.print("4 ");
                    break;
                case "void":
                    System.out.print("5 ");
                    break;
                case "while":
                    System.out.print("6 ");
                    break;
            }  
        }else{
            System.out.print("27 ");
        }
    }


    public static void tokenize(String line){
        StringBuffer consumed = new StringBuffer();
        outerloop:
        for (int i = 0; i < line.length(); i++) {
            char ch = line.charAt(i);
            if(isLetter(ch) && consumed.length() == 0){
                consumed.append(line.charAt(i));
                for (int j = i+1; j < line.length(); j++) {
                    ch = line.charAt(j);
                    if(isLetter(ch) || isNumber(ch)){
                        consumed.append(ch);
                    }else{
                        //call lexme to tokenize string

                        lexMe(consumed);

                        consumed.setLength(0);
                        i = j - 1;
                        break;
                    }

                }
            }else if(isNumber(ch) && consumed.length() == 0){
                consumed.append(line.charAt(i) );
                for (int j = i+1; j < line.length(); j++) {
                    ch = line.charAt(j);
                    if(isNumber(ch) || line.charAt(j) == '.'){
                        consumed.append(ch);
                    }else{
                        System.out.print("28 ");
                        consumed.setLength(0);
                        i = j - 1;
                        break;
                    }
                }
            }else if (isSymbol(ch)){
                switch(ch){
                    case '+':
                        System.out.print("7 ");
                        break;
                    case '-':
                        System.out.print("8 ");
                        break;
                    case '*':
                        if(line.charAt(i-1) == '/'){
                            break outerloop;
                        }else{
                            System.out.println("9 ");
                        }                       
                        break;
                    case '/':
                        if(line.charAt(i+1) == '/')
                            break outerloop;
                        else if((ch = line.charAt(i+1)) == '*'){
                            consumed.append(ch);
                            for (int j = i; j < line.length(); j++) {
                                ch = line.charAt(j);
                                if(ch == '*'){
                                    if(ch == '/'){
                                        break outerloop;
                                    }
                                }else{
                                    consumed.append(ch);
                                }        

                            }
                        }else{
                            System.out.println("10 ");

                        } 
                        break;
                    case '<':
                        if(line.charAt(i+1) == '='){
                            System.out.print("12 ");
                            break;
                        }
                        System.out.print("11 ");
                        break;                 
                    case '>':
                        if(line.charAt(i+1) == '='){
                            System.out.print("14 ");
                            break;
                        }
                        System.out.print("13 ");
                        break;
                    case '!':
                        if(line.charAt(i+1) == '='){
                            System.out.print("16 ");
                            break;
                        }
                        break;
                    case '=':
                        System.out.print("15 ");
                        break;
                    case ';':
                        System.out.print("18 ");
                        break;
                    case ',':
                        System.out.print("19 ");
                        break;
                    case '.':
                        System.out.print("20 ");
                        break;
                    case '(':
                        System.out.print("21 ");
                        break;
                    case ')':
                        System.out.print("22 ");
                        break;
                    case '[':
                        System.out.print("23 ");
                        break;
                    case ']':
                        System.out.print("24 ");
                        break;
                    case '{':
                        System.out.print("25 ");
                        break;
                    case '}':
                        System.out.print("26 ");
                        break;
                }
            }
        }
        System.out.println("");
    }

    public static void main(String[] args) throws FileNotFoundException, IOException {
        File file = new File("src\\testCode.txt");
        String testCode;

        try {

            Scanner scanner = new Scanner(file);

            while (scanner.hasNextLine()) {
                String line = scanner.nextLine();
                tokenize(line);
            }
            scanner.close();
        } catch (FileNotFoundException e) {

        }

    }
}
于 2012-05-13T20:26:14.630 に答える
0

手書きの字句解析プログラムは、作成とデバッグが常に面倒です。これを行うには、JLexやJFlexなどのより高いレベルのツールを使用することをお勧めします。これはあなたに多くの苦痛を救うでしょう。

于 2012-05-13T20:56:16.090 に答える