1

I was asked to build a tool that can identify if a string match a pattern.

Example:

{1:20} stuff t(x) {a,b,c}

would match:

  • 1 stuff tx a
  • 20 stuff t c

It is a sort of regex but with a different syntax

  • Parentheses indicate an optional value
  • {1:20} is a interval; I will have to check if the token is a number and if it is between 1 and 20
  • {a,b,c} is just an enumeration; it can be either a or b or c

Right now I implemented this with a regex, and the interval stuff was a pain to do.

On my own time I tried implementing some kind of matcher by hand, but it turns out it's not that easy to do.

By experimenting I ended up with a function that generates a state table from the pattern and a state machine. It worked well until I tried to implement the optional value, and I got stuck and how to generate the state table.

After that I searched how I could do this, and that led me to stuff like LL parser, LALR parser, recursive-descent parser, context-free grammars, etc. I never studied any of this so it's hard to know what is relevant here, but I think this is what I need:

  • A grammar
  • A parser which generates states from the grammar and a pattern
  • A state machine to see if a string match the states

So my first question is: Is this right ? And second question, what do you recommend I read/study to be able to implement this ?

2
  • 1-20 should just be ((1?\d)|20) Oct 20, 2012 at 0:25
  • @PeterSmith: That also accepts '0', which is out of range. Oct 20, 2012 at 3:35

1 Answer 1

4

If the requirements are as described (just matching static text, integers in a set range, optional values and alternation), then your patterns do describe regular languages, so a regular expression is probably the right way to go -- full context-free grammars give you more power than you need here.

If you want to implement a matcher from scratch, you should read up on DFAs, and NFAs. I would also recommend you read Regular Expression Matching Can Be Simple And Fast, which describes how to implement efficient (linear in the length of the text being searched) matching using NFAs and DFAs.

Alternatively, you could just hack something together to turn your patterns into a more common regular expression syntax and use an existing regex engine (I would recommend re2, which was created by the same person who wrote the above description).

To avoid the difficulties of matching integer intervals textually, I would suggest you turn intervals into general integer matching (i.e., match any sequence of digits) and use a separate pass to check whether the value is in the specified interval. If you end up writing your own matcher, you could build this functionality into the core. Note that matching integer intervals textually is entirely possible (they're still regular), but pulling out arbitrary integers and performing a separate range check may be simpler.

1
  • Yes, right now I do this by turning the pattern into a regex and use a second pass to match the intervals. My goal here was to implement a matcher from scratch, so thank you for the pointers, I will look into it. Oct 21, 2012 at 11:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.