|
|
|
package lexer
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bufio"
|
|
|
|
// "log"
|
|
|
|
"strings"
|
|
|
|
)
|
|
|
|
|
|
|
|
type Token int
|
|
|
|
|
|
|
|
const (
|
|
|
|
LinkBeginToken = iota
|
|
|
|
LinkEndToken
|
|
|
|
LinkTextToken
|
|
|
|
LinkAliasBeginToken
|
|
|
|
LinkAliasTextToken
|
|
|
|
LinkSectionBeginToken
|
|
|
|
LinkSectionTextToken
|
|
|
|
LinkBlockBeginToken
|
|
|
|
LinkBlockTextToken
|
|
|
|
)
|
|
|
|
|
|
|
|
/*
|
|
|
|
var (
|
|
|
|
LinkBeginToken = Token{Raw: "[["}
|
|
|
|
LinkEndToken = Token{Raw: "]]"}
|
|
|
|
LinkTextToken = Token{}
|
|
|
|
LinkAliasBeginToken = Token{Raw: "|"}
|
|
|
|
LinkAliasTextToken = Token{}
|
|
|
|
LinkSectionBeginToken = Token{Raw: "#"}
|
|
|
|
LinkSectionTextToken = Token{}
|
|
|
|
LinkBlockBeginToken = Token{Raw: "^"}
|
|
|
|
LinkBlockTextToken = Token{}
|
|
|
|
)
|
|
|
|
*/
|
|
|
|
|
|
|
|
type Lexer struct {
|
|
|
|
input []string
|
|
|
|
pos int
|
|
|
|
link bool
|
|
|
|
Tokens chan Token
|
|
|
|
}
|
|
|
|
|
|
|
|
func Lex(input string) (*Lexer, chan Token) {
|
|
|
|
l := &Lexer{
|
|
|
|
input: make([]string, 0),
|
|
|
|
pos: 0,
|
|
|
|
Tokens: make(chan Token),
|
|
|
|
}
|
|
|
|
|
|
|
|
scanner := bufio.NewScanner(strings.NewReader(input))
|
|
|
|
scanner.Split(bufio.ScanRunes)
|
|
|
|
|
|
|
|
for scanner.Scan() {
|
|
|
|
l.input = append(l.input, scanner.Text())
|
|
|
|
}
|
|
|
|
|
|
|
|
go l.Run()
|
|
|
|
return l, l.Tokens
|
|
|
|
}
|
|
|
|
|
|
|
|
func (l *Lexer) Next() string {
|
|
|
|
if l.pos > len(l.input)-1 {
|
|
|
|
return "eof"
|
|
|
|
}
|
|
|
|
r := l.input[l.pos]
|
|
|
|
l.pos++
|
|
|
|
return r
|
|
|
|
}
|
|
|
|
|
|
|
|
func (l *Lexer) Backup() {
|
|
|
|
l.pos--
|
|
|
|
}
|
|
|
|
|
|
|
|
func (l *Lexer) Peek() string {
|
|
|
|
r := l.Next()
|
|
|
|
l.Backup()
|
|
|
|
return r
|
|
|
|
}
|
|
|
|
|
|
|
|
func (l *Lexer) Emit(t Token) {
|
|
|
|
// log.Printf("token emitted: %#v\n", t)
|
|
|
|
l.Tokens <- t
|
|
|
|
}
|
|
|
|
|
|
|
|
func (l *Lexer) Run() {
|
|
|
|
defer close(l.Tokens)
|
|
|
|
for {
|
|
|
|
s := l.Next()
|
|
|
|
if s == "eof" {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if s == "[" && l.Peek() == "[" {
|
|
|
|
l.link = true
|
|
|
|
l.Next()
|
|
|
|
l.Emit(LinkBeginToken)
|
|
|
|
|
|
|
|
switch s {
|
|
|
|
case "|":
|
|
|
|
l.Emit(LinkAliasBeginToken)
|
|
|
|
case "#":
|
|
|
|
l.Emit(LinkSectionBeginToken)
|
|
|
|
case "^":
|
|
|
|
l.Emit(LinkBlockBeginToken)
|
|
|
|
}
|
|
|
|
|
|
|
|
if s == "]" && l.Peek() == "]" {
|
|
|
|
l.link = false
|
|
|
|
l.Next()
|
|
|
|
l.Emit(LinkEndToken)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|