如何在另一个呼叫中正确返回令牌?

时间:2017-02-24 02:12:53

标签: java iterator token

我很难在字符串中获取正确的标记。我只能接受诸如(假,真,或,而不是),())之类的令牌。如果字符串中的标记是“(false”,那么我需要同时返回“(”和“false”。这是我遇到问题的地方。

例如,我想要的输出是:

line: [ not (false or error true) ]
next token: [not]
next token: [(]
next token: [false]
next token: [or]
next token: [true]
next token: [)]

但我的输出是:

line: [ not (false or error true) ]
next token: [not]
next token: [(]
next token: [or]
next token: [true]
next token: [)]

在迭代扫描下一个“或”标记时,我之前已经返回“(”并且我的下一个标记是“假”,但我无法弄清楚如何返回它。它跳过它并返回“或”

以下是我的方法。

public boolean hasNext() {
    if(!scan.hasNext()){
        return false;
    }
    return true;
}

public String next() {
    while(scan.hasNext()){
        scan.useDelimiter(" ");
        otherToken = scan.next();

    if(otherToken.contains("(") || otherToken.contains(")")){
        if(otherToken.contains("(")){
            nextToken = otherToken.substring(1, otherToken.length());
            return "(";
        }
        if(otherToken.contains(")")){
            nextToken = ")";
            return otherToken.substring(0, otherToken.length()-1);
        }
    }
    if(otherToken.equals("true") || otherToken.equals("false") || 
            otherToken.equals("or") || otherToken.equals("and") || 
            otherToken.equals("not")){
        nextToken = otherToken;
        return nextToken;
    }
    if(otherToken.equals("(") || otherToken.equals(")")){
        nextToken = otherToken;
        return nextToken;
    }
    else{
        continue;
    }
}
return nextToken;
}

3 个答案:

答案 0 :(得分:1)

通过稍微调整分隔符正则表达式模式,您可以让java Scanner返回您想要的标记:

    String line =" not (false or error true) ";
    Scanner scan = new Scanner(line);
    scan.useDelimiter(
            "(?<=(?:\\b(?:false|true|or|and|not)\\b)|[()]|^)" // lookbehind
            +".*?" // non-greedy match all
            +"(?=(?:\\b(?:false|true|or|and|not)\\b)|[()]|$)"); // lookahead
    while(scan.hasNext()) {
        System.out.format("next token: [%s]%n", scan.next());
    }

<强>输出:

  

下一个标记:[不]

     

下一个标记:[(]

     

下一个标记:[false]

     

下一个标记:[或]

     

下一个标记:[true]

     

下一个标记:[)]

但是,使用正则表达式自行查找令牌会更简单:

    String line = "not (false or error true)";
    Pattern p = Pattern.compile("(?:\\b(?:false|true|or|and|not)\\b)|[()]");
    Matcher m = p.matcher(line);
    while(m.find()) {
        System.out.format("next token: [%s]%n", m.group());
    }

答案 1 :(得分:0)

您正在使用空格作为分隔符。这是为您的字符串“not(false或error true)”

创建的标记列表
  1. (假
  2. 错误
  3. 真)
  4. 第二个标记是“(false”。以下代码返回“(”如果遇到包含“(”的字符串:

    if(otherToken.contains("(") || otherToken.contains(")")){ // STRING (false CONTAINS (
        if(otherToken.contains("(")){ // IF STRING CONTAINS ( WHICH (FALSE DOES
            nextToken = otherToken.substring(1, otherToken.length()); // NOT SURE WHERE nextToken IS USED.
            return "(";  // RETURN "("
        }
        if(otherToken.contains(")")){  // EVEN IF TOKEN IS 
            nextToken = ")";
            return otherToken.substring(0, otherToken.length()-1);
        }
    }
    

答案 2 :(得分:0)

别介意令牌化,有split()的单行解决方案:

String[] tokens = input.replaceAll("^.*?(?=[()]|\\b(or|not|true|false)\\b)|((?![()]|\\b(or|not|true|false)\\b).)*$", "")
.split("((?<=[()])|(?<=\\bor\\b)|(?<=\\bnot\\b)|(?<=\\btrue\\b)|(?<=\\bfalse\\b)).*?((?=[()]|\\b(or|not|true|false)\\b|$))");

请参阅live demo

首先删除任何前导或尾随垃圾,然后使用环顾四周来匹配目标令牌之间的

虽然有些正则表达式列车残骸,但这适用于任意“其他角色”,前提是单词用空格分隔,并且只能拔出目标令牌。例如,它适用于"xxx not yyy(zzz false aaa or bbb true ccc)ddd"等输入。