diff options
| author | Miquel Sabaté Solà <mikisabate@gmail.com> | 2025-01-04 17:12:11 +0100 |
|---|---|---|
| committer | Miquel Sabaté Solà <mikisabate@gmail.com> | 2025-01-04 23:26:57 +0100 |
| commit | 1f8a6becc7cdca285333d51b4548373974df7dd3 (patch) | |
| tree | bc95144b3f31d89433b505a7998a5ad685f6af77 /lib/xixanta/src/node.rs | |
| parent | 3c8773bf8ea8a17550f50f17eb211ae1a561bfb6 (diff) | |
| download | tools.nes-1f8a6becc7cdca285333d51b4548373974df7dd3.tar.gz tools.nes-1f8a6becc7cdca285333d51b4548373974df7dd3.zip | |
parser: Implement block bodies
These are bodies which are the right node of some proc controls. This
way the parser comes back to sanity for statements like .macro and the
likes, and behaves more like a usual parser. This was not done in the
past because I thought things could have been simpler this way, but it
ended up making the assembler way more complicated that it needed to.
Signed-off-by: Miquel Sabaté Solà <mikisabate@gmail.com>
Diffstat (limited to 'lib/xixanta/src/node.rs')
| -rw-r--r-- | lib/xixanta/src/node.rs | 49 |
1 files changed, 48 insertions, 1 deletions
diff --git a/lib/xixanta/src/node.rs b/lib/xixanta/src/node.rs index 9739c9d..575b4bb 100644 --- a/lib/xixanta/src/node.rs +++ b/lib/xixanta/src/node.rs @@ -215,9 +215,14 @@ pub enum NodeType { /// the enum to detect which function was exactly provided), the `left` an /// optional identifier (e.g. the "foo" on ".proc foo"), and the `args` /// contain any possible arguments that have been passed to this control - /// statement. + /// statement. The right arm might contain the body of the control statement + /// if it has some (e.g. the body inside of a .macro declaration). Control(ControlType), + /// The body of a control statement. The only relevant info here is `args`, + /// which contain the instructions of the body. + ControlBody, + /// A literal expression, that is, something that starts with '#', '%' or /// '$'. The `left` node contains the inner expression. Literal, @@ -242,6 +247,7 @@ impl fmt::Display for NodeType { NodeType::Indirection => write!(f, "indirection"), NodeType::Assignment => write!(f, "assignment"), NodeType::Control(control_type) => write!(f, "control function ({})", control_type), + NodeType::ControlBody => write!(f, "control function body"), NodeType::Literal => write!(f, "literal"), NodeType::Label => write!(f, "label"), NodeType::Call => write!(f, "call"), @@ -265,6 +271,24 @@ impl fmt::Display for NodeType { } } +impl NodeType { + /// Returns the NodeType that closes the current one if any. + pub fn closing_type(&self) -> Option<NodeType> { + match self { + NodeType::Control(ControlType::StartMacro) => { + Some(NodeType::Control(ControlType::EndMacro)) + } + NodeType::Control(ControlType::StartProc) => { + Some(NodeType::Control(ControlType::EndProc)) + } + NodeType::Control(ControlType::StartScope) => { + Some(NodeType::Control(ControlType::EndScope)) + } + _ => None, + } + } +} + /// A Position Node. This is a node on a binary tree which holds a PString as a /// value. The node type determines the actual representation of the value and /// both childs (see the `NodeType` enum). Moreover, out of convenience, a node @@ -292,7 +316,16 @@ pub struct PNode { pub args: Option<Vec<PNode>>, } +/// Whether there is a body for a given node and whether it starts or ends it. +#[derive(Debug)] +pub enum NodeBodyType { + None, + Starts, + Ends, +} + impl PNode { + /// Returns true if the current node represents a branching instruction. pub fn is_branch(&self) -> bool { if self.node_type != NodeType::Instruction { return false; @@ -304,4 +337,18 @@ impl PNode { "bcc" | "bcs" | "beq" | "bmi" | "bne" | "bpl" | "bvc" | "bvs" ) } + + /// Returns whether the node describes a starting/ending statement or none + /// of them. + pub fn body_type(&self) -> NodeBodyType { + match self.node_type { + NodeType::Control(ControlType::StartMacro) + | NodeType::Control(ControlType::StartProc) + | NodeType::Control(ControlType::StartScope) => NodeBodyType::Starts, + NodeType::Control(ControlType::EndMacro) + | NodeType::Control(ControlType::EndProc) + | NodeType::Control(ControlType::EndScope) => NodeBodyType::Ends, + _ => NodeBodyType::None, + } + } } |
