package muesli import ( "fmt" ) /* Position of a token in an input stream */ type Position struct { FileName string Line int Column int } func (p Position) String() string { return fmt.Sprintf("%s:%d:%d", p.FileName, p.Line, p.Column) } /* Token Kind. Uses a rune to easily handle single character tokens. */ type TokenKind rune const ( TokenKindNone = TokenKind(0) TokenKindInteger = TokenKind('i') TokenKindFloat = TokenKind('f') TokenKindString = TokenKind('s') TokenKindSymbol = TokenKind('S') TokenKindBoolean = TokenKind('b') TokenKindNil = TokenKind('N') TokenKindWord = TokenKind('w') TokenKindType = TokenKind('t') TokenKindGet = TokenKind('$') TokenKindSet = TokenKind('=') TokenKindOpenBlock = TokenKind('{') TokenKindCloseBlock = TokenKind('}') TokenKindOpenList = TokenKind('[') TokenKindCloseList = TokenKind(']') TokenKindOpenParen = TokenKind('(') TokenKindCloseParen = TokenKind(')') TokenKindError = TokenKind('!') TokenKindEOX = TokenKind('\n') TokenKindEOF = TokenKind(0x255) ) /* Names of the different token types. */ var TokenKindNames map[TokenKind]string = map[TokenKind]string{ TokenKindNone: "None", TokenKindInteger: "Integer", TokenKindFloat: "Float", TokenKindSymbol: "Symbol", TokenKindString: "String", TokenKindBoolean: "Boolean", TokenKindNil: "Nil", TokenKindWord: "Word", TokenKindType: "Type", TokenKindGet: "Get", TokenKindSet: "Set", TokenKindOpenBlock: "OpenBlock", TokenKindCloseBlock: "CloseBlock", TokenKindOpenList: "OpenList", TokenKindCloseList: "CloseList", TokenKindOpenParen: "OpenParen", TokenKindCloseParen: "CloseParen", TokenKindError: "Error", TokenKindEOX: "EOX", TokenKindEOF: "EOF", } /* Transforms a token kind to a String */ func (kind TokenKind) String() string { name, ok := TokenKindNames[kind] if !ok { return "Unknown TokenKind!" } return name } type Token struct { TokenKind Value Position } func (token Token) String() string { if token.Value == nil { return fmt.Sprintf("%s:%s:nil", token.Position.String(), token.TokenKind.String()) } return fmt.Sprintf("%s:%s:%v", token.Position.String(), token.TokenKind.String(), token.Value) } func (token Token) Error() string { if token.TokenKind == TokenKindError { return token.Value.String() } return "No error" } /* Returns whether or not the token is the last to be expected, * that is either an error or EOF. */ func (token Token) IsLast() bool { switch token.TokenKind { case TokenKindError, TokenKindEOF, TokenKindNone: return true default: return false } } /* Creates a new token. */ func NewToken(kind TokenKind, val Value, pos Position) Token { return Token{kind, val, pos} } /* Creates a token with type TokenTypeNone */ func NoToken() Token { return NewToken(TokenKindNone, NilValue, Position{}) } func (token Token) IsNone() bool { return token.TokenKind == TokenKindNone } func (token Token) IsError() bool { return token.TokenKind == TokenKindError }