diff options
| author | Miquel Sabaté Solà <mikisabate@gmail.com> | 2025-01-15 08:05:06 +0100 |
|---|---|---|
| committer | Miquel Sabaté Solà <mikisabate@gmail.com> | 2025-01-15 08:05:06 +0100 |
| commit | b6f2d3f8bf503efde672f4bb1a34e2ee8f985c38 (patch) | |
| tree | f57c0dd7270c812d698d1f196f8b036028189d32 | |
| parent | e9564ef4324b1740c8e9306d59162e39fb62f9d2 (diff) | |
| download | tools.nes-b6f2d3f8bf503efde672f4bb1a34e2ee8f985c38.tar.gz tools.nes-b6f2d3f8bf503efde672f4bb1a34e2ee8f985c38.zip | |
Parse a string literal as a single object
Before this it was left to the `parse_identifier` to figure things out,
but this was prone to silly errors like "a: b", in which it would
mistake it as the start of a label. Instead of any of this, just consume
a string literal if it has been detected.
Signed-off-by: Miquel Sabaté Solà <mikisabate@gmail.com>
| -rw-r--r-- | lib/xixanta/src/parser.rs | 47 |
1 files changed, 47 insertions, 0 deletions
diff --git a/lib/xixanta/src/parser.rs b/lib/xixanta/src/parser.rs index eb06040..5a46daf 100644 --- a/lib/xixanta/src/parser.rs +++ b/lib/xixanta/src/parser.rs @@ -896,6 +896,36 @@ impl Parser { // And return what you can parse from the inner expression. self.offset = 0; return self.parse_expression(l); + } else if first == '"' { + let start = self.offset; + let start_column = self.column; + self.next(); + + let mut prev = '"'; + + for ch in line.get(self.offset..).unwrap_or("").chars() { + if ch == '"' && prev != '\\' { + self.next(); + + return Ok(PNode { + node_type: NodeType::Literal, + value: PString { + value: line.get(start..self.offset).unwrap().to_string(), + line: self.line, + start: start_column, + end: self.column, + }, + left: None, + right: None, + args: None, + source: self.current_source, + }); + } + + self.next(); + prev = ch; + } + return Err(self.parser_error("unclosed string")); } else if let Some(node_type) = self.get_unary_from_line(line) { // This is a unary operation. Just parse the right side and return // early. @@ -1524,6 +1554,23 @@ mod tests { } } + #[test] + fn parse_string() { + let mut parser = Parser::default(); + let line = ".asciiz \"a: b\""; + + assert!(parser.parse(line.as_bytes(), SourceInfo::default()).is_ok()); + + let stmt = parser.nodes.last().unwrap().last().unwrap(); + let inner = stmt.args.as_ref().unwrap().first().clone().unwrap(); + assert_eq!(inner.node_type, NodeType::Literal); + assert_eq!(inner.value.value, "\"a: b\""); + assert_eq!( + line.get(inner.value.start..inner.value.end).unwrap(), + "\"a: b\"" + ); + } + // Regular instructions. #[test] |
