Сопоставление скобок с оператором деления — регулярное выражение

Примеры:

input: (n!/(1+n))
output: frac{n!}{1+n}

input: ((n+11)!/(n-k)^(-1))
output: frac{(n+11)!}{(n-k)^(-1)}

input: (9/10)
output: frac{9}{10}

input: ((n+11)!/(n-k)^(-1))+(11)/(2)
output: frac{(n+11)!}{(n-k)^(-1)}+(11)/(2)

Следующее регулярное выражение работает, если нет вложенных скобок.

\(([^\/\)]*)\/([^\)]*)\)

Следующее делает соответствующие круглые скобки

@\((([^()]++|\((?:[^()]++|(?R))+\))+)\)@

Я просто не могу понять, как их "объединить" - написать одно регулярное выражение для обработки деления и сбалансированных скобок.


person SamB    schedule 17.01.2011    source источник
comment
Регулярные выражения не являются хорошим инструментом для сложного синтаксического анализа, особенно, если он должен соответствовать сбалансированному тексту. Вы можете взломать что-то с расширениями, которые предоставляют некоторые варианты регулярных выражений, но вы действительно хотите использовать настоящий синтаксический анализатор для такого рода вещей.   -  person Anon.    schedule 17.01.2011
comment
Дело в том, что я так близко. Я действительно ничего не знаю о синтаксическом анализаторе, и его реализация займет больше времени, чем мне хотелось бы. Я знаю, что это возможно с регулярным выражением, и для меня это самый простой способ.   -  person SamB    schedule 17.01.2011
comment
Я добавил ответ, который как минимум работает для тестовых случаев. Не стесняйтесь изменять его - он далек от совершенства (вы можете добавить притяжательные квантификаторы и, возможно, унарный +, если вы смелы). Самая большая проблема с ним заключается в том, что он рассматривает все / как дробь без порядка операторов: a+2/3+b -> (a+2)/(3+b).   -  person Kobi    schedule 18.01.2011


Ответы (2)


Я думаю, что-то вроде этого должно работать:

((?:\w+|\((?1)\))(?:[+*^-](?1)|!)?)\/((?1))

Это, вероятно, не идеально, но вот идея:

Первая группа, $1, это ((?:\w+|\((?1)\))(?:[+*^-](?1)|!)?), то есть:

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

Рабочий пример: http://ideone.com/PNLOD

person Kobi    schedule 17.01.2011
comment
Спасибо за работу. Мне нужно, чтобы это работало только тогда, когда в скобках есть знак деления. Это достаточно близко, хотя, я смогу понять это отсюда. Спасибо! - person SamB; 18.01.2011
comment
@SamB - нет проблем! Кстати, это интересный вопрос, и пример ввода/вывода очень нагляден. Вы правы, я пропустил внешние скобки, но я думаю, что это сработает. - person Kobi; 18.01.2011
comment
@Kobi Есть ли шанс, что вы могли бы помочь мне адаптировать это регулярное выражение к формату, совместимому с регулярным выражением javascript? - person adolfosrs; 12.12.2020
comment
@adolfosrs - JavaScript не поддерживает рекурсивное регулярное выражение, поэтому его нельзя адаптировать. Самый простой вариант здесь - задать новый вопрос, я уверен, что кто-то знает лучший инструмент для JavaScript. - person Kobi; 13.12.2020

Я знаю, что вы уже приняли регулярное выражение, но реальным ответом на то, что вы пытаетесь сделать, является правильный синтаксический анализатор... и нет, вам не нужно кодировать его с нуля или изобретать велосипед. Хотя многие люди ненавидят php-классы, evalMath класс, который вы можете там найти, невероятно полезен для разбора и оценки математических формул. См. мой ответ на похожий вопрос, чтобы узнать, как его можно использовать и расширять.

person Mark Baker    schedule 17.01.2011
comment
Марк: На самом деле я не занимаюсь математической оценкой. Я разбираю математику и автоматически конвертирую ее в LaTeX. Есть ли парсер, который будет хорошо работать для этого? - person SamB; 18.01.2011
comment
@SamB - попробуйте ответы здесь: stackoverflow.com/questions/2421768/ - person Spudley; 17.04.2012