コード例 #1
0
ファイル: state_test.go プロジェクト: gavingroovygrover/kern
//================================================================================
func TestStateStack(t *testing.T) {
	ts.LogAsserts("StateStack", t, func(tt *ts.T) {
		p0 := Bind(PushStateStack(555), func(c1 interface{}) Parser {
			return Bind(PushStateStack(556), func(c2 interface{}) Parser {
				return PushStateStack(557)
			})
		})

		p2 := SeqRight(
			SeqRight(p0, Bind(AnyChar, func(x interface{}) (p Parser) {
				if u8.Sur(x.(u8.Codepoint)) == "\n" {
					return PopStateStack()
				} else {
					return Return(nil)
				}
			})),
			GetState)

		tt.AssertEqual(parseStr(p2, "\naa"),
			PState{input: "aa", pos: 1, value: []interface{}{555, 556},
				ok: true, user: []interface{}{555, 556}})
		tt.AssertEqual(parseStr(p2, "abba"),
			PState{input: "bba", pos: 1, value: []interface{}{555, 556, 557},
				ok: true, user: []interface{}{555, 556, 557}})

		p3 := SeqRight(p0, Bind(AnyChar, func(x interface{}) (p Parser) {
			if u8.Sur(x.(u8.Codepoint)) == "\n" {
				return AlterTopStateStack(777)
			} else {
				return PeekStateStack()
			}
		}))

		tt.AssertEqual(parseStr(p3, "\nbc"),
			PState{input: "bc", pos: 1, ok: true, user: []interface{}{555, 556, 777}})
		tt.AssertEqual(parseStr(p3, "abc"),
			PState{input: "bc", pos: 1, value: 557, ok: true, user: []interface{}{555, 556, 557}})

		p4 := Bind(AnyChar, func(x interface{}) (p Parser) {
			if u8.Sur(x.(u8.Codepoint)) == "\n" {
				return AlterTopStateStack(777)
			} else {
				return PeekStateStack()
			}
		})

		tt.AssertEqual(parseStr(p4, "\naa"),
			PState{input: "aa", pos: 1, error: "AlterTopStateStack doesn't handle zero-sized stacks."})
		tt.AssertEqual(parseStr(p4, "abc"),
			PState{input: "bc", pos: 1, ok: true})
	})
}
コード例 #2
0
ファイル: kern.go プロジェクト: gavingroovygrover/kern
// Expect parses p and if it fails (regardless of input consumed) will replace
// the error with the message "Expecting" m. This helps to produce more abstract
// and accurate error messages.
func Expect(p Parser, m u8.Text) Parser {
	return func(s PState) PState {
		st := p(s)
		if st.ok {
			return st
		} else {
			return st.clone(func(e *PState) {
				e.error = st.error + " Expecting " + u8.Sur(m...)
			})
		}
	}
}
コード例 #3
0
ファイル: kern.go プロジェクト: gavingroovygrover/kern
// Ask parses p and if it fails consuming no input, will replace the error
// with the message "Expecting" m. This helps to produce more abstract and
// accurate error messages. Same functionality as <?> in Clojure's kern.
func Ask(p Parser, m u8.Text) Parser {
	return func(s PState) PState {
		st := p(s)
		if !st.ok && st.empty {
			return st.clone(func(e *PState) {
				e.error = st.error + " Expecting " + u8.Sur(m...)
			})
		} else {
			return st
		}
	}
}
コード例 #4
0
func ExampleNoneOf() {
	p := kern.NoneOf(utf88.Text("xyz\n\t"))

	t := utf88.Text("abcde")
	r, ok := kern.ParseText(p, t)
	if ok {
		fmt.Printf("Result: %s\n", utf88.Sur(r.(utf88.Codepoint)))
	} else {
		fmt.Printf("Error: %v\n", r)
	}

	// Output:
	// Result: a
}
コード例 #5
0
func ExampleAsk() {
	letter := kern.Regexp(`\pL`)
	digit := kern.Regexp(`\p{Nd}`)

	p := kern.Ask(kern.Collect(digit, letter), utf88.Text("digit,letter"))

	t := utf88.Text(";efg")
	r, ok := kern.ParseText(p, t)
	if ok {
		fmt.Printf("Result: %s\n", utf88.Sur(r.(utf88.Codepoint)))
	} else {
		fmt.Printf("Error: %v\n", r)
	}

	// Output:
	// Error: Unexpected ; input. Expecting digit,letter
}
コード例 #6
0
ファイル: kern.go プロジェクト: gavingroovygrover/kern
// Satisfy succeeds if the next character satisfies the predicate pred, in which case
// advances the position of the input stream. It may fail on an unexpected end of input.
func Satisfy(pred func(u8.Codepoint) bool) Parser {
	return func(st PState) (so PState) {
		if log["Satisfy"] || (len(st.log) > 0 && st.log[len(st.log)-1] && loggingEnabled) {
			defer logFnBA("Satisfy", &st, &so)
		}
		if st.input == "" {
			so = st.clone(func(e *PState) {
				e.value = nil
				e.ok = false
				e.empty = true
				e.error = errUnexpEof
			})
			return
		}
		c, _ := u8.DesurrogateFirstPoint([]rune(st.input))
		if pred(c) {
			so = st.clone(func(e *PState) {
				e.input = st.input[u8.LenInBytes(c):]
				e.pos = st.pos + uint64(u8.LenInBytes(c))
				e.value = c
				e.ok = true
				e.empty = false
				e.error = ""
			})
			return
		} else {
			so = st.clone(func(e *PState) {
				e.value = nil
				e.ok = false
				e.empty = true
				e.error = makeUnexpInp(u8.Sur(c))
			})
			return
		}
	}
}
コード例 #7
0
ファイル: kern.go プロジェクト: gavingroovygrover/kern
// Symbol succeeds if the next Codepoint equals the given Codepoint, in which case it
// increments the position of the input stream. It may fail on an unexpected end of input.
func Symbol(t u8.Codepoint) Parser {
	sym := u8.Sur(t)
	return func(st PState) (so PState) {
		if log["Symbol"] || (len(st.log) > 0 && st.log[len(st.log)-1] && loggingEnabled) {
			defer logFnBA("Symbol", &st, &so)
		}
		if len(sym) == 0 {
			so = st.clone(func(e *PState) {
				e.value = nil
				e.ok = false
				e.empty = true
				e.error = errEmptyStr
			})
			return
		} else if len(sym) > 1 && st.input[:len(sym)] == sym {
			so = st.clone(func(e *PState) {
				e.input = st.input[len(sym):]
				e.pos = st.pos + uint64(len(sym))
				e.value = t
				e.ok = true
				e.empty = false
				e.error = ""
			})
			return
		} else if len(sym) > 1 {
			so = st.clone(func(e *PState) {
				e.value = nil
				e.ok = false
				e.empty = true
				e.error = errInvalStr
			})
			return
		} else if st.input == "" {
			so = st.clone(func(e *PState) {
				e.value = nil
				e.ok = false
				e.empty = true
				e.error = errUnexpEof
			})
			return
		} else if st.input[:1] == sym {
			so = st.clone(func(e *PState) {
				e.input = st.input[1:]
				e.pos = st.pos + 1
				e.value = t
				e.ok = true
				e.empty = false
				e.error = ""
			})
			return
		} else {
			so = st.clone(func(e *PState) {
				e.value = nil
				e.ok = false
				e.empty = true
				e.error = makeUnexpInp(st.input[:1])
			})
			return
		}
	}
}