2016-02-03 193 views
0

我正在制作一个Lexer,并选择使用正则表达式来分割我的令牌。正则表达式 - 包含多个下划线的单词

我正在处理所有不同的标记,除了真正让我感到困惑的标记是单词和标识符

你看,我已经制定的规则如下:

  • 词不能启动或下划线结束。
  • 单词的长度可以是一个或多个字符。
  • 下划线只能用于之间的之间的字母,并且可以多次出现。我想要什么

例子:

_foo   <- Invalid. 
foo_   <- Invalid. 
_foo_  <- Invalid. 
foo_foo  <- Valid. 
foo_foo_foo <- Valid. 
foo_foo_  <- Partially Valid. Only "foo_foo" should be picked up. 
_foo_foo  <- Partially Valid. Only "foo_foo" should be picked up. 

我越来越近,因为这是我目前有:

([a-zA-Z]+_[a-zA-Z]+|[a-zA-Z]+)

除此之外,它只能检测中第一次出现下划线。我想要所有人。

个人的要求:

我宁愿答案被包含在一个组里,因为我已经构建我的身边tokeniser,但我会很乐意改变我的设计,如果你能想到的更好的处理方式。这是我目前使用:

private void tokenise(String regex, String[] data) { 
    Set<String> tokens = new LinkedHashSet<String>(); 
    Pattern pattern = Pattern.compile(regex); 
    // First pass. Uses regular expressions to split data and catalog token types. 
    for (String line : data) { 
     Matcher matcher = pattern.matcher(line); 
     while (matcher.find()) { 
      for (int i = 1; i < matcher.groupCount() + 1; i++) { 
       if (matcher.group(i) != null) { 
        switch(i) { 
        case (1): 
         // Example group. 
         // Normally I would structure like: 
         // 0: Identifiers 
         // 1: Strings 
         // 2-?: So on so forth. 
         tokens.add("FOO:" + matcher.group()); 
         break; 
        } 
       } 
      } 
     } 
    } 
} 

回答

5

尝试([a-zA-Z]+(?:_[a-zA-Z]+)*)

格局,[a-zA-Z]+的第一部分,一个或多个字母匹配。
该模式的第二部分(?:_[a-zA-Z]+)与后跟一个或多个字母的非内容匹配。
末尾的*表示第二部分可以重复零次或多次。
(?:)与普通()类似,但不返回匹配的组。

+1

哦,我的天啊!谢谢。你能解释一下你对我做了什么不同吗? – finnrayment

+0

如果你不使用'String#matches()',或者你想查找单词,而不是更大文本中的标识符,这个正则表达式也会匹配'_foo'中的'foo'。不确定是否有预期。 –

+0

@frayment该模式的第一部分“[a-zA-Z] +'匹配一个或多个字母。该模式的第二部分“(?:_ [a-zA-Z] +)”匹配一个不希望的结果,如果后面跟着一个或多个字母。 *末尾意味着第二部分可以重复零次或多次。 '(?:)'就像普通的'()',但不会返回匹配的组。 – RootTwo

相关问题