Permalink
Browse files

Inject input stream on start, not init

  • Loading branch information...
BenchR267 committed Mar 18, 2017
1 parent 63a9641 commit 0c061cd3d7926b194c34f826b540d862f56fcdd0
Showing with 61 additions and 40 deletions.
  1. +25 −5 lexer/lexer.go
  2. +31 −10 lexer/lexer_test.go
  3. +5 −25 repl/repl.go
@@ -1,6 +1,18 @@
package lexer

import "github.com/BenchR267/lbd/lexer/token"
import (
"errors"

"github.com/BenchR267/lbd/lexer/token"
)

var (
// ErrNotFinished is returned on Start() when Lexer was started before and has not finished yet
ErrNotFinished = errors.New("lexer still not finished lexing")

// ErrInputStreamNil is returned on Start() if the given inputStream is nil
ErrInputStreamNil = errors.New("input stream should not be nil")
)

// Lexer represents an instance to get a lexical representation of the source code.
//
@@ -15,10 +27,8 @@ type Lexer struct {
}

// NewLexer creates a new instance of Lexer, ready to be started.
func NewLexer(inputStream <-chan rune) *Lexer {
func NewLexer() *Lexer {
l := &Lexer{
NextToken: make(chan token.Token),
input: inputStream,
curPos: token.Position{
Column: 0,
Line: 0,
@@ -32,7 +42,15 @@ func NewLexer(inputStream <-chan rune) *Lexer {

// Start will read from the inputStream, forwarding tokens via NextToken.
// Start runs in its own go routine and will get a zombie if NextToken is not read!
func (l *Lexer) Start() {
func (l *Lexer) Start(inputStream <-chan rune) error {
if l.input != nil {
return ErrNotFinished
}
if inputStream == nil {
return ErrInputStreamNil
}
l.input = inputStream
l.NextToken = make(chan token.Token)
go func() {
for b := range l.input {
if !isWhitespace(b) {
@@ -59,6 +77,8 @@ func (l *Lexer) Start() {
if t != nil {
l.NextToken <- *t
}
l.input = nil
close(l.NextToken)
}()
return nil
}
@@ -8,8 +8,8 @@ import (

func TestIgnoreWhitespace(t *testing.T) {
stream := StreamFromString("a= 5")
l := NewLexer(stream)
l.Start()
l := NewLexer()
l.Start(stream)

expectedValues := []token.Token{
{
@@ -43,8 +43,8 @@ func TestIgnoreWhitespace(t *testing.T) {

func TestStart_OneLine(t *testing.T) {
stream := StreamFromString("abc = dfe + 3")
l := NewLexer(stream)
l.Start()
l := NewLexer()
l.Start(stream)

expectedValues := []token.Token{
{
@@ -90,8 +90,8 @@ func TestStart_MultipleLines(t *testing.T) {
stream := StreamFromString(`a = 5
b = 4
c = a + b`)
l := NewLexer(stream)
l.Start()
l := NewLexer()
l.Start(stream)

expectedValues := []token.Token{
{
@@ -165,8 +165,8 @@ c = a + b`)

func TestConditions(t *testing.T) {
stream := StreamFromString("a<=b")
l := NewLexer(stream)
l.Start()
l := NewLexer()
l.Start(stream)

expectedValues := []token.Token{
{
@@ -205,8 +205,8 @@ a = (a int, b int) -> int {
}
`)

l := NewLexer(stream)
l.Start()
l := NewLexer()
l.Start(stream)

expectedValues := []struct {
Type token.Type
@@ -245,4 +245,25 @@ a = (a int, b int) -> int {

i++
}

}

func TestStartError(t *testing.T) {
l := NewLexer()

err := l.Start(nil)
if err == nil || err != ErrInputStreamNil {
t.Errorf("Expected err to be ErrInputStreamNil, but got %v", err)
}

err = l.Start(StreamFromString("a = b"))
if err != nil {
t.Errorf("Expected err to be nil, but got %v", err)
}

err = l.Start(StreamFromString("b = 6"))
if err == nil || err != ErrNotFinished {
t.Errorf("Expected err to be ErrNotFinished, but got %v", err)
}

}
@@ -7,8 +7,6 @@ import (

"bufio"

"time"

"github.com/BenchR267/lbd/lexer"
)

@@ -18,39 +16,21 @@ var writer io.Writer = os.Stdout
// Start is starting the interactive REPL (currently just printing out tokens)
func Start() {

c := make(chan rune)
l := lexer.NewLexer(c)
l.Start()
l := lexer.NewLexer()

scanner := bufio.NewScanner(reader)
for {
fmt.Fprint(writer, "lbd $ ")
scanner.Scan()
text := scanner.Text()
if text == "e" || text == "exit" {
close(c)
break
}

done := make(chan struct{})

go func() {
for _, r := range text {
c <- r
}
c <- '\n'
time.Sleep(time.Millisecond * 1)
done <- struct{}{}
}()

waitLoop:
for {
select {
case t := <-l.NextToken:
fmt.Fprintln(writer, t)
case <-done:
break waitLoop
}
l.Start(lexer.StreamFromString(text))

for t := range l.NextToken {
fmt.Fprintln(writer, t)
}

fmt.Fprintln(writer)

0 comments on commit 0c061cd

Please sign in to comment.