Mako/parser/token.go
2025-06-11 00:23:50 -05:00

141 lines
2.0 KiB
Go

package parser
// TokenType represents the type of a token
type TokenType int
const (
// Literals
IDENT TokenType = iota
NUMBER
STRING
TRUE
FALSE
NIL
// Operators
ASSIGN // =
PLUS // +
MINUS // -
STAR // *
SLASH // /
DOT // .
// Comparison operators
EQ // ==
NOT_EQ // !=
LT // <
GT // >
LT_EQ // <=
GT_EQ // >=
// Logical operators
AND // and
OR // or
NOT // not
// Delimiters
LPAREN // (
RPAREN // )
LBRACE // {
RBRACE // }
LBRACKET // [
RBRACKET // ]
COMMA // ,
ELLIPSIS // ...
// Keywords
IF
THEN
ELSEIF
ELSE
END
ECHO
FOR
WHILE
IN
DO
BREAK
EXIT
FN
RETURN
// Special
EOF
ILLEGAL
)
// Token represents a single token
type Token struct {
Type TokenType
Literal string
Line int
Column int
}
// Precedence levels for Pratt parsing
type Precedence int
const (
_ Precedence = iota
LOWEST
PREC_OR // or
PREC_AND // and
EQUALS // ==, !=
LESSGREATER // >, <, >=, <=
SUM // +, -
PRODUCT // *, /
PREFIX // -x, not x
MEMBER // table[key], table.key
CALL // function()
)
// precedences maps token types to their precedence levels
var precedences = map[TokenType]Precedence{
OR: PREC_OR,
AND: PREC_AND,
EQ: EQUALS,
NOT_EQ: EQUALS,
LT: LESSGREATER,
GT: LESSGREATER,
LT_EQ: LESSGREATER,
GT_EQ: LESSGREATER,
PLUS: SUM,
MINUS: SUM,
SLASH: PRODUCT,
STAR: PRODUCT,
DOT: MEMBER,
LBRACKET: MEMBER,
LPAREN: CALL,
}
// lookupIdent checks if an identifier is a keyword
func lookupIdent(ident string) TokenType {
keywords := map[string]TokenType{
"true": TRUE,
"false": FALSE,
"nil": NIL,
"and": AND,
"or": OR,
"not": NOT,
"if": IF,
"then": THEN,
"elseif": ELSEIF,
"else": ELSE,
"end": END,
"echo": ECHO,
"for": FOR,
"while": WHILE,
"in": IN,
"do": DO,
"break": BREAK,
"exit": EXIT,
"fn": FN,
"return": RETURN,
}
if tok, ok := keywords[ident]; ok {
return tok
}
return IDENT
}