Synchronizing access to state

main
Nick Dumas 2 years ago
parent 2859ccd56f
commit c963462545

@ -4,6 +4,7 @@ package wikilink
import (
"fmt"
"strings"
"sync"
// "unicode"
"unicode/utf8"
@ -67,19 +68,20 @@ func (l *Lexer) NextItem() Item {
}
func (l *Lexer) ignore() {
l.start = l.pos
l.SetStart(l.pos)
}
func (l *Lexer) backup() {
l.pos -= l.width
l.SetPos(l.GetPos() - l.GetWidth())
}
type Lexer struct {
L *zap.SugaredLogger
name, input string
start, pos, width int
state stateFn
items chan Item
L *zap.SugaredLogger
name, input string
start, pos, width int
state stateFn
items chan Item
widthMutex, startMutex, posMutex, chanMutex sync.Mutex
}
func (l *Lexer) peek() rune {
@ -106,17 +108,19 @@ func (l *Lexer) acceptRun(valid string) {
}
func (l *Lexer) emit(t ItemType) {
i := Item{t, l.input[l.start:l.pos]}
defer l.chanMutex.Unlock()
l.chanMutex.Lock()
i := Item{t, l.input[l.GetStart():l.GetPos()]}
L := l.L.With(
zap.Int("pos", l.pos),
zap.Int("width", l.width),
zap.Int("pos", l.GetPos()),
zap.Int("width", l.GetWidth()),
).Named("emit")
L.Debugw("emitting item",
zap.String("item", i.String()),
)
l.items <- i
l.start = l.pos
l.SetStart(l.GetPos())
}
func (l *Lexer) errorf(format string, args ...interface{}) stateFn {
@ -135,12 +139,13 @@ func (l *Lexer) errorf(format string, args ...interface{}) stateFn {
func (l *Lexer) next() rune {
var r rune
if l.pos >= len(l.input) {
l.width = 0
if l.GetPos() >= len(l.input) {
l.SetWidth(0)
return EOF
}
r, l.width = utf8.DecodeRuneInString(l.input[l.pos:])
l.pos += l.width
r, width := utf8.DecodeRuneInString(l.input[l.GetPos():])
l.SetWidth(width)
l.SetPos(l.GetPos() + l.GetWidth())
return r
}
@ -148,9 +153,46 @@ func (l *Lexer) run() {
for state := lexText; state != nil; {
state = state(l)
}
l.chanMutex.Lock()
close(l.items)
}
func (l *Lexer) GetPos() int {
defer l.posMutex.Unlock()
l.posMutex.Lock()
return l.pos
}
func (l *Lexer) SetPos(pos int) {
defer l.posMutex.Unlock()
l.posMutex.Lock()
l.pos = pos
}
func (l *Lexer) GetWidth() int {
defer l.widthMutex.Unlock()
l.widthMutex.Lock()
return l.width
}
func (l *Lexer) SetWidth(width int) {
defer l.widthMutex.Unlock()
l.widthMutex.Lock()
l.width = width
}
func (l *Lexer) GetStart() int {
defer l.startMutex.Unlock()
l.startMutex.Lock()
return l.start
}
func (l *Lexer) SetStart(start int) {
defer l.startMutex.Unlock()
l.startMutex.Lock()
l.start = start
}
type stateFn func(*Lexer) stateFn
type ItemType int

@ -1,7 +1,6 @@
package wikilink
import (
"log"
"strings"
)
@ -26,10 +25,9 @@ func isBlockRef(s string) bool {
}
func lexIdent(l *Lexer) stateFn {
log.Println("lexIdent")
for {
r := l.next()
s := l.input[l.pos:]
s := l.input[l.GetPos():]
if r == '\\' { // i think this will handle escape characters?
break
}
@ -53,33 +51,29 @@ func lexIdent(l *Lexer) stateFn {
}
func lexHeading(l *Lexer) stateFn {
log.Println("lexHeading")
l.pos += len(Heading)
l.SetPos(l.GetPos() + len(Heading))
l.emit(ItemHeading)
return lexIdent
}
func lexBlockRef(l *Lexer) stateFn {
log.Println("lexBlockRef")
l.pos += len(BlockRef)
l.SetPos(l.GetPos() + len(BlockRef))
l.emit(ItemBlockRef)
return lexIdent
}
func lexAlias(l *Lexer) stateFn {
log.Println("lexAlias")
l.pos += len(Alias)
l.SetPos(l.GetPos() + len(Alias))
l.emit(ItemAlias)
return lexIdent
}
func lexText(l *Lexer) stateFn {
log.Println("lexText")
for {
if isOpenLink(l.input[l.pos:]) {
if isOpenLink(l.input[l.GetPos():]) {
return lexOpenLink
}
r := l.next()
@ -92,16 +86,14 @@ func lexText(l *Lexer) stateFn {
}
func lexOpenLink(l *Lexer) stateFn {
log.Println("lexOpenLink")
l.pos += len(OpenLink)
l.SetPos(l.GetPos() + len(OpenLink))
l.emit(ItemOpenLink)
return lexIdent
}
func lexCloseLink(l *Lexer) stateFn {
log.Println("lexCloseLink")
l.pos += len(CloseLink)
l.SetPos(l.GetPos() + len(CloseLink))
l.emit(ItemCloseLink)
return lexText

Loading…
Cancel
Save