%PDF- %PDF-
| Direktori : /proc/thread-self/root/usr/share/doc/re2c/examples/go/state/ |
| Current File : //proc/thread-self/root/usr/share/doc/re2c/examples/go/state/push.go |
// Code generated by re2c, DO NOT EDIT.
//line "go/state/push.re":1
//go:generate re2go -f $INPUT -o $OUTPUT
package main
import (
"fmt"
"os"
)
// Use a small buffer to cover the case when a lexeme doesn't fit.
// In real world use a larger buffer.
const BUFSIZE int = 10
type State struct {
file *os.File
buf []byte
cur int
mar int
tok int
lim int
state int
}
const (
lexEnd = iota
lexReady
lexWaitingForInput
lexPacketBroken
lexPacketTooBig
)
func fill(st *State) int {
shift := st.tok
used := st.lim - st.tok
free := BUFSIZE - used
// Error: no space. In real life can reallocate a larger buffer.
if free < 1 { return lexPacketTooBig }
// Shift buffer contents (discard already processed data).
copy(st.buf[0:], st.buf[shift:shift+used])
st.cur -= shift
st.mar -= shift
st.lim -= shift
st.tok -= shift
// Fill free space at the end of buffer with new data.
n, _ := st.file.Read(st.buf[st.lim:BUFSIZE])
st.lim += n
st.buf[st.lim] = 0 // append sentinel symbol
return lexReady
}
func lex(st *State, recv *int) int {
var yych byte
//line "go/state/push.go":60
switch (st.state) {
default:
goto yy0
case 0:
if (st.lim <= st.cur) {
goto yy8
}
goto yyFillLabel0
case 1:
if (st.lim <= st.cur) {
goto yy3
}
goto yyFillLabel1
case 2:
if (st.lim <= st.cur) {
goto yy7
}
goto yyFillLabel2
}
//line "go/state/push.re":56
loop:
st.tok = st.cur
//line "go/state/push.go":85
yy0:
yyFillLabel0:
yych = st.buf[st.cur]
switch (yych) {
case 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z':
goto yy4
default:
if (st.lim <= st.cur) {
st.state = 0
return lexWaitingForInput
}
goto yy2
}
yy2:
st.cur += 1
yy3:
st.state = -1
//line "go/state/push.re":72
{ return lexPacketBroken }
//line "go/state/push.go":106
yy4:
st.cur += 1
st.mar = st.cur
yyFillLabel1:
yych = st.buf[st.cur]
switch (yych) {
case ';':
goto yy5
case 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z':
goto yy6
default:
if (st.lim <= st.cur) {
st.state = 1
return lexWaitingForInput
}
goto yy3
}
yy5:
st.cur += 1
st.state = -1
//line "go/state/push.re":74
{ *recv = *recv + 1; goto loop }
//line "go/state/push.go":129
yy6:
st.cur += 1
yyFillLabel2:
yych = st.buf[st.cur]
switch (yych) {
case ';':
goto yy5
case 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z':
goto yy6
default:
if (st.lim <= st.cur) {
st.state = 2
return lexWaitingForInput
}
goto yy7
}
yy7:
st.cur = st.mar
goto yy3
yy8:
st.state = -1
//line "go/state/push.re":73
{ return lexEnd }
//line "go/state/push.go":153
//line "go/state/push.re":75
}
func test(expect int, packets []string) {
// Create a "socket" (open the same file for reading and writing).
fname := "pipe"
fw, _ := os.Create(fname)
fr, _ := os.Open(fname)
// Initialize lexer state: `state` value is -1, all offsets are at the end
// of buffer.
st := &State{
file: fr,
// Sentinel at `lim` offset is set to zero, which triggers YYFILL.
buf: make([]byte, BUFSIZE+1),
cur: BUFSIZE,
mar: BUFSIZE,
tok: BUFSIZE,
lim: BUFSIZE,
state: -1,
}
// Main loop. The buffer contains incomplete data which appears packet by
// packet. When the lexer needs more input it saves its internal state and
// returns to the caller which should provide more input and resume lexing.
var status int
send := 0
recv := 0
for {
status = lex(st, &recv)
if status == lexEnd {
break
} else if status == lexWaitingForInput {
if send < len(packets) {
fw.WriteString(packets[send])
send += 1
}
status = fill(st)
if status != lexReady {
break
}
} else if status == lexPacketBroken {
break
}
}
// Check results.
if status != expect || (status == lexEnd && recv != send) {
panic(fmt.Sprintf("got %d, want %d", status, expect))
}
// Cleanup: remove input file.
fr.Close()
fw.Close()
os.Remove(fname)
}
func main() {
test(lexEnd, []string{})
test(lexEnd, []string{"zero;", "one;", "two;", "three;", "four;"})
test(lexPacketBroken, []string{"??;"})
test(lexPacketTooBig, []string{"looooooooooooong;"})
}