Как реализовать лексический анализ в Javascript
Эй ребята, спасибо за чтение
в настоящее время я пытаюсь сделать калькулятор в стиле Google. Вы вводите строку, она определяет, можно ли ее вычислить и возвращает результат.
Я начал медленно с основ:+ - / *
и обращении скобках.
Я готов улучшить калькулятор с течением времени, и узнав немного о лексическом анализе некоторое время назад, я построил список токенов и связанных с ними регулярных выражений узоры.
этот вид работы легко применим к таким языкам, как Lex и Yacc, за исключением того, что я разрабатываю приложение только для Javascript.
Я попытался расшифровать идею в Javascript, но я не могу понять, как обрабатывать все чистым и красивым способом, особенно вложенные скобки.
анализ
давайте определим, что запрос калькулятора есть:
// NON TERMINAL EXPRESSIONS //
query -> statement
query -> ε // means end of query
statement -> statement operator statement
statement -> ( statement )
statement -> prefix statement
statement -> number
number -> integer
number -> float
// TERMINAL EXPRESSIONS //
operator -> [+*/%^-]
prefix -> -
integer -> [0-9]+
float -> [0-9]+[.,][0-9]+
Javascript
лексический анализ заключается в проверке нет ничего, что не выглядит как одно из терминальных выражений : оператор, префиксы, целое число и float. Которое можно сократить до одного регулярного выражения:
(Я добавил пробелы, чтобы сделать его более читабельным)
var calcPat =
/^ (s*
( ([+/*%^-]) | ([0-9]+) | ([0-9]+[.,][0-9]+) | (() | ()) )
)+ s* $/;
если этот тест проходит, запрос лексически корректен и должен быть проверен грамматикой, чтобы определить, можно ли его вычислить. это хитрая часть
Я не собираюсь вставлять код, потому что он не чист и не понятен, но я собираюсь объяснить процесс, за которым я следовал, и почему я застрял:
Я создал метод, называемый isStatement(string)
это должно называться рекурсивно. Основная идея состоит в том, чтобы разделить строку на "потенциальные" операторы и проверить, действительно ли они являются операторами и образуют один.
Процесс следующий:
- если первые два токена номер, за которым следует оператор:
-тогда
-- Если оставшийся только один токен и это число:
--- Тогда это заявление.
--- В противном случае проверьте, образуют ли оставшиеся токены оператор (рекурсивный вызов)
-Else, если первый токен является скобкой
- Затем найдите подходящую закрывающую скобку и проверьте, является ли то, что внутри, оператором (рекурсией)
-- Также проверьте, есть ли что-то после закрытия скобки, и если он образует оператор, связанный со структурой скобок.
в чем проблема ?
моя проблема в том, что я не могу найти соответствующие скобки, когда есть вложенные структуры. как я могу это сделать ? кроме того, как вы можете видеть, это не особенно общий и чистый алгоритм проверки грамматики. У вас есть идеи, как улучшить эту модель ?
большое спасибо за то, что нашли время, чтобы прочитать всё. Гаэль!--5-->
(PS: Как вы, наверное, заметили, я не носитель английского языка ! Извините за ошибки и все !)
1 ответов
У вас есть правильное представление о том, что такое лексический анализ, но вы, похоже, запутались в различии между знак грамматики и язык грамматика. Это две разные вещи.
на знак грамматики - это набор шаблонов (обычно регулярных выражений), описывающих токены для анализируемого языка. Регулярные выражения-это выражения над символом набор.
на язык грамматика (или цель грамматика, я полагаю) грамматика для языка, который вы хотите обработать. Эта грамматика выражается в терминах токенов.
вы не можете написать регулярное выражение для разбора алгебраической нотации. вы просто не можете. Ты!--1-- > can написать грамматику для него, но это не регулярные грамматики. Что вы хотите сделать, это признать отдельной токены, которые в вашем случае можно было бы сделать с регулярным выражением, похожим на то, что у вас есть. Фокус в том, что вы на самом деле не применяете это выражение к общему предложению для анализа. Вместо этого вы хотите сопоставить токен в текущей точке предложения.
теперь, потому что у вас есть регулярные выражения Javascript для работы, вы может придумайте регулярное выражение, предназначенное для соответствия строке токенов. Трюк с этим будет придуман способ определить, какой токен был выбран из списка возможностей. Движок JavaScript regex может вернуть вам массивы групп, поэтому, возможно, вы могли бы построить что-то поверх этого.
редактировать - Я пытаюсь понять, как вы могли бы собрать (несколько) универсальный tokenizer builder, начиная со списка отдельных регулярных выражений (по одному для каждого токена). Это, возможно, не очень сложно, и было бы довольно весело иметь вокруг.