1// Copyright 2009 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5// Package token defines constants representing the lexical tokens of the Go
6// programming language and basic operations on tokens (printing, predicates).
7//
8package token
9
10import "strconv"
11
12// Token is the set of lexical tokens of the Go programming language.
13type Token int
14
15// The list of tokens.
16const (
17	// Special tokens
18	ILLEGAL Token = iota
19	EOF
20	COMMENT
21
22	literal_beg
23	// Identifiers and basic type literals
24	// (these tokens stand for classes of literals)
25	IDENT  // main
26	INT    // 12345
27	FLOAT  // 123.45
28	IMAG   // 123.45i
29	CHAR   // 'a'
30	STRING // "abc"
31	literal_end
32
33	operator_beg
34	// Operators and delimiters
35	ADD // +
36	SUB // -
37	MUL // *
38	QUO // /
39	REM // %
40
41	AND     // &
42	OR      // |
43	XOR     // ^
44	SHL     // <<
45	SHR     // >>
46	AND_NOT // &^
47
48	ADD_ASSIGN // +=
49	SUB_ASSIGN // -=
50	MUL_ASSIGN // *=
51	QUO_ASSIGN // /=
52	REM_ASSIGN // %=
53
54	AND_ASSIGN     // &=
55	OR_ASSIGN      // |=
56	XOR_ASSIGN     // ^=
57	SHL_ASSIGN     // <<=
58	SHR_ASSIGN     // >>=
59	AND_NOT_ASSIGN // &^=
60
61	LAND  // &&
62	LOR   // ||
63	ARROW // <-
64	INC   // ++
65	DEC   // --
66
67	EQL    // ==
68	LSS    // <
69	GTR    // >
70	ASSIGN // =
71	NOT    // !
72
73	NEQ      // !=
74	LEQ      // <=
75	GEQ      // >=
76	DEFINE   // :=
77	ELLIPSIS // ...
78
79	LPAREN // (
80	LBRACK // [
81	LBRACE // {
82	COMMA  // ,
83	PERIOD // .
84
85	RPAREN    // )
86	RBRACK    // ]
87	RBRACE    // }
88	SEMICOLON // ;
89	COLON     // :
90	operator_end
91
92	keyword_beg
93	// Keywords
94	BREAK
95	CASE
96	CHAN
97	CONST
98	CONTINUE
99
100	DEFAULT
101	DEFER
102	ELSE
103	FALLTHROUGH
104	FOR
105
106	FUNC
107	GO
108	GOTO
109	IF
110	IMPORT
111
112	INTERFACE
113	MAP
114	PACKAGE
115	RANGE
116	RETURN
117
118	SELECT
119	STRUCT
120	SWITCH
121	TYPE
122	VAR
123	keyword_end
124)
125
126var tokens = [...]string{
127	ILLEGAL: "ILLEGAL",
128
129	EOF:     "EOF",
130	COMMENT: "COMMENT",
131
132	IDENT:  "IDENT",
133	INT:    "INT",
134	FLOAT:  "FLOAT",
135	IMAG:   "IMAG",
136	CHAR:   "CHAR",
137	STRING: "STRING",
138
139	ADD: "+",
140	SUB: "-",
141	MUL: "*",
142	QUO: "/",
143	REM: "%",
144
145	AND:     "&",
146	OR:      "|",
147	XOR:     "^",
148	SHL:     "<<",
149	SHR:     ">>",
150	AND_NOT: "&^",
151
152	ADD_ASSIGN: "+=",
153	SUB_ASSIGN: "-=",
154	MUL_ASSIGN: "*=",
155	QUO_ASSIGN: "/=",
156	REM_ASSIGN: "%=",
157
158	AND_ASSIGN:     "&=",
159	OR_ASSIGN:      "|=",
160	XOR_ASSIGN:     "^=",
161	SHL_ASSIGN:     "<<=",
162	SHR_ASSIGN:     ">>=",
163	AND_NOT_ASSIGN: "&^=",
164
165	LAND:  "&&",
166	LOR:   "||",
167	ARROW: "<-",
168	INC:   "++",
169	DEC:   "--",
170
171	EQL:    "==",
172	LSS:    "<",
173	GTR:    ">",
174	ASSIGN: "=",
175	NOT:    "!",
176
177	NEQ:      "!=",
178	LEQ:      "<=",
179	GEQ:      ">=",
180	DEFINE:   ":=",
181	ELLIPSIS: "...",
182
183	LPAREN: "(",
184	LBRACK: "[",
185	LBRACE: "{",
186	COMMA:  ",",
187	PERIOD: ".",
188
189	RPAREN:    ")",
190	RBRACK:    "]",
191	RBRACE:    "}",
192	SEMICOLON: ";",
193	COLON:     ":",
194
195	BREAK:    "break",
196	CASE:     "case",
197	CHAN:     "chan",
198	CONST:    "const",
199	CONTINUE: "continue",
200
201	DEFAULT:     "default",
202	DEFER:       "defer",
203	ELSE:        "else",
204	FALLTHROUGH: "fallthrough",
205	FOR:         "for",
206
207	FUNC:   "func",
208	GO:     "go",
209	GOTO:   "goto",
210	IF:     "if",
211	IMPORT: "import",
212
213	INTERFACE: "interface",
214	MAP:       "map",
215	PACKAGE:   "package",
216	RANGE:     "range",
217	RETURN:    "return",
218
219	SELECT: "select",
220	STRUCT: "struct",
221	SWITCH: "switch",
222	TYPE:   "type",
223	VAR:    "var",
224}
225
226// String returns the string corresponding to the token tok.
227// For operators, delimiters, and keywords the string is the actual
228// token character sequence (e.g., for the token ADD, the string is
229// "+"). For all other tokens the string corresponds to the token
230// constant name (e.g. for the token IDENT, the string is "IDENT").
231//
232func (tok Token) String() string {
233	s := ""
234	if 0 <= tok && tok < Token(len(tokens)) {
235		s = tokens[tok]
236	}
237	if s == "" {
238		s = "token(" + strconv.Itoa(int(tok)) + ")"
239	}
240	return s
241}
242
243// A set of constants for precedence-based expression parsing.
244// Non-operators have lowest precedence, followed by operators
245// starting with precedence 1 up to unary operators. The highest
246// precedence serves as "catch-all" precedence for selector,
247// indexing, and other operator and delimiter tokens.
248//
249const (
250	LowestPrec  = 0 // non-operators
251	UnaryPrec   = 6
252	HighestPrec = 7
253)
254
255// Precedence returns the operator precedence of the binary
256// operator op. If op is not a binary operator, the result
257// is LowestPrecedence.
258//
259func (op Token) Precedence() int {
260	switch op {
261	case LOR:
262		return 1
263	case LAND:
264		return 2
265	case EQL, NEQ, LSS, LEQ, GTR, GEQ:
266		return 3
267	case ADD, SUB, OR, XOR:
268		return 4
269	case MUL, QUO, REM, SHL, SHR, AND, AND_NOT:
270		return 5
271	}
272	return LowestPrec
273}
274
275var keywords map[string]Token
276
277func init() {
278	keywords = make(map[string]Token)
279	for i := keyword_beg + 1; i < keyword_end; i++ {
280		keywords[tokens[i]] = i
281	}
282}
283
284// Lookup maps an identifier to its keyword token or IDENT (if not a keyword).
285//
286func Lookup(ident string) Token {
287	if tok, is_keyword := keywords[ident]; is_keyword {
288		return tok
289	}
290	return IDENT
291}
292
293// Predicates
294
295// IsLiteral returns true for tokens corresponding to identifiers
296// and basic type literals; it returns false otherwise.
297//
298func (tok Token) IsLiteral() bool { return literal_beg < tok && tok < literal_end }
299
300// IsOperator returns true for tokens corresponding to operators and
301// delimiters; it returns false otherwise.
302//
303func (tok Token) IsOperator() bool { return operator_beg < tok && tok < operator_end }
304
305// IsKeyword returns true for tokens corresponding to keywords;
306// it returns false otherwise.
307//
308func (tok Token) IsKeyword() bool { return keyword_beg < tok && tok < keyword_end }
309