我正在玩一个分词来学习如何解析,我不能确定为什么这是出乎意料的。
// 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使用不同的值也能修复它。
1条答案
按热度按时间bvhaajcl1#
我相信我发现了问题,这是顺序,Ident通过\w标记在我的lexer中查找数字,所以这导致我的整数被标记为ident。
我发现我必须把带引号的字符串和不带引号的字符串分开,否则不带引号的字符串会选择整数,或者我可以确保它只选择非数字值,但是这样会错过像
stringwithnum2
这样的东西这是我的解决方案
这修复了我的问题,因为它现在查找带引号的字符串,然后查找数字,然后查找不带引号的字符串。