Overview
Full Moon supports multiple Lua versions and dialects through Cargo feature flags. You can parse Lua 5.1, 5.2, 5.3, 5.4, Luau (Roblox), LuaJIT, and CFX Lua (FiveM).
Feature Flags
Enable Lua versions in your Cargo.toml:
[ dependencies ]
full_moon = { version = "2.1" , features = [ "lua54" ] }
Available Features
Enables Lua 5.2 syntax support including:
goto statements
Labels (::)
Hexadecimal float literals
Enables Lua 5.3 syntax (includes lua52):
Bitwise operators (&, |, ~, <<, >>)
Integer division (//)
Floor division
Enables Lua 5.4 syntax (includes lua53):
Attributes in local declarations (local x <const> = 1)
Close variables (<close>)
To-be-closed variables
Enables Luau (Roblox Lua) syntax:
Type annotations
Generics
String interpolation
If expressions
Continue statements
Compound assignments
Enables LuaJIT-specific syntax:
goto statements (like Lua 5.2)
Label support
Enables CFX Lua (FiveM) syntax:
Set constructor syntax (.a in tables)
Compound assignments (includes lua54)
Version Relationships
Enabling lua54 automatically enables lua53 and lua52. Similarly, cfxlua includes lua54 features.
Selecting a Version at Runtime
Use LuaVersion to control which version to parse:
use full_moon :: {parse_fallible, LuaVersion };
// Automatic version selection (based on features)
let auto_version = LuaVersion :: new ();
let ast = parse_fallible ( code , auto_version );
Explicit Version Selection
use full_moon :: LuaVersion ;
// Parse as Lua 5.1
let lua51 = LuaVersion :: lua51 ();
// Parse as Lua 5.2
#[cfg(feature = "lua52" )]
let lua52 = LuaVersion :: lua52 ();
// Parse as Lua 5.3
#[cfg(feature = "lua53" )]
let lua53 = LuaVersion :: lua53 ();
// Parse as Lua 5.4
#[cfg(feature = "lua54" )]
let lua54 = LuaVersion :: lua54 ();
// Parse as Luau
#[cfg(feature = "luau" )]
let luau = LuaVersion :: luau ();
Version-Specific Syntax
Lua 5.2: Goto and Labels
:: start ::
print ( "hello" )
goto start
#[cfg(any(feature = "lua52" , feature = "luajit" ))]
use full_moon :: ast :: { Stmt , Goto , Label };
#[cfg(any(feature = "lua52" , feature = "luajit" ))]
fn handle_goto ( stmt : & Stmt ) {
match stmt {
Stmt :: Goto ( goto_stmt ) => {
println! ( "Goto: {}" , goto_stmt . label_name ());
}
Stmt :: Label ( label ) => {
println! ( "Label: {}" , label . name ());
}
_ => {}
}
}
Lua 5.4: Attributes
local x <const> = 10
local file <close> = io.open ( "file.txt" )
#[cfg(feature = "lua54" )]
use full_moon :: ast :: Attribute ;
#[cfg(feature = "lua54" )]
fn handle_attributes ( local : & LocalAssignment ) {
for attr in local . attributes () {
if let Some ( attribute ) = attr {
println! ( "Attribute: {}" , attribute . name ());
}
}
}
Luau: Type Annotations
function add ( a : number , b : number ): number
return a + b
end
type Point = { x : number , y : number }
#[cfg(feature = "luau" )]
use full_moon :: ast :: {
TypeSpecifier ,
TypeDeclaration ,
TypeInfo ,
};
#[cfg(feature = "luau" )]
fn handle_types ( body : & FunctionBody ) {
// Check parameter types
for type_spec in body . type_specifiers () {
if let Some ( spec ) = type_spec {
println! ( "Parameter type: {}" , spec . type_info ());
}
}
// Check return type
if let Some ( return_type ) = body . return_type () {
println! ( "Return type: {}" , return_type . type_info ());
}
}
Luau: String Interpolation
local name = "World"
print ( `Hello, {name}!` )
#[cfg(feature = "luau" )]
use full_moon :: ast :: InterpolatedString ;
#[cfg(feature = "luau" )]
fn handle_interpolation ( expr : & Expression ) {
if let Expression :: InterpolatedString ( interp ) = expr {
for segment in interp . segments () {
println! ( "Segment: {}" , segment );
}
}
}
Luau: If Expressions
local result = if condition then value1 else value2
#[cfg(feature = "luau" )]
use full_moon :: ast :: IfExpression ;
#[cfg(feature = "luau" )]
fn handle_if_expr ( expr : & Expression ) {
if let Expression :: IfExpression ( if_expr ) = expr {
println! ( "Condition: {}" , if_expr . condition ());
println! ( "True branch: {}" , if_expr . if_expression ());
println! ( "False branch: {}" , if_expr . else_expression ());
}
}
Compound Assignments (Luau & CFX Lua)
#[cfg(any(feature = "luau" , feature = "cfxlua" ))]
use full_moon :: ast :: { CompoundAssignment , CompoundOp };
#[cfg(any(feature = "luau" , feature = "cfxlua" ))]
fn handle_compound ( stmt : & Stmt ) {
if let Stmt :: CompoundAssignment ( compound ) = stmt {
match compound . compound_operator () {
CompoundOp :: PlusEqual ( _ ) => println! ( "+=" ),
CompoundOp :: MinusEqual ( _ ) => println! ( "-=" ),
CompoundOp :: StarEqual ( _ ) => println! ( "*=" ),
CompoundOp :: SlashEqual ( _ ) => println! ( "/=" ),
_ => println! ( "Other compound op" ),
}
}
}
CFX Lua: Set Constructors
local set = { . a , . b , . c }
-- Equivalent to: { a = true, b = true, c = true }
#[cfg(feature = "cfxlua" )]
use full_moon :: ast :: Field ;
#[cfg(feature = "cfxlua" )]
fn handle_set_constructor ( table : & TableConstructor ) {
for field in table . fields () {
if let Field :: SetConstructor { dot , name } = field {
println! ( "Set field: {}" , name );
}
}
}
Multi-Version Support
If you need to support multiple versions in one binary:
[ dependencies ]
full_moon = { version = "2.1" , features = [ "lua54" , "luau" ] }
use full_moon :: {parse_fallible, LuaVersion };
enum TargetVersion {
Lua51 ,
Lua54 ,
Luau ,
}
fn parse_for_version ( code : & str , target : TargetVersion ) -> full_moon :: ast :: Ast {
let version = match target {
TargetVersion :: Lua51 => LuaVersion :: lua51 (),
#[cfg(feature = "lua54" )]
TargetVersion :: Lua54 => LuaVersion :: lua54 (),
#[cfg(feature = "luau" )]
TargetVersion :: Luau => LuaVersion :: luau (),
#[cfg(not(feature = "lua54" ))]
TargetVersion :: Lua54 => panic! ( "lua54 feature not enabled" ),
#[cfg(not(feature = "luau" ))]
TargetVersion :: Luau => panic! ( "luau feature not enabled" ),
};
parse_fallible ( code , version ) . into_ast ()
}
Feature Detection
Check which features are enabled at compile time:
// Check for Lua 5.2+
#[cfg(feature = "lua52" )]
fn has_goto_support () -> bool {
true
}
#[cfg(not(feature = "lua52" ))]
fn has_goto_support () -> bool {
false
}
// Check for Luau
#[cfg(feature = "luau" )]
fn has_type_support () -> bool {
true
}
#[cfg(not(feature = "luau" ))]
fn has_type_support () -> bool {
false
}
Recommended Feature Combinations
Lua 5.1 Only Minimal features, most compatible
Modern Lua full_moon = { version = "2.1" , features = [ "lua54" ] }
Full Lua 5.4 support with all modern features
Roblox/Luau full_moon = { version = "2.1" , features = [ "luau" ] }
Type annotations and Roblox-specific syntax
Game Development full_moon = { version = "2.1" , features = [ "cfxlua" ] }
FiveM/CFX Lua with compound assignments
Version-Specific AST Nodes
Different features enable different AST node types:
Node Type Feature Required Description Gotolua52 or luajitGoto statements Labellua52 or luajitLabel declarations Attributelua54Variable attributes TypeDeclarationluauType definitions TypeAssertionluauType assertions IfExpressionluauIf expressions InterpolatedStringluauString interpolation CompoundAssignmentluau or cfxluaCompound operators SetConstructor (Field)cfxluaSet syntax in tables
Best Practices
Enable Only What You Need
Each feature increases compile time. Only enable versions you actually support.
Use Conditional Compilation
Wrap version-specific code in #[cfg(feature = "...")] blocks.
Document Version Requirements
Clearly document which Lua versions your tool supports.
Test Against Multiple Versions
If supporting multiple versions, test your code against each one.
Next Steps
Parsing Guide Learn how to parse with different versions
API Reference Explore version-specific APIs