Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to use custom patterns such as a regex or functions in a match?

I'm writing a toy programming language in Rust. I prototyped the parser logic in Ruby:

def rd_tree(chars)
  loop do
    case c = chars.next
    when /\s/
      # whitespace stuff
    when "("
      # open paren stuff
    when ")"
      # close paren stuff
    else
      # default stuff
    end
  end
end

And now I'm converting it to Rust:

fn rd_tree(chars: std::str::Chars) {
    while let Some(c) = chars.next() {
        if c.is_whitespace() {
            // whitespace stuff
        } else if c == '(' {
            // open paren stuff
        } else if c == ')' {
            // close paren stuff
        } else {
            // default stuff
        }
    }
}

I resorted to using an if, else-if chain because as far as I can tell, Rust's match feature is limited to destructuring, enums, and type patterns. Is there a way to match on regexes or boolean functions? If not, is there a more idiomatic pattern here than if, else-if? I expect the logic to have more branches in the future and I want it to stay neat.

like image 661
eiko Avatar asked Apr 04 '17 15:04

eiko


People also ask

How do I use regex to match?

To match a character having special meaning in regex, you need to use a escape sequence prefix with a backslash ( \ ). E.g., \. matches "." ; regex \+ matches "+" ; and regex \( matches "(" . You also need to use regex \\ to match "\" (back-slash).

What is regex pattern matching?

Pattern matching is used by the shell commands such as the ls command, whereas regular expressions are used to search for strings of text in a file by using commands, such as the grep command.

What method should you use when you want to get all sequences matching a regex pattern in a string?

To find all the matching strings, use String's scan method.

What is pattern matching with regular expressions?

Pattern Matching with Regular Expres . . . Regular expressions are an ancient and powerful technique for finding patterns in text. They have been tested by the ages and been found to be so useful that practically every computer language in use today provides support for using regular expressions. Of course this includes the Core JavaScript model.

How to match a string with regex in Python?

Pattern matching in Python with Regex 1 Following regex is used in Python to match a string of three numbers, a hyphen, three more numbers, another hyphen, and... 2 Regular expressions can be much more sophisticated. For example, adding a 3 in curly brackets ( {3}) after a pattern is... More ...

What is the difference between following regex and regular expression in Python?

Following regex is used in Python to match a string of three numbers, a hyphen, three more numbers, another hyphen, and four numbers. Regular expressions can be much more sophisticated. For example, adding a 3 in curly brackets ( {3}) after a pattern is like saying, “ Match this pattern three times.” So the slightly shorter regex

Is it possible to symbolize regular expression patterns in Python?

No, when using the standard library re module, regular expression patterns cannot be 'symbolized'. I often do use this technique to compose larger, more complex patterns from re-usable sub-patterns. If you are prepared to install an external library, then the regex project can solve this problem with a regex subroutine call.


1 Answers

Not yet. The match patterns must be composed of things that can be statically verified by the compiler.

However, you can use a match guard:

fn rd_tree(chars: std::str::Chars) {
    while let Some(c) = chars.next() {
        match c {
            c if c.is_whitespace() => {}
            '(' => {}
            ')' => {}
            _ => {}
        }
    }
}

A match guard allows you to run a function against whatever the pattern matched.


In the future, constant evaluation may be improved to allow calling functions in place of a pattern:

#[derive(PartialEq, Eq)]
struct Foo {
    f: usize,
    g: usize,
}

impl Foo {
    const fn repeated(x: usize) -> Self {
        Foo { f: x, g: x }
    }
}

fn main() {
    let f = Foo { f: 0, g: 1 };
    match f {
        const { Foo::repeated(22) } => println!("hi"),
        _ => println!("1"),
    }
}

This work is tracked in issue #57240. RFC 2920 "const expressions and patterns" (and its tracking issue #76001) are also relevant.

It's not immediately obvious to me how this would work with your exact example or a regex without a substantial amount of effort though.

like image 139
Shepmaster Avatar answered Sep 28 '22 10:09

Shepmaster