macro_rules! definition { {@build ($n:ident structure) ($($t:tt)*) null () } => { struct $n ($($t)*); }; {@build ($n:ident enumeration new ($($f:tt)*) ($m:ident($($mt:tt)*)$($r:tt)*)) () null ()} => { definition!{@build ($n enumeration ($($f)*) ($m($($mt)*)$($r)*)) () null () $($mt)*} }; {@build ($n:ident enumeration ($($f:tt)*) ($m:ident($($mt:tt)*)$($r:tt)*)) ($($t:tt)*) null ()} => { definition!{@build ($n enumeration new ($($f)*$m($($t)*)) ($($r)*)) () null () } }; {@build ($n:ident enumeration new ($($m:ident($($mt:tt)*))*) ()) () null () } => { definition!{@build ($n enumeration filter () ($($m($($mt)*))*))} }; {@build ($n:ident enumeration filter ($($e:tt)*) ($m:ident($($mt:tt)+)$($t:tt)*))} => { definition!{@build ($n enumeration filter ($($e)*$m($($mt)*),) ($($t)*))} }; {@build ($n:ident enumeration filter ($($e:tt)*) ($m:ident()$($t:tt)*))} => { definition!{@build ($n enumeration filter ($($e)*$m,) ($($t)*))} }; {@build ($n:ident enumeration filter ($($e:tt)*) ())} => { enum $n { $($e)* } }; {@build $m:tt ($($t:tt)*) null () $l:literal $($r:tt)*} => { definition!{@build $m ($($t)*) null () $($r)*} }; {@build $m:tt ($($t:tt)*) null () $i:ident $($r:tt)*} => { definition!{@build $m ($($t)*Box<$i>,) null () $($r)*} }; {@build $m:tt ($($t:tt)*) option ($a:tt) () $($r:tt)*} => { definition!{@build $m ($($t)*Option<$a>,) null () $($r)*} }; {@build $m:tt ($($t:tt)*) vector ($a:tt) () $($r:tt)*} => { definition!{@build $m ($($t)*Vec<$a>,) null () $($r)*} }; {@build $m:tt ($($t:tt)*) option ($($a:tt)*) () $($r:tt)*} => { definition!{@build $m ($($t)*Option<($($a),*)>,) null () $($r)*} }; {@build $m:tt ($($t:tt)*) vector ($($a:tt)*) () $($r:tt)*} => { definition!{@build $m ($($t)*Vec<($($a),*)>,) null () $($r)*} }; {@build $m:tt ($($t:tt)*) null () [$($b:tt)*] $($r:tt)*} => { definition!{@build $m ($($t)*) option () ($($b)*) $($r)*} }; {@build $m:tt ($($t:tt)*) null () {$($b:tt)*} $($r:tt)*} => { definition!{@build $m ($($t)*) vector () ($($b)*) $($r)*} }; {@build $m:tt ($($t:tt)*) $i:ident ($($a:tt)*) ($l:literal $($b:tt)*) $($r:tt)*} => { definition!{@build $m ($($t)*) $i ($($a)*) ($($b)*) $($r)*} }; {@build $m:tt ($($t:tt)*) $i:ident ($($a:tt)*) ($n:ident $($b:tt)*) $($r:tt)*} => { definition!{@build $m ($($t)*) $i ($($a)*$n) ($($b)*) $($r)*} }; } macro_rules! implement { {@begin $n:ident structure $($t:tt)*} => { implement!{@build (state result) (structure $n) {} {} $($t)*} }; {@begin $n:ident enumeration ($m:ident ($($t2:tt)*)$($t:tt)*)} => { implement!{@build (state result) (enumeration $m {} ($($t)*) $n) {} {} $($t2)*} }; {@build ($st:ident $r:ident) $m:tt $f:tt {$($f2:tt)*} $s:literal $($t:tt)*} => { implement!{@build ($st $r) $m $f { $($f2)* $st = $st.trim_start(); if $st.starts_with($s) { $st = &$st[$s.len()..] } else { return Err("error".to_string()) } } $($t)*} }; {@build ($s:ident $r:ident) $m:tt {$($f:tt)*} {$($f2:tt)*} $i:ident $($t:tt)*} => { implement!{@build ($s $r) $m {$($f)*{$($f2)*}} { let $r; match $i::consume($s) { Ok((r,s)) => { $s = s; $r = r; } Err(error) => { return Err(error); } } } $($t)*} }; {@build $va:tt ($($m:tt)*) {$($f:tt)*} {$($f2:tt)*} {$($r:tt)*} $($t:tt)*} => { implement!{@build $va (vector {$($f)*{$($f2)*}} ($($t)*) $($m)*) {} {} $($r)*} }; {@build $va:tt ($($m:tt)*) {$($f:tt)*} {$($f2:tt)*} [$($r:tt)*] $($t:tt)*} => { implement!{@build $va (option {$($f)*{$($f2)*}} ($($t)*) $($m)*) {} {} $($r)*} }; {@finish ($s:ident $re:ident) (option {$($l:tt)*} ($($t:tt)*) $($m:tt)*) {{$($f:tt)*}$({$($r:tt)*})*} } => { implement!{@build ($s $re) ($($m)*) {$($l)*} { let mut $re; let taker = move |_state| { let mut $s: &str = _state; $($f)* Ok((( $({$($r)*$re}),* ),$s)) }; match taker($s) { Ok((r,s)) => { $s = s; $re = Some(r); } Err(error) => { $re = None; } } } $($t)*} }; {@finish ($s:ident $re:ident) (vector {$($l:tt)*} ($($t:tt)*) $($m:tt)*) {{$($f:tt)*}$({$($r:tt)*})*} } => { implement!{@build ($s $re) ($($m)*) {$($l)*} { let mut $re = Vec::new(); let taker = move |_state| { let mut $s: &str = _state; $($f)* Ok((( $({$($r)*$re}),* ),$s)) }; loop { match taker($s) { Ok((r,s)) => { $s = s; $re.push(r); } Err(error) => { break; } }; } } $($t)*} }; {@build $va:tt $m:tt {$($r:tt)*} $r2:tt} => { implement!{@finish $va $m {$($r)*$r2}} }; {@finish ($s:ident $re:ident) (structure $n:ident) {{$($f:tt)*}$({$($r:tt)*})*} } => { impl Parse for $n { fn consume(_state: &str) -> Result<(Self, &str), Error> where Self: Sized { let mut $s: &str = _state; $($f)* Ok(( $n($({$($r)*$re.into()}),*),$s )) } } }; {@finish ($s:ident $re:ident) (enumeration $m2:ident {$($l:tt)*} ($m:ident ($($t2:tt)*)$($t:tt)*) $n:ident) {$f:tt$({$($r:tt)*})+} } => { implement!{@build ($s $re) (enumeration $m {$($l)*{ $f Ok(( $n::$m2($({$($r)*$re.into()}),+),$s )) }} ($($t)*) $n) {} {} $($t2)*} }; {@finish ($s:ident $re:ident) (enumeration $m3:ident {$($l:tt)*} ($m:ident ($($t2:tt)*)$($t:tt)*) $n:ident) {$f:tt} } => { implement!{@build ($s $re) (enumeration $m {$($l)*{ $f Ok(( $n::$m3,$s )) }} ($($t)*) $n) {} {} $($t2)*} }; {@finish ($s:ident $re:ident) (enumeration $m2:ident {$($l:tt)*} () $n:ident) {$f:tt$({$($r:tt)*})+}} => { implement!{@finish ($s $re) (enumeration {$($l)*{ $f Ok(( $n::$m2($({$($r)*$re.into()}),+),$s )) }} () $n)} // straight to below }; {@finish ($s:ident $re:ident) (enumeration $m2:ident {$($l:tt)*} () $n:ident) {$f:tt}} => { implement!{@finish ($s $re) (enumeration {$($l)*{ $f Ok(( $n::$m2,$s )) }} () $n)} // straight to below }; {@finish ($s:ident $re:ident) (enumeration {$($f:tt)*} () $n:ident)} => { impl Parse for $n { fn consume(_state: &str) -> Result<(Self, &str), Error> where Self: Sized { let mut $s: &str = _state; $( let case = $f; if case.is_ok() { return case; } )* Err("error".into()) } } }; } macro_rules! class { ($i:ident($($t:tt)*)) => { definition!{@build ($i structure) () null () $($t)*} implement!{@begin $i structure $($t)*} }; ($i:ident{$($n:ident($($t:tt)*)),*}) => { definition!{@build ($i enumeration new () ($($n($($t)*))*)) () null ()} implement!{@begin $i enumeration ($($n($($t)*))*)} } } macro_rules! parser { () => {}; ($i:ident$t:tt;$($tail:tt)*) => { class!($i$t); parser!($($tail)*); }; } struct Number(String); struct Name(String); type Error = String; trait Parse { fn consume(state: &str) -> Result<(Self, &str), Error> where Self: Sized; } impl Parse for Name { fn consume(state: &str) -> Result<(Self, &str), Error> where Self: Sized { todo!() } } impl Parse for String { fn consume(state: &str) -> Result<(Self, &str), Error> where Self: Sized { todo!() } } impl Parse for Number { fn consume(state: &str) -> Result<(Self, &str), Error> where Self: Sized { todo!() } } parser!( Block2 ( {Statement} [Return] ); ); parser! { // LiteralString -> "..." // LiteralNumber -> 0x... 123.456 Chunk ( Block ); Block ( {Statement} [Return Name] ); Statement { Semicolon (";"), Assignment (Variables "=" Expressions), Call (FunctionCall), Label (Label), Break ("break"), Goto ("goto" Name), Do ("do" Block "end"), While ("while" Expression "do" Block "end"), Repeat ("repeat" Block "until" Expression), If ("if" Expression "then" Block {"elseif" Expression "then" Block} ["else" Block] "end"), ForRange ("for" Name "=" Expression "," Expression ["," Expression] "do" Block "end"), ForIn ("for" Names "in" Expressions "do" Block "end"), Function ("function" FunctionName FunctionBody), LocalFunction ("local" "function" Name FunctionBody), GlobalFunction ("global" "function" Name FunctionBody), Declaration ("local" Names ["=" Expressions]), Global ("global" Names) }; Return( "return" [Expressions] [";"] ); Label( "::" Name "::" ); FunctionName( Name {"." Name} [":" Name] ); Variables( Variable {"," Variable} ); Variable { Name (Name), Index (PrefixExpression "[" Expression "]"), DotIndex (PrefixExpression "." Name) }; Names( Name {"," Name} ); Expressions( Expression {"," Expression} ); Expression { Nil ("nil"), False ("false"), True ("true"), Number (Number), String (String), VarArg ("..."), FunctionDef (FunctionDef), PrefixExpression (PrefixExpression), Table (Table), Binary (Expression BinaryOp Expression), Unary (UnaryOp Expression) }; PrefixExpression { Variable (Variable), Call (FunctionCall), Expression ("(" Expression ")") }; FunctionCall { Normal (PrefixExpression Arguments), Instanced (PrefixExpression ":" Name Arguments) }; Arguments { Expressions ("(" [Expressions] ")"), Table (Table), String (String) }; FunctionDef( "function" FunctionBody ); FunctionBody( "(" [Parameters] ")" Block "end" ); Parameters { Names (Names ["," VarArg]), VarArg (VarArg) }; VarArg( "..." [Name] ); Table( "{" [Fields] "}" ); Fields( Field {FieldSep Field} [FieldSep] ); Field { ExpressionIndex ("[" Expression "]" "=" Expression), Name (Name "=" Expression), Expression (Expression) }; FieldSep { Comma (","), Semicolon (";") }; BinaryOp { Plus ("+"), Minus ("-"), Mul ("*"), Divide ("/"), DivFloor ("//"), Caret ("^"), Modulo ("%"), Ampersand ("&"), Tilde ("~"), Pipe ("|"), ShiftRight (">>"), ShiftLeft ("<<"), Concat (".."), Less ("<"), LessEqual ("<="), Greater (">"), GreatEqual (">="), Equivalent ("=="), NotEqual ("~="), And ("and"), Or ("or") }; UnaryOp { Negate ("-"), Not ("!"), Ampersand ("#"), Tilde ("~") }; }