scanner.Scanner: initial struct and methods for the low level text scanner
Signed-off-by: Alejandro Mery <amery@geeks.cl>
This commit is contained in:
@@ -1 +1,73 @@
|
||||
package scanner
|
||||
|
||||
import (
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
const (
|
||||
EOF = -1
|
||||
)
|
||||
|
||||
type Position struct {
|
||||
Offset uint
|
||||
Line, Column uint
|
||||
}
|
||||
|
||||
type Scanner struct {
|
||||
name string
|
||||
input string
|
||||
|
||||
base Position
|
||||
cursor Position
|
||||
runes uint
|
||||
}
|
||||
|
||||
// Creates new Scanner to parse a given string, or nil if empty
|
||||
func NewScannerFromString(name, input string) *Scanner {
|
||||
if len(input) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
return &Scanner{
|
||||
name: name,
|
||||
input: input,
|
||||
base: Position{0, 1, 1},
|
||||
cursor: Position{0, 1, 1},
|
||||
runes: 0,
|
||||
}
|
||||
}
|
||||
|
||||
// Current length of the upcomming Terminal
|
||||
func (l *Scanner) Length() (uint, uint) {
|
||||
return l.cursor.Offset - l.base.Offset, l.runes
|
||||
}
|
||||
|
||||
// Is the upcoming Terminal stil empty?
|
||||
func (l *Scanner) Empty() bool {
|
||||
return l.runes == 0
|
||||
}
|
||||
|
||||
// Move cursor forward
|
||||
func (l *Scanner) StepForth(runes, bytes uint) {
|
||||
l.cursor.Offset += bytes
|
||||
l.cursor.Column += runes
|
||||
l.runes += runes
|
||||
}
|
||||
|
||||
// Return the next rune but not moving the cursor
|
||||
func (l *Scanner) Peek() (rune, uint) {
|
||||
if l.cursor.Offset == uint(len(l.input)) {
|
||||
return EOF, 0
|
||||
}
|
||||
r, bytes := utf8.DecodeRuneInString(l.input[l.cursor.Offset:])
|
||||
return r, uint(bytes)
|
||||
}
|
||||
|
||||
// Return the next rune but moving the cursor
|
||||
func (l *Scanner) Next() (rune, uint) {
|
||||
r, bytes := l.Peek()
|
||||
if bytes > 0 {
|
||||
l.StepForth(1, bytes)
|
||||
}
|
||||
return r, bytes
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user