Compare commits
2 Commits
a86a1736ec
...
64ff6a12ca
Author | SHA1 | Date |
---|---|---|
Nocturn9x | 64ff6a12ca | |
Nocturn9x | 79af16ccc9 |
|
@ -383,7 +383,7 @@ proc literal(self: Compiler, node: ASTNode) =
|
|||
self.emitBytes(y.keys.len().toTriple())
|
||||
of awaitExpr:
|
||||
var y = AwaitExpr(node)
|
||||
self.expression(y.awaitee)
|
||||
self.expression(y.expression)
|
||||
self.emitByte(OpCode.Await)
|
||||
else:
|
||||
self.error(&"invalid AST node of kind {node.kind} at literal(): {node} (This is an internal error and most likely a bug)")
|
||||
|
@ -417,9 +417,9 @@ proc binary(self: Compiler, node: BinaryExpr) =
|
|||
self.emitByte(BinaryAdd)
|
||||
of Minus:
|
||||
self.emitByte(BinarySubtract)
|
||||
of Asterisk:
|
||||
of Star:
|
||||
self.emitByte(BinaryMultiply)
|
||||
of DoubleAsterisk:
|
||||
of DoubleStar:
|
||||
self.emitByte(BinaryPow)
|
||||
of Percentage:
|
||||
self.emitByte(BinaryMod)
|
||||
|
@ -497,7 +497,7 @@ proc declareName(self: Compiler, node: ASTNode) =
|
|||
self.error("cannot declare more than 16777215 static variables at a time")
|
||||
self.names.add(Name(depth: self.scopeDepth, name: IdentExpr(node.name),
|
||||
isPrivate: node.isPrivate,
|
||||
owner: node.owner,
|
||||
owner: "",
|
||||
isConst: node.isConst))
|
||||
self.emitByte(StoreFast)
|
||||
self.emitBytes(self.names.high().toTriple())
|
||||
|
@ -514,7 +514,7 @@ proc declareName(self: Compiler, node: ASTNode) =
|
|||
for argument in node.arguments:
|
||||
if self.names.high() > 16777215:
|
||||
self.error("cannot declare more than 16777215 static variables at a time")
|
||||
self.names.add(Name(depth: self.scopeDepth + 1, isPrivate: true, owner: self.currentModule, isConst: false, name: IdentExpr(argument)))
|
||||
self.names.add(Name(depth: self.scopeDepth + 1, isPrivate: true, owner: self.currentModule, isConst: false, name: IdentExpr(argument.name)))
|
||||
self.emitByte(LoadFast)
|
||||
self.emitBytes(self.names.high().toTriple())
|
||||
self.scopeDepth -= 1
|
||||
|
@ -542,14 +542,6 @@ proc resolveStatic(self: Compiler, name: IdentExpr,
|
|||
return nil
|
||||
|
||||
|
||||
proc deleteStatic(self: Compiler, name: IdentExpr) =
|
||||
## Traverses self.staticNames backwards and deletes the
|
||||
## a name object with the given name. Does nothing when
|
||||
## the name can't be found
|
||||
for i, obj in reversed(self.names):
|
||||
if obj.name.token.lexeme == name.token.lexeme:
|
||||
self.names.del(i)
|
||||
|
||||
|
||||
proc getStaticIndex(self: Compiler, name: IdentExpr, depth: int = self.scopeDepth): int =
|
||||
## Gets the predicted stack position of the given variable
|
||||
|
@ -796,24 +788,6 @@ proc expression(self: Compiler, node: ASTNode) =
|
|||
self.error(&"invalid AST node of kind {node.kind} at expression(): {node} (This is an internal error and most likely a bug)")
|
||||
|
||||
|
||||
proc delStmt(self: Compiler, node: ASTNode) =
|
||||
## Compiles del statements, which unbind
|
||||
## a name from the current scope
|
||||
case node.kind:
|
||||
of identExpr:
|
||||
var node = IdentExpr(node)
|
||||
let i = self.getStaticIndex(node)
|
||||
if i != -1:
|
||||
self.emitByte(DeleteFast)
|
||||
self.emitBytes(i.toTriple())
|
||||
self.deleteStatic(node)
|
||||
else:
|
||||
self.emitByte(DeleteName)
|
||||
self.emitBytes(self.identifierConstant(node))
|
||||
else:
|
||||
discard # The parser already handles the other cases
|
||||
|
||||
|
||||
proc awaitStmt(self: Compiler, node: AwaitStmt) =
|
||||
## Compiles await statements. An await statement
|
||||
## is like an await expression, but parsed in the
|
||||
|
@ -824,7 +798,7 @@ proc awaitStmt(self: Compiler, node: AwaitStmt) =
|
|||
## run coroutines from within an already asynchronous
|
||||
## loop (which should be orchestrated by an event loop).
|
||||
## They block in the caller until the callee returns
|
||||
self.expression(node.awaitee)
|
||||
self.expression(node.expression)
|
||||
self.emitByte(OpCode.Await)
|
||||
|
||||
|
||||
|
@ -833,7 +807,7 @@ proc deferStmt(self: Compiler, node: DeferStmt) =
|
|||
## is executed right before the function exits
|
||||
## (either because of a return or an exception)
|
||||
let current = self.chunk.code.len
|
||||
self.expression(node.deferred)
|
||||
self.expression(node.expression)
|
||||
for i in countup(current, self.chunk.code.high()):
|
||||
self.deferred.add(self.chunk.code[i])
|
||||
self.chunk.code.del(i)
|
||||
|
@ -908,8 +882,6 @@ proc statement(self: Compiler, node: ASTNode) =
|
|||
self.emitByte(Pop) # Expression statements discard their value. Their main use case is side effects in function calls
|
||||
of NodeKind.ifStmt:
|
||||
self.ifStmt(IfStmt(node))
|
||||
of NodeKind.delStmt:
|
||||
self.delStmt(DelStmt(node).name)
|
||||
of NodeKind.assertStmt:
|
||||
self.assertStmt(AssertStmt(node))
|
||||
of NodeKind.raiseStmt:
|
||||
|
@ -922,8 +894,6 @@ proc statement(self: Compiler, node: ASTNode) =
|
|||
self.returnStmt(ReturnStmt(node))
|
||||
of NodeKind.importStmt:
|
||||
discard
|
||||
of NodeKind.fromImportStmt:
|
||||
discard
|
||||
of NodeKind.whileStmt, NodeKind.forStmt:
|
||||
## Our parser already desugars for loops to
|
||||
## while loops!
|
||||
|
@ -1006,12 +976,6 @@ proc funDecl(self: Compiler, node: FunDecl) =
|
|||
self.currentFunction = function
|
||||
|
||||
|
||||
proc classDecl(self: Compiler, node: ClassDecl) =
|
||||
## Compiles class declarations
|
||||
self.declareName(node.name)
|
||||
self.emitByte(MakeClass)
|
||||
self.blockStmt(BlockStmt(node.body))
|
||||
|
||||
|
||||
proc declaration(self: Compiler, node: ASTNode) =
|
||||
## Compiles all declarations
|
||||
|
@ -1020,8 +984,6 @@ proc declaration(self: Compiler, node: ASTNode) =
|
|||
self.varDecl(VarDecl(node))
|
||||
of NodeKind.funDecl:
|
||||
self.funDecl(FunDecl(node))
|
||||
of NodeKind.classDecl:
|
||||
self.classDecl(ClassDecl(node))
|
||||
else:
|
||||
self.statement(node)
|
||||
|
||||
|
@ -1045,4 +1007,4 @@ proc compile*(self: Compiler, ast: seq[ASTNode], file: string): Chunk =
|
|||
self.emitByte(OpCode.Return) # Exits the VM's main loop when used at the global scope
|
||||
result = self.chunk
|
||||
if self.ast.len() > 0 and self.scopeDepth != -1:
|
||||
self.error(&"internal error: invalid scopeDepth state (expected -1, got {self.scopeDepth}), did you forget to call endScope/beginScope?")
|
||||
self.error(&"invalid state: invalid scopeDepth value (expected -1, got {self.scopeDepth}), did you forget to call endScope/beginScope?")
|
||||
|
|
|
@ -161,18 +161,18 @@ type
|
|||
# Simple instructions encompass:
|
||||
# - Instructions that push onto/pop off the stack unconditionally (True, False, Pop, etc.)
|
||||
# - Unary and binary operators
|
||||
const simpleInstructions* = {Return, BinaryAdd, BinaryMultiply,
|
||||
const simpleInstructions* = {OpCode.Return, BinaryAdd, BinaryMultiply,
|
||||
BinaryDivide, BinarySubtract,
|
||||
BinaryMod, BinaryPow, Nil,
|
||||
True, False, OpCode.Nan, OpCode.Inf,
|
||||
BinaryMod, BinaryPow, OpCode.Nil,
|
||||
OpCode.True, OpCode.False, OpCode.Nan, OpCode.Inf,
|
||||
BinaryShiftLeft, BinaryShiftRight,
|
||||
BinaryXor, LogicalNot, EqualTo,
|
||||
GreaterThan, LessThan, LoadAttribute,
|
||||
BinaryXor, OpCode.LogicalNot, EqualTo,
|
||||
OpCode.GreaterThan, OpCode.LessThan, LoadAttribute,
|
||||
BinarySlice, Pop, UnaryNegate,
|
||||
BinaryIs, BinaryAs, GreaterOrEqual,
|
||||
LessOrEqual, BinaryOr, BinaryAnd,
|
||||
UnaryNot, BinaryFloorDiv, BinaryOf, Raise,
|
||||
ReRaise, BeginTry, FinishTry, Yield, Await,
|
||||
BinaryIs, BinaryAs, OpCode.GreaterOrEqual,
|
||||
OpCode.LessOrEqual, BinaryOr, BinaryAnd,
|
||||
UnaryNot, BinaryFloorDiv, BinaryOf, OpCode.Raise,
|
||||
ReRaise, BeginTry, FinishTry, OpCode.Yield, OpCode.Await,
|
||||
MakeClass, ImplicitReturn}
|
||||
|
||||
# Constant instructions are instructions that operate on the bytecode constant table
|
||||
|
|
|
@ -177,11 +177,11 @@ proc optimizeBinary(self: Optimizer, node: BinaryExpr): ASTNode =
|
|||
z = x + y
|
||||
of Minus:
|
||||
z = x - y
|
||||
of Asterisk:
|
||||
of Star:
|
||||
z = x * y
|
||||
of FloorDiv:
|
||||
z = int(x / y)
|
||||
of DoubleAsterisk:
|
||||
of DoubleStar:
|
||||
if y >= 0:
|
||||
z = x ^ y
|
||||
else:
|
||||
|
@ -232,11 +232,11 @@ proc optimizeBinary(self: Optimizer, node: BinaryExpr): ASTNode =
|
|||
z = x + y
|
||||
of Minus:
|
||||
z = x - y
|
||||
of Asterisk:
|
||||
of Star:
|
||||
z = x * y
|
||||
of FloorDiv, Slash:
|
||||
z = x / y
|
||||
of DoubleAsterisk:
|
||||
of DoubleStar:
|
||||
z = pow(x, y)
|
||||
of Percentage:
|
||||
z = x mod y
|
||||
|
@ -260,7 +260,7 @@ proc optimizeBinary(self: Optimizer, node: BinaryExpr): ASTNode =
|
|||
var bb: int
|
||||
assert parseInt(b.literal.lexeme, bb) == b.literal.lexeme.len()
|
||||
case node.operator.kind:
|
||||
of Asterisk:
|
||||
of Star:
|
||||
result = StrExpr(kind: strExpr, literal: Token(kind: String, lexeme: "'" & a.literal.lexeme[1..<(^1)].repeat(bb) & "'"))
|
||||
else:
|
||||
result = node
|
||||
|
@ -270,7 +270,7 @@ proc optimizeBinary(self: Optimizer, node: BinaryExpr): ASTNode =
|
|||
var aa: int
|
||||
assert parseInt(a.literal.lexeme, aa) == a.literal.lexeme.len()
|
||||
case node.operator.kind:
|
||||
of Asterisk:
|
||||
of Star:
|
||||
result = StrExpr(kind: strExpr, literal: Token(kind: String, lexeme: "'" & b.literal.lexeme[1..<(^1)].repeat(aa) & "'"))
|
||||
else:
|
||||
result = node
|
||||
|
@ -290,12 +290,11 @@ proc detectClosures(self: Optimizer, node: FunDecl) =
|
|||
names.add(VarDecl(line))
|
||||
of funDecl:
|
||||
names.add(FunDecl(line))
|
||||
of classDecl:
|
||||
names.add(ClassDecl(line))
|
||||
else:
|
||||
discard
|
||||
for name in names:
|
||||
|
||||
discard
|
||||
|
||||
|
||||
proc optimizeNode(self: Optimizer, node: ASTNode): ASTNode =
|
||||
## Analyzes an AST node and attempts to perform
|
||||
|
@ -327,7 +326,7 @@ proc optimizeNode(self: Optimizer, node: ASTNode): ASTNode =
|
|||
var node = SliceExpr(node)
|
||||
for i, e in node.ends:
|
||||
node.ends[i] = self.optimizeNode(e)
|
||||
node.slicee = self.optimizeNode(node.slicee)
|
||||
node.expression = self.optimizeNode(node.expression)
|
||||
result = node
|
||||
of tryStmt:
|
||||
var node = TryStmt(node)
|
||||
|
|
|
@ -77,8 +77,12 @@ proc newParser*(): Parser =
|
|||
result.scopeDepth = 0
|
||||
|
||||
# Public getters for improved error formatting
|
||||
proc getCurrent*(self: Parser): int = self.current
|
||||
proc getCurrentToken*(self: Parser): Token = (if self.getCurrent() >= self.tokens.len(): self.tokens[^1] else: self.tokens[self.current - 1])
|
||||
proc getCurrent*(self: Parser): int {.inline.} = self.current
|
||||
proc getCurrentToken*(self: Parser): Token =
|
||||
if self.getCurrent() >= self.tokens.high() or self.getCurrent() - 1 < 0:
|
||||
return self.tokens[^1]
|
||||
else:
|
||||
return self.tokens[self.current - 1]
|
||||
|
||||
# Handy templates to make our life easier, thanks nim!
|
||||
template endOfFile: Token = Token(kind: EndOfFile, lexeme: "", line: -1)
|
||||
|
@ -190,7 +194,8 @@ proc declaration(self: Parser): ASTNode
|
|||
proc primary(self: Parser): ASTNode =
|
||||
## Parses primary expressions such
|
||||
## as integer literals and keywords
|
||||
## that map to builtin types (true, false, etc)
|
||||
## that map to builtin types (true,
|
||||
## false, nil, etc.)
|
||||
case self.peek().kind:
|
||||
of True:
|
||||
result = newTrueExpr(self.step())
|
||||
|
@ -326,7 +331,7 @@ proc makeCall(self: Parser, callee: ASTNode): ASTNode =
|
|||
if not self.check(RightParen):
|
||||
while true:
|
||||
if argCount >= 255:
|
||||
self.error("cannot store more than 255 arguments")
|
||||
self.error("call can not have more than 255 arguments")
|
||||
break
|
||||
argument = self.expression()
|
||||
if argument.kind == assignExpr:
|
||||
|
@ -337,7 +342,7 @@ proc makeCall(self: Parser, callee: ASTNode): ASTNode =
|
|||
elif arguments.keyword.len() == 0:
|
||||
arguments.positionals.add(argument)
|
||||
else:
|
||||
self.error("positional argument(s) cannot follow keyword argument(s) in call")
|
||||
self.error("positional argument cannot follow keyword argument in call")
|
||||
if not self.match(Comma):
|
||||
break
|
||||
argCount += 1
|
||||
|
@ -879,7 +884,7 @@ proc funDecl(self: Parser, isAsync: bool = false, isGenerator: bool = false, isL
|
|||
return result
|
||||
elif isLambda:
|
||||
self.currentFunction = newLambdaExpr(arguments, defaults, newBlockStmt(@[], Token()), isGenerator=isGenerator, isAsync=isAsync, token=tok)
|
||||
else:
|
||||
elif not isOperator:
|
||||
self.error("funDecl: invalid state")
|
||||
if self.match(Colon):
|
||||
# A function without an explicit
|
||||
|
@ -913,11 +918,17 @@ proc funDecl(self: Parser, isAsync: bool = false, isGenerator: bool = false, isL
|
|||
# Function's return type
|
||||
self.expect(Identifier, "expecting return type after ':'")
|
||||
returnType = newIdentExpr(self.peek(-1))
|
||||
self.expect(LeftBrace)
|
||||
if self.currentFunction.kind == funDecl:
|
||||
if not self.match(Semicolon):
|
||||
# Forward declaration!
|
||||
# If we don't find a semicolon,
|
||||
# it's not a forward declaration
|
||||
self.expect(LeftBrace)
|
||||
FunDecl(self.currentFunction).body = self.blockStmt()
|
||||
else:
|
||||
# This is a forward declaration so we explicitly
|
||||
# nullify the function's body to tell the compiler
|
||||
# to look for it elsewhere in the file later
|
||||
FunDecl(self.currentFunction).body = nil
|
||||
FunDecl(self.currentFunction).arguments = arguments
|
||||
FunDecl(self.currentFunction).returnType = returnType
|
||||
else:
|
||||
|
@ -934,6 +945,8 @@ proc funDecl(self: Parser, isAsync: bool = false, isGenerator: bool = false, isL
|
|||
self.error("cannot declare argument-less operator")
|
||||
elif arguments.len() > 2:
|
||||
self.error("cannot declare operator with more than 2 arguments")
|
||||
elif FunDecl(result).returnType == nil:
|
||||
self.error("operator cannot have void return type")
|
||||
self.currentFunction = enclosingFunction
|
||||
|
||||
|
||||
|
@ -1047,7 +1060,7 @@ proc parse*(self: Parser, tokens: seq[Token], file: string): seq[ASTNode] =
|
|||
# ending the input with an EOF token
|
||||
if token.kind == Operator:
|
||||
if i == self.tokens.high():
|
||||
self.error("invalid state: found malformed tokenizer input while looking for operators")
|
||||
self.error("invalid state: found malformed tokenizer input while looking for operators (missing EOF)")
|
||||
elif self.tokens[i + 1].kind != Identifier:
|
||||
# The input is probably malformed,
|
||||
# we'll catch this error later
|
||||
|
|
75
src/test.nim
75
src/test.nim
|
@ -6,6 +6,9 @@ import strformat
|
|||
# Our stuff
|
||||
import frontend/lexer as l
|
||||
import frontend/parser as p
|
||||
import frontend/compiler as c
|
||||
import util/debugger
|
||||
|
||||
|
||||
# Thanks art <3
|
||||
import jale/editor as ed
|
||||
|
@ -21,12 +24,20 @@ proc fillSymbolTable(tokenizer: Lexer)
|
|||
proc getLineEditor: LineEditor
|
||||
|
||||
|
||||
const debugLexer = false
|
||||
const debugParser = true
|
||||
const debugCompiler = true
|
||||
|
||||
|
||||
when isMainModule:
|
||||
setControlCHook(proc () {.noconv.} = quit(0))
|
||||
var keep = true
|
||||
var tokens: seq[Token] = @[]
|
||||
var tree: seq[ASTNode] = @[]
|
||||
var compiled: Chunk
|
||||
var tokenizer = newLexer()
|
||||
var parser = newParser()
|
||||
var compiler = initCompiler()
|
||||
let editor = getLineEditor()
|
||||
var input: string
|
||||
editor.bindEvent(jeQuit):
|
||||
|
@ -42,18 +53,32 @@ when isMainModule:
|
|||
if input.len() > 0:
|
||||
# Currently the parser doesn't handle these tokens well
|
||||
tokens = filter(tokenizer.lex(input, "<stdin>"), proc (x: Token): bool = x.kind notin {TokenType.Whitespace, Tab})
|
||||
echo "Tokenization step:"
|
||||
for i, token in tokens:
|
||||
if i == tokens.high():
|
||||
# Who cares about EOF?
|
||||
break
|
||||
echo "\t", token
|
||||
when debugLexer:
|
||||
echo "Tokenization step:"
|
||||
for i, token in tokens:
|
||||
if i == tokens.high():
|
||||
# Who cares about EOF?
|
||||
break
|
||||
echo "\t", token
|
||||
echo ""
|
||||
tree = parser.parse(tokens, "<stdin>")
|
||||
when debugParser:
|
||||
echo "Parsing step:"
|
||||
for node in tree:
|
||||
echo "\t", node
|
||||
echo ""
|
||||
compiled = compiler.compile(tree, "<stdin>")
|
||||
when debugCompiler:
|
||||
echo "Compilation step:"
|
||||
stdout.write("\t")
|
||||
echo &"""Raw byte stream: [{compiled.code.join(", ")}]"""
|
||||
echo "\nBytecode disassembler output below:\n"
|
||||
disassembleChunk(compiled, "<stdin>")
|
||||
echo ""
|
||||
echo "Parsing step:"
|
||||
for node in parser.parse(tokens, "<stdin>"):
|
||||
echo "\t", node
|
||||
except IOError:
|
||||
break
|
||||
# TODO: The code for error reporting completely
|
||||
# breaks down with multiline input, fix it
|
||||
except LexingError:
|
||||
let lineNo = tokenizer.getLine()
|
||||
let relPos = tokenizer.getRelPos(lineNo)
|
||||
|
@ -91,8 +116,8 @@ proc fillSymbolTable(tokenizer: Lexer) =
|
|||
tokenizer.symbols.addSymbol("]", RightBracket)
|
||||
tokenizer.symbols.addSymbol(".", Dot)
|
||||
tokenizer.symbols.addSymbol(",", Comma)
|
||||
tokenizer.symbols.addSymbol(">", GreaterThan)
|
||||
tokenizer.symbols.addSymbol("<", LessThan)
|
||||
tokenizer.symbols.addSymbol(">", TokenType.GreaterThan)
|
||||
tokenizer.symbols.addSymbol("<", TokenType.LessThan)
|
||||
tokenizer.symbols.addSymbol(";", Semicolon)
|
||||
tokenizer.symbols.addSymbol("=", Equal)
|
||||
tokenizer.symbols.addSymbol("~", Tilde)
|
||||
|
@ -104,8 +129,8 @@ proc fillSymbolTable(tokenizer: Lexer) =
|
|||
# 2-byte symbols
|
||||
tokenizer.symbols.addSymbol("+=", InplaceAdd)
|
||||
tokenizer.symbols.addSymbol("-=", InplaceSub)
|
||||
tokenizer.symbols.addSymbol(">=", GreaterOrEqual)
|
||||
tokenizer.symbols.addSymbol("<=", LessOrEqual)
|
||||
tokenizer.symbols.addSymbol(">=", TokenType.GreaterOrEqual)
|
||||
tokenizer.symbols.addSymbol("<=", TokenType.LessOrEqual)
|
||||
tokenizer.symbols.addSymbol("*=", InplaceMul)
|
||||
tokenizer.symbols.addSymbol("/=", InplaceDiv)
|
||||
tokenizer.symbols.addSymbol("&=", InplaceAnd)
|
||||
|
@ -131,26 +156,26 @@ proc fillSymbolTable(tokenizer: Lexer) =
|
|||
tokenizer.symbols.addKeyword("generator", Generator)
|
||||
tokenizer.symbols.addKeyword("function", Function)
|
||||
tokenizer.symbols.addKeyword("coroutine", Coroutine)
|
||||
tokenizer.symbols.addKeyword("break", Break)
|
||||
tokenizer.symbols.addKeyword("break", TokenType.Break)
|
||||
tokenizer.symbols.addKeyword("continue", Continue)
|
||||
tokenizer.symbols.addKeyword("while", While)
|
||||
tokenizer.symbols.addKeyword("for", For)
|
||||
tokenizer.symbols.addKeyword("foreach", Foreach)
|
||||
tokenizer.symbols.addKeyword("if", If)
|
||||
tokenizer.symbols.addKeyword("else", Else)
|
||||
tokenizer.symbols.addKeyword("await", Await)
|
||||
tokenizer.symbols.addKeyword("await", TokenType.Await)
|
||||
tokenizer.symbols.addKeyword("defer", Defer)
|
||||
tokenizer.symbols.addKeyword("try", Try)
|
||||
tokenizer.symbols.addKeyword("except", Except)
|
||||
tokenizer.symbols.addKeyword("finally", Finally)
|
||||
tokenizer.symbols.addKeyword("raise", Raise)
|
||||
tokenizer.symbols.addKeyword("assert", Assert)
|
||||
tokenizer.symbols.addKeyword("raise", TokenType.Raise)
|
||||
tokenizer.symbols.addKeyword("assert", TokenType.Assert)
|
||||
tokenizer.symbols.addKeyword("const", Const)
|
||||
tokenizer.symbols.addKeyword("let", Let)
|
||||
tokenizer.symbols.addKeyword("var", Var)
|
||||
tokenizer.symbols.addKeyword("import", Import)
|
||||
tokenizer.symbols.addKeyword("yield", Yield)
|
||||
tokenizer.symbols.addKeyword("return", Return)
|
||||
tokenizer.symbols.addKeyword("yield", TokenType.Yield)
|
||||
tokenizer.symbols.addKeyword("return", TokenType.Return)
|
||||
# These are technically more like expressions
|
||||
# with a reserved name that produce a value of a
|
||||
# builtin type, but we don't need to care about
|
||||
|
@ -158,9 +183,9 @@ proc fillSymbolTable(tokenizer: Lexer) =
|
|||
# steps so it's fine
|
||||
tokenizer.symbols.addKeyword("nan", NotANumber)
|
||||
tokenizer.symbols.addKeyword("inf", Infinity)
|
||||
tokenizer.symbols.addKeyword("nil", Nil)
|
||||
tokenizer.symbols.addKeyword("true", True)
|
||||
tokenizer.symbols.addKeyword("false", False)
|
||||
tokenizer.symbols.addKeyword("nil", TokenType.Nil)
|
||||
tokenizer.symbols.addKeyword("true", TokenType.True)
|
||||
tokenizer.symbols.addKeyword("false", TokenType.False)
|
||||
# These are technically operators, but since
|
||||
# they fit neatly into the definition for an
|
||||
# identifier/keyword we parse them as such
|
||||
|
@ -169,9 +194,9 @@ proc fillSymbolTable(tokenizer: Lexer) =
|
|||
tokenizer.symbols.addKeyword("is", Is)
|
||||
tokenizer.symbols.addKeyword("as", As)
|
||||
tokenizer.symbols.addKeyword("of", Of)
|
||||
tokenizer.symbols.addKeyword("and", LogicalAnd)
|
||||
tokenizer.symbols.addKeyword("or", LogicalOr)
|
||||
tokenizer.symbols.addKeyword("not", LogicalNot)
|
||||
tokenizer.symbols.addKeyword("and", TokenType.LogicalAnd)
|
||||
tokenizer.symbols.addKeyword("or", TokenType.LogicalOr)
|
||||
tokenizer.symbols.addKeyword("not", TokenType.LogicalNot)
|
||||
|
||||
# P.S.: There's no reason for the order of addition of
|
||||
# symbols to be ascending in length (the symbol table uses
|
||||
|
|
Loading…
Reference in New Issue