【问题标题】:How to identify data that doesn't match pattern如何识别与模式不匹配的数据
【发布时间】:2019-02-01 14:15:18
【问题描述】:

所以我正在使用匹配器类并使用它来识别我在枚举中定义的标记。

  public static enum TokenType {
    // Definitions of accepted tokens
     IF("if"), WHILE("while"), PRINT("print"), TYPE("int|string|boolean"), BOOLOP("==|!="), BOOLVAL("false|true"), INTOP("[+]"), CHAR("[a-z]"), DIGIT("[0-9]"), WHITESPACE("[ \t\f\r\n]+"), LPAREN("[(]"), RPAREN("[)]");
    public final String pattern;

    private TokenType(String pattern) {
      this.pattern = pattern;
    }
  }

  public static class Token {
    public TokenType type;
    public String data;

我的问题是,我还需要识别我的模式中未定义的任何内容,并在发生这种情况时打印错误。

这就是我的匹配器逻辑的样子

    // Begin matching tokens
    Matcher matcher = tokenPatterns.matcher(input);
      while (matcher.find()) {
        if (matcher.group(TokenType.DIGIT.name()) != null) {
          tokens.add(new Token(TokenType.DIGIT, matcher.group(TokenType.DIGIT.name())));
          continue;
      } else if (matcher.group(TokenType.IF.name()) != null) {
          tokens.add(new Token(TokenType.IF, matcher.group(TokenType.IF.name())));
          continue;
      } else if (matcher.group(TokenType.WHILE.name()) != null) {
          tokens.add(new Token(TokenType.WHILE, matcher.group(TokenType.WHILE.name())));
          continue;
      } else if (matcher.group(TokenType.TYPE.name()) != null) {
          tokens.add(new Token(TokenType.TYPE, matcher.group(TokenType.TYPE.name())));
          continue;
      } else if (matcher.group(TokenType.PRINT.name()) != null) {
          tokens.add(new Token(TokenType.PRINT, matcher.group(TokenType.PRINT.name())));
          continue;
      } else if (matcher.group(TokenType.BOOLOP.name()) != null) {
          tokens.add(new Token(TokenType.BOOLOP, matcher.group(TokenType.BOOLOP.name())));
          continue;
      } else if (matcher.group(TokenType.BOOLVAL.name()) != null) {
          tokens.add(new Token(TokenType.BOOLVAL, matcher.group(TokenType.BOOLVAL.name())));
          continue;
      } else if (matcher.group(TokenType.INTOP.name()) != null) {
          tokens.add(new Token(TokenType.INTOP, matcher.group(TokenType.INTOP.name())));
          continue;
      } else if (matcher.group(TokenType.CHAR.name()) != null) {
        tokens.add(new Token(TokenType.CHAR, matcher.group(TokenType.CHAR.name())));
        continue;
      } else if (matcher.group(TokenType.LPAREN.name()) != null) {
          tokens.add(new Token(TokenType.LPAREN, matcher.group(TokenType.LPAREN.name())));
          continue;
      } else if (matcher.group(TokenType.RPAREN.name()) != null) {
          tokens.add(new Token(TokenType.RPAREN, matcher.group(TokenType.RPAREN.name())));
          continue;  
      } else if (matcher.group(TokenType.WHITESPACE.name()) != null) {
          continue; 
      }
    }

    return tokens;
  }

一种可能的解决方案是在我的模式中添加一个案例,以解释尚未定义的所有内容,看起来像这样 WHITESPACE("[ \t\f\r\n]+"), LPAREN ("[(]"), ERROR("@|#,$,%,^,&.....") 但我不确定实现它的任何现实方法。

感谢您的帮助。 这是完整代码的链接,以防我遗漏任何内容 - https://pastebin.com/jLtnJwgj

【问题讨论】:

    标签: java regex pattern-matching lex matcher


    【解决方案1】:

    你会尝试这样的事情吗?

    public class Lexer {
    
    public static enum TokenType {
        // Definitions of accepted tokens
        IF("if"),
        WHILE("while"),
        PRINT("print"),
        TYPE("int|string|boolean"),
        BOOLOP("==|!="),
        BOOLVAL("false|true"),
        INTOP("[+]"),
        CHAR("[a-z]"),
        DIGIT("[0-9]"),
        WHITESPACE("[ \t\f\r\n]+"),
        LPAREN("[(]"),
        RPAREN("[)]"),
        OTHER(".");
        public final String pattern;
    
        private TokenType(final String pattern) {
            this.pattern = pattern;
        }
    }
    
    public static class Token {
        public TokenType type;
        public String data;
    
        public Token(final TokenType type, final String data) {
            this.type = type;
            this.data = data;
        }
    }
    
    public static ArrayList<Token> lex(final String input) {
        // The tokens to return
        final ArrayList<Token> tokens = new ArrayList<Token>();
    
        // allows us to work with a mutable string
        final StringBuffer tokenPatternsBuffer = new StringBuffer();
    
        for (final TokenType tokenType : TokenType.values()) {
            tokenPatternsBuffer.append(String.format("|(?<%s>%s)",
                    tokenType.name(), tokenType.pattern));
        }
        final Pattern tokenPatterns = Pattern.compile(
                new String(tokenPatternsBuffer.substring(1)));
    
        // Begin matching tokens
        String other = "";
        final Matcher matcher = tokenPatterns.matcher(input);
        while (matcher.find()) {
            if (matcher.group(TokenType.DIGIT.name()) != null) {
                other = unknow(tokens, other);
                tokens.add(new Token(TokenType.DIGIT,
                        matcher.group(TokenType.DIGIT.name())));
                continue;
            } else if (matcher.group(TokenType.IF.name()) != null) {
                other = unknow(tokens, other);
                tokens.add(new Token(TokenType.IF,
                        matcher.group(TokenType.IF.name())));
                continue;
            } else if (matcher.group(TokenType.WHILE.name()) != null) {
                other = unknow(tokens, other);
                tokens.add(new Token(TokenType.WHILE,
                        matcher.group(TokenType.WHILE.name())));
                continue;
            } else if (matcher.group(TokenType.TYPE.name()) != null) {
                other = unknow(tokens, other);
                tokens.add(new Token(TokenType.TYPE,
                        matcher.group(TokenType.TYPE.name())));
                continue;
            } else if (matcher.group(TokenType.PRINT.name()) != null) {
                other = unknow(tokens, other);
                tokens.add(new Token(TokenType.PRINT,
                        matcher.group(TokenType.PRINT.name())));
                continue;
            } else if (matcher.group(TokenType.BOOLOP.name()) != null) {
                other = unknow(tokens, other);
                tokens.add(new Token(TokenType.BOOLOP,
                        matcher.group(TokenType.BOOLOP.name())));
                continue;
            } else if (matcher.group(TokenType.BOOLVAL.name()) != null) {
                other = unknow(tokens, other);
                tokens.add(new Token(TokenType.BOOLVAL,
                        matcher.group(TokenType.BOOLVAL.name())));
                continue;
            } else if (matcher.group(TokenType.INTOP.name()) != null) {
                other = unknow(tokens, other);
                tokens.add(new Token(TokenType.INTOP,
                        matcher.group(TokenType.INTOP.name())));
                continue;
            } else if (matcher.group(TokenType.CHAR.name()) != null) {
                other = unknow(tokens, other);
                tokens.add(new Token(TokenType.CHAR,
                        matcher.group(TokenType.CHAR.name())));
                continue;
            } else if (matcher.group(TokenType.LPAREN.name()) != null) {
                other = unknow(tokens, other);
                tokens.add(new Token(TokenType.LPAREN,
                        matcher.group(TokenType.LPAREN.name())));
                continue;
            } else if (matcher.group(TokenType.RPAREN.name()) != null) {
                other = unknow(tokens, other);
                tokens.add(new Token(TokenType.RPAREN,
                        matcher.group(TokenType.RPAREN.name())));
                continue;
            } else if (matcher.group(TokenType.WHITESPACE.name()) != null) {
                continue;
            } else if (matcher.group(TokenType.OTHER.name()) != null) {
                other += matcher.group(TokenType.OTHER.name());
                continue;
            }
        }
        other = unknow(tokens, other);
        return tokens;
    }
    
    private static String unknow(final ArrayList<Token> tokens, final String _unknow) {
        if (!_unknow.isEmpty()) {
            tokens.add(new Token(TokenType.OTHER,_unknow));
        }
        return "";
    }
    
    public static void main(final String[] args) {
        final String input = "if\nprint\nta!?!?!taelse?§.?toto";
        // Create tokens and print them
        final ArrayList<Token> tokens = lex(input);
        for (final Token token : tokens)
            System.out.println("DEBUG Lexer - " + token.type + " [ "
                    + token.data + " ] " + "found at " + "linenumber");
    }
    
    }
    

    【讨论】:

    • 模式 tokenPatterns = Pattern.compile(new String(tokenPatternsBuffer.substring(1)));这是完整的代码,以防我遗漏了其他任何内容 - pastebin.com/NaC8xCQW
    • 您有输入示例文件吗?
    • 输入在main方法中定义。字符串输入 = "a";一个好的测试用例是这样的输入... String input = "if (int 5) abc @";我希望它检测到“@”符号是一个错误。另外,我忘记了我链接的原始 pastebin 中的一些过时代码,所以如果您想参考完整代码,请使用这个代码 - pastebin.com/jLtnJwgj
    • @alexflex25 这肯定更接近我想要的,尽管它仍然不能正常工作。例如,如果我使用“hello world!”作为输入,我希望它能够检测到“!”最后,但事实并非如此。如果我使用's@@@!!!'作为输入,它出于某种原因只检测到“s”标记。
    • 我实际上刚刚开始工作!您的解决方案让我得到了解决的版本,非常感谢
    猜你喜欢
    • 1970-01-01
    • 2012-12-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-26
    • 1970-01-01
    相关资源
    最近更新 更多