Перегрузка умножения с использованием менгира и OCaml
Я написал лексер и парсер для анализа операторов линейной алгебры. Каждое утверждение состоит из одного или нескольких выражений, за которыми следует одно или несколько объявлений. Я использую menhir и OCaml для написания лексера и парсера.
Например: Ax = b, где A обратимо.
Это следует читать как A * x = b, (A, обратимый)
В выражении все идентификаторы должны быть прописными или строчными. Я хотел бы перегрузить оператор умножения, чтобы пользователю не приходилось вводить символ "*".
Однако, так как лексеру также нужно уметь читать строки (например, "обратимые" в данном случае), часть "Ax" выражения отправляется парсеру в виде строки. Это вызывает ошибку синтаксического анализатора, поскольку в части выражения оператора не должно быть никаких строк.
Вот основная идея грамматики
stmt :=
| expr "."
| decl "."
| expr "," decl "."
expr :=
| term
| unop expr
| expr binop expr
term :=
| <int> num
| <char> id
| "(" expr ")"
decl :=
| id "is" kinds
kinds :=
| <string> kind
| kind "and" kinds
Есть ли способ отделить отдельные символы и сказать парсеру, что их следует рассматривать как умножение? Есть ли способ изменить лексер так, чтобы он был достаточно умен, чтобы знать, что все кластеры символов до запятой являются идентификаторами, а все кластеры после должны рассматриваться как строки?
1 ответ
Мне кажется, у вас есть две проблемы:
Вы хотите, чтобы ваш лексер обрабатывал последовательности символов по-разному в разных местах.
Вы хотите, чтобы умножение было указано смежными выражениями (между ними нет оператора).
Первая проблема, которую я бы решил в лексере.
Один вопрос, почему вы говорите, что вам нужно использовать строки. Это подразумевает, что есть совершенно открытый набор вещей, которые вы можете сказать. Это может быть правдой, но если вы можете ограничить себя небольшим числом, вы можете использовать ключевые слова, а не строки. Например, invertible
будет ключевым словом.
Если вы действительно хотите разрешить какую-либо строку в таких местах, определенно все еще возможно взломать лексер, чтобы он поддерживал состояние, описывающее то, что он видел, и смотрел вперед, чтобы увидеть, что будет. Если вам не нужно придерживаться заранее определенной грамматики, вы можете изменить свою грамматику, чтобы сделать это проще. (Например, вы можете использовать запятые только для одной цели.)
Что касается второй проблемы, я бы сказал, что вам нужно добавить смежность в вашу грамматику. Т.е. вашей грамматике нужно правило, которое говорит что-то вроде term := term term
, Я подозреваю, что сложно заставить это работать правильно, но он работает в OCaml (где смежные выражения представляют приложение функции) и в awk (где смежные выражения представляют конкатенацию строк).