Add misses-rt crate, component example, README, and fix codegen for non-keyword literal tokens
- misses-rt: add Buffer/Markup HTML helpers, name/type helpers, parse_sections/parse_kv, and template AST - codegen: add is_syn_keyword() — non-keyword idents in patterns now generate parse+compare instead of syn::Token![…] - parser: split punct vs ident chars in literal pattern tokens so `props:` becomes two tokens - examples: add component.mrs/.rs demonstrating named literal tokens and tt capture - README: comprehensive guide covering .mrs syntax, running the compiler, misses-rt helpers, and examples https://claude.ai/code/session_01Tppkab4eLsL21asHGjQJoF
This commit is contained in:
@@ -170,13 +170,20 @@ fn codegen_parser_stmts(pattern: &Pattern) -> Vec<String> {
|
||||
} else if tok == "}" {
|
||||
// already consumed by braced!
|
||||
in_brace = false;
|
||||
} else if tok.chars().all(|c| c.is_alphanumeric() || c == '_') {
|
||||
stmts.push(format!(
|
||||
"_input.parse::<syn::Token![{tok}]>()?;",
|
||||
tok = tok
|
||||
));
|
||||
} else if tok == "," {
|
||||
stmts.push("_input.parse::<syn::Token![,]>()?;".to_string());
|
||||
} else if tok.chars().all(|c| c.is_alphanumeric() || c == '_') {
|
||||
if is_syn_keyword(tok) {
|
||||
stmts.push(format!(
|
||||
"_input.parse::<syn::Token![{tok}]>()?;",
|
||||
tok = tok
|
||||
));
|
||||
} else {
|
||||
stmts.push(format!(
|
||||
r#"{{ let __lit: syn::Ident = _input.parse()?; if __lit != "{tok}" {{ return Err(syn::Error::new(__lit.span(), concat!("expected `", "{tok}", "`"))); }} }}"#,
|
||||
tok = tok
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
PatternItem::Binding { name, kind } => {
|
||||
@@ -213,6 +220,22 @@ fn codegen_parser_stmts(pattern: &Pattern) -> Vec<String> {
|
||||
stmts
|
||||
}
|
||||
|
||||
/// Returns true if `tok` is a valid operand for `syn::Token![...]`.
|
||||
/// This covers Rust keywords and built-in punctuation recognized by syn.
|
||||
fn is_syn_keyword(tok: &str) -> bool {
|
||||
matches!(
|
||||
tok,
|
||||
"as" | "async" | "await" | "break" | "const" | "continue" | "crate"
|
||||
| "dyn" | "else" | "enum" | "extern" | "false" | "fn" | "for"
|
||||
| "if" | "impl" | "in" | "let" | "loop" | "match" | "mod"
|
||||
| "move" | "mut" | "pub" | "ref" | "return" | "self" | "Self"
|
||||
| "static" | "struct" | "super" | "trait" | "true" | "type"
|
||||
| "union" | "unsafe" | "use" | "where" | "while" | "abstract"
|
||||
| "become" | "box" | "do" | "final" | "macro" | "override"
|
||||
| "priv" | "try" | "typeof" | "unsized" | "virtual" | "yield"
|
||||
)
|
||||
}
|
||||
|
||||
/// Generate code for the output body
|
||||
fn codegen_output_body(body: &OutputBody) -> String {
|
||||
let mut out = String::new();
|
||||
|
||||
Reference in New Issue
Block a user