diff options
Diffstat (limited to 'lib/xixanta/src/parser.rs')
| -rw-r--r-- | lib/xixanta/src/parser.rs | 43 |
1 files changed, 43 insertions, 0 deletions
diff --git a/lib/xixanta/src/parser.rs b/lib/xixanta/src/parser.rs index 19b4530..d2bb75b 100644 --- a/lib/xixanta/src/parser.rs +++ b/lib/xixanta/src/parser.rs @@ -634,6 +634,24 @@ impl Parser { // and the offset has been set accordingly). Returns a new node for the // expression at hand. fn parse_expression(&mut self, line: &str) -> Result<PNode, ParseError> { + let first = line.chars().next().unwrap_or_default(); + + if first == '(' { + // Skip '(' character and whitespace characters in between. + self.next(); + self.skip_whitespace(line); + + // Extract what's inside of the enclosing parenthesis. + let paren = self.find_matching_paren(line, self.offset)?; + let l = line.get(self.offset..paren).unwrap_or_default(); + + // And return what you can parse from the inner expression. + self.offset = 0; + return self.parse_expression(l); + } + + // There's no complex expression going on. Hence, we can try to parse an + // "identifier" and pass it along. let (id, nt) = self.parse_identifier(line)?; if nt == NodeType::Label { @@ -1024,6 +1042,31 @@ mod tests { } #[test] + fn parse_paren_expression() { + let line = "ldx #(Variable)"; + let mut parser = Parser::default(); + assert!(parser.parse(line.as_bytes()).is_ok()); + + let instr = parser.nodes.last().unwrap(); + assert_eq!(instr.node_type, NodeType::Instruction); + assert!(instr.right.is_none()); + assert!(instr.args.is_none()); + + let node = instr.left.clone().unwrap(); + assert_eq!(node.node_type, NodeType::Literal); + assert!(node.right.is_none()); + assert!(node.args.is_none()); + + let inner = node.left.clone().unwrap(); + assert_eq!(inner.node_type, NodeType::Value); + assert_eq!(inner.value.value, "Variable"); + assert_eq!( + line.get(inner.value.start..inner.value.end).unwrap(), + "Variable" + ); + } + + #[test] fn parse_bad_literals() { for line in vec!["#", "#%", "$"].into_iter() { let mut parser = Parser::default(); |
