Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使用Java';s扫描器类和正则表达式?_Java_Regex_Compiler Construction_Tokenize - Fatal编程技术网

如何使用Java';s扫描器类和正则表达式?

如何使用Java';s扫描器类和正则表达式?,java,regex,compiler-construction,tokenize,Java,Regex,Compiler Construction,Tokenize,出于我自己的目的,我正在尝试用Java构建一个标记器,在这里我可以定义一个常规语法,并让它基于它标记输入。StringTokenizer类已被弃用,我在Scanner中发现了一些函数,这些函数提示了我要做的事情,但运气不佳。有人知道一个很好的方法吗?如果我能很好地理解你的问题,那么这里有两个标记字符串的示例方法。您甚至不需要Scanner类,仅当您想要预铸令牌,或者比使用数组更实际地迭代令牌时才需要。如果一个数组足够,只需使用String.split(),如下所示 请给出更多要求,以获得更准确的

出于我自己的目的,我正在尝试用Java构建一个标记器,在这里我可以定义一个常规语法,并让它基于它标记输入。StringTokenizer类已被弃用,我在Scanner中发现了一些函数,这些函数提示了我要做的事情,但运气不佳。有人知道一个很好的方法吗?

如果我能很好地理解你的问题,那么这里有两个标记字符串的示例方法。您甚至不需要Scanner类,仅当您想要预铸令牌,或者比使用数组更实际地迭代令牌时才需要。如果一个数组足够,只需使用String.split(),如下所示

请给出更多要求,以获得更准确的答案

 import java.util.Scanner;


  public class Main {    

    public static void main(String[] args) {

        String textToTokenize = "This is a text that will be tokenized. I will use 1-2 methods.";
        Scanner scanner = new Scanner(textToTokenize);
        scanner.useDelimiter("i.");
        while (scanner.hasNext()){
            System.out.println(scanner.next());
        }

        System.out.println(" **************** ");
        String[] sSplit = textToTokenize.split("i.");

        for (String token: sSplit){
            System.out.println(token);
        }
    }

}

如果这是一个简单的项目(学习事物是如何工作的),那么就按照巴林特·帕托所说的去做

<>如果这是一个更大的项目,请考虑使用扫描仪生成器来代替。有点复杂,但速度更快,功能更强大。

Scanner这个名字有点误导人,因为这个词通常用来表示词法分析器,而Scanner不是用来做这个的。它只是在C、Perl等语言中找到的
scanf()
函数的替代品。与StringTokenizer和
split()
一样,它被设计为提前扫描,直到找到与给定模式的匹配,并且在过程中跳过的任何内容都将作为标记返回

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

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

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

public class RETokenizer
{
  static List<Token> tokenize(String source, List<Rule> rules)
  {
    List<Token> tokens = new ArrayList<Token>();
    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<Rule> rules = new ArrayList<Rule>();
    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<Token> result = RETokenizer.tokenize(str, rules);
    for (Token t : result)
    {
      System.out.println(t);
    }
  }
}
import java.util.*;
导入java.util.regex.*;
公共级复述机
{
静态列表标记化(字符串源、列表规则)
{
List tokens=new ArrayList();
int pos=0;
final int end=source.length();
Matcher m=Pattern.compile(“dummy”).Matcher(源代码);
m、 useTransparentBounds(真)。useAnchoringBounds(假);
while(pos

顺便说一句,这是我发现的
lookingAt()的唯一一个很好的用途
method.:D

这里的大多数答案都已经很好了,但如果我没有指出的话,那我就是失职了。我已经围绕这个优秀的工具创建了完整的编译器。版本3有一些惊人的功能,我推荐它用于任何需要根据定义良好的语法解析输入的项目。

我也高度推荐写扫描器规范需要一些练习,但JFlex有很好的启动文件,而且是一项很好的技能。是的,我应该详细阐述一下。这有助于将字符串拆分为与正则表达式匹配的字符串,但不用于查找实际与正则表达式匹配的标记。您的pos