// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// This package defines constants representing the lexical
// tokens of the Go programming language and basic operations
// on tokens (printing, predicates).
//
package token
import (
"fmt";
"strconv";
)
// Token is the set of lexical tokens of the Go programming language.
type Token int
// The list of tokens.
const (
// Special tokens
ILLEGAL Token = iota;
EOF;
COMMENT;
literal_beg;
// Identifiers and basic type literals
// (these tokens stand for classes of literals)
IDENT; // main
INT; // 12345
FLOAT; // 123.45
CHAR; // 'a'
STRING; // "abc"
literal_end;
operator_beg;
// Operators and delimiters
ADD; // +
SUB; // -
MUL; // *
QUO; // /
REM; // %
AND; // &
OR; // |
XOR; // ^
SHL; // <<
SHR; // >>
AND_NOT; // &^
ADD_ASSIGN; // +=
SUB_ASSIGN; // -=
MUL_ASSIGN; // *=
QUO_ASSIGN; // /=
REM_ASSIGN; // %=
AND_ASSIGN; // &=
OR_ASSIGN; // |=
XOR_ASSIGN; // ^=
SHL_ASSIGN; // <<=
SHR_ASSIGN; // >>=
AND_NOT_ASSIGN; // &^=
LAND; // &&
LOR; // ||
ARROW; // <-
INC; // ++
DEC; // --
EQL; // ==
LSS; // <
GTR; // >
ASSIGN; // =
NOT; // !
NEQ; // !=
LEQ; // <=
GEQ; // >=
DEFINE; // :=
ELLIPSIS; // ...
LPAREN; // (
LBRACK; // [
LBRACE; // {
COMMA; // ,
PERIOD; // .
RPAREN; // )
RBRACK; // ]
RBRACE; // }
SEMICOLON; // ;
COLON; // :
operator_end;
keyword_beg;
// Keywords
BREAK;
CASE;
CHAN;
CONST;
CONTINUE;
DEFAULT;
DEFER;
ELSE;
FALLTHROUGH;
FOR;
FUNC;
GO;
GOTO;
IF;
IMPORT;
INTERFACE;
MAP;
PACKAGE;
RANGE;
RETURN;
SELECT;
STRUCT;
SWITCH;
TYPE;
VAR;
keyword_end;
)
// At the moment we have no array literal syntax that lets us describe
// the index for each element - use a map for now to make sure they are
// in sync.
var tokens = map[Token]string{
ILLEGAL: "ILLEGAL",
EOF: "EOF",
COMMENT: "COMMENT",
IDENT: "IDENT",
INT: "INT",
FLOAT: "FLOAT",
CHAR: "CHAR",
STRING: "STRING",
ADD: "+",
SUB: "-",
MUL: "*",
QUO: "/",
REM: "%",
AND: "&",
OR: "|",
XOR: "^",
SHL: "<<",
SHR: ">>",
AND_NOT: "&^",
ADD_ASSIGN: "+=",
SUB_ASSIGN: "-=",
MUL_ASSIGN: "*=",
QUO_ASSIGN: "/=",
REM_ASSIGN: "%=",
AND_ASSIGN: "&=",
OR_ASSIGN: "|=",
XOR_ASSIGN: "^=",
SHL_ASSIGN: "<<=",
SHR_ASSIGN: ">>=",
AND_NOT_ASSIGN: "&^=",
LAND: "&&",
LOR: "||",
ARROW: "<-",
INC: "++",
DEC: "--",
EQL: "==",
LSS: "<",
GTR: ">",
ASSIGN: "=",
NOT: "!",
NEQ: "!=",
LEQ: "<=",
GEQ: ">=",
DEFINE: ":=",
ELLIPSIS: "...",
LPAREN: "(",
LBRACK: "[",
LBRACE: "{",
COMMA: ",",
PERIOD: ".",
RPAREN: ")",
RBRACK: "]",
RBRACE: "}",
SEMICOLON: ";",
COLON: ":",
BREAK: "break",
CASE: "case",
CHAN: "chan",
CONST: "const",
CONTINUE: "continue",
DEFAULT: "default",
DEFER: "defer",
ELSE: "else",
FALLTHROUGH: "fallthrough",
FOR: "for",
FUNC: "func",
GO: "go",
GOTO: "goto",
IF: "if",
IMPORT: "import",
INTERFACE: "interface",
MAP: "map",
PACKAGE: "package",
RANGE: "range",
RETURN: "return",
SELECT: "select",
STRUCT: "struct",
SWITCH: "switch",
TYPE: "type",
VAR: "var",
}
// String returns the string corresponding to the token tok.
// For operators, delimiters, and keywords the string is the actual
// token character sequence (e.g., for the token ADD, the string is
// "+"). For all other tokens the string corresponds to the token
// constant name (e.g. for the token IDENT, the string is "IDENT").
//
func (tok Token) String() string {
if str, exists := tokens[tok]; exists {
return str
}
return "token(" + strconv.Itoa(int(tok)) + ")";
}
// A set of constants for precedence-based expression parsing.
// Non-operators have lowest precedence, followed by operators
// starting with precedence 1 up to unary operators. The highest
// precedence corresponds serves as "catch-all" precedence for
// selector, indexing, and other operator and delimiter tokens.
//
const (
LowestPrec = 0; // non-operators
UnaryPrec = 7;
HighestPrec = 8;
)
// Precedence returns the operator precedence of the binary
// operator op. If op is not a binary operator, the result
// is LowestPrecedence.
//
func (op Token) Precedence() int {
switch op {
case LOR:
return 1
case LAND:
return 2
case ARROW:
return 3
case EQL, NEQ, LSS, LEQ, GTR, GEQ:
return 4
case ADD, SUB, OR, XOR:
return 5
case MUL, QUO, REM, SHL, SHR, AND, AND_NOT:
return 6
}
return LowestPrec;
}
var keywords map[string]Token
func init() {
keywords = make(map[string]Token);
for i := keyword_beg + 1; i < keyword_end; i++ {
keywords[tokens[i]] = i
}
}
// Lookup maps an identifier to its keyword token or IDENT (if not a keyword).
//
func Lookup(ident []byte) Token {
// TODO Maps with []byte key are illegal because []byte does not
// support == . Should find a more efficient solution eventually.
if tok, is_keyword := keywords[string(ident)]; is_keyword {
return tok
}
return IDENT;
}
// Predicates
// IsLiteral returns true for tokens corresponding to identifiers
// and basic type literals; returns false otherwise.
//
func (tok Token) IsLiteral() bool { return literal_beg < tok && tok < literal_end }
// IsOperator returns true for tokens corresponding to operators and
// delimiters; returns false otherwise.
//
func (tok Token) IsOperator() bool { return operator_beg < tok && tok < operator_end }
// IsKeyword returns true for tokens corresponding to keywords;
// returns false otherwise.
//
func (tok Token) IsKeyword() bool { return keyword_beg < tok && tok < keyword_end }
// Token source positions are represented by a Position value.
// A Position is valid if the line number is > 0.
//
type Position struct {
Filename string; // filename, if any
Offset int; // byte offset, starting at 0
Line int; // line number, starting at 1
Column int; // column number, starting at 1 (character count)
}
// Pos is an accessor method for anonymous Position fields.
// It returns its receiver.
//
func (pos *Position) Pos() Position { return *pos }
// IsValid returns true if the position is valid.
func (pos *Position) IsValid() bool { return pos.Line > 0 }
func (pos Position) String() string {
s := pos.Filename;
if pos.IsValid() {
if s != "" {
s += ":"
}
s += fmt.Sprintf("%d:%d", pos.Line, pos.Column);
}
if s == "" {
s = "???"
}
return s;
}
|