Added Lua parser implementation and Lua BNF through macro_rules!;

This commit is contained in:
2026-06-10 02:27:51 +01:00
committed by paladin
parent ce2bd0b360
commit 3eb69b3759
2 changed files with 294 additions and 228 deletions
+294 -228
View File
@@ -1,81 +1,84 @@
macro_rules! definition { macro_rules! definition {
{@build ($n:ident structure) ($($t:tt)*) null () } => { {@build ($n:ident structure) ($($t:tt)*) null () } => {
struct $n ($($t)*); struct $n ($($t)*);
}; };
{@build ($n:ident enumeration new ($($f:tt)*) ($m:ident($($mt:tt)*)$($r:tt)*)) () null ()} => { {@build ($n:ident enumeration new ($($f:tt)*) ($m:ident($($mt:tt)*)$($r:tt)*)) () null ()} => {
definition!{@build ($n enumeration ($($f)*) ($m($($mt)*)$($r)*)) () null () $($mt)*} 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 ()} => { {@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 () } definition!{@build ($n enumeration new ($($f)*$m($($t)*)) ($($r)*)) () null () }
}; };
{@build ($n:ident enumeration new ($($m:ident($($mt:tt)*))*) ()) () null () } => { {@build ($n:ident enumeration new ($($m:ident($($mt:tt)*))*) ()) () null () } => {
definition!{@build ($n enumeration filter () ($($m($($mt)*))*))} definition!{@build ($n enumeration filter () ($($m($($mt)*))*))}
}; };
{@build ($n:ident enumeration filter ($($e:tt)*) ($m:ident($($mt:tt)+)$($t:tt)*))} => { {@build ($n:ident enumeration filter ($($e:tt)*) ($m:ident($($mt:tt)+)$($t:tt)*))} => {
definition!{@build ($n enumeration filter ($($e)*$m($($mt)*),) ($($t)*))} definition!{@build ($n enumeration filter ($($e)*$m($($mt)*),) ($($t)*))}
}; };
{@build ($n:ident enumeration filter ($($e:tt)*) ($m:ident()$($t:tt)*))} => { {@build ($n:ident enumeration filter ($($e:tt)*) ($m:ident()$($t:tt)*))} => {
definition!{@build ($n enumeration filter ($($e)*$m,) ($($t)*))} definition!{@build ($n enumeration filter ($($e)*$m,) ($($t)*))}
}; };
{@build ($n:ident enumeration filter ($($e:tt)*) ())} => { {@build ($n:ident enumeration filter ($($e:tt)*) ())} => {
enum $n { enum $n {
$($e)* $($e)*
} }
}; };
{@build $m:tt ($($t:tt)*) null () $l:literal $($r:tt)*} => { {@build $m:tt ($($t:tt)*) null () $l:literal $($r:tt)*} => {
definition!{@build $m ($($t)*) null () $($r)*} definition!{@build $m ($($t)*) null () $($r)*}
}; };
{@build $m:tt ($($t:tt)*) null () $i:ident $($r:tt)*} => { {@build $m:tt ($($t:tt)*) null () $i:ident $($r:tt)*} => {
definition!{@build $m ($($t)*Box<$i>,) null () $($r)*} definition!{@build $m ($($t)*Box<$i>,) null () $($r)*}
}; };
{@build $m:tt ($($t:tt)*) option ($a:tt) () $($r:tt)*} => { {@build $m:tt ($($t:tt)*) option ($a:tt) () $($r:tt)*} => {
definition!{@build $m ($($t)*Option<$a>,) null () $($r)*} definition!{@build $m ($($t)*Option<$a>,) null () $($r)*}
}; };
{@build $m:tt ($($t:tt)*) vector ($a:tt) () $($r:tt)*} => { {@build $m:tt ($($t:tt)*) vector ($a:tt) () $($r:tt)*} => {
definition!{@build $m ($($t)*Vec<$a>,) null () $($r)*} definition!{@build $m ($($t)*Vec<$a>,) null () $($r)*}
}; };
{@build $m:tt ($($t:tt)*) option ($($a:tt)*) () $($r:tt)*} => { {@build $m:tt ($($t:tt)*) option ($($a:tt)*) () $($r:tt)*} => {
definition!{@build $m ($($t)*Option<($($a),*)>,) null () $($r)*} definition!{@build $m ($($t)*Option<($($a),*)>,) null () $($r)*}
}; };
{@build $m:tt ($($t:tt)*) vector ($($a:tt)*) () $($r:tt)*} => { {@build $m:tt ($($t:tt)*) vector ($($a:tt)*) () $($r:tt)*} => {
definition!{@build $m ($($t)*Vec<($($a),*)>,) null () $($r)*} definition!{@build $m ($($t)*Vec<($($a),*)>,) null () $($r)*}
}; };
{@build $m:tt ($($t:tt)*) null () [$($b:tt)*] $($r:tt)*} => { {@build $m:tt ($($t:tt)*) null () [$($b:tt)*] $($r:tt)*} => {
definition!{@build $m ($($t)*) option () ($($b)*) $($r)*} definition!{@build $m ($($t)*) option () ($($b)*) $($r)*}
}; };
{@build $m:tt ($($t:tt)*) null () {$($b:tt)*} $($r:tt)*} => { {@build $m:tt ($($t:tt)*) null () {$($b:tt)*} $($r:tt)*} => {
definition!{@build $m ($($t)*) vector () ($($b)*) $($r)*} definition!{@build $m ($($t)*) vector () ($($b)*) $($r)*}
}; };
{@build $m:tt ($($t:tt)*) $i:ident ($($a:tt)*) ($l:literal $($b:tt)*) $($r:tt)*} => { {@build $m:tt ($($t:tt)*) $i:ident ($($a:tt)*) ($l:literal $($b:tt)*) $($r:tt)*} => {
definition!{@build $m ($($t)*) $i ($($a)*) ($($b)*) $($r)*} definition!{@build $m ($($t)*) $i ($($a)*) ($($b)*) $($r)*}
}; };
{@build $m:tt ($($t:tt)*) $i:ident ($($a:tt)*) ($n:ident $($b:tt)*) $($r:tt)*} => { {@build $m:tt ($($t:tt)*) $i:ident ($($a:tt)*) ($n:ident $($b:tt)*) $($r:tt)*} => {
definition!{@build $m ($($t)*) $i ($($a)*$n) ($($b)*) $($r)*} definition!{@build $m ($($t)*) $i ($($a)*$n) ($($b)*) $($r)*}
}; };
} }
macro_rules! implement { macro_rules! implement {
{@begin $n:ident $i:ident $($t:tt)*} => { {@begin $n:ident structure $($t:tt)*} => {
implement!{@build ($i $n) {} {} $($t)*} implement!{@build (state result) (structure $n) {} {} $($t)*}
}; };
{@build $m:tt $f:tt {$($f2:tt)*} $s:literal $($t:tt)*} => { {@begin $n:ident enumeration ($m:ident ($($t2:tt)*)$($t:tt)*)} => {
implement!{@build $m $f { 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)* $($f2)*
state = state.trim_start(); $st = $st.trim_start();
if state.starts_with($s) { if $st.starts_with($s) {
state = &state[$s.len()..] $st = &$st[$s.len()..]
} else { } else {
return Err("error".into()) return Err("error".to_string())
} }
} $($t)*} } $($t)*}
}; };
{@build $m:tt {$($f:tt)*} {$($f2:tt)*} $i:ident $($t:tt)*} => { {@build ($s:ident $r:ident) $m:tt {$($f:tt)*} {$($f2:tt)*} $i:ident $($t:tt)*} => {
implement!{@build $m {$($f)*{$($f2)*}} { implement!{@build ($s $r) $m {$($f)*{$($f2)*}} {
let mut result; let $r;
match $i::take(state) { match $i::consume($s) {
Ok((r,s)) => { Ok((r,s)) => {
state = s; $s = s;
result = r; $r = r;
} }
Err(error) => { Err(error) => {
return Err(error); return Err(error);
@@ -83,36 +86,48 @@ macro_rules! implement {
} }
} $($t)*} } $($t)*}
}; };
{@build ($($m:tt)*) {$($f:tt)*} {$($f2:tt)*} {$($r:tt)*} $($t:tt)*} => { {@build $va:tt ($($m:tt)*) {$($f:tt)*} {$($f2:tt)*} {$($r:tt)*} $($t:tt)*} => {
implement!{@build (vector {$($f)*{$($f2)*}} ($($t)*) $($m)*) {} {} $($r)*} implement!{@build $va (vector {$($f)*{$($f2)*}} ($($t)*) $($m)*) {} {} $($r)*}
}; };
{@build ($($m:tt)*) {$($f:tt)*} {$($f2:tt)*} [$($r:tt)*] $($t:tt)*} => { {@build $va:tt ($($m:tt)*) {$($f:tt)*} {$($f2:tt)*} [$($r:tt)*] $($t:tt)*} => {
implement!{@build (option {$($f)*{$($f2)*}} ($($t)*) $($m)*) {} {} $($r)*} implement!{@build $va (option {$($f)*{$($f2)*}} ($($t)*) $($m)*) {} {} $($r)*}
}; };
{@finish (option {$($l:tt)*} ($($t:tt)*) $($m:tt)*) {{$($f:tt)*}$({$($r:tt)*})*} } => { {@finish ($s:ident $re:ident) (option {$($l:tt)*} ($($t:tt)*) $($m:tt)*) {{$($f:tt)*}$({$($r:tt)*})*} } => {
implement!{@build ($($m)*) {$($l)*} { implement!{@build ($s $re) ($($m)*) {$($l)*} {
let mut result; let mut $re;
let taker = |_state: &str| { let taker = move |_state| {
let mut state: &str = _state; let mut $s: &str = _state;
$($f)* $($f)*
Ok(($({$($r)*result}),*)) Ok(((
$({$($r)*$re}),*
),$s))
}; };
result = taker(state).ok(); match taker($s) {
Ok((r,s)) => {
$s = s;
$re = Some(r);
}
Err(error) => {
$re = None;
}
}
} $($t)*} } $($t)*}
}; };
{@finish (vector {$($l:tt)*} ($($t:tt)*) $($m:tt)*) {{$($f:tt)*}$({$($r:tt)*})*} } => { {@finish ($s:ident $re:ident) (vector {$($l:tt)*} ($($t:tt)*) $($m:tt)*) {{$($f:tt)*}$({$($r:tt)*})*} } => {
implement!{@build ($($m)*) {$($l)*} { implement!{@build ($s $re) ($($m)*) {$($l)*} {
let mut result = Vec::new(); let mut $re = Vec::new();
let taker = |_state: &str| { let taker = move |_state| {
let mut state: &str = _state; let mut $s: &str = _state;
$($f)* $($f)*
Ok(($({$($r)*result}),*)) Ok(((
$({$($r)*$re}),*
),$s))
}; };
loop { loop {
match taker(state) { match taker($s) {
Ok((r,s)) => { Ok((r,s)) => {
state = s; $s = s;
result.push(r); $re.push(r);
} }
Err(error) => { Err(error) => {
break; break;
@@ -121,45 +136,103 @@ macro_rules! implement {
} }
} $($t)*} } $($t)*}
}; };
{@build $m:tt {$($r:tt)*} $r2:tt} => { {@build $va:tt $m:tt {$($r:tt)*} $r2:tt} => {
implement!{@finish $m {$($r)*$r2}} implement!{@finish $va $m {$($r)*$r2}}
}; };
{@finish (structure $n:ident) {{$($f:tt)*}$({$($r:tt)*})*} } => { {@finish ($s:ident $re:ident) (structure $n:ident) {{$($f:tt)*}$({$($r:tt)*})*} } => {
impl Parse for $n { impl Parse for $n {
fn take(_state: &str) -> Result<(Self, &str), Error> where Self: Sized { fn consume(_state: &str) -> Result<(Self, &str), Error> where Self: Sized {
let mut state: &str = _state; let mut $s: &str = _state;
$($f)* $($f)*
Ok(($n($({$($r)*result.into()}),*),state)) 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 { macro_rules! class {
($i:ident($($t:tt)*)) => { ($i:ident($($t:tt)*)) => {
definition!{@build ($i structure) () null () $($t)*} definition!{@build ($i structure) () null () $($t)*}
implement!{@begin $i structure $($t)*} implement!{@begin $i structure $($t)*}
}; };
($i:ident{$($n:ident($($t:tt)*)),*}) => { ($i:ident{$($n:ident($($t:tt)*)),*}) => {
definition!{@build ($i enumeration new () ($($n($($t)*))*)) () null ()} definition!{@build ($i enumeration new () ($($n($($t)*))*)) () null ()}
} implement!{@begin $i enumeration ($($n($($t)*))*)}
}
} }
macro_rules! parser { macro_rules! parser {
() => {}; () => {};
($i:ident$t:tt;$($tail:tt)*) => { ($i:ident$t:tt;$($tail:tt)*) => {
class!($i$t); class!($i$t);
parser!($($tail)*); parser!($($tail)*);
}; };
} }
struct Number(String); struct Number(String);
struct Name(String); struct Name(String);
type Error = String; type Error = String;
trait Parse { trait Parse {
fn take(state: &str) -> Result<(Self, &str), Error> fn consume(state: &str) -> Result<(Self, &str), Error>
where Self: Sized; where Self: Sized;
} }
impl Parse for Name {
fn consume(state: &str) -> Result<(Self, &str), Error>
where
Self: Sized
{
todo!()
}
}
impl Parse for String { impl Parse for String {
fn take(state: &str) -> Result<(Self, &str), Error> fn consume(state: &str) -> Result<(Self, &str), Error>
where where
Self: Sized Self: Sized
{ {
@@ -167,133 +240,126 @@ impl Parse for String {
} }
} }
fn g() -> Result<Chunk,()> { impl Parse for Number {
Ok(Chunk( fn consume(state: &str) -> Result<(Self, &str), Error>
{ where
if 1 == 2 { Self: Sized
Box::new(Block(Vec::new(),None)) {
} else { todo!()
return Err(()) }
}
}
))
} }
parser! { parser!(
Chunk3 ( "Pookie" Block "Dookie" ); Block2 ( {Statement} [Return] );
} );
parser! { parser! {
Block2 ( {Statement} [Return] ); // LiteralString -> "..."
} // LiteralNumber -> 0x... 123.456
Chunk ( Block );
parser! { Block ( {Statement} [Return Name] );
// LiteralString -> "..." Statement {
// LiteralNumber -> 0x... 123.456 Semicolon (";"),
Chunk ( Block ); Assignment (Variables "=" Expressions),
Block ( {Statement} [Return] ); Call (FunctionCall),
Statement { Label (Label),
Semicolon (";"), Break ("break"),
Assignment (Variables "=" Expressions), Goto ("goto" Name),
Call (FunctionCall), Do ("do" Block "end"),
Label (Label), While ("while" Expression "do" Block "end"),
Break ("break"), Repeat ("repeat" Block "until" Expression),
Goto ("goto" Name), If ("if" Expression "then" Block {"elseif" Expression "then" Block} ["else" Block] "end"),
Do ("do" Block "end"), ForRange ("for" Name "=" Expression "," Expression ["," Expression] "do" Block "end"),
While ("while" Expression "do" Block "end"), ForIn ("for" Names "in" Expressions "do" Block "end"),
Repeat ("repeat" Block "until" Expression), Function ("function" FunctionName FunctionBody),
If ("if" Expression "then" Block {"elseif" Expression "then" Block} ["else" Block] "end"), LocalFunction ("local" "function" Name FunctionBody),
ForRange ("for" Name "=" Expression "," Expression ["," Expression] "do" Block "end"), GlobalFunction ("global" "function" Name FunctionBody),
ForIn ("for" Names "in" Expressions "do" Block "end"), Declaration ("local" Names ["=" Expressions]),
Function ("function" FunctionName FunctionBody), Global ("global" Names)
LocalFunction ("local" "function" Name FunctionBody), };
GlobalFunction ("global" "function" Name FunctionBody), Return( "return" [Expressions] [";"] );
Declaration ("local" Names ["=" Expressions]), Label( "::" Name "::" );
Global ("global" Names) FunctionName( Name {"." Name} [":" Name] );
}; Variables( Variable {"," Variable} );
Return( "return" [Expressions] [";"] ); Variable {
Label( "::" Name "::" ); Name (Name),
FunctionName( Name {"." Name} [":" Name] ); Index (PrefixExpression "[" Expression "]"),
Variables( Variable {"," Variable} ); DotIndex (PrefixExpression "." Name)
Variable { };
Name (Name), Names( Name {"," Name} );
Index (PrefixExpression "[" Expression "]"), Expressions( Expression {"," Expression} );
DotIndex (PrefixExpression "." Name) Expression {
}; Nil ("nil"),
Names( Name {"," Name} ); False ("false"),
Expressions( Expression {"," Expression} ); True ("true"),
Expression { Number (Number),
Nil ("nil"), String (String),
False ("false"), VarArg ("..."),
True ("true"), FunctionDef (FunctionDef),
Number (Number), PrefixExpression (PrefixExpression),
String (String), Table (Table),
VarArg ("..."), Binary (Expression BinaryOp Expression),
FunctionDef (FunctionDef), Unary (UnaryOp Expression)
PrefixExpression (PrefixExpression), };
Table (Table), PrefixExpression {
Binary (Expression BinaryOp Expression), Variable (Variable),
Unary (UnaryOp Expression) Call (FunctionCall),
}; Expression ("(" Expression ")")
PrefixExpression { };
Variable (Variable), FunctionCall {
Call (FunctionCall), Normal (PrefixExpression Arguments),
Expression ("(" Expression ")") Instanced (PrefixExpression ":" Name Arguments)
}; };
FunctionCall { Arguments {
Normal (PrefixExpression Arguments), Expressions ("(" [Expressions] ")"),
Instanced (PrefixExpression ":" Name Arguments) Table (Table),
}; String (String)
Arguments { };
Expressions ("(" [Expressions] ")"), FunctionDef( "function" FunctionBody );
Table (Table), FunctionBody( "(" [Parameters] ")" Block "end" );
String (String) Parameters {
}; Names (Names ["," VarArg]),
FunctionDef( "function" FunctionBody ); VarArg (VarArg)
FunctionBody( "(" [Parameters] ")" Block "end" ); };
Parameters { VarArg( "..." [Name] );
Names (Names ["," VarArg]), Table( "{" [Fields] "}" );
VarArg (VarArg) Fields( Field {FieldSep Field} [FieldSep] );
}; Field {
VarArg( "..." [Name] ); ExpressionIndex ("[" Expression "]" "=" Expression),
Table( "{" [Fields] "}" ); Name (Name "=" Expression),
Fields( Field {FieldSep Field} [FieldSep] ); Expression (Expression)
Field { };
ExpressionIndex ("[" Expression "]" "=" Expression), FieldSep {
Name (Name "=" Expression), Comma (","),
Expression (Expression) Semicolon (";")
}; };
FieldSep { BinaryOp {
Comma (","), Plus ("+"),
Semicolon (";") Minus ("-"),
}; Mul ("*"),
BinaryOp { Divide ("/"),
Plus ("+"), DivFloor ("//"),
Minus ("-"), Caret ("^"),
Mul ("*"), Modulo ("%"),
Divide ("/"), Ampersand ("&"),
DivFloor ("//"), Tilde ("~"),
Caret ("^"), Pipe ("|"),
Modulo ("%"), ShiftRight (">>"),
Ampersand ("&"), ShiftLeft ("<<"),
Tilde ("~"), Concat (".."),
Pipe ("|"), Less ("<"),
ShiftRight (">>"), LessEqual ("<="),
ShiftLeft ("<<"), Greater (">"),
Concat (".."), GreatEqual (">="),
Less ("<"), Equivalent ("=="),
LessEqual ("<="), NotEqual ("~="),
Greater (">"), And ("and"),
GreatEqual (">="), Or ("or")
Equivalent ("=="), };
NotEqual ("~="), UnaryOp {
And ("and"), Negate ("-"),
Or ("or") Not ("!"),
}; Ampersand ("#"),
UnaryOp { Tilde ("~")
Negate ("-"), };
Not ("!"), }
Ampersand ("#"),
Tilde ("~")
};
}
Regular → Executable
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 MiB

After

Width:  |  Height:  |  Size: 254 KiB