Skip to content

Commit b66a9aa

Browse files
committed
Support CfxLua
1 parent aeb4d4b commit b66a9aa

File tree

154 files changed

+16907
-179
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

154 files changed

+16907
-179
lines changed

.vscode/settings.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
{
2-
"rust-analyzer.cargo.features": ["luau", "lua52", "lua53", "lua54", "luau"]
2+
"rust-analyzer.cargo.features": ["luau", "lua52", "lua53", "lua54", "luau", "cfxlua"]
33
}

CHANGELOG.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,17 @@ All notable changes to this project will be documented in this file.
44
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
55
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
66

7+
## Unreleased
8+
9+
### Added
10+
- Implemented CFX Lua as a feature flag - `cfxlua`
11+
- Compound Operators: `+=, -=, *=, /=, <<=, >>=, &=, |=, and ^=`
12+
- Safe Navigation e.g. `t?.x?.y == nil`
13+
- In Unpacking e.g. `local a, b, c = t` is equivalent to `local a, b, c = t.a, t.b, t.c`
14+
- Set Constructors e.g. `t = { .x, .y }` is equivalent to `t = { x = true, y = true }`
15+
- C-Style Comments (single & multiline) e.g. `/* comment */`
16+
- Compile Time Jenkins' Hashes e.g. ``` `Hello, World!` -> 1395890823```
17+
718
## [1.2.0] - 2025-01-09
819

920
### Added

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
</h1>
66
</div>
77

8-
A lossless Lua 5.1 / 5.2 / 5.3 / 5.4 / [Luau](https://luau-lang.org/) parser written in Rust.
8+
A lossless Lua 5.1 / 5.2 / 5.3 / 5.4 / [Luau](https://luau-lang.org/) / [CfxLua](https://docs.fivem.net/docs/scripting-manual/runtimes/lua/) parser written in Rust.
99

1010

1111
## Lossless?

full-moon/Cargo.toml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@ license = "MPL-2.0"
77
readme = "README.md"
88
repository = "https://github.com/Kampfkarren/full-moon"
99
categories = ["parsing"]
10-
keywords = ["lua", "parser", "lua51", "lua52", "luau"]
10+
keywords = ["lua", "parser", "lua51", "lua52", "luau", "cfxlua"]
1111
edition = "2021"
1212

1313
[package.metadata.docs.rs]
1414
# Build Locally: RUSTDOCFLAGS="--cfg docsrs" cargo +nightly doc --features luau,lua52,lua53,lua54,luajit --no-deps --open
15-
features = ["luau", "lua52", "lua53", "lua54", "luajit"]
15+
features = ["luau", "lua52", "lua53", "lua54", "luajit", "cfxlua"]
1616
rustdoc-args = ["--cfg", "docsrs"]
1717

1818
[features]
@@ -23,6 +23,7 @@ lua52 = []
2323
lua53 = ["lua52"]
2424
lua54 = ["lua53"]
2525
luajit = []
26+
cfxlua = ["lua54"]
2627
no-source-tests = []
2728

2829
[dependencies]

full-moon/src/ast/compound.rs

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
use derive_more::Display;
2+
use serde::{Deserialize, Serialize};
3+
use full_moon_derive::{Node, Visit};
4+
use crate::ast::{Expression, Var};
5+
use crate::tokenizer::{Symbol, TokenReference};
6+
7+
#[derive(Clone, Debug, Display, PartialEq, Eq, Node, Visit)]
8+
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
9+
#[non_exhaustive]
10+
#[allow(missing_docs)]
11+
#[display("{_0}")]
12+
/// Compound operators, such as X += Y or X -= Y
13+
pub enum CompoundOp {
14+
PlusEqual(TokenReference),
15+
MinusEqual(TokenReference),
16+
StarEqual(TokenReference),
17+
SlashEqual(TokenReference),
18+
CaretEqual(TokenReference),
19+
20+
// luau sepcific
21+
DoubleSlashEqual(TokenReference),
22+
PercentEqual(TokenReference),
23+
TwoDotsEqual(TokenReference),
24+
25+
// cfxlua sepcific
26+
LeftShift(TokenReference),
27+
RightShift(TokenReference),
28+
BitwiseAndAssignment(TokenReference),
29+
BitwiseOrAssignment(TokenReference),
30+
}
31+
32+
impl CompoundOp {
33+
/// The token associated with the operator
34+
pub fn token(&self) -> &TokenReference {
35+
match self {
36+
Self::PlusEqual(token)
37+
| Self::MinusEqual(token)
38+
| Self::StarEqual(token)
39+
| Self::SlashEqual(token)
40+
| Self::DoubleSlashEqual(token)
41+
| Self::PercentEqual(token)
42+
| Self::CaretEqual(token)
43+
| Self::TwoDotsEqual(token)
44+
| Self::LeftShift(token)
45+
| Self::RightShift(token)
46+
| Self::BitwiseAndAssignment(token)
47+
| Self::BitwiseOrAssignment(token) => token,
48+
}
49+
}
50+
51+
pub(crate) fn from_token(token: TokenReference) -> Self {
52+
if token.is_symbol(Symbol::PlusEqual) {
53+
return Self::PlusEqual(token)
54+
} else if token.is_symbol(Symbol::MinusEqual) {
55+
return Self::MinusEqual(token)
56+
} else if token.is_symbol(Symbol::StarEqual) {
57+
return Self::StarEqual(token)
58+
} else if token.is_symbol(Symbol::SlashEqual) {
59+
return Self::SlashEqual(token)
60+
} else if token.is_symbol(Symbol::CaretEqual) {
61+
return Self::CaretEqual(token)
62+
}
63+
64+
#[cfg(feature = "luau")]
65+
if token.is_symbol(Symbol::DoubleSlashEqual) {
66+
return Self::DoubleSlashEqual(token)
67+
} else if token.is_symbol(Symbol::PercentEqual) {
68+
return Self::PercentEqual(token)
69+
} else if token.is_symbol(Symbol::TwoDotsEqual) {
70+
return Self::TwoDotsEqual(token)
71+
}
72+
73+
#[cfg(feature = "cfxlua")]
74+
if token.is_symbol(Symbol::LeftShift) {
75+
return Self::LeftShift(token)
76+
} else if token.is_symbol(Symbol::RightShift) {
77+
return Self::RightShift(token)
78+
} else if token.is_symbol(Symbol::BitwiseAndAssignment) {
79+
return Self::BitwiseAndAssignment(token)
80+
} else if token.is_symbol(Symbol::BitwiseOrAssignment) {
81+
return Self::BitwiseOrAssignment(token)
82+
}
83+
84+
unreachable!("converting an unknown token into a compound operator")
85+
}
86+
}
87+
88+
89+
/// A Compound Assignment statement, such as `x += 1` or `x -= 1`
90+
#[derive(Clone, Debug, Display, PartialEq, Node, Visit)]
91+
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
92+
#[display("{lhs}{compound_operator}{rhs}")]
93+
pub struct CompoundAssignment {
94+
pub(crate) lhs: Var,
95+
pub(crate) compound_operator: CompoundOp,
96+
pub(crate) rhs: Expression,
97+
}
98+
99+
impl CompoundAssignment {
100+
/// Creates a new CompoundAssignment from the left and right hand side
101+
pub fn new(lhs: Var, compound_operator: CompoundOp, rhs: Expression) -> Self {
102+
Self {
103+
lhs,
104+
compound_operator,
105+
rhs,
106+
}
107+
}
108+
109+
/// The variable assigned to, the `x` part of `x += 1`
110+
pub fn lhs(&self) -> &Var {
111+
&self.lhs
112+
}
113+
114+
/// The operator used, the `+=` part of `x += 1`
115+
pub fn compound_operator(&self) -> &CompoundOp {
116+
&self.compound_operator
117+
}
118+
119+
/// The value being assigned, the `1` part of `x += 1`
120+
pub fn rhs(&self) -> &Expression {
121+
&self.rhs
122+
}
123+
124+
/// Returns a new CompoundAssignment with the given variable being assigned to
125+
pub fn with_lhs(self, lhs: Var) -> Self {
126+
Self { lhs, ..self }
127+
}
128+
129+
/// Returns a new CompoundAssignment with the given operator used
130+
pub fn with_compound_operator(self, compound_operator: CompoundOp) -> Self {
131+
Self {
132+
compound_operator,
133+
..self
134+
}
135+
}
136+
137+
/// Returns a new CompoundAssignment with the given value being assigned
138+
pub fn with_rhs(self, rhs: Expression) -> Self {
139+
Self { rhs, ..self }
140+
}
141+
}

full-moon/src/ast/lua54.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,4 +50,4 @@ impl Attribute {
5050
pub fn with_brackets(self, brackets: ContainedSpan) -> Self {
5151
Self { brackets, ..self }
5252
}
53-
}
53+
}

full-moon/src/ast/luau.rs

Lines changed: 3 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -893,114 +893,9 @@ impl ExportedTypeFunction {
893893
}
894894
}
895895

896-
#[derive(Clone, Debug, Display, PartialEq, Eq, Node, Visit)]
897-
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
898-
#[non_exhaustive]
899-
#[allow(missing_docs)]
900-
#[display("{_0}")]
901-
/// Compound operators, such as X += Y or X -= Y
902-
pub enum CompoundOp {
903-
PlusEqual(TokenReference),
904-
MinusEqual(TokenReference),
905-
StarEqual(TokenReference),
906-
SlashEqual(TokenReference),
907-
DoubleSlashEqual(TokenReference),
908-
PercentEqual(TokenReference),
909-
CaretEqual(TokenReference),
910-
TwoDotsEqual(TokenReference),
911-
}
912-
913-
impl CompoundOp {
914-
/// The token associated with the operator
915-
pub fn token(&self) -> &TokenReference {
916-
match self {
917-
Self::PlusEqual(token)
918-
| Self::MinusEqual(token)
919-
| Self::StarEqual(token)
920-
| Self::SlashEqual(token)
921-
| Self::DoubleSlashEqual(token)
922-
| Self::PercentEqual(token)
923-
| Self::CaretEqual(token)
924-
| Self::TwoDotsEqual(token) => token,
925-
}
926-
}
927-
928-
pub(crate) fn from_token(token: TokenReference) -> Self {
929-
if token.is_symbol(Symbol::PlusEqual) {
930-
Self::PlusEqual(token)
931-
} else if token.is_symbol(Symbol::MinusEqual) {
932-
Self::MinusEqual(token)
933-
} else if token.is_symbol(Symbol::StarEqual) {
934-
Self::StarEqual(token)
935-
} else if token.is_symbol(Symbol::SlashEqual) {
936-
Self::SlashEqual(token)
937-
} else if token.is_symbol(Symbol::DoubleSlashEqual) {
938-
Self::DoubleSlashEqual(token)
939-
} else if token.is_symbol(Symbol::PercentEqual) {
940-
Self::PercentEqual(token)
941-
} else if token.is_symbol(Symbol::CaretEqual) {
942-
Self::CaretEqual(token)
943-
} else if token.is_symbol(Symbol::TwoDotsEqual) {
944-
Self::TwoDotsEqual(token)
945-
} else {
946-
unreachable!("converting an unknown token into a compound operator")
947-
}
948-
}
949-
}
950-
951-
/// A Compound Assignment statement, such as `x += 1` or `x -= 1`
952-
#[derive(Clone, Debug, Display, PartialEq, Node, Visit)]
953-
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
954-
#[display("{lhs}{compound_operator}{rhs}")]
955-
pub struct CompoundAssignment {
956-
pub(crate) lhs: Var,
957-
pub(crate) compound_operator: CompoundOp,
958-
pub(crate) rhs: Expression,
959-
}
960-
961-
impl CompoundAssignment {
962-
/// Creates a new CompoundAssignment from the left and right hand side
963-
pub fn new(lhs: Var, compound_operator: CompoundOp, rhs: Expression) -> Self {
964-
Self {
965-
lhs,
966-
compound_operator,
967-
rhs,
968-
}
969-
}
970-
971-
/// The variable assigned to, the `x` part of `x += 1`
972-
pub fn lhs(&self) -> &Var {
973-
&self.lhs
974-
}
975-
976-
/// The operator used, the `+=` part of `x += 1`
977-
pub fn compound_operator(&self) -> &CompoundOp {
978-
&self.compound_operator
979-
}
980-
981-
/// The value being assigned, the `1` part of `x += 1`
982-
pub fn rhs(&self) -> &Expression {
983-
&self.rhs
984-
}
985-
986-
/// Returns a new CompoundAssignment with the given variable being assigned to
987-
pub fn with_lhs(self, lhs: Var) -> Self {
988-
Self { lhs, ..self }
989-
}
990-
991-
/// Returns a new CompoundAssignment with the given operator used
992-
pub fn with_compound_operator(self, compound_operator: CompoundOp) -> Self {
993-
Self {
994-
compound_operator,
995-
..self
996-
}
997-
}
998-
999-
/// Returns a new CompoundAssignment with the given value being assigned
1000-
pub fn with_rhs(self, rhs: Expression) -> Self {
1001-
Self { rhs, ..self }
1002-
}
1003-
}
896+
/*
897+
CompoundOp and CompoundAssignment have been moved to `compound.rs´, since CfxLua makes use of them as well.
898+
*/
1004899

1005900
/// An if statement
1006901
#[derive(Clone, Debug, Display, PartialEq, Node, Visit)]

0 commit comments

Comments
 (0)