Skip to content

Latest commit

 

History

History
110 lines (79 loc) · 2.73 KB

File metadata and controls

110 lines (79 loc) · 2.73 KB

快速开始

pegtool 使用 Go 编写。下面统一使用命令名 pegtool

安装

从 Go 模块安装最新版本:

go install github.com/fy0/pegtool@latest
pegtool -h

从当前仓库构建:

go build -o .\bin\pegtool.exe .

创建第一份文法

::: tip 使用其他目标语言 本节以 Go 为例。要生成其他语言的 parser,请直接查看 HaxeTypeScriptC#C99Rust 的最小可运行示例。

不准备运行 Go 示例?可以跳到切换目标语言,或直接查看下一步。 :::

新建 identifier.peg。下面的 Go 文法识别一个 Unicode 标识符,并返回捕获到的文本:

{
package main

type ParserCustomData struct{}

func ParseIdentifier(filename string, input []byte) (string, error) {
    value, err := parse(filename, input)
    if err != nil {
        return "", err
    }
    return value.(string), nil
}
}

Start = value:<Identifier> !. {
    return value
}

Identifier = [\pL_] [\pL\p{Nd}_]*

这里的关键点是:

  • initializer 中的 Go 代码声明生成文件所属的 package 和公开调用函数。
  • 即使不使用自定义状态,Go target 也需要声明空的 ParserCustomData
  • 第一条规则是默认入口。
  • <Identifier> 显式捕获匹配文本。
  • !. 要求输入已经结束,避免只接受合法前缀。
  • \pL\p{Nd} 使用生成器所认识的 Unicode 类。

生成 Go parser

go mod init example.com/identifier
pegtool -t go -o parser.go identifier.peg

新建 main.go 调用生成的 parser:

package main

import "fmt"

func main() {
    value, err := ParseIdentifier("input.txt", []byte("name_世界"))
    if err != nil {
        panic(err)
    }
    fmt.Println(value)
}

编译并运行:

go run .
# 输出:name_世界

切换目标语言

使用 -t-target 选择输出:

目标 参数 常用输出名
Go go parser.go
Haxe hxhaxe Parser.hx
TypeScript tstypescript parser.ts
C# cscsharpc# Parser.cs
C99 cc99 parser.c
Rust rust parser.rs

文法中的动作代码属于目标语言。需要从同一文件生成多种语言时,使用目标条件模板

下一步

  1. 阅读PEG 语法,理解有序选择与回溯。
  2. 阅读动作与值,避免依赖上游 Pigeon 的序列返回值。
  3. 在真实输入上基准测试后,再选择性能参数