goparsec

package module
v0.0.0-...-6e7bffa Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 4, 2015 License: MIT Imports: 5 Imported by: 4

README

GoParsec

Haskell Parsec Libraray's golang version

PLEASE USE goparsec2 BUT THIS. GOPARSEC2 LIKE HASKELL PRASEC LIBRARY THAN GOPARSEC. IT SUPPORT MONAD BIND/THEN/OVER.

Document

Paper Style

http://bms.tratao.com/desktop/doc/0c3802e4ee404a71407f34996eff98ef

Slide Style

http://bms.tratao.com/slide/simple/0c3802e4ee404a71407f34996eff98ef##1

概述

还是那句话,公司自用的东西肯定不会坑,但是可能达到一个可用阶段后会停一段时间。

第一步先支持几个常用组合子,让公司的项目可以做下去,然后……

我的项目大量的参考了 https://github.com/sanyaade-buildtools/goparsec ,但是这个项目面向 byte流,而我需要一个面向 unicode 或更通用的规则解析的工具。所以只好重新实现了一遍。

这里 https://github.com/vito/go-parse 还有一个实现,但是五年没有更新了。

测试

由于用在团队内部一个 markdown like 的文档内容解析功能上, 所以目前的测试用例都是基于 markdown 转 json 这个场景展开的。

对 parsec 和 parsex 的深度运用,可以参见 http://github.com/Dwarfartisan/gisp ,这是 一个类 lisp 语言的解释器,里面大量运用了 parsec 和 parsex 。

Parsex

Parsex 是 go parsec 的一个包。parsec 的主干是以一个字符流 state parser 接口为基础的。在工作 中,我遇到了一些更通用的规则构造和解析的需求。所以在 parsec/parsex 包里,我写了一个基于 []interface{} 序列的组合子功能。其实这本质上是因为 golang 没有泛型,否则直接把 state parer 泛型化就可以了。这也是 Haskell 原版的 parsec 没有这种区分的原因。

parsex/combinator_test.go 文件中包含了一个测试用例,可以看作是对一个经过词法解析的简单 token 流的语法解析。

最后

如果有同行参与进来一起把它通用化当然最好啦,口嫌体正直什么的我是不会做的 ε-(´∀`; ) 。

对了我还准备再用 swift 做一遍,这个主意怎么看都酷毙了,目前唯一就缺个会写代码的了……

Documentation

Overview

parsec 的部分代码实现参考了 https://github.com/sanyaade-buildtools/goparsechttps://github.com/prataprc/goparsec 但是我需要一个面向 unicode 的简洁实现,所以只好重写了自己的版本。

parser state 包参考了 golang 的内置包定义,部分代码模仿或来自 text/scanner ,其中有向 https://github.com/sanyaade-buildtools/goparsec 学习一部分设计思路

Index

Constants

This section is empty.

Variables

View Source
var Digit = RuneChecker(unicode.IsDigit, "digit")
View Source
var Float = Either(UnsignedFloat,
	Bind_(Rune('-'), func(st ParseState) (interface{}, error) {
		value, err := UnsignedFloat(st)
		if err == nil {
			return ExtractString(append([]interface{}{'-'},
				value.([]interface{})...)), nil
		} else {
			return nil, err
		}
	}))
View Source
var Letter = RuneChecker(unicode.IsLetter, "letter")
View Source
var NewLine = OneOf(NewLineRunes)
View Source
var NewLineRunes = "\r\n"
View Source
var Number = RuneChecker(unicode.IsNumber, "number")
View Source
var Space = RuneChecker(unicode.IsSpace, "space")
View Source
var Spaces = Skip(Space)
View Source
var UnsignedFloat = Bind(Many(Digit), func(input interface{}) Parser {
	return func(st ParseState) (interface{}, error) {
		value, err := Bind_(Rune('.'), Many1(Digit))(st)
		if err != nil {
			return nil, err
		}
		ret := []interface{}{}
		ret = append(ret, input.([]interface{})...)
		ret = append(ret, '.')
		ret = append(ret, value.([]interface{})...)
		return ExtractString(ret), nil
	}
})

Functions

func AnyRune

func AnyRune(st ParseState) (interface{}, error)

func Eof

func Eof(st ParseState) (interface{}, error)

func ExtractString

func ExtractString(input interface{}) string

func ExtraString 将 interface{} 转成 string,如果输入数据与前面提到的规范不符,会 panic

func Int

func Int(st ParseState) (interface{}, error)

Types

type ParseError

type ParseError struct {
	Line    int
	Column  int
	Pos     int
	Message string
}

func (ParseError) Error

func (err ParseError) Error() string

type ParseState

type ParseState interface {
	Next(pred func(rune) bool) (r rune, ok bool, err error)
	Line() int
	Column() int
	Pos() int
	SeekTo(int)
	Trap(message string, args ...interface{}) error
}

func MemoryParseState

func MemoryParseState(data string) ParseState

type Parser

type Parser func(ParseState) (interface{}, error)

func Between

func Between(start, end, p Parser) Parser

func Bind

func Bind(parser Parser, fun func(interface{}) Parser) Parser

func Bind_

func Bind_(parserx, parsery Parser) Parser

func Binds

func Binds(first Parser, then ...func(interface{}) Parser) Parser

Binds 相当于用 Bind 对一个 func(interface{})Parser 链做左折叠,起始参数为 first

func Binds_

func Binds_(parsers ...Parser) Parser

Binds_ 逐个尝试每一个 Parser,直至发生错误或者到达最后,如果到达最后一个 Parser, 返回其结果

func Choice

func Choice(parsers ...Parser) Parser

Choice 实现为以下逻辑的迭代版本:

func Choice(parsers ...Parser) Parser {
	switch len(parsers) {
	case 0:
		panic(errors.New("empty choice chain"))
	case 1:
		return parsers[0]
	case 2:
		return Either(Try(parsers[0]), Try(parsers[1]))
	default:
		return Either(Try(parsers[0]), Choice(parsers[1:]))
	}
}

其实我比较希望把下面那个东西实现成上面这个样子,就是好像在golang里不太经济……

func Either

func Either(parserx, parsery Parser) Parser

try one parser, if it fails (without consuming input) try the next

func Fail

func Fail(message string) Parser

func Many

func Many(parser Parser) Parser

func Many1

func Many1(parser Parser) Parser

func ManyTil

func ManyTil(p, end Parser) Parser

func Maybe

func Maybe(p Parser) Parser

func NoneOf

func NoneOf(runes string) Parser

func OneOf

func OneOf(runes string) Parser

func Option

func Option(v interface{}, parser Parser) Parser

func Return

func Return(v interface{}) Parser

func ReturnString

func ReturnString(input interface{}) Parser

func ReturnString 用 Return 包装 ExtraString,使其适用于 Bind 这样的组合子。

func Rune

func Rune(r rune) Parser

func RuneChecker

func RuneChecker(checker func(rune) bool, expected string) Parser

func SepBy

func SepBy(p, sep Parser) Parser

func SepBy1

func SepBy1(p, sep Parser) Parser

func Skip

func Skip(p Parser) Parser

func String

func String(s string) Parser

func Try

func Try(parser Parser) Parser

func Union

func Union(parsers ...Parser) Parser

func UnionAll

func UnionAll(parsers ...Parser) Parser

type StateInMemory

type StateInMemory struct {
	// contains filtered or unexported fields
}

func (*StateInMemory) Column

func (this *StateInMemory) Column() int

func (*StateInMemory) Line

func (this *StateInMemory) Line() int

func (*StateInMemory) Next

func (this *StateInMemory) Next(pred func(rune) bool) (r rune, match bool, err error)

func (*StateInMemory) Pos

func (this *StateInMemory) Pos() int

func (*StateInMemory) SeekTo

func (this *StateInMemory) SeekTo(pos int)

func (*StateInMemory) Trap

func (this *StateInMemory) Trap(message string, args ...interface{}) error

Directories

Path Synopsis
parsec 的部分代码实现参考了 https://github.com/sanyaade-buildtools/goparsec 和 https://github.com/prataprc/goparsec 但是我需要一个面向 unicode 的简洁实现,所以只好重写了自己的版本。
parsec 的部分代码实现参考了 https://github.com/sanyaade-buildtools/goparsec 和 https://github.com/prataprc/goparsec 但是我需要一个面向 unicode 的简洁实现,所以只好重写了自己的版本。

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL