Как реализовать лексический анализ в 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, начиная со списка отдельных регулярных выражений (по одному для каждого токена). Это, возможно, не очень сложно, и было бы довольно весело иметь вокруг.