147 lines
2.1 KiB
Go
147 lines
2.1 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 // /
|
|
MOD // %
|
|
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 // ...
|
|
COLON // :
|
|
|
|
// Keywords
|
|
IF
|
|
THEN
|
|
ELSEIF
|
|
ELSE
|
|
END
|
|
ECHO
|
|
FOR
|
|
WHILE
|
|
IN
|
|
DO
|
|
BREAK
|
|
EXIT
|
|
FN
|
|
RETURN
|
|
STRUCT
|
|
|
|
// 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,
|
|
MOD: PRODUCT,
|
|
DOT: MEMBER,
|
|
LBRACKET: MEMBER,
|
|
LPAREN: CALL,
|
|
LBRACE: 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,
|
|
"struct": STRUCT,
|
|
}
|
|
|
|
if tok, ok := keywords[ident]; ok {
|
|
return tok
|
|
}
|
|
return IDENT
|
|
}
|