-1

我正在使用text/scanner包来解析一些任意表达式。我目前正在尝试实现一个not in选项,即如果当前标识符是not,而下一个是in,则使用 function 解析它notin(left, right),否则我们将其解析为negate(right)

我基本上已经获得了管理这些情况的代码,但是,如果下一个令牌不是,我无法倒带扫描仪in。我已经尝试通过记录位置然后重新分配它,但无济于事并且无法找到不同的解决方案。

func readToken(stream *scanner.Scanner) {
    switch stream.Scan() {
    case scanner.Ident:
        switch stream.TokenText() {
        case "in":
            in(left, right)
        case "not":
            oldPosition := stream.Position
            nextToken := stream.Scan()
            if nextToken == scanner.Ident {
                switch stream.TokenText() {
                case "in":
                    fmt.Println("notin")
                default:
                    // how do we rewind the scanner?
                    stream.Position = oldPosition 
                    fmt.Println("negate default")
                }
            } else {
                fmt.Println("negate no-ident")
            }
        }
    }
}

找不到有效标识符时,如何倒带扫描仪?

编辑,我也尝试Peek()如下使用,但这仍然会将状态更改为我需要倒带的点。

// other code
case "not":
    nextIdent, err := getNextIdent(stream)
    if err != nil {
        fmt.Println("negate no-ident")
    } else {
        switch nextIdent {
        case "in":
            fmt.Println("notin")
        default:
            fmt.Println("negate default")
        }
    }
// other code


func getNextIdent(s *scanner.Scanner) (string, error) {
    var nextIdent string

    ch := s.Peek()

    // skip white space
    for s.Whitespace&(1<<uint(ch)) != 0 {
        ch = s.Next()
    }

    if isIdentRune(ch, 0) {
        nextIdent = string(ch)
        ch = s.Next()
        nextIdent += string(ch)
        for i := 1; isIdentRune(ch, i); i++ {
            ch = s.Next()
            if s.Whitespace&(1<<uint(ch)) != 0 {
                break
            }
            nextIdent += string(ch)
        }
        return nextIdent, nil
    }

    return "",errors.New("not a ident")
}

请注意,我得到的代码是来自Knetic/govaluate的分叉,以及来自 GH 用户generikvault的PR和其他一些分叉。完整代码可以在我的Github 个人资料中找到

4

1 回答 1

3

通过查看 API 引用text/scanner,我似乎无法找到一种方法以您想要的方式倒带扫描仪。

但是,该Peek()方法可以在不推进扫描仪的情况下为您提供下一个符文。在“不”的情况下,您可以使用它提前查看是否匹配。

于 2019-10-13T01:04:52.117 回答