Go语言 分词正在陈述Unexpected Token

yrwegjxp  于 2023-02-27  发布在  Go
关注(0)|答案(1)|浏览(169)

我正在玩一个分词来学习如何解析,我不能确定为什么这是出乎意料的。

// nolint: golint, dupl
package main

import (
    "fmt"
    "io"

    "github.com/alecthomas/participle/v2"
    "github.com/alecthomas/participle/v2/lexer"
)

var htaccessLexer = lexer.MustSimple([]lexer.SimpleRule{
    {"Comment", `^#[^\n]*`},
    {"Ident", `^\w+`},
    {"Int", `\d+`},
    {"String", `("(\\"|[^"])*"|\S+)`},
    {"EOL", `[\n\r]+`},
    {"whitespace", `[ \t]+`},
})

type HTACCESS struct {
    Directives []*Directive `@@*`
}

type Directive struct {
    Pos lexer.Position

    ErrorDocument *ErrorDocument `@@`
}

type ErrorDocument struct {
    Code int    `"ErrorDocument" @Int`
    Path string `@String`
}

var htaccessParser = participle.MustBuild[HTACCESS](
    participle.Lexer(htaccessLexer),
    participle.CaseInsensitive("Ident"),
    participle.Unquote("String"),
    participle.Elide("whitespace"),
)

func Parse(r io.Reader) (*HTACCESS, error) {
    program, err := htaccessParser.Parse("", r)
    if err != nil {
        return nil, err
    }

    return program, nil
}

func main() {
    v, err := htaccessParser.ParseString("", `ErrorDocument 403 test`)

    if err != nil {
        panic(err)
    }

    fmt.Println(v)
}

据我所知,这似乎是正确的,我希望403在那里,但我不知道为什么它不承认它。
编辑:我将我的lexer更改为:

var htaccessLexer = lexer.MustSimple([]lexer.SimpleRule{
    {"dir", `^\w+`},
    {"int", `\d+`},
    {"str", `("(\\"|[^"])*"|\S+)`},
    {"EOL", `[\n\r]+`},
    {"whitespace", `\s+`},
})

错误消失了,但它仍然打印一个空数组,不知道为什么。我也不知道为什么对lexer使用不同的值也能修复它。

bvhaajcl

bvhaajcl1#

我相信我发现了问题,这是顺序,Ident通过\w标记在我的lexer中查找数字,所以这导致我的整数被标记为ident。
我发现我必须把带引号的字符串和不带引号的字符串分开,否则不带引号的字符串会选择整数,或者我可以确保它只选择非数字值,但是这样会错过像stringwithnum2这样的东西
这是我的解决方案

var htaccessLexer = lexer.MustSimple([]lexer.SimpleRule{
    {"Comment", `(?i)#[^\n]*`},
    {"QuotedString", `"(\\"|[^"])*"`},
    {"Number", `[-+]?(\d*\.)?\d+`},
    {"UnQuotedString", `[^ \t]+`},
    {"Ident", `^[a-zA-Z_]`},
    {"EOL", `[\n\r]+`},
    {"whitespace", `[ \t]+`},
})
type ErrorDocument struct {
    Pos lexer.Position

    Code int    `"ErrorDocument" @Number`
    Path string `(@QuotedString | @UnQuotedString)`
}

这修复了我的问题,因为它现在查找带引号的字符串,然后查找数字,然后查找不带引号的字符串。

相关问题