|
|
|
@ -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
|
|
|
|
|