113 lines
2.5 KiB
Plaintext
113 lines
2.5 KiB
Plaintext
#! GRAMMAR:
|
|
#! * type ..... -> identifier
|
|
#! * assignment -> :: | :=
|
|
#! * literal .. -> int | float | string
|
|
#! * expr ..... -> identifier | literal
|
|
#! * decl ..... -> identifier [type] assignment expr
|
|
#! * stmt ..... -> decl
|
|
|
|
import "@std/debug"
|
|
import "@source/lexer"
|
|
|
|
@hide:file
|
|
TokenId :: alias lexer.TokenId
|
|
|
|
@hide:file
|
|
NO_TOKEN :: alias lexer.NO_TOKEN
|
|
|
|
NodeId :: distinct u32
|
|
ExtraId :: distinct u32
|
|
|
|
NO_NODE :: maxval!(NodeId)
|
|
NO_EXTRA :: maxval!(ExtraId)
|
|
|
|
# unsafe access on its own; NodeKind serves as a the tag
|
|
# that determines the variant.
|
|
NodeData :: union {
|
|
token_id TokenId
|
|
node_id NodeId
|
|
extra_id ExtraId
|
|
}
|
|
|
|
Node :: struct {
|
|
kind NodeKind
|
|
main_token TokenId = NO_TOKEN
|
|
|
|
data0 NodeData = NodeData{ node_id = NO_NODE }
|
|
data1 NodeData = NodeData{ node_id = NO_NODE }
|
|
}
|
|
|
|
NodeKind :: enum {
|
|
# LITERALS:
|
|
# * main_token: token literal
|
|
literal_int
|
|
literal_float
|
|
literal_string
|
|
|
|
# IDENTIFIER EXPR:
|
|
# * main_token: token literal
|
|
expr_identifier
|
|
|
|
# UNARY:
|
|
# * main_token: operator
|
|
# * data0: NodeId - expression
|
|
expr_unary
|
|
|
|
# BINARY:
|
|
# * main_token: operator
|
|
# * data0: NodeId - left-hand side
|
|
# * data1: NodeId - right-hand side
|
|
expr_binary
|
|
|
|
# STATEMENT DECLS:
|
|
# * main_token: symbol name (identifier)
|
|
# * data0: ExtraId
|
|
# + extra[data0]: NodeId - type expr or NO_NODE
|
|
# + extra[data0 + 1]: NodeId - initializer expression
|
|
# * data1: TokenId of either `::` or `:=` indicating mutability
|
|
stmt_decl
|
|
|
|
# FUNC DECLS:
|
|
# * main_token: function name (identifier)
|
|
# * data0: NodeId - body block (or NO_NODE for extern)
|
|
# * data1: ExtraId
|
|
# + extra[data1]: NodeId - return type
|
|
# + extra[data1 + 1]: u32 - param count
|
|
# + extra[data1 + 2..]: NodeId - param decls
|
|
func_decl
|
|
|
|
# PARAM DECLS:
|
|
# * main_token: param name (identifier)
|
|
# * data0: NodeId - param type
|
|
param_decl
|
|
|
|
# BLOCK:
|
|
# * data0: ExtraId - statement range start
|
|
# * data1: ExtraId - statement range end
|
|
block
|
|
|
|
# PACKAGE:
|
|
# * data0: ExtraId
|
|
# * data1: ExtraId
|
|
#
|
|
# extra[data0..data1]: NodeId - all statement node ids in package
|
|
package
|
|
|
|
invalid
|
|
}
|
|
|
|
node_id proc(idx uint) NodeId {
|
|
debug.assert(u64(idx) < u64(NO_NODE))
|
|
return NodeId(idx)
|
|
}
|
|
|
|
maybe_node_id proc(idx uint) ?NodeId {
|
|
if (u64(idx) >= u64(NO_NODE)) return null
|
|
return NodeId(idx)
|
|
}
|
|
|
|
extra_id proc(idx uint) ExtraId {
|
|
debug.assert(u64(idx) < u64(NO_EXTRA))
|
|
return ExtraId(idx)
|
|
}
|