简体   繁体   中英

Logic on a Complicated Regex on My Napkin Math Parser

So I'm writing my own napkin math parser[1] for fun. Napkin math is a part of a custom text editor I am building - when you press space after an equals sign it will detect the equation prior to the equals sign and does the math for you. Eg, you type 1+1= and it kicks out the 2 for you magically so you have 1+1=2 on the screen.

I'm really struggling with getting a regex to match equations prior to the equals sign. My brain is shot and I am in desparate need of help from a lord of regex. Below are my test strings, with the highlighted sections being what I want the regex to match.

Particularly, I'm having trouble getting the regex to match the true start of an equation. My current regex gets thrown off if there are numbers or words before the equation starts. I feel like I need to somehow work backwards from the equals sign. I started reversing my string characters around and that's when I threw my hands up and came to you for help.

My test strings with desired matches (the true equation part of the string):


test text (1) pi =

test text (1 pi =

test text 1) pi =

test text (2) pi + 10 / 20 =

test text (3) test pi ^ 10 / 20 =

test text (30) 10 + 5 =

test text (500) abs(10 + 5) =

test text (1) pi + 10 / 20 =

test text 10*5 =

test text pi / phi =

test text 10 mod phi =

test text 50 10 mod phi =

test text pi mod abs(phi) =

apple banana cherry apple 10 apple cherry banana hi 10 99+1 =


Here are all of my special key words allowed and useful in napkin math:

var napkinMathKeyWords = [
    'pi',
    '\\u03C0',
    '\\u03A0',
    'phi',
    '\\u03C6',
    '\\u03A6',
    'abs',
    'acos',
    'cos',
    'atan',
    'tan',
    'asin',
    'sin',
    'ceil',
    'floor',
    'sqrt',
    'log',
    'ln',
    'mod',
];

EDIT

Here's the regex I've got so far:

(\d|pi|\\u03C0|\\u03A0|phi|\\u03C6|\\u03A6|abs|acos|cos|atan|tan|asin|sin|ceil|floor|sqrt|log|ln|mod).*?=

It's hitting most of my cases, there are just a couple of cases throwing it off:

http://i.imgur.com/QbueeFC.png


[1] http://blogs.msdn.com/b/onenotetips/archive/2008/05/09/napkin-math-in-onenote.aspx

As you implied, this regex gets a little messy. But I have one that works (see regex101 ). On regex101, I used the PCRE mode, but only so I could use the "extended" option to make the regex more readable. In JavaScript, just collapse all the line-breaks and spaces and it will work.

I realized that your list of keywords contained two distinct groups:

  1. keywords that are functions, to be followed by operations in parens

    var regex_function = "(abs|acos|cos|atan|tan|asin|sin|ceil|floor|sqrt|log|ln)\\([^)]+ )";

  2. keywords that are constants (stand-alone)

    var regex_constant = "(\\d+|pi|\\\π|\\\Π|phi|\\\φ|\\\Φ)";

Then the combination (alternation) of the above parts represents an operand:

var regex_operand = "(" + regex_constant + "|" + regex_function + ")";

Each operand must have an operator in-between:

var regex_operator = "([+\\-*\\/^]|mod)";

The entire regex can be put together like this:

var regex = new RegExp(regex_operand + "(\\s*" + regex_operator + "\\s*" + regex_operand + ")*\\s*=");

Basically, you have an operand followed by any number of operator/operand pairs, then the equal sign.

Looks to me like your best bet is asserting that spaces must always be followed by some sort of operator . For instance, "5 5 =" is invalid while "5 + 5 =" and "5 =" are valid. Thus, I'd say your regex should look something like this:

([numbers and special names like pi][ ]?[operators][ ]?)*[numbers and special names like pi][ ]?\=[ ]?

I may have written the spaces wrong, what I mean to say is that they can appear at most one time. The other things in brackets would just be big or statements. Parentheses might get tricky, if I get the chance I'll edit my answer to properly handle them.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM