I'm working on a parsing application and I have to deal with both terminal and
non-terminal nodes in the model. The terminal nodes (tokens) can have values of
different types, expressed as an object variant:
type
TokenKind = enum
IntegerNumber,
FloatNumber,
StringToken,
Plus,
Minus,
Multiply,
Divide,
#...
Location = object
line : int
column : int
TokenValue = object
case kind: TokenKind
of FloatNumber: floatValue: float64
of StringToken: stringValue: string
else: intValue: int64
Token = ref object of RootObj
text: string
value: TokenValue
Run
But the non-terminal nodes also have a "kind-of", for example
type
ASTNode = ref object of RootObj
kind: TokenKind # could be Plus, Minus, etc.
startpos: Location
endpos: Location
# ...
BinaryNode = ref object of ASTNode
lhs, rhs: ASTNode
Run
I'd like to unify `ASTNode` and `Token` so that `Token` inherits from
`ASTNode`, but the `kind` is already "embedded" in the `TokenValue`. To unify
the two things, does that mean that storage for `kind` would be duplicated (one
in the `ASTNode`, one in the `TokenValue`), or is there some way of avoiding
this by somehow disconnecting the discriminator field from the discriminated
fields?