Как работает данный лексер ? Не очень понимаю принцип работы

191
13 апреля 2018, 18:11

Класс main

public class main {
    public static void main(String args[]){
        Lexems lex = new Lexems();
        LinkedList<Token> tokens = new LinkedList<Token>();
        String test = "q = 300 - 150 * 2 + 3 / 5";
        String str_1 = "";

        for (int i = 0; i < test.length(); i++) {
            if (test.toCharArray()[i] == ' ') {
                continue;
            }
            str_1 += test.toCharArray()[i];
            String str_2 = " ";
            if(i < test.length()-1){
                str_2 = str_1 + test.toCharArray()[i+1];
            }
            for (String key: lex.lexems.keySet()) {
                Pattern p = Pattern.compile(lex.lexems.get(key));
                Matcher m_1 = p.matcher(str_1);
                Matcher m_2 = p.matcher(str_2);

                if (m_1.find() && !m_2.find()) {
                    tokens.add(new Token(key.toString(), str_1));
                    str_1 = "";
                }
            }
        }
        for (Token t: tokens) {
            System.out.println(t.type + " " + t.token);
        }
    }

Класс Lexems

public class Lexems {
    static Map<String, String> lexems = new HashMap<String,String>();
    public Lexems(){
        lexems.put("VAR", "^[a-z]+$");
        lexems.put("DIGIT", "^0|[1-9][0-9]*$");
        lexems.put("OPERATOR", "^[-|+|/|*]$");
        lexems.put("ASSIGNMENT OPERATOR", "^=$");
    }
}

Класс Token

public class Token {
    String type;
    String token;
    Token(String Type, String Token){
        type = Type;
        token = Token;
    }
}
Answer 1

Всё на самом деле очень просто.

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

Таким образом, код ведёт себя так: он ищет, какой из лексем соответствует начало текста, запоминает эту лексему, откусывает от текста прочитанную лексему, и повторяет процесс до исчерпания текста.

Я описал идеальный вариант, но данный код делает немного странно. Он накапливает текущую часть строки в переменной, и делает проверку: если текущая строка принимается регуляркой, а вот строка со следующим символом уже нет, то токен считается оконченным. Это не самая хорошая идея: лучше было бы переписать регулярки так, чтобы они не обращали внимания на «хвост» текста, и выбирали наибольший подходящий кусок.

Кроме того, метод компилирует регулярки на каждом входящем символе. Это затратно, намного проще было бы скомпилировать их один раз перед циклом.

READ ALSO
Логика работы фрагментов

Логика работы фрагментов

Я новичокПытаюсь понять логику

127
расстояние между городами. [требует правки]

расстояние между городами. [требует правки]

расстояние между городамивычисляет расстояние между двумя городами и позволяет пользователю выбрать размерность расстояния

183
Как правильно определить TimePicker

Как правильно определить TimePicker

У меня есть класс DatePickerFragment и с ним связанная кнопкаВ итоге у меня появляется окошко с выбором даты

204