blob: 5e15443449ee6ade9f95d7237b5c52f389d0a2f5 [file] [log] [blame]
// Copyright 2018 The CUE Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Package token defines constants representing the lexical tokens of the Go
// programming language and basic operations on tokens (printing, predicates).
package token // import "cuelang.org/go/cue/token"
import "strconv"
// Token is the set of lexical tokens of the CUE configuration language.
type Token int
// The list of tokens.
const (
// Special tokens
ILLEGAL Token = iota
EOF
COMMENT
ATTRIBUTE // @foo(bar,baz=4)
literalBeg
// Identifiers and basic type literals
// (these tokens stand for classes of literals)
IDENT // main, _tmp
INT // 12_345Mi, 0700, 0xdeadbeef, 1.2M
FLOAT // 123.45,
// DURATION // 3m4s TODO
STRING // "abc"
INTERPOLATION // a part of a template string, e.g. `"age: \(`
BOTTOM // _|_
literalEnd
operatorBeg
// Operators and delimiters
ADD // +
SUB // -
MUL // *
POW // ^
QUO // /
IQUO // quo
IREM // rem
IDIV // div
IMOD // mod
AND // &
OR // |
LAND // &&
LOR // ||
BIND // =
EQL // ==
LSS // <
GTR // >
NOT // !
ARROW // <-
NEQ // !=
LEQ // <=
GEQ // >=
MAT // =~
NMAT // !~
LPAREN // (
LBRACK // [
LBRACE // {
COMMA // ,
PERIOD // .
ELLIPSIS // ...
RPAREN // )
RBRACK // ]
RBRACE // }
SEMICOLON // ;
COLON // :
ISA // ::
OPTION // ?
operatorEnd
keywordBeg
IF
FOR
IN
LET
TRUE
FALSE
NULL
keywordEnd
)
var tokens = [...]string{
ILLEGAL: "ILLEGAL",
EOF: "EOF",
COMMENT: "COMMENT",
IDENT: "IDENT",
INT: "INT",
FLOAT: "FLOAT",
STRING: "STRING",
INTERPOLATION: "INTERPOLATION",
ATTRIBUTE: "ATTRIBUTE",
ADD: "+",
SUB: "-",
MUL: "*",
POW: "^",
QUO: "/",
IQUO: "quo",
IREM: "rem",
IDIV: "div",
IMOD: "mod",
AND: "&",
OR: "|",
LAND: "&&",
LOR: "||",
BIND: "=",
EQL: "==",
LSS: "<",
GTR: ">",
NOT: "!",
ARROW: "<-",
NEQ: "!=",
LEQ: "<=",
GEQ: ">=",
MAT: "=~",
NMAT: "!~",
LPAREN: "(",
LBRACK: "[",
LBRACE: "{",
COMMA: ",",
PERIOD: ".",
ELLIPSIS: "...",
RPAREN: ")",
RBRACK: "]",
RBRACE: "}",
SEMICOLON: ";",
COLON: ":",
ISA: "::",
OPTION: "?",
BOTTOM: "_|_",
FALSE: "false",
TRUE: "true",
NULL: "null",
FOR: "for",
IF: "if",
IN: "in",
LET: "let",
}
// 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 {
s := ""
if 0 <= tok && tok < Token(len(tokens)) {
s = tokens[tok]
}
if s == "" {
s = "token(" + strconv.Itoa(int(tok)) + ")"
}
return s
}
// 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 serves as "catch-all" precedence for selector,
// indexing, and other operator and delimiter tokens.
const (
LowestPrec = lowestPrec
UnaryPrec = unaryPrec
HighestPrec = highestPrec
)
const (
lowestPrec = 0 // non-operators
unaryPrec = 8
highestPrec = 9
)
// Precedence returns the operator precedence of the binary
// operator op. If op is not a binary operator, the result
// is LowestPrecedence.
//
func (tok Token) Precedence() int {
switch tok {
case OR:
return 1
case AND:
return 2
case LOR:
return 3
case LAND:
return 4
case EQL, NEQ, LSS, LEQ, GTR, GEQ, MAT, NMAT:
return 5
case ADD, SUB:
return 6
case MUL, QUO, IDIV, IMOD, IQUO, IREM:
return 7
}
return lowestPrec
}
var keywords map[string]Token
func init() {
keywords = make(map[string]Token)
for i := keywordBeg + 1; i < keywordEnd; i++ {
keywords[tokens[i]] = i
}
}
// Lookup maps an identifier to its keyword token or IDENT (if not a keyword).
//
func Lookup(ident string) Token {
if tok, isKeyword := keywords[ident]; isKeyword {
return tok
}
return IDENT
}
// Predicates
// IsLiteral returns true for tokens corresponding to identifiers
// and basic type literals; it returns false otherwise.
func (tok Token) IsLiteral() bool { return literalBeg < tok && tok < literalEnd }
// IsOperator returns true for tokens corresponding to operators and
// delimiters; it returns false otherwise.
func (tok Token) IsOperator() bool { return operatorBeg < tok && tok < operatorEnd }
// IsKeyword returns true for tokens corresponding to keywords;
// it returns false otherwise.
func (tok Token) IsKeyword() bool { return keywordBeg < tok && tok < keywordEnd }