Synchronizing access to state

dev
Nick Dumas 1 year ago
parent 2859ccd56f
commit c963462545

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

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

Loading…
Cancel
Save