summaryrefslogtreecommitdiff
path: root/src/tokens/semantic.rs
blob: ac5179c76a0e37527e55e829a50ad9ac4bfbe80b (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
use crate::*;

use SemanticTokenVariant as SemVar;


pub struct SemanticToken {
    pub source: SourceSpan,
    pub bytecode: BytecodeSpan,
    pub variant: SemanticTokenVariant,
}


pub enum SemanticTokenVariant {
    LabelDefinition(LabelDefinition),
    MacroDefinition(MacroDefinition),

    /// Pointer to the matching label definition.
    LabelReference(usize),
    /// Pointer to the matching macro definition.
    MacroInvocation(usize),

    Literal(Value),
    Padding(Value),
    Instruction(Instruction),

    Comment(String),
    String(Vec<u8>),

    /// Pointer to the matching block close.
    BlockOpen(usize),
    /// Pointer to the matching block open.
    BlockClose(usize),
    MarkOpen,
    MarkClose,

    Error(SemanticParseError),
}

impl std::fmt::Debug for SemanticToken {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
        match &self.variant {
            SemVar::LabelDefinition(def) => write!(f, "LabelDefinition({})", def.name),
            SemVar::MacroDefinition(def) => write!(f, "MacroDefinition({})", def.name),
            SemVar::LabelReference(pointer) => write!(f, "LabelReference(*{pointer})"),
            SemVar::MacroInvocation(pointer) => write!(f, "MacroInvocation(*{pointer})"),
            SemVar::Literal(value) => write!(f, "Literal({value})"),
            SemVar::Padding(value) => write!(f, "Padding({value})"),
            SemVar::Instruction(instr) => write!(f, "Instruction(0x{:02x})", instr.value),
            SemVar::Comment(comment) => write!(f, "Comment({comment})"),
            SemVar::String(string) => write!(f, "String({})", String::from_utf8_lossy(&string)),
            SemVar::BlockOpen(_) => write!(f, "BlockOpen"),
            SemVar::BlockClose(_) => write!(f, "BlockClose"),
            SemVar::MarkOpen => write!(f, "MarkOpen"),
            SemVar::MarkClose => write!(f, "MarkClose"),
            SemVar::Error(_) => write!(f, "Error"),
        }
    }
}


pub struct LabelDefinition {
    /// The absolute name of the label or sublabel.
    pub name: String,
    /// List of pointers to label reference tokens.
    pub references: Vec<usize>,
}


pub struct MacroDefinition {
    pub name: String,
    pub references: Vec<usize>,
    pub body_tokens: Vec<SemanticToken>,
}


pub enum SemanticParseError {
    LabelDefinitionInMacroDefinition,
    MacroDefinitionInMacroDefinition,

    StrayMacroTerminator,
    StrayBlockClose,
    UnclosedBlock,

    UndefinedSymbol(String),
    RedefinedSymbol((String, SourceSpan)),

    MacroInvocationBeforeDefinition((String, SourceSpan)),

    SyntaxError(SyntacticParseError)
}