d9aceeac6e
- Add syntax - Desugars to if-else chain in HIR lowering (both compilers) - No new HIR/C backend nodes needed — reuses hIf/hBinary/hBlock - Supports integer, char, and enum tag dispatch - Case body can be single statement (no braces required)
352 lines
8.8 KiB
Nim
352 lines
8.8 KiB
Nim
import source_location
|
|
|
|
type
|
|
TokenKind* = enum
|
|
##Literals
|
|
tkIntLiteral # 42 0xFF 0b1010 0o77
|
|
tkFloatLiteral # 3.14 1.0e-9
|
|
tkStringLiteral # "hello" c8"hello" c16"hello" c32"hello" `raw multi-line`
|
|
tkCharLiteral # 'A' c8'A' c16'A' c32'A'
|
|
tkBoolLiteral # true false
|
|
|
|
##Identifiers
|
|
tkIdent # foo Bar _x
|
|
tkUnderscore # _
|
|
|
|
##Control flow keywords
|
|
tkIf # if
|
|
tkElse # else
|
|
tkWhile # while
|
|
tkDo # do
|
|
tkLoop # loop
|
|
tkFor # for
|
|
tkIn # in
|
|
tkBreak # break
|
|
tkContinue # continue
|
|
tkReturn # return
|
|
tkMatch # match
|
|
tkSwitch # switch
|
|
tkCase # case
|
|
tkDefault # default
|
|
|
|
##Declaration keywords
|
|
tkFunc # func
|
|
tkLet # let
|
|
tkVar # var
|
|
tkConst # const
|
|
tkType # type
|
|
tkStruct # struct
|
|
tkEnum # enum
|
|
tkUnion # union
|
|
tkInterface # interface
|
|
tkExtend # extend
|
|
tkModule # module
|
|
tkImport # import
|
|
tkPub # pub
|
|
tkExtern # extern
|
|
|
|
##Other keywords
|
|
tkAs # as
|
|
tkIs # is
|
|
tkNull # null
|
|
tkSelf # self
|
|
tkSuper # super
|
|
tkSizeOf # sizeof
|
|
tkOwn # own (gradual ownership transfer)
|
|
tkMut # mut (mutable reference)
|
|
tkBorrow # borrow (explicit borrow expression)
|
|
tkDiscard # discard (evaluate and throw away)
|
|
tkAsync # async
|
|
tkAwait # await
|
|
tkSpawn # spawn
|
|
tkStaticAssert # static_assert
|
|
tkComptime # comptime
|
|
tkDyn # dyn
|
|
tkDefer # defer
|
|
tkLifetime # 'a (lifetime parameter)
|
|
|
|
##Punctuation
|
|
tkLParen # (
|
|
tkRParen # )
|
|
tkLBrace # {
|
|
tkRBrace # }
|
|
tkLBracket # [
|
|
tkRBracket # ]
|
|
tkComma # ,
|
|
tkSemicolon # ;
|
|
tkColon # :
|
|
tkColonColon # ::
|
|
tkDot # .
|
|
tkDotDot # ..
|
|
tkDotDotDot # ...
|
|
tkDotDotEqual # ..=
|
|
tkArrow # ->
|
|
tkFatArrow # =>
|
|
tkAt # @
|
|
tkHash # #
|
|
tkQuestion # ?
|
|
|
|
##Arithmetic operators
|
|
tkPlus # +
|
|
tkMinus # -
|
|
tkStar # *
|
|
tkSlash # /
|
|
tkPercent # %
|
|
tkStarStar # **
|
|
tkPlusPlus # ++
|
|
tkMinusMinus # --
|
|
|
|
##Bitwise operators
|
|
tkAmp # &
|
|
tkPipe # |
|
|
tkCaret # ^
|
|
tkTilde # ~
|
|
tkShl # <<
|
|
tkShr # >>
|
|
|
|
##Logical operators
|
|
tkAmpAmp # &&
|
|
tkPipePipe # ||
|
|
tkBang # !
|
|
|
|
##Comparison operators
|
|
tkEq # ==
|
|
tkNe # !=
|
|
tkLt # <
|
|
tkLe # <=
|
|
tkGt # >
|
|
tkGe # >=
|
|
|
|
##Assignment operators
|
|
tkAssign # =
|
|
tkPlusAssign # +=
|
|
tkMinusAssign # -=
|
|
tkStarAssign # *=
|
|
tkSlashAssign # /=
|
|
tkPercentAssign # %=
|
|
tkAmpAssign # &=
|
|
tkPipeAssign # |=
|
|
tkCaretAssign # ^=
|
|
tkShlAssign # <<=
|
|
tkShrAssign # >>=
|
|
|
|
##Compile-time intrinsics
|
|
tkHashLine # #line
|
|
tkHashColumn # #column
|
|
tkHashFile # #file
|
|
tkHashFunction # #function
|
|
tkHashDate # #date
|
|
tkHashTime # #time
|
|
tkHashModule # #module
|
|
tkHashEmit # #emit
|
|
|
|
##Special
|
|
tkNewLine # significant newline (if grammar uses them)
|
|
tkEndOfFile # end of file
|
|
tkUnknown # unrecognized character
|
|
|
|
Token* = object
|
|
kind*: TokenKind
|
|
text*: string # original source spelling
|
|
loc*: SourceLocation
|
|
|
|
proc isKeyword*(kind: TokenKind): bool =
|
|
case kind
|
|
of tkIf, tkElse, tkWhile, tkDo, tkLoop, tkFor, tkIn,
|
|
tkBreak, tkContinue, tkReturn, tkMatch, tkSwitch, tkCase, tkDefault,
|
|
tkFunc, tkLet, tkVar, tkConst, tkType, tkStruct, tkEnum,
|
|
tkUnion, tkInterface, tkExtend, tkModule, tkImport,
|
|
tkPub, tkExtern, tkAs, tkIs, tkNull, tkSelf, tkSuper, tkOwn, tkMut, tkBorrow, tkDiscard, tkAsync, tkAwait, tkSpawn, tkStaticAssert, tkComptime, tkDyn, tkDefer:
|
|
true
|
|
else:
|
|
false
|
|
|
|
proc isLiteral*(kind: TokenKind): bool =
|
|
case kind
|
|
of tkIntLiteral, tkFloatLiteral, tkStringLiteral, tkCharLiteral, tkBoolLiteral:
|
|
true
|
|
else:
|
|
false
|
|
|
|
proc isOperator*(kind: TokenKind): bool =
|
|
case kind
|
|
of tkPlus..tkShrAssign:
|
|
true
|
|
else:
|
|
false
|
|
|
|
proc isEof*(kind: TokenKind): bool = kind == tkEndOfFile
|
|
|
|
proc keywordKind*(text: string): TokenKind =
|
|
case text
|
|
of "func": tkFunc
|
|
of "let": tkLet
|
|
of "var": tkVar
|
|
of "const": tkConst
|
|
of "type": tkType
|
|
of "struct": tkStruct
|
|
of "enum": tkEnum
|
|
of "union": tkUnion
|
|
of "interface": tkInterface
|
|
of "extend": tkExtend
|
|
of "module": tkModule
|
|
of "import": tkImport
|
|
of "pub": tkPub
|
|
of "extern": tkExtern
|
|
of "if": tkIf
|
|
of "else": tkElse
|
|
of "while": tkWhile
|
|
of "do": tkDo
|
|
of "loop": tkLoop
|
|
of "for": tkFor
|
|
of "in": tkIn
|
|
of "break": tkBreak
|
|
of "continue": tkContinue
|
|
of "return": tkReturn
|
|
of "match": tkMatch
|
|
of "switch": tkSwitch
|
|
of "case": tkCase
|
|
of "default": tkDefault
|
|
of "as": tkAs
|
|
of "is": tkIs
|
|
of "null": tkNull
|
|
of "self": tkSelf
|
|
of "super": tkSuper
|
|
of "sizeof": tkSizeOf
|
|
of "own": tkOwn
|
|
of "mut": tkMut
|
|
of "borrow": tkBorrow
|
|
of "discard": tkDiscard
|
|
of "async": tkAsync
|
|
of "await": tkAwait
|
|
of "spawn": tkSpawn
|
|
of "static_assert": tkStaticAssert
|
|
of "comptime": tkComptime
|
|
of "dyn": tkDyn
|
|
of "defer": tkDefer
|
|
of "true", "false": tkBoolLiteral
|
|
else: tkIdent
|
|
|
|
proc tokenKindName*(kind: TokenKind): string =
|
|
case kind
|
|
of tkIntLiteral: "integer literal"
|
|
of tkFloatLiteral: "float literal"
|
|
of tkStringLiteral: "string literal"
|
|
of tkCharLiteral: "char literal"
|
|
of tkBoolLiteral: "boolean literal"
|
|
of tkIdent: "identifier"
|
|
of tkUnderscore: "'_'"
|
|
of tkSizeOf: "'sizeof'"
|
|
of tkIf: "'if'"
|
|
of tkElse: "'else'"
|
|
of tkWhile: "'while'"
|
|
of tkDo: "'do'"
|
|
of tkLoop: "'loop'"
|
|
of tkFor: "'for'"
|
|
of tkIn: "'in'"
|
|
of tkBreak: "'break'"
|
|
of tkContinue: "'continue'"
|
|
of tkReturn: "'return'"
|
|
of tkMatch: "'match'"
|
|
of tkSwitch: "'switch'"
|
|
of tkCase: "'case'"
|
|
of tkDefault: "'default'"
|
|
of tkFunc: "'func'"
|
|
of tkLet: "'let'"
|
|
of tkVar: "'var'"
|
|
of tkConst: "'const'"
|
|
of tkType: "'type'"
|
|
of tkStruct: "'struct'"
|
|
of tkEnum: "'enum'"
|
|
of tkUnion: "'union'"
|
|
of tkInterface: "'interface'"
|
|
of tkExtend: "'extend'"
|
|
of tkModule: "'module'"
|
|
of tkImport: "'import'"
|
|
of tkPub: "'pub'"
|
|
of tkExtern: "'extern'"
|
|
of tkAs: "'as'"
|
|
of tkIs: "'is'"
|
|
of tkNull: "'null'"
|
|
of tkSelf: "'self'"
|
|
of tkSuper: "'super'"
|
|
of tkOwn: "'own'"
|
|
of tkMut: "'mut'"
|
|
of tkBorrow: "'borrow'"
|
|
of tkDiscard: "'discard'"
|
|
of tkAsync: "'async'"
|
|
of tkAwait: "'await'"
|
|
of tkSpawn: "'spawn'"
|
|
of tkStaticAssert: "'static_assert'"
|
|
of tkComptime: "'comptime'"
|
|
of tkDyn: "'dyn'"
|
|
of tkDefer: "'defer'"
|
|
of tkLifetime: "lifetime"
|
|
of tkLParen: "'('"
|
|
of tkRParen: "')'"
|
|
of tkLBrace: "'{'"
|
|
of tkRBrace: "'}'"
|
|
of tkLBracket: "'['"
|
|
of tkRBracket: "']'"
|
|
of tkComma: "','"
|
|
of tkSemicolon: "';'"
|
|
of tkColon: "':'"
|
|
of tkColonColon: "'::'"
|
|
of tkDot: "'.'"
|
|
of tkDotDot: "'..'"
|
|
of tkDotDotDot: "'...'"
|
|
of tkDotDotEqual: "'..='"
|
|
of tkArrow: "'->'"
|
|
of tkFatArrow: "'=>'"
|
|
of tkAt: "'@'"
|
|
of tkHash: "'#'"
|
|
of tkQuestion: "'?'"
|
|
of tkPlus: "'+'"
|
|
of tkMinus: "'-'"
|
|
of tkStar: "'*'"
|
|
of tkSlash: "'/'"
|
|
of tkPercent: "'%'"
|
|
of tkStarStar: "'**'"
|
|
of tkPlusPlus: "'++'"
|
|
of tkMinusMinus: "'--'"
|
|
of tkAmp: "'&'"
|
|
of tkPipe: "'|'"
|
|
of tkCaret: "'^'"
|
|
of tkTilde: "'~'"
|
|
of tkShl: "'<<'"
|
|
of tkShr: "'>>'"
|
|
of tkAmpAmp: "'&&'"
|
|
of tkPipePipe: "'||'"
|
|
of tkBang: "'!'"
|
|
of tkEq: "'=='"
|
|
of tkNe: "'!='"
|
|
of tkLt: "'<'"
|
|
of tkLe: "'<='"
|
|
of tkGt: "'>'"
|
|
of tkGe: "'>='"
|
|
of tkAssign: "'='"
|
|
of tkPlusAssign: "'+='"
|
|
of tkMinusAssign: "'-='"
|
|
of tkStarAssign: "'*='"
|
|
of tkSlashAssign: "'/='"
|
|
of tkPercentAssign: "'%='"
|
|
of tkAmpAssign: "'&='"
|
|
of tkPipeAssign: "'|='"
|
|
of tkCaretAssign: "'^='"
|
|
of tkShlAssign: "'<<='"
|
|
of tkShrAssign: "'>>='"
|
|
of tkHashLine: "'#line'"
|
|
of tkHashColumn: "'#column'"
|
|
of tkHashFile: "'#file'"
|
|
of tkHashFunction: "'#function'"
|
|
of tkHashDate: "'#date'"
|
|
of tkHashTime: "'#time'"
|
|
of tkHashModule: "'#module'"
|
|
of tkHashEmit: "'#emit'"
|
|
of tkNewLine: "newline"
|
|
of tkEndOfFile: "end of file"
|
|
of tkUnknown: "unknown token"
|
|
|
|
proc `$`*(tok: Token): string =
|
|
result = tokenKindName(tok.kind) & " '" & tok.text & "' @ " & $tok.loc
|