2017-01-12 4 views
2

Я пытаюсь разделить строку уравнений на токены. Ive нашел хорошую отправную точку »([A-Za-z] + | [0-9.] + | [& => < \ |!] + | \ S) '. Однако это имеет проблемы с отрицательными числами:tokenizing математическое уравнение с использованием regex

turns: '5--4=sin(2+3)' 
into: ['5','-','-','4','=','sin','(','2','+','3',')'] 
want: ['5','-','-4','=','sin','(','2','+','3',')'] 

а также

turns: -3+3 
into: ['-','3','+','3'] 
want: ['-3','+','3'] 

Похоже мое регулярное выражение может использовать то, что проверяет, есть ли номер для слева от «-» если не держите его со следующим номером (примечание «-3» ничего не имеет слева). Можно ли это сделать с помощью регулярного выражения? Или есть лучший инструмент, чтобы разделить это на .NET?

ответ

1

Regex недостаточно силен, чтобы делать то, что вы хотите во всех контекстах. Хотя вы можете заставить regex распознать + или - как часть целочисленного литерала, например, добавив необязательный [+-]? перед последовательностью цифр, результирующее регулярное выражение будет хотеть tokenize '-3+3' как ['-3', '+3'] (demo).

Использование генератора лексера должно решить эту проблему; альтернативно, вы можете иметь дело с «связыванием» унарных операторов с их операндами в парсере .

+0

О да, регулярное выражение отлично подходит для лексинга - это проблема типа Хомски 3. OP не понимает, что результат, который он получил, на самом деле * точно *, что ему нужно. в '' '' '' '' '- фактически оператор унарного отрицания. –

+0

@LucasTrzesniewski Конечно, регулярное выражение отлично подходит для лексинга, но OP хочет, чтобы его лексинг был контекстно-зависимым. Он хочет, чтобы два минуса в «-3-3» обрабатывались по-разному, что не является ни тем, что он хочет, ни тем, что может предложить регулярное выражение. – dasblinkenlight

+0

Да, прочитав свой ответ уже второй раз, я понял, что вы имели в виду. Кстати, генератор лексеров не просто волшебным образом исправит «проблему», большинство просто используют regex под капотом;) –

2

Вы не очень правильно подходите к проблеме. В результате вы действительно получили - правильный.

-3+3 следует разобрать на:

operator binary + 
| 
+-- operator unary - 
| | 
| +-- 3 
| 
+-- 3 

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

См. here для соответствующего ответного вопроса, который подходит к проблеме таким образом (он использует ANTLR, но лексический проход делает именно то, что я вам советую).

Смежные вопросы