微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

无法完全使词法分析器在我的Java程序中工作

如何解决无法完全使词法分析器在我的Java程序中工作

我正在尝试获取这段Java代码,以词法分析短语“(和+ 47)/总数”,并将其吐出为:

    Next token is: 25 Next lexeme is (
    Next token is: 11 Next lexeme is sum 
    Next token is: 21 Next lexeme is +
    Next token is: 10 Next lexeme is 47
    Next token is: 26 Next lexeme is )
    Next token is: 24 Next lexeme is /
    Next token is: 11 Next lexeme is total
    Next token is: -1 Next lexeme is EOF

但是,结果却是这样的:

    Next token is: 25 Next lexeme is (
    Next token is: 11 Next lexeme is um 
    Next token is: 21 Next lexeme is +
    Next token is: 10 Next lexeme is 47
    Next token is: 24 Next lexeme is /
    Next token is: 11 Next lexeme is total

我知道我正在为EOF弄乱某些内容,但我无法弄清楚为什么它会截断47之后的“ s”和“)”。这是我的代码供参考。请让我知道我是否需要对此帖子做任何事情,因为这是我的第一个帖子。

    import java.io.*;
    import java.util.*;

    public class Main
    {
       private static final int LETTER=0;
       private static final int DIGIT=1;
       private static final int UNKNowN=99;
       private static final int EOF=-1;
       private static final int INT_LIT=10;
       private static final int IDENT=11;
       private static final int ASSIGN_OP=20;
       private static final int ADD_OP=21;
       private static final int SUB_OP=22;
       private static final int MULT_OP=23;
       private static final int DIV_OP=24;
       private static final int LEFT_PAREN=25;
       private static final int RIGHT_PAREN=26;


       private static int charClass;
       private static char lexeme[];
       private static char nextChar;
       private static int lexLen;
       private static int token;
       private static int nextToken;
       private static File file;
       private static FileInputStream fis;
       public static int lookup(char ch)
       {
           switch (ch)
           {
            case '(':
                addChar();
                nextToken = LEFT_PAREN;
                break;
            case ')':
                addChar();
                nextToken = RIGHT_PAREN;
                break;
            case '+':
                addChar();
                nextToken = ADD_OP;
                break;
            case '-':
                addChar();
                nextToken = SUB_OP;
                break;
            case '*':
                addChar();
                nextToken = MULT_OP;
                break;
            case '/':
                addChar();
                nextToken = DIV_OP;
                break;
            default:
                addChar();
                nextToken = EOF;
                break;
           }
           return nextToken;
       }
       public static void addChar()
       {
            if (lexLen <= 98)
            {
                lexeme[lexLen++] = nextChar;
                lexeme[lexLen] = 0;
            }
            else
               System.out.println("Error -lexeme is too long\n");
       }
       public static void getChar()
       {
           try
           {
           if(fis.available()>0)
           {
               nextChar=(char)fis.read();
               if(Character.isLetter(nextChar))
                   charClass=LETTER;
               else if(Character.isDigit(nextChar))
                   charClass=DIGIT;
               else
                   charClass=UNKNowN;
           }
           else
               charClass=EOF;
      
           }
           catch(IOException e)
           {
               e.printstacktrace();
           }
       }
       public static void getnonblank()
       {
           while(Character.isspaceChar(nextChar))
               getChar();
  
       }
       public static int lex()
       {
           lexLen = 0;
            getnonblank();
            switch (charClass)
            {
            /* parse identifiers */
                case LETTER:
                    addChar();
                    getChar();
                    while (charClass == LETTER || charClass == DIGIT)
                    {
                       addChar();
                       getChar();
                   }
                    nextToken = IDENT;
                    break;
                    /* parse integer literals and integers */
                case DIGIT:
                    addChar();
                    getChar();
                   while(charClass == DIGIT)
                   {
                        addChar();
                        getChar();
                   }
                   nextToken = INT_LIT;
                   break;
                /* parentheses and operators */
                case UNKNowN:
                    lookup(nextChar);
                    getChar();
                   break;
       /* EOF */
        case EOF:
            nextToken = EOF;
            break;

           } /* end of switch */
           System.out.print("Next token is :"+nextToken+" Next lexeme is :");
           for(int i=0;i<lexLen;i++)
               System.out.print(lexeme[i]);
           System.out.println();
           return nextToken;
       }
       public static void main(String args[])
       {
                   lexLen=0;
           lexeme=new char[100];
           for(int i=0;i<100;i++)
               lexeme[i]='0';
           file = new File("input1.txt");
           if (!file.exists())
           {
                 System.out.println( "input1.txt does not exist.");
                 return;
           }
           if (!(file.isFile() && file.canRead()))
           {
                 System.out.println(file.getName() + " cannot be read.");
                 return;
                   }
           try
           {
                 fis = new FileInputStream(file);
                 char current;
                 while (fis.available() > 0)
                 {
                     getChar();
                 //   System.out.println(nextChar+" "+charClass);
                   lex();
               }
           }
           catch (IOException e)
           {
                 e.printstacktrace();
           }
       }
    }

解决方法

丢弃的字符错误和缺少的EOF错误均在此循环中发生:

while (fis.available() > 0)
    {
        getChar();
        lex();
    }

只需执行该循环即可在纸上进行简单输入,您应该就能解决问题。 (例如,尝试()后跟文件结尾。)

解决这两个问题的关键是,lex的合同(即,有关世界执行之前和之后的外观规范)包括:

  • 前提条件(在调用lex时必须为真):nextChar是下一个可用的输入字符,而charClass是其类。
  • 后置条件lex保证在调用后为true):nextChar是下一个可用的输入字符,而charClass是其类。 / li>

请注意,它们是相同的,这并不罕见。通常称为不变

getChar的合同是:

  • 前提条件:不再需要nextCharcharClass的值。
  • 后置条件nextChar是下一个可用的输入字符,charClass是其类。

为您编写的每个函数明确记录合同始终是一个好习惯。这样做将帮助您发现问题。特别是,考虑到lex的后置条件和getChar的前提(在下一个循环迭代的开始将被调用),您能怎么说?

如果将文件结尾指示符的条件添加到上述模型中,您可能还会看到该错误。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。