当前位置:  开发笔记 > 编程语言 > 正文

如何使用Java的Scanner类和正则表达式对输入进行标记?

如何解决《如何使用Java的Scanner类和正则表达式对输入进行标记?》经验,为你挑选了1个好方法。

仅仅出于我自己的目的,我正在尝试在Java中构建一个tokenizer,我可以在其中定义一个常规语法并根据它来标记输入.不推荐使用StringTokenizer类,我在Scanner中发现了一些暗示我想要做的事情,但还没有运气.有人知道这个问题的好方法吗?



1> Alan Moore..:

名称"扫描仪"有点误导,因为这个词通常用于表示词法分析器,而这不是Scanner的用途.它只是scanf()你在C,Perl 等人中发现的功能的替代品.像StringTokenizer一样split(),它设计用于向前扫描,直到找到给定模式的匹配,并且在途中跳过的任何内容都将作为标记返回.

另一方面,词法分析器必须检查和分类每个字符,即使它只是决定它是否可以安全地忽略它们.这意味着,在每次匹配之后,它可以应用多个模式,直到找到一个匹配从该点开始的模式.否则,它可能会找到序列"//",并认为它是一个注释的开头,当它真的在一个字符串文字中时,它只是没有注意到开始的引号.

当然,它实际上要复杂得多,但我只是说明为什么像StringTokenizer split()和Scanner 这样的内置工具不适合这种任务.但是,可以将Java的正则表达式类用于有限形式的词法分析.事实上,添加Scanner类使得它更容易,因为添加了新的Matcher API来支持它,即区域和usePattern()方法.这是一个基于Java正则表达式类构建的基本扫描程序的示例.

import java.util.*;
import java.util.regex.*;

public class RETokenizer
{
  static List tokenize(String source, List rules)
  {
    List tokens = new ArrayList();
    int pos = 0;
    final int end = source.length();
    Matcher m = Pattern.compile("dummy").matcher(source);
    m.useTransparentBounds(true).useAnchoringBounds(false);
    while (pos < end)
    {
      m.region(pos, end);
      for (Rule r : rules)
      {
        if (m.usePattern(r.pattern).lookingAt())
        {
          tokens.add(new Token(r.name, m.start(), m.end()));
          pos = m.end();
          break;
        }
      }
      pos++;  // bump-along, in case no rule matched
    }
    return tokens;
  }

  static class Rule
  {
    final String name;
    final Pattern pattern;

    Rule(String name, String regex)
    {
      this.name = name;
      pattern = Pattern.compile(regex);
    }
  }

  static class Token
  {
    final String name;
    final int startPos;
    final int endPos;

    Token(String name, int startPos, int endPos)
    {
      this.name = name;
      this.startPos = startPos;
      this.endPos = endPos;
    }

    @Override
    public String toString()
    {
      return String.format("Token [%2d, %2d, %s]", startPos, endPos, name);
    }
  }

  public static void main(String[] args) throws Exception
  {
    List rules = new ArrayList();
    rules.add(new Rule("WORD", "[A-Za-z]+"));
    rules.add(new Rule("QUOTED", "\"[^\"]*+\""));
    rules.add(new Rule("COMMENT", "//.*"));
    rules.add(new Rule("WHITESPACE", "\\s+"));

    String str = "foo //in \"comment\"\nbar \"no //comment\" end";
    List result = RETokenizer.tokenize(str, rules);
    for (Token t : result)
    {
      System.out.println(t);
    }
  }
}

顺便说一句,这是我在该lookingAt()方法中找到的唯一好处.:d

推荐阅读
勤奋的瞌睡猪_715
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有