feat: hint at unterminated strings in unknown prefix errors

When encountering 'unknown literal prefix' errors, check for unbalanced
quotes in recent code and suggest checking for unterminated string literals.
diff --git a/crates/parser/src/lexed_str.rs b/crates/parser/src/lexed_str.rs
index 8fff1c3..dcf3971 100644
--- a/crates/parser/src/lexed_str.rs
+++ b/crates/parser/src/lexed_str.rs
@@ -149,6 +149,24 @@
         }
     }
 
+    /// Check for likely unterminated string by analyzing STRING token content
+    fn has_likely_unterminated_string(&self) -> bool {
+        let Some(last_idx) = self.res.kind.len().checked_sub(1) else { return false };
+
+        for i in (0..=last_idx).rev().take(5) {
+            if self.res.kind[i] == STRING {
+                let start = self.res.start[i] as usize;
+                let end = self.res.start.get(i + 1).map(|&s| s as usize).unwrap_or(self.offset);
+                let content = &self.res.text[start..end];
+
+                if content.contains('(') && (content.contains("//") || content.contains(";\n")) {
+                    return true;
+                }
+            }
+        }
+        false
+    }
+
     fn finalize_with_eof(mut self) -> LexedStr<'a> {
         self.res.push(EOF, self.offset);
         self.res
@@ -267,7 +285,17 @@
                 rustc_lexer::TokenKind::Unknown => ERROR,
                 rustc_lexer::TokenKind::UnknownPrefix if token_text == "builtin" => IDENT,
                 rustc_lexer::TokenKind::UnknownPrefix => {
-                    errors.push("unknown literal prefix".into());
+                    let has_unterminated = self.has_likely_unterminated_string();
+
+                    let error_msg = if has_unterminated {
+                        format!(
+                            "unknown literal prefix `{}` (note: check for unterminated string literal)",
+                            token_text
+                        )
+                    } else {
+                        "unknown literal prefix".to_owned()
+                    };
+                    errors.push(error_msg);
                     IDENT
                 }
                 rustc_lexer::TokenKind::Eof => EOF,
diff --git a/crates/parser/test_data/lexer/err/unterminated_string_unknown_prefix.rast b/crates/parser/test_data/lexer/err/unterminated_string_unknown_prefix.rast
new file mode 100644
index 0000000..f7f24ca
--- /dev/null
+++ b/crates/parser/test_data/lexer/err/unterminated_string_unknown_prefix.rast
@@ -0,0 +1,15 @@
+FN_KW "fn"
+WHITESPACE " "
+IDENT "main"
+L_PAREN "("
+R_PAREN ")"
+WHITESPACE " "
+L_CURLY "{"
+WHITESPACE "\n    "
+IDENT "hello"
+L_PAREN "("
+STRING "\"world);\n    // a bunch of code was here\n    env(\"FLAGS"
+STRING "\", \""
+MINUS "-"
+IDENT "help" error: unknown literal prefix `help` (note: check for unterminated string literal)
+STRING "\")\n}" error: Missing trailing `"` symbol to terminate the string literal
diff --git a/crates/parser/test_data/lexer/err/unterminated_string_unknown_prefix.rs b/crates/parser/test_data/lexer/err/unterminated_string_unknown_prefix.rs
new file mode 100644
index 0000000..338b958
--- /dev/null
+++ b/crates/parser/test_data/lexer/err/unterminated_string_unknown_prefix.rs
@@ -0,0 +1,5 @@
+fn main() {
+    hello("world);
+    // a bunch of code was here
+    env("FLAGS", "-help")
+}
\ No newline at end of file