Skip to content

Instantly share code, notes, and snippets.

@rightfold
Last active August 29, 2015 14:16
Show Gist options
  • Save rightfold/50377565dec6cc1425c3 to your computer and use it in GitHub Desktop.
Save rightfold/50377565dec6cc1425c3 to your computer and use it in GitHub Desktop.
package parse
import (
"bufio"
"errors"
"io"
"unicode"
)
var InvalidToken = errors.New("invalid token")
const (
Symbol = iota
Integer
String
LeftParenthesis
RightParenthesis
)
type Token struct {
Kind int
Value interface{}
}
func Lex(reader io.Reader) ([]Token, error) {
rd := bufio.NewReader(reader)
tokens := []Token{}
for {
r, _, err := rd.ReadRune()
if err != nil {
if err == io.EOF {
return tokens, nil
} else {
return nil, err
}
}
switch {
case isSpace(r):
break
case r == '(':
tokens = append(tokens, Token{LeftParenthesis, nil})
case r == ')':
tokens = append(tokens, Token{RightParenthesis, nil})
case isIdentifierHead(r):
name := string(r)
for {
r, _, err = rd.ReadRune()
if isIdentifierTail(r) {
name += string(r)
} else if err == nil || err == io.EOF {
break
} else {
return nil, err
}
}
rd.UnreadRune()
tokens = append(tokens, Token{Symbol, name})
default:
return nil, InvalidToken
}
}
return tokens, nil
}
func isSpace(r rune) bool {
return unicode.In(r, unicode.Zs)
}
func isIdentifierHead(r rune) bool {
return unicode.In(r, unicode.L, unicode.Sm, unicode.Pc, unicode.Pd)
}
func isIdentifierTail(r rune) bool {
return isIdentifierHead(r) || unicode.In(r, unicode.N)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment