Skip to content

Commit 085d52a

Browse files
committed
support soft parse new keyword like const
1 parent b04f2a2 commit 085d52a

5 files changed

Lines changed: 91 additions & 28 deletions

File tree

crates/emmylua_parser/src/grammar/lua/stat.rs

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -240,13 +240,13 @@ fn parse_stat(p: &mut LuaParser) -> ParseResult {
240240
LuaTokenKind::TkReturn => parse_return(p)?,
241241
LuaTokenKind::TkBreak => parse_break(p)?,
242242
LuaTokenKind::TkContinue => parse_continue(p)?,
243-
LuaTokenKind::TkConst => parse_const(p)?,
243+
LuaTokenKind::TkConst => try_parse_const(p)?,
244244
LuaTokenKind::TkDo => parse_do(p)?,
245245
LuaTokenKind::TkRepeat => parse_repeat(p)?,
246246
LuaTokenKind::TkGoto => parse_goto(p)?,
247247
LuaTokenKind::TkDbColon => parse_label_stat(p)?,
248248
LuaTokenKind::TkSemicolon => parse_empty_stat(p)?,
249-
_ => parse_assign_or_expr_or_global_stat(p)?,
249+
_ => parse_assign_or_expr_or_soft_keyword_stat(p)?,
250250
};
251251

252252
Ok(cm)
@@ -645,8 +645,9 @@ fn parse_local(p: &mut LuaParser) -> ParseResult {
645645
Ok(m.complete(p))
646646
}
647647

648-
fn parse_const(p: &mut LuaParser) -> ParseResult {
648+
fn try_parse_const(p: &mut LuaParser) -> ParseResult {
649649
let mut m = p.mark(LuaSyntaxKind::ConstStat);
650+
p.set_current_token_kind(LuaTokenKind::TkConst);
650651
p.bump(); // consume 'const'
651652

652653
match p.current_token() {
@@ -773,6 +774,7 @@ fn parse_break(p: &mut LuaParser) -> ParseResult {
773774

774775
fn parse_continue(p: &mut LuaParser) -> ParseResult {
775776
let m = p.mark(LuaSyntaxKind::ContinueStat);
777+
p.set_current_token_kind(LuaTokenKind::TkContinue);
776778
p.bump();
777779
if_token_bump(p, LuaTokenKind::TkSemicolon);
778780
Ok(m.complete(p))
@@ -878,12 +880,24 @@ fn try_parse_global_stat(p: &mut LuaParser) -> ParseResult {
878880
Ok(m.complete(p))
879881
}
880882

881-
fn parse_assign_or_expr_or_global_stat(p: &mut LuaParser) -> ParseResult {
882-
if p.parse_config.level >= LuaLanguageLevel::Lua55 && p.current_token() == LuaTokenKind::TkName
883-
{
884-
let token_text = p.current_token_text();
885-
if token_text == "global" {
886-
let cm = try_parse_global_stat(p)?;
883+
fn try_soft_keyword_stat(p: &mut LuaParser) -> Option<ParseResult> {
884+
let keyword = p.current_token_text();
885+
match keyword {
886+
"global" if p.parse_config.support(LuaFeatures::GlobalDeclaration) => {
887+
Some(try_parse_global_stat(p))
888+
}
889+
"const" if p.parse_config.support(LuaFeatures::ConstDeclaration) => {
890+
Some(try_parse_const(p))
891+
}
892+
"continue" if p.parse_config.support(LuaFeatures::Continue) => Some(parse_continue(p)),
893+
_ => None,
894+
}
895+
}
896+
897+
fn parse_assign_or_expr_or_soft_keyword_stat(p: &mut LuaParser) -> ParseResult {
898+
if p.current_token() == LuaTokenKind::TkName {
899+
if let Some(cm_result) = try_soft_keyword_stat(p) {
900+
let cm = cm_result?;
887901
if !cm.is_invalid() {
888902
return Ok(cm);
889903
}
@@ -921,7 +935,10 @@ fn parse_assign_or_expr_or_global_stat(p: &mut LuaParser) -> ParseResult {
921935
}
922936

923937
// 验证左值
924-
if !matches!(cm.kind, LuaSyntaxKind::NameExpr | LuaSyntaxKind::IndexExpr) {
938+
if !matches!(
939+
cm.kind,
940+
LuaSyntaxKind::NameExpr | LuaSyntaxKind::IndexExpr | LuaSyntaxKind::SafeIndexExpr
941+
) {
925942
p.push_error(LuaParseError::syntax_error_from(
926943
&t!("invalid left-hand side in assignment (expected variable or table index)"),
927944
range,
@@ -937,7 +954,9 @@ fn parse_assign_or_expr_or_global_stat(p: &mut LuaParser) -> ParseResult {
937954
Ok(expr_cm) => {
938955
if !matches!(
939956
expr_cm.kind,
940-
LuaSyntaxKind::NameExpr | LuaSyntaxKind::IndexExpr
957+
LuaSyntaxKind::NameExpr
958+
| LuaSyntaxKind::IndexExpr
959+
| LuaSyntaxKind::SafeIndexExpr
941960
) {
942961
p.push_error(LuaParseError::syntax_error_from(
943962
&t!(

crates/emmylua_parser/src/grammar/lua/test.rs

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1454,6 +1454,63 @@ Syntax(Chunk)@0..30
14541454
);
14551455
}
14561456

1457+
#[test]
1458+
fn test_safe_navigation_assign() {
1459+
let code = "obj?.field = 1\n";
1460+
let result = r#"
1461+
Syntax(Chunk)@0..15
1462+
Syntax(Block)@0..15
1463+
Syntax(AssignStat)@0..14
1464+
Syntax(SafeIndexExpr)@0..10
1465+
Syntax(NameExpr)@0..3
1466+
Token(TkName)@0..3 "obj"
1467+
Token(TkSafeNavigation)@3..5 "?."
1468+
Token(TkName)@5..10 "field"
1469+
Token(TkWhitespace)@10..11 " "
1470+
Token(TkAssign)@11..12 "="
1471+
Token(TkWhitespace)@12..13 " "
1472+
Syntax(LiteralExpr)@13..14
1473+
Token(TkInt)@13..14 "1"
1474+
Token(TkEndOfLine)@14..15 "\n"
1475+
"#;
1476+
1477+
assert_ast_eq!(
1478+
code,
1479+
result,
1480+
ParserConfig::with_level(LuaLanguageLevel::LuaJITExt)
1481+
);
1482+
}
1483+
1484+
#[test]
1485+
fn test_safe_navigation_assign_chain() {
1486+
let code = "a?.b?.c = 2\n";
1487+
let result = r#"
1488+
Syntax(Chunk)@0..12
1489+
Syntax(Block)@0..12
1490+
Syntax(AssignStat)@0..11
1491+
Syntax(SafeIndexExpr)@0..7
1492+
Syntax(SafeIndexExpr)@0..4
1493+
Syntax(NameExpr)@0..1
1494+
Token(TkName)@0..1 "a"
1495+
Token(TkSafeNavigation)@1..3 "?."
1496+
Token(TkName)@3..4 "b"
1497+
Token(TkSafeNavigation)@4..6 "?."
1498+
Token(TkName)@6..7 "c"
1499+
Token(TkWhitespace)@7..8 " "
1500+
Token(TkAssign)@8..9 "="
1501+
Token(TkWhitespace)@9..10 " "
1502+
Syntax(LiteralExpr)@10..11
1503+
Token(TkInt)@10..11 "2"
1504+
Token(TkEndOfLine)@11..12 "\n"
1505+
"#;
1506+
1507+
assert_ast_eq!(
1508+
code,
1509+
result,
1510+
ParserConfig::with_level(LuaLanguageLevel::LuaJITExt)
1511+
);
1512+
}
1513+
14571514
#[test]
14581515
fn test_safe_navigation_dot() {
14591516
let code = "local x = obj?.field\n";

crates/emmylua_parser/src/kind/lua_features.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ pub enum LuaFeatures {
4141
Ternary, // "a ? b : c"
4242
SafeNavigationOperator, // "?."
4343
NilCoalescingOperator, // "??"
44-
ConstStatement, // "const"
44+
ConstDeclaration, // "const"
4545

4646
// luajit3
4747
StringInterpolation, // "`"
@@ -127,7 +127,7 @@ impl LuaFeaturesSet {
127127
set.add(LuaFeatures::Ternary);
128128
set.add(LuaFeatures::SafeNavigationOperator);
129129
set.add(LuaFeatures::NilCoalescingOperator);
130-
set.add(LuaFeatures::ConstStatement);
130+
set.add(LuaFeatures::ConstDeclaration);
131131
set
132132
}
133133

crates/emmylua_parser/src/lexer/lua_lexer.rs

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -109,20 +109,6 @@ impl<'a> LuaLexer<'a> {
109109
"true" => LuaTokenKind::TkTrue,
110110
"until" => LuaTokenKind::TkUntil,
111111
"while" => LuaTokenKind::TkWhile,
112-
"continue" => {
113-
if self.support(LuaFeatures::Continue) {
114-
LuaTokenKind::TkContinue
115-
} else {
116-
LuaTokenKind::TkName
117-
}
118-
}
119-
"const" => {
120-
if self.support(LuaFeatures::ConstStatement) {
121-
LuaTokenKind::TkConst
122-
} else {
123-
LuaTokenKind::TkName
124-
}
125-
}
126112
_ => LuaTokenKind::TkName,
127113
}
128114
}

crates/emmylua_parser/src/lexer/test.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1151,6 +1151,7 @@ LuaTokenData { kind: TkWhitespace, range: SourceRange { start_offset: 2036, leng
11511151
.map(|x| format!("{:?}", x))
11521152
.collect::<Vec<String>>()
11531153
.join("\n");
1154+
11541155
let expected = r#"
11551156
LuaTokenData { kind: TkShebang, range: SourceRange { start_offset: 0, length: 19 } }
11561157
LuaTokenData { kind: TkEndOfLine, range: SourceRange { start_offset: 19, length: 1 } }
@@ -1266,7 +1267,7 @@ LuaTokenData { kind: TkWhitespace, range: SourceRange { start_offset: 311, lengt
12661267
LuaTokenData { kind: TkName, range: SourceRange { start_offset: 312, length: 1 } }
12671268
LuaTokenData { kind: TkEndOfLine, range: SourceRange { start_offset: 313, length: 1 } }
12681269
LuaTokenData { kind: TkWhitespace, range: SourceRange { start_offset: 314, length: 8 } }
1269-
LuaTokenData { kind: TkContinue, range: SourceRange { start_offset: 322, length: 8 } }
1270+
LuaTokenData { kind: TkName, range: SourceRange { start_offset: 322, length: 8 } }
12701271
LuaTokenData { kind: TkEndOfLine, range: SourceRange { start_offset: 330, length: 1 } }
12711272
LuaTokenData { kind: TkWhitespace, range: SourceRange { start_offset: 331, length: 8 } }
12721273
"#;

0 commit comments

Comments
 (0)