Question

How do you create a regular expression for a certain string? And can you do it in the Assertion (precondition part of the code)?

I've been google-ing around but couldn't get anything convincing.

The question is like this:

Add a precondition to the DEPARTMENT (the class that we're working on) creation procedure that ensures that the phone number is valid. There are three possible valid phone number formats. A valid phone number consists of one of:

  • eight digits, the first of which is non-zero
  • a leading zero, a single non-zero digit area code, and then eight digits, the first of which is non-zero
  • a leading ‘+’, followed by a two digit country code, then a single non-zero digit area code, and then eight digits, the first of which is non-zero

Any embedded spaces are to be ignored when validating a phone number.

It is acceptable, but not required, to add a PHONE_NUMBER class to the system as part of solving this problem.

Was it helpful?

Solution

There are several different questions to be answered:

  1. How to check if a given string matches a specified regular expression in Eiffel? One can use a class RX_PCRE_MATCHER from the Gobo library. The feature compile allows setting the required regular expression and the feature recognizes allows testing if the string matches it.

  2. How to write a regular expression for the given phone number specification? Something like "(|0[1-9]|\+[0-9]{2}[1-9])[1-9][0-8]{7}" should do though I have not checked it. It's possible to take intermediate white spaces into account in the regular expression itself, but it's much easier to get rid of them before passing to the regular expression matcher by applying prune_all (' ') on the input string.

  3. How to add a precondition to a creation procedure to verify that the argument satisfies it? Let's assume that from the previous items we constructed a function is_phone_number that takes a STRING and returns a BOOLEAN that indicates if the specified string represents a valid phone number. A straightforward solution would be to write

    make (tel: STRING)
        require
            is_phone_number (tel)
        ...
    

    and have a feature is_phone_number in the class DEPARTMENT itself. But this prevents us from checking if the specified string represents a phone number before calling this creation procedure. So it makes sense to move is_phone_number to the class PHONE_NUMBER_VALIDATOR that class DEPARTMENT will inherit. Similarly, if PHONE_NUMBER needs to validate the string against specified rules, it can inherit PHONE_NUMBER_VALIDATOR and reuse the feature is_phone_number.

OTHER TIPS

Halikal actually worked this one out, but dudn't share until now ...

This works in eiffelStudio 6.2 (note - this is gobo)

http://se.inf.ethz.ch/old/people/leitner/gobo_guidelines/naming_conventions.html

A valid phone number consists of one of:

  • eight digits, the first of which is non-zero
  • a leading zero, a single non-zero digit area code, and then eight digits, the first of which is non-zero
  • a leading + followed by a two digit country code, then a single non-zero digit area code, and then eight digits, the first of which is non-zero

Any embedded spaces are to be ignored when validating a phone number.

require                  -- 040 is ascii hex space
valid_phone: 
  match(phone, "^\040*[1-9]\040*([0-9]\040*){7}$") = TRUE or
  match(phone, "^\040*0\040*([1-9]\040*){2}([0-9]\040*){7}$") = TRUE or
  match(phone, "^\040*\+\040*([0-9]\040*){2}([1-9]\040*){2}([0-9]\040*){7}$") = TRUE


feature --Regular Expression check
  match(text: STRING; pattern: STRING): BOOLEAN is
        -- checks whether 'text' matches a regular expression 'pattern'
    require
      text /= Void
      pattern /= Void
    local
      dfa: LX_DFA_REGULAR_EXPRESSION         --There's the Trick!
      do
        create dfa.make
        dfa.compile(pattern, True)           --There's the Trick!
        check      -- regex must be compiled before we can use it
          dfa.is_compiled;
        end
        Result := dfa.matches(text)
     -- debug: make sure of which pattern
        if dfa.matches (text) then
          io.putstring(text + " matches " + pattern + "%N")
        end
      end
  end
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top