Java简单Lexer程序

Java简单Lexer程序,java,lexical-analysis,Java,Lexical Analysis,我用Java创建了一个简单的lexer程序,它提示用户输入一个字符串并显示该字符串中的词素。但是,当我输入一个值时,如果提示中包含左括号和/或右括号,则在左括号或右括号后添加一个空字符,该字符由程序标识为标识符 此外,如果在用户提示的字符串中不包含左括号和右括号,则字符串中的最后一个字符不会作为词素计算 这是我的密码: import javax.swing.JOptionPane; public class Append { public static void main (String

我用Java创建了一个简单的lexer程序,它提示用户输入一个字符串并显示该字符串中的词素。但是,当我输入一个值时,如果提示中包含左括号和/或右括号,则在左括号或右括号后添加一个空字符,该字符由程序标识为标识符

此外,如果在用户提示的字符串中不包含左括号和右括号,则字符串中的最后一个字符不会作为词素计算

这是我的密码:

import javax.swing.JOptionPane;

public class Append
{
  public static void main (String [] args)
  {
    String str = JOptionPane.showInputDialog("Enter string : ");
    char [] arr = str.toCharArray();

    JOptionPane.showMessageDialog(null,arr.length);

    determineLexemes(arr);

   }

  public static void determineLexemes(char [] arr)
  {
    int j = 0;

    String [] arrayString = new String [1000];

    String strTwo = "";

    System.out.println("Symbol Table");

    System.out.println("Lexeme\t\tToken");

    for(int i = 0; i < arr.length; i++)
    {

       if(arr[i] == '+')
            {
                System.out.println("+ \t\t ADD_OP");
            }

       if(arr[i] == '-')
            {
                System.out.println("- \t\t SUB_OP");
            }

       if(arr[i] == '*')
            {
                System.out.println("* \t\t MULT_OP");
            }

       if(arr[i] == '/')
            {
                System.out.println("/ \t\t DIV_OP");
            }

       if(arr[i] == '(')
            {
                System.out.println("( \t\t LEFT_PAREN");
            }

       if(arr[i] == ')')
            {
                System.out.println(") \t\t RIGHT_PAREN");
            }

       if(arr[i] == '=')
            {
                System.out.println("= \t\t EQUAL_OP");
            }

       if(Character.isLetter(arr[i]) || Character.isDigit(arr[i]))
        {
            strTwo += arr[i];
        }

       if(!Character.isLetter(arr[i]) && !Character.isDigit(arr[i]))
        {
            if(!(Character.isWhitespace(arr[i])))
            {
                arrayString[j] = strTwo;
                System.out.println(arrayString[j] + "\t\t" + "IDENTIFIER");
                strTwo = "";
                j++;

            }
        }
    }


 }
}
import javax.swing.JOptionPane;
公共类附加
{
公共静态void main(字符串[]args)
{
String str=JOptionPane.showInputDialog(“输入字符串:”);
char[]arr=str.toCharArray();
JOptionPane.showMessageDialog(null,arr.length);
确定性基因(arr);
}
公共静态void determineLexemes(char[]arr)
{
int j=0;
String[]arrayString=新字符串[1000];
字符串strTwo=“”;
System.out.println(“符号表”);
System.out.println(“Lexeme\t\tToken”);
对于(int i=0;i

感谢您为解决此问题提供的任何帮助。

问题在于您没有在lexer中维护状态。识别一种常规语言可以用有限自动机来完成,这是一种跟踪其状态的简单机制(并且可以为积累更长的词素保留一个缓冲区)

因此,最初您应该将状态设置为S0,然后识别每个运算符和括号,并保持状态S0。对于字母,输入SI并保留,同时在SI中识别更多字母和数字。运算符终止SI,并发出运算符并返回S0。-识别S0中的一个数字,输入SN,然后以类似于SI的方式处理它

enum State { S0, IDENTIFIER, NUMBER } 

State state = State.S0;
for(int i = 0; i < arr.length; i++) {
switch( state ){
case S0:
    switch(arr[i]){
    case '+':
        System.out.println("+ \t\t ADD_OP");
        break;
    //...
    default:
        if(Character.isLetter(arr[i])){
            strTwo = ""; strTwo += arr[i];
            state = State.IDENTIFIER;
        }
        if(Character.isDigit(arr[i])){
            strTwo = ""; strTwo += arr[i];
            state = State.NUMBER;
        }
        break;
    }
case IDENTIFIER:
    if(Character.isLetter(arr[i]) || Character.isDigit(arr[i])){
        strTwo += arr[i];
    } else {
        System.out.println(strTwo + "\t\t" + "IDENTIFIER");
        i--;
        state = State.S0;
    }
        break;
case NUMBER:
    if(Character.isDigit(arr[i])){
        strTwo += arr[i];
    } else {
         System.out.println(strTwo + "\t\t" + "NUMBER");
         i--;
         State = State.S0;      
    }
    break;
}
enum状态{S0,标识符,编号}
State=State.S0;
对于(int i=0;i

这里缺少一些东西:处理输入字符串末尾的数字或标识符。这可以通过检查变量状态和使用strTwo的内容来确定。

您有一些示例输入吗?这可以而且应该作为命令行应用程序进行调试。因此,我正在删除Swing标记。一个输入是(a+b)它显示所有词素,但在(和a之间)添加一个新的词素。另一个输入是a+b。它仅将+和a显示为词素(即它跳过将b作为词素)。尝试使用类似于
if(!(Character.isWhitespace(arr[i])&&!strTwo.isEmpty()的方法{
另外,让我向你介绍我的小朋友
System.out.printf
System.out.printf(“%s%20s%n”,“=”,“EQUAL_OP”);
你能再解释一下如何维护状态吗。你提供的描述对我来说很复杂,想想“有限自动机”基本上是一个有向图,图中的每个“节点”都是一个“状态”,一次只能在一个“节点”中(从技术上讲,这是“确定性有限自动机”,但嘿…)这就是它的用途,然后你有从一个状态到另一个状态的“转换”,这些转换是有效的输入字符…当你“读”字符时,你在图形中移动,如果你读的字符没有转换,这意味着输入的“句子”与你的语法不匹配(词汇量识别的语言)@user3023315我的代码被剪断现在是可以忍受的(除了
i--
,我讨厌在for语句中这样做),尽管还有其他(更好的)实现技术。