2015-12-24 4 views
0

Я создал простую программу lexer в Java, которая запрашивает у пользователя строку и отображает лексемы в этой строке. Однако, когда я ввожу значение, если в приглашение включены левые и/или правые круглые скобки, после левого или правого круглых скобок добавляется нулевой символ, который он идентифицирует программой как идентификатор.Java Simple Lexer Program

Кроме того, если я не включаю левую и правую круглые скобки в запрошенной пользователем строке, последний символ в строке не оценивается как лексема.

Вот мой код:

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++; 

      } 
     } 
    } 


} 
} 

Любая помощь по решению проблемы ценится.

+0

У вас есть образец ввода? – MadProgrammer

+1

Это может и должно быть отлажено как приложение командной строки. поэтому я удаляю тэг Swing. –

+0

Один вход (a + b), который отображает все лексемы, но добавляет новую лексему между (и a). Другой вход - + b. Который отображает только + и a как лексемы (т.е. он пропускает букву b как лексему). – user3023315

ответ

0

Проблема в том, что вы не поддерживаете состояние в своем лексере. Признание обычного языка может быть выполнено с помощью конечного автомата, который является простым механизмом, который отслеживает его состояние (и может поддерживать буфер для накопления более длинных лексем).

Итак, сначала вы должны установить состояние на 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; 
} 

Здесь что-то не хватает: обработка номера или идентификатора в конце строки ввода. Это можно определить, исследуя состояние переменной и используя содержимое strTwo.

+0

Можете ли вы объяснить мне немного больше о поддержании состояния. Описание, которое вы предоставили, мне сложно, – user3023315

+0

Подумайте о «конечных автоматах», как в основном диаграмме направленности, каждый «узел» в графе является «состоянием», и вы можете быть только в одном «узле» за раз (технически это «детерминированные конечные автоматы», но эй ...) Его то, что используется для этого. Тогда у вас есть «переходы» из одного состояния в другое, эти переходы являются допустимыми входными символами ... и вы перемещаетесь по граф, когда вы читаете символы, и если вы читаете символ, у вас нет перехода, это означает, что вход «предложение» не соответствует вашей грамматике (язык, который распознает лексер) – mawalker

+0

@ user3023315 Теперь мой код отключен, за исключением 'i -', который я ненавижу делать в инструкции for), хотя существуют и другие (более совершенные) методы реализации. Google DFA (то, что написал mawaler), или lexer, или регулярный синтаксический анализ языка. – laune