Skip to main content
CfxLua is a Lua variant used by CitizenFX (FiveM, RedM) that extends Lua 5.4 with additional syntax features.

Feature Flag

To parse CfxLua syntax, you must enable the cfxlua feature flag in your Cargo.toml:
[dependencies]
full_moon = { version = "2.1", features = ["cfxlua"] }
Note: The cfxlua feature automatically enables lua54, lua53, and lua52, so you get all Lua 5.x features.

CfxLua-Specific Features

Compound Assignment Operators

CfxLua extends Lua with C-style compound assignment operators. Location: full_moon::ast::compound::CompoundAssignment
pub struct CompoundAssignment {
    pub(crate) lhs: Var,
    pub(crate) compound_operator: CompoundOp,
    pub(crate) rhs: Expression,
}

pub enum CompoundOp {
    // Shared with Luau
    PlusEqual(TokenReference),        // +=
    MinusEqual(TokenReference),       // -=
    StarEqual(TokenReference),        // *=
    SlashEqual(TokenReference),       // /=
    CaretEqual(TokenReference),       // ^=
    
    // CfxLua-specific bitwise compound operators
    DoubleLessThanEqual(TokenReference),    // <<=
    DoubleGreaterThanEqual(TokenReference), // >>=
    AmpersandEqual(TokenReference),         // &=
    PipeEqual(TokenReference),              // |=
}

Examples

-- Arithmetic compound operators
x += 5    -- x = x + 5
y -= 3    -- y = y - 3
z *= 2    -- z = z * 2
w /= 4    -- w = w / 4
a ^= 2    -- a = a ^ 2

-- Bitwise compound operators (CfxLua-specific)
flags &= 0xFF    -- flags = flags & 0xFF (AND)
flags |= 0x10    -- flags = flags | 0x10 (OR)
value <<= 2      -- value = value << 2 (left shift)
value >>= 1      -- value = value >> 1 (right shift)

Safe Navigation Operator

Safe navigation using ?. prevents nil errors when accessing nested properties.
local a = {
  b = 1,
  c = 2,
  d = {
    e = 3
  }
}

-- Safe access - returns nil if any part is nil
local x = a?.b        -- 1
local y = a?.d?.e     -- 3
local z = a?.missing  -- nil (no error)
Without safe navigation:
-- Traditional nil checking
local y = a and a.d and a.d.e

In Unpacking

Shorthand syntax for unpacking table fields into local variables.
local t = {
  a = 1,
  b = 2,
  c = 3
}

-- In unpacking
local a, b, c in t
-- Equivalent to:
-- local a, b, c = t.a, t.b, t.c

print(a, b, c)  -- 1, 2, 3

Set Constructors

Shorthand for creating sets (tables where keys are set to true).
-- Set constructor
local flags = { .enabled, .visible, .active }
-- Equivalent to:
-- local flags = { enabled = true, visible = true, active = true }

if flags.enabled then
  print("Enabled!")
end

-- Can mix with regular fields
local config = {
  .debug,
  .verbose,
  level = 5,
  name = "test"
}
-- Results in: { debug = true, verbose = true, level = 5, name = "test" }

C-Style Comments

CfxLua supports both single-line and multi-line C-style comments.
// Single-line C-style comment
local x = 5  // Inline comment

/*
  Multi-line C-style comment
  Can span multiple lines
*/
local function example()
  /* Block comment */ return true
end

-- Traditional Lua comments still work
--[[
  Traditional multi-line comment
]]

Compile-Time Jenkins Hashes

Backtick syntax for compile-time string hashing using Jenkins hash algorithm.
local hash = `Hello, World!`  -- Compiles to: 1395890823

-- Useful for game identifiers
local modelHash = `vehicle_name`
local weaponHash = `WEAPON_PISTOL`

-- The hash is computed at parse time, not runtime
print(hash)  -- 1395890823

Usage Example

use full_moon::parse;
use full_moon::ast::compound::{CompoundAssignment, CompoundOp};

let ast = parse(r#"
  -- Compound assignments
  x += 10
  flags |= 0x01
  
  -- Safe navigation
  local value = obj?.property?.nested
  
  -- In unpacking
  local x, y, z in vector
  
  -- Set constructor
  local flags = { .debug, .verbose }
  
  -- C-style comments
  // This is valid
  /* So is this */
  
  -- Jenkins hash
  local id = `identifier`
"#)?;

Compound Operator Methods

CompoundAssignment

  • new(lhs: Var, compound_operator: CompoundOp, rhs: Expression) -> Self
  • lhs(&self) -> &Var - The variable being assigned to
  • compound_operator(&self) -> &CompoundOp - The compound operator used
  • rhs(&self) -> &Expression - The right-hand side expression
  • with_lhs(self, lhs: Var) -> Self
  • with_compound_operator(self, compound_operator: CompoundOp) -> Self
  • with_rhs(self, rhs: Expression) -> Self

CompoundOp

  • token(&self) -> &TokenReference - Returns the token reference for the operator

Inherited Features

Since cfxlua enables lua54, lua53, and lua52, you also get:
  • Variable attributes like <const> and <close> (see Lua 5.4)
  • Bitwise operators (see Lua 5.3)
  • Goto statements and labels (see Lua 5.2)
  • All Lua 5.x syntax features

Comparison with Luau

Both Luau and CfxLua extend Lua, but serve different purposes:
FeatureCfxLuaLuau
Compound operators+=, -=, *=, /=, ^=, <<=, >>=, &=, `=`+=, -=, *=, /=, ^=, //=, %=, ..=
Type systemNoYes (full gradual typing)
Safe navigationYes (?.)No
In unpackingYesNo
Set constructorsYes (.field)No
C-style commentsYes (//, /* */)No
Jenkins hashesYes (backticks)No (backticks are string interpolation)
String interpolationNoYes
If expressionsNoYes

Notes

  • CfxLua is designed for game scripting in FiveM/RedM environments
  • The Jenkins hash feature is specifically useful for game engine identifiers
  • Safe navigation can significantly reduce nil-checking boilerplate
  • In unpacking is particularly useful for destructuring configuration tables
  • Set constructors provide a cleaner syntax for flag-like tables
  • All CfxLua features are compile-time syntax extensions and don’t require runtime support

Build docs developers (and LLMs) love