From 79ef2a486c9e4b2f3fce63a91cb24fa70ad2cb39 Mon Sep 17 00:00:00 2001 From: Semenov Dmitry Date: Sat, 6 Jan 2024 00:03:31 +0400 Subject: [PATCH 1/3] Fixed id extraction and visitor virtual methods --- .../SimpleTokens/GDIdentifier.cs | 9 ++++ src/GDShrapt.Reader/Walking/GDVisitor.cs | 42 +++++++------------ 2 files changed, 25 insertions(+), 26 deletions(-) diff --git a/src/GDShrapt.Reader/SimpleTokens/GDIdentifier.cs b/src/GDShrapt.Reader/SimpleTokens/GDIdentifier.cs index 1422555..21b8816 100644 --- a/src/GDShrapt.Reader/SimpleTokens/GDIdentifier.cs +++ b/src/GDShrapt.Reader/SimpleTokens/GDIdentifier.cs @@ -183,6 +183,15 @@ public bool TryExtractLocalScopeVisibleDeclarationFromParents(out GDIdentifier d if (node is GDMethodDeclaration method) { + foreach (var item in node.GetMethodScopeDeclarations(startLine)) + { + if (item == this) + { + declaration = item; + return true; + } + } + if (method.Identifier == this) { declaration = method.Identifier; diff --git a/src/GDShrapt.Reader/Walking/GDVisitor.cs b/src/GDShrapt.Reader/Walking/GDVisitor.cs index e58097a..2e0f7bc 100644 --- a/src/GDShrapt.Reader/Walking/GDVisitor.cs +++ b/src/GDShrapt.Reader/Walking/GDVisitor.cs @@ -352,92 +352,82 @@ public virtual void LeftListChild(GDNode node) // Nothing } - public void Visit(GDClassMemberAttributeDeclaration d) + public virtual void Visit(GDClassMemberAttributeDeclaration d) { // Nothing } - public void Left(GDClassMemberAttributeDeclaration d) + public virtual void Left(GDClassMemberAttributeDeclaration d) { // Nothing } - public void Visit(GDAttribute a) + public virtual void Visit(GDAttribute a) { // Nothing } - public void Left(GDAttribute a) + public virtual void Left(GDAttribute a) { // Nothing } - public void Visit(GDGetAccessorBodyDeclaration d) + public virtual void Visit(GDGetAccessorBodyDeclaration d) { // Nothing } - public void Left(GDGetAccessorBodyDeclaration d) + public virtual void Left(GDGetAccessorBodyDeclaration d) { // Nothing } - public void Visit(GDSetAccessorBodyDeclaration d) + public virtual void Visit(GDSetAccessorBodyDeclaration d) { // Nothing } - public void Left(GDSetAccessorBodyDeclaration d) + public virtual void Left(GDSetAccessorBodyDeclaration d) { // Nothing } - public void Visit(GDSetAccessorMethodDeclaration d) + public virtual void Visit(GDSetAccessorMethodDeclaration d) { // Nothing } - public void Left(GDSetAccessorMethodDeclaration d) + public virtual void Left(GDSetAccessorMethodDeclaration d) { // Nothing } - public void Visit(GDSingleTypeNode t) + public virtual void Visit(GDSingleTypeNode t) { // Nothing } - public void Left(GDSingleTypeNode t) + public virtual void Left(GDSingleTypeNode t) { // Nothing } - public void Visit(GDArrayTypeNode t) + public virtual void Visit(GDArrayTypeNode t) { // Nothing } - public void Left(GDArrayTypeNode t) + public virtual void Left(GDArrayTypeNode t) { // Nothing } - public void Visit(GDGetAccessorMethodDeclaration d) + public virtual void Visit(GDGetAccessorMethodDeclaration d) { // Nothing } - public void Left(GDGetAccessorMethodDeclaration d) - { - // Nothing - } - - public virtual void DidLeft(GDExpression expr) - { - // Nothing - } - - public virtual void WillVisit(GDExpression expr) + public virtual void Left(GDGetAccessorMethodDeclaration d) { // Nothing } From 02f2eda991b9aaff7de055188494cf26ac332614 Mon Sep 17 00:00:00 2001 From: Semenov Dmitry Date: Tue, 9 Jan 2024 23:41:36 +0400 Subject: [PATCH 2/3] Fixed Unique node expression. Fixed subtype resolving. Fixed intended comments parsing --- src/GDShrapt.Reader.Tests/BigScriptTests.cs | 13 ++ src/GDShrapt.Reader.Tests/ParsingTests.cs | 30 ++++ .../Expressions/GDGetUniqueNodeExpression.cs | 124 +++++++++++++ .../Resolvers/GDExpressionResolver.cs | 7 + .../Resolvers/GDIntendedResolver.cs | 5 + .../Resolvers/GDResolvingHelper.cs | 15 +- .../Resolvers/GDStatementsResolver.cs | 6 + .../Resolvers/GDTypeResolver.cs | 32 ++++ src/GDShrapt.Reader/SimpleTokens/GDPercent.cs | 12 ++ src/GDShrapt.Reader/Types/GDSubTypeNode.cs | 163 ++++++++++++++++++ src/GDShrapt.Reader/Walking/IGDVisitor.cs | 4 + 11 files changed, 410 insertions(+), 1 deletion(-) create mode 100644 src/GDShrapt.Reader/Expressions/GDGetUniqueNodeExpression.cs create mode 100644 src/GDShrapt.Reader/SimpleTokens/GDPercent.cs create mode 100644 src/GDShrapt.Reader/Types/GDSubTypeNode.cs diff --git a/src/GDShrapt.Reader.Tests/BigScriptTests.cs b/src/GDShrapt.Reader.Tests/BigScriptTests.cs index a97a5ec..00a9c48 100644 --- a/src/GDShrapt.Reader.Tests/BigScriptTests.cs +++ b/src/GDShrapt.Reader.Tests/BigScriptTests.cs @@ -61,5 +61,18 @@ public void BigScriptParsingTest4() AssertHelper.CompareCodeStrings(fileText, declaration.ToString()); AssertHelper.NoInvalidTokens(declaration); } + + [TestMethod] + public void ScriptTest1() + { + var reader = new GDScriptReader(); + + var code = "# _at_position is not used because it doesn't matter where on the panel\r\n# the item is dropped\r\nfunc _can_drop_data(_at_position: Vector2, data: Variant) -> bool:\t\r\n\tif data is InventoryItem:\r\n\t\t#This is the text that displays uupon pulling an item out.\r\n\t\t%summary.text =( str(\"atk:\" + str(data.physicalattack) +'\\n' + data.lore))\r\n\t\tif type == InventoryItem.Type.MAIN:\r\n\t\t\tif get_child_count() == 0:\r\n\t\t\t\treturn true\r\n\t\t\telse:\r\n\t\t\t\t# Swap two items\r\n\t\t\t\treturn get_child(0).type == data.type\r\n\t\telse:\r\n\t\t\treturn data.type == type\r\n\t\t\t\r\n\t\r\n\treturn false"; + + var declaration = reader.ParseFileContent(code); + + AssertHelper.CompareCodeStrings(code, declaration.ToString()); + AssertHelper.NoInvalidTokens(declaration); + } } } diff --git a/src/GDShrapt.Reader.Tests/ParsingTests.cs b/src/GDShrapt.Reader.Tests/ParsingTests.cs index e679b73..5eabd79 100644 --- a/src/GDShrapt.Reader.Tests/ParsingTests.cs +++ b/src/GDShrapt.Reader.Tests/ParsingTests.cs @@ -2303,5 +2303,35 @@ public void StatementAtributesTest2() AssertHelper.CompareCodeStrings(code, @class.ToString()); AssertHelper.NoInvalidTokens(@class); } + + [TestMethod] + public void ParseGetNodeNewSyntax() + { + var reader = new GDScriptReader(); + + var code = @"if Input.is_anything_pressed() == false: + %summary.text = ""physical attack: "" + str(Physical_attack_sum) + '\n'"; + + var @class = reader.ParseStatement(code); + + AssertHelper.CompareCodeStrings(code, @class.ToString()); + AssertHelper.NoInvalidTokens(@class); + } + + [TestMethod] + public void ParseScriptSubtype() + { + var reader = new GDScriptReader(); + + var code = @"# Custom init function so that it doesn't error +func init(t: InventoryItem.Type, cms: Vector2) -> void: + type = t + custom_minimum_size = cms"; + + var @class = reader.ParseFileContent(code); + + AssertHelper.CompareCodeStrings(code, @class.ToString()); + AssertHelper.NoInvalidTokens(@class); + } } } \ No newline at end of file diff --git a/src/GDShrapt.Reader/Expressions/GDGetUniqueNodeExpression.cs b/src/GDShrapt.Reader/Expressions/GDGetUniqueNodeExpression.cs new file mode 100644 index 0000000..081578c --- /dev/null +++ b/src/GDShrapt.Reader/Expressions/GDGetUniqueNodeExpression.cs @@ -0,0 +1,124 @@ +namespace GDShrapt.Reader +{ + public sealed class GDGetUniqueNodeExpression : GDExpression, + ITokenOrSkipReceiver, + ITokenOrSkipReceiver + { + public override int Priority => GDHelper.GetOperationPriority(GDOperationType.GetNode); + + public GDPercent Percent + { + get => _form.Token0; + set => _form.Token0 = value; + } + + public GDPathList Path + { + get => _form.Token1 ?? (_form.Token1 = new GDPathList()); + set => _form.Token1 = value; + } + + public enum State + { + Percent, + Path, + Completed + } + + readonly GDTokensForm _form; + public override GDTokensForm Form => _form; + public GDTokensForm TypedForm => _form; + public GDGetUniqueNodeExpression() + { + _form = new GDTokensForm(this); + } + + internal override void HandleChar(char c, GDReadingState state) + { + switch (_form.State) + { + case State.Percent: + if (this.ResolveSpaceToken(c, state)) + return; + this.ResolvePercent(c, state); + break; + case State.Path: + _form.State = State.Completed; + + if (this.ResolveSpaceToken(c, state)) + return; + state.PushAndPass(Path, c); + break; + default: + state.PopAndPass(c); + break; + } + } + + internal override void HandleNewLineChar(GDReadingState state) + { + state.PopAndPassNewLine(); + } + + public override GDNode CreateEmptyInstance() + { + return new GDGetNodeExpression(); + } + + internal override void Visit(IGDVisitor visitor) + { + visitor.Visit(this); + } + + internal override void Left(IGDVisitor visitor) + { + visitor.Left(this); + } + + void ITokenReceiver.HandleReceivedToken(GDPercent token) + { + if (_form.IsOrLowerState(State.Percent)) + { + _form.State = State.Path; + Percent = token; + return; + } + + throw new GDInvalidStateException(); + } + + void ITokenSkipReceiver.HandleReceivedTokenSkip() + { + if (_form.IsOrLowerState(State.Percent)) + { + _form.State = State.Path; + return; + } + + throw new GDInvalidStateException(); + } + + void ITokenReceiver.HandleReceivedToken(GDPathList token) + { + if (_form.IsOrLowerState(State.Path)) + { + _form.State = State.Path; + Path = token; + return; + } + + throw new GDInvalidStateException(); + } + + void ITokenSkipReceiver.HandleReceivedTokenSkip() + { + if (_form.IsOrLowerState(State.Path)) + { + _form.State = State.Path; + return; + } + + throw new GDInvalidStateException(); + } + } +} diff --git a/src/GDShrapt.Reader/Resolvers/GDExpressionResolver.cs b/src/GDShrapt.Reader/Resolvers/GDExpressionResolver.cs index cf90518..9247a0e 100644 --- a/src/GDShrapt.Reader/Resolvers/GDExpressionResolver.cs +++ b/src/GDShrapt.Reader/Resolvers/GDExpressionResolver.cs @@ -138,6 +138,13 @@ internal override void HandleChar(char c, GDReadingState state) state.PassChar(c); return; } + + if (c == '%') + { + PushAndSave(state, new GDGetUniqueNodeExpression()); + state.PassChar(c); + return; + } } else { diff --git a/src/GDShrapt.Reader/Resolvers/GDIntendedResolver.cs b/src/GDShrapt.Reader/Resolvers/GDIntendedResolver.cs index 5506593..73ff833 100644 --- a/src/GDShrapt.Reader/Resolvers/GDIntendedResolver.cs +++ b/src/GDShrapt.Reader/Resolvers/GDIntendedResolver.cs @@ -241,8 +241,13 @@ protected void SendIntendationTokensToOwner() protected void PassIntendationSequence(GDReadingState state) { + if (_intendationTokensSent) + return; + for (int i = 0; i < _sequenceBuilder.Length; i++) state.PassChar(_sequenceBuilder[i]); + + ResetIntendation(); } protected void ResetIntendation() diff --git a/src/GDShrapt.Reader/Resolvers/GDResolvingHelper.cs b/src/GDShrapt.Reader/Resolvers/GDResolvingHelper.cs index 6ffb3e6..5c35042 100644 --- a/src/GDShrapt.Reader/Resolvers/GDResolvingHelper.cs +++ b/src/GDShrapt.Reader/Resolvers/GDResolvingHelper.cs @@ -29,6 +29,19 @@ public static void ResolveKeyword(this ITokenOrSkipReceiver receiver, char state.PushAndPass(new GDKeywordResolver(receiver), c); } + public static bool ResolvePercent(this ITokenOrSkipReceiver receiver, char c, GDReadingState state) + { + var result = c == '%'; + if (result) + receiver.HandleReceivedToken(new GDPercent()); + else + { + receiver.HandleReceivedTokenSkip(); + state.PassChar(c); + } + return result; + } + public static bool ResolveDollar(this ITokenOrSkipReceiver receiver, char c, GDReadingState state) { var result = c == '$'; @@ -376,7 +389,7 @@ public static bool ResolveCommentToken(this ITokenReceiver receiver, { if (IsCommentStartChar(c)) { - receiver.HandleReceivedToken(new GDComment()); + receiver.HandleReceivedToken(state.Push(new GDComment())); state.PassChar(c); return true; } diff --git a/src/GDShrapt.Reader/Resolvers/GDStatementsResolver.cs b/src/GDShrapt.Reader/Resolvers/GDStatementsResolver.cs index f5a0dbf..ddf8a76 100644 --- a/src/GDShrapt.Reader/Resolvers/GDStatementsResolver.cs +++ b/src/GDShrapt.Reader/Resolvers/GDStatementsResolver.cs @@ -30,6 +30,12 @@ internal override void HandleCharAfterIntendation(char c, GDReadingState state) if (_resolvedAsExpression) { + if (c.IsExpressionStopChar()) + { + Owner.HandleAsInvalidToken(c, state, x => x.IsSpace() || x.IsNewLine()); + return; + } + // Resolving multiple expressions on the same string var statement = new GDExpressionStatement(); Owner.HandleReceivedToken(statement); diff --git a/src/GDShrapt.Reader/Resolvers/GDTypeResolver.cs b/src/GDShrapt.Reader/Resolvers/GDTypeResolver.cs index d7ae8e9..d366737 100644 --- a/src/GDShrapt.Reader/Resolvers/GDTypeResolver.cs +++ b/src/GDShrapt.Reader/Resolvers/GDTypeResolver.cs @@ -94,6 +94,15 @@ internal override void HandleChar(char c, GDReadingState state) Owner.HandleReceivedToken(arrayTypeNode); state.Push(arrayTypeNode); + + if (_space != null) + { + for (int i = 0; i < _space.Sequence.Length; i++) + state.PassChar(_space.Sequence[i]); + + _space = null; + } + state.PassChar(c); return; } @@ -104,6 +113,29 @@ internal override void HandleChar(char c, GDReadingState state) return; } + if (c == '.' && _type != null) + { + var subTypeNode = new GDSubTypeNode(); + subTypeNode.Add(new GDSingleTypeNode() { Type = _type }); + + Owner.HandleReceivedToken(subTypeNode); + _type = null; + state.Pop(); + + state.Push(subTypeNode); + + if (_space != null) + { + for (int i = 0; i < _space.Sequence.Length; i++) + state.PassChar(_space.Sequence[i]); + + _space = null; + } + + state.PassChar(c); + return; + } + state.Pop(); Complete(state); state.PassChar(c); diff --git a/src/GDShrapt.Reader/SimpleTokens/GDPercent.cs b/src/GDShrapt.Reader/SimpleTokens/GDPercent.cs new file mode 100644 index 0000000..37ee937 --- /dev/null +++ b/src/GDShrapt.Reader/SimpleTokens/GDPercent.cs @@ -0,0 +1,12 @@ +namespace GDShrapt.Reader +{ + public sealed class GDPercent : GDSingleCharToken + { + public override char Char => '%'; + + public override GDSyntaxToken Clone() + { + return new GDPercent(); + } + } +} diff --git a/src/GDShrapt.Reader/Types/GDSubTypeNode.cs b/src/GDShrapt.Reader/Types/GDSubTypeNode.cs new file mode 100644 index 0000000..0801704 --- /dev/null +++ b/src/GDShrapt.Reader/Types/GDSubTypeNode.cs @@ -0,0 +1,163 @@ +namespace GDShrapt.Reader +{ + public class GDSubTypeNode : GDTypeNode, + ITokenOrSkipReceiver, + ITokenOrSkipReceiver, + ITokenOrSkipReceiver + { + public override bool IsArray => false; + public override GDTypeNode SubType => null; + public GDTypeNode OverType + { + get => _form.Token0; + set => _form.Token0 = value; + } + + public GDPoint Point + { + get => _form.Token1; + set => _form.Token1 = value; + } + + public GDType Type + { + get => _form.Token2; + set => _form.Token2 = value; + } + + public enum State + { + OverType, + Point, + Type, + Completed + } + + readonly GDTokensForm _form; + public override GDTokensForm Form => _form; + public GDTokensForm TypedForm => _form; + + public GDSubTypeNode() + { + _form = new GDTokensForm(this); + } + + public override GDNode CreateEmptyInstance() + { + return new GDArrayTypeNode(); + } + + internal override void Visit(IGDVisitor visitor) + { + visitor.Visit(this); + } + + internal override void Left(IGDVisitor visitor) + { + visitor.Left(this); + } + + internal override void HandleChar(char c, GDReadingState state) + { + switch (_form.State) + { + case State.OverType: + if (!this.ResolveSpaceToken(c, state)) + ((ITokenOrSkipReceiver)this).ResolveType(c, state); + break; + case State.Point: + if (!this.ResolveSpaceToken(c, state)) + this.ResolvePoint(c, state); + break; + case State.Type: + if (!this.ResolveSpaceToken(c, state)) + ((ITokenOrSkipReceiver)this).ResolveType(c, state); + break; + default: + state.PopAndPass(c); + break; + } + } + + internal override void HandleNewLineChar(GDReadingState state) + { + _form.State = State.Completed; + state.PopAndPassNewLine(); + } + + + void ITokenReceiver.HandleReceivedToken(GDTypeNode token) + { + if (_form.State == State.OverType) + { + _form.State = State.Point; + OverType = token; + return; + } + + throw new GDInvalidStateException(); + } + + void ITokenSkipReceiver.HandleReceivedTokenSkip() + { + if (_form.State == State.OverType) + { + _form.State = State.Point; + return; + } + + throw new GDInvalidStateException(); + } + + void ITokenReceiver.HandleReceivedToken(GDPoint token) + { + if (_form.State == State.Point) + { + _form.State = State.Type; + Point = token; + return; + } + + throw new GDInvalidStateException(); + } + + void ITokenSkipReceiver.HandleReceivedTokenSkip() + { + if (_form.State == State.Point) + { + _form.State = State.Type; + return; + } + + throw new GDInvalidStateException(); + } + + void ITokenReceiver.HandleReceivedToken(GDType token) + { + if (_form.State == State.Type) + { + _form.State = State.Completed; + Type = token; + return; + } + + throw new GDInvalidStateException(); + } + + void ITokenSkipReceiver.HandleReceivedTokenSkip() + { + if (_form.State == State.Type) + { + _form.State = State.Completed; + return; + } + + throw new GDInvalidStateException(); + } + + public override string BuildName() + { + return $"{OverType?.BuildName()}.{Type?.ToString()}"; + } + } +} diff --git a/src/GDShrapt.Reader/Walking/IGDVisitor.cs b/src/GDShrapt.Reader/Walking/IGDVisitor.cs index 745aa88..aecd740 100644 --- a/src/GDShrapt.Reader/Walking/IGDVisitor.cs +++ b/src/GDShrapt.Reader/Walking/IGDVisitor.cs @@ -162,5 +162,9 @@ public interface IGDVisitor : IGDBaseVisitor void Visit(GDTripleDoubleQuotasStringNode sn); void Visit(GDDoubleQuotasStringNode sn); void Visit(GDSingleQuotasStringNode sn); + void Visit(GDGetUniqueNodeExpression e); + void Left(GDGetUniqueNodeExpression e); + void Visit(GDSubTypeNode t); + void Left(GDSubTypeNode t); } } \ No newline at end of file From 556d74bb1988c1ceb896f87ab315dce6e4dbb987 Mon Sep 17 00:00:00 2001 From: Semenov Dmitry Date: Fri, 12 Jan 2024 22:11:18 +0400 Subject: [PATCH 3/3] Fixed intendation bugs in lambdas and match cases --- src/GDShrapt.Reader.Tests/BigScriptTests.cs | 14 ++ .../GDShrapt.Reader.Tests.csproj | 3 + src/GDShrapt.Reader.Tests/ParsingTests.cs | 63 +++++++++ src/GDShrapt.Reader.Tests/Scripts/Sample5.gd | 42 ++++++ src/GDShrapt.Reader/Basics/GDOperationType.cs | 1 + .../GDDictionaryKeyValueDeclaration.cs | 11 +- .../Declarations/GDEnumValueDeclaration.cs | 11 +- .../Declarations/GDMethodDeclaration.cs | 2 +- .../Declarations/GDParameterDeclaration.cs | 10 +- .../Declarations/GDVariableDeclaration.cs | 2 +- .../GDArrayInitializerExpression.cs | 10 +- .../Expressions/GDAwaitExpression.cs | 12 +- .../Expressions/GDBracketExpression.cs | 10 +- .../Expressions/GDCallExpression.cs | 11 +- .../GDDictionaryInitializerExpression.cs | 11 +- .../Expressions/GDDualOperatorExpression.cs | 12 +- .../Expressions/GDGetUniqueNodeExpression.cs | 40 +++--- .../Expressions/GDIfExpression.cs | 14 +- .../Expressions/GDIndexerExpression.cs | 17 ++- .../Expressions/GDMemberOperatorExpression.cs | 10 +- .../Expressions/GDMethodExpression.cs | 2 +- .../Expressions/GDReturnExpression.cs | 10 +- .../Expressions/GDSingleOperatorExpression.cs | 10 +- .../Expressions/GDYieldExpression.cs | 10 +- src/GDShrapt.Reader/GDScriptReader.cs | 2 +- .../GDDictionaryKeyValueDeclarationList.cs | 13 +- .../Lists/GDExpressionsList.cs | 13 +- .../Lists/GDStringPartsList.cs | 13 +- .../Resolvers/GDExpressionResolver.cs | 43 +++--- .../Resolvers/GDResolvingHelper.cs | 19 ++- .../Resolvers/GDStringPartResolver.cs | 14 +- .../SimpleTokens/GDExternalName.cs | 130 ++++++++++++++++++ .../Statements/GDExpressionStatement.cs | 2 +- .../Statements/GDForStatement.cs | 4 +- .../Statements/GDMatchStatement.cs | 2 +- .../GDVariableDeclarationStatement.cs | 2 +- .../Statements/GDWhileStatement.cs | 4 +- .../Statements/IfStatement/GDElifBranch.cs | 4 +- .../Statements/IfStatement/GDElseBranch.cs | 2 +- .../Statements/IfStatement/GDIfBranch.cs | 2 +- 40 files changed, 512 insertions(+), 95 deletions(-) create mode 100644 src/GDShrapt.Reader.Tests/Scripts/Sample5.gd create mode 100644 src/GDShrapt.Reader/SimpleTokens/GDExternalName.cs diff --git a/src/GDShrapt.Reader.Tests/BigScriptTests.cs b/src/GDShrapt.Reader.Tests/BigScriptTests.cs index 00a9c48..5e610c8 100644 --- a/src/GDShrapt.Reader.Tests/BigScriptTests.cs +++ b/src/GDShrapt.Reader.Tests/BigScriptTests.cs @@ -62,6 +62,20 @@ public void BigScriptParsingTest4() AssertHelper.NoInvalidTokens(declaration); } + [TestMethod] + public void BigScriptParsingTest5() + { + var reader = new GDScriptReader(); + + var path = Path.Combine("Scripts", "Sample5.gd"); + var declaration = reader.ParseFile(path); + + var fileText = File.ReadAllText(path); + + AssertHelper.CompareCodeStrings(fileText, declaration.ToString()); + AssertHelper.NoInvalidTokens(declaration); + } + [TestMethod] public void ScriptTest1() { diff --git a/src/GDShrapt.Reader.Tests/GDShrapt.Reader.Tests.csproj b/src/GDShrapt.Reader.Tests/GDShrapt.Reader.Tests.csproj index 0281b75..ec0df5f 100644 --- a/src/GDShrapt.Reader.Tests/GDShrapt.Reader.Tests.csproj +++ b/src/GDShrapt.Reader.Tests/GDShrapt.Reader.Tests.csproj @@ -19,6 +19,9 @@ + + PreserveNewest + PreserveNewest diff --git a/src/GDShrapt.Reader.Tests/ParsingTests.cs b/src/GDShrapt.Reader.Tests/ParsingTests.cs index 5eabd79..4353aed 100644 --- a/src/GDShrapt.Reader.Tests/ParsingTests.cs +++ b/src/GDShrapt.Reader.Tests/ParsingTests.cs @@ -2333,5 +2333,68 @@ func init(t: InventoryItem.Type, cms: Vector2) -> void: AssertHelper.CompareCodeStrings(code, @class.ToString()); AssertHelper.NoInvalidTokens(@class); } + + [TestMethod] + public void ParseLambdaExpressionWithStatementTest() + { + var reader = new GDScriptReader(); + + var code = @" +class_name Helper + +func print_hello(): + var messageGenerator = func(): return ""Hello, World!"" + + print(messageGenerator()) +"; + + var @class = reader.ParseFileContent(code); + + Assert.AreEqual(2, @class.Methods.First().Statements.Count); + AssertHelper.CompareCodeStrings(code, @class.ToString()); + AssertHelper.NoInvalidTokens(@class); + } + + [TestMethod] + public void ParseMatchInMethodTest() + { + var reader = new GDScriptReader(); + + var code = @" +class_name Helper + +func switch(x): + match x: + 1: + print(""It's one!"") + 2: + print(""It's one times two!"") + var new_var: + print(""It's not 1 or 2, it's "", new_var) +"; + + var @class = reader.ParseFileContent(code); + Assert.AreEqual(1, @class.Methods.Count()); + + var method = @class.Methods.First(); + Assert.AreEqual(1, method.Statements.Count); + + var statement = method.Statements.First(); + + Assert.IsInstanceOfType(statement, typeof(GDMatchStatement)); + + var match = (GDMatchStatement)statement; + + Assert.AreEqual(3, match.Cases.Count); + + for (int i = 0; i < match.Cases.Count; i++) + { + var @case = match.Cases[i]; + Assert.AreEqual(1, @case.Statements.Count); + } + + AssertHelper.CompareCodeStrings(code, @class.ToString()); + AssertHelper.NoInvalidTokens(@class); + } } } \ No newline at end of file diff --git a/src/GDShrapt.Reader.Tests/Scripts/Sample5.gd b/src/GDShrapt.Reader.Tests/Scripts/Sample5.gd new file mode 100644 index 0000000..bd9fe1b --- /dev/null +++ b/src/GDShrapt.Reader.Tests/Scripts/Sample5.gd @@ -0,0 +1,42 @@ +extends PanelContainer +class_name InventorySlot + + +@export var type: InventoryItem.Type + + +# Custom init function so that it doesn't error +func init(t: InventoryItem.Type, cms: Vector2) -> void: + type = t + custom_minimum_size = cms + + +# _at_position is not used because it doesn't matter where on the panel +# the item is dropped +func _can_drop_data(_at_position: Vector2, data: Variant) -> bool: + if data is InventoryItem: + #This is the text that displays uupon pulling an item out. + %summary.text =( str("atk:" + str(data.physicalattack) +'\n' + data.lore)) + if type == InventoryItem.Type.MAIN: + if get_child_count() == 0: + return true + else: + # Swap two items + return get_child(0).type == data.type + else: + return data.type == type + + + return false + + +# _at_position is not used because it doesn't matter where on the panel +# the item is dropped +func _drop_data(_at_position: Vector2, data: Variant) -> void: + if get_child_count() > 0: + var item := get_child(0) + if item == data: return + remove_child(item) + data.get_parent().add_child(item) + data.get_parent().remove_child(data) + add_child(data) diff --git a/src/GDShrapt.Reader/Basics/GDOperationType.cs b/src/GDShrapt.Reader/Basics/GDOperationType.cs index b454a6c..f015850 100644 --- a/src/GDShrapt.Reader/Basics/GDOperationType.cs +++ b/src/GDShrapt.Reader/Basics/GDOperationType.cs @@ -14,6 +14,7 @@ public enum GDOperationType Pass, MatchCaseVariable, DictionaryInitializer, + GetUniqueNode, GetNode, NodePath, If, diff --git a/src/GDShrapt.Reader/Declarations/GDDictionaryKeyValueDeclaration.cs b/src/GDShrapt.Reader/Declarations/GDDictionaryKeyValueDeclaration.cs index 889f120..0e9d7f0 100644 --- a/src/GDShrapt.Reader/Declarations/GDDictionaryKeyValueDeclaration.cs +++ b/src/GDShrapt.Reader/Declarations/GDDictionaryKeyValueDeclaration.cs @@ -37,6 +37,13 @@ public enum State } readonly GDTokensForm _form; + readonly int _intendation; + + internal GDDictionaryKeyValueDeclaration(int intendation) + { + _form = new GDTokensForm(this); + _intendation = intendation; + } public GDDictionaryKeyValueDeclaration() { @@ -53,7 +60,7 @@ internal override void HandleChar(char c, GDReadingState state) switch (_form.State) { case State.Key: - this.ResolveExpression(c, state); + this.ResolveExpression(c, state, _intendation); break; case State.ColonOrAssign: if (!_checkedColon) @@ -62,7 +69,7 @@ internal override void HandleChar(char c, GDReadingState state) this.ResolveAssign(c, state); break; case State.Value: - this.ResolveExpression(c, state); + this.ResolveExpression(c, state, _intendation); break; default: state.PopAndPass(c); diff --git a/src/GDShrapt.Reader/Declarations/GDEnumValueDeclaration.cs b/src/GDShrapt.Reader/Declarations/GDEnumValueDeclaration.cs index b4e41e0..8170b72 100644 --- a/src/GDShrapt.Reader/Declarations/GDEnumValueDeclaration.cs +++ b/src/GDShrapt.Reader/Declarations/GDEnumValueDeclaration.cs @@ -38,8 +38,17 @@ public enum State } readonly GDTokensForm _form; + readonly int _intendation; + public override GDTokensForm Form => _form; public GDTokensForm TypedForm => _form; + + internal GDEnumValueDeclaration(int intendation) + { + _form = new GDTokensForm(this); + _intendation = intendation; + } + public GDEnumValueDeclaration() { _form = new GDTokensForm(this); @@ -66,7 +75,7 @@ internal override void HandleChar(char c, GDReadingState state) this.ResolveAssign(c, state); break; case State.Value: - this.ResolveExpression(c, state); + this.ResolveExpression(c, state, _intendation); break; default: state.PopAndPass(c); diff --git a/src/GDShrapt.Reader/Declarations/GDMethodDeclaration.cs b/src/GDShrapt.Reader/Declarations/GDMethodDeclaration.cs index b68210d..21b8bc4 100644 --- a/src/GDShrapt.Reader/Declarations/GDMethodDeclaration.cs +++ b/src/GDShrapt.Reader/Declarations/GDMethodDeclaration.cs @@ -205,7 +205,7 @@ internal override void HandleChar(char c, GDReadingState state) break; case State.Expression: - this.ResolveExpression(c, state); + this.ResolveExpression(c, state, Intendation); break; case State.Statements: this.HandleAsInvalidToken(c, state, x => x.IsSpace() || x.IsNewLine()); diff --git a/src/GDShrapt.Reader/Declarations/GDParameterDeclaration.cs b/src/GDShrapt.Reader/Declarations/GDParameterDeclaration.cs index 61fbb04..25c5a2c 100644 --- a/src/GDShrapt.Reader/Declarations/GDParameterDeclaration.cs +++ b/src/GDShrapt.Reader/Declarations/GDParameterDeclaration.cs @@ -44,8 +44,16 @@ public enum State } readonly GDTokensForm _form; + readonly int _intendation; + public override GDTokensForm Form => _form; public GDTokensForm TypedForm => _form; + internal GDParameterDeclaration(int intendation) + { + _form = new GDTokensForm(this); + _intendation = intendation; + } + public GDParameterDeclaration() { _form = new GDTokensForm(this); @@ -71,7 +79,7 @@ internal override void HandleChar(char c, GDReadingState state) this.ResolveAssign(c, state); break; case State.DefaultValue: - this.ResolveExpression(c, state); + this.ResolveExpression(c, state, _intendation); break; default: state.PopAndPass(c); diff --git a/src/GDShrapt.Reader/Declarations/GDVariableDeclaration.cs b/src/GDShrapt.Reader/Declarations/GDVariableDeclaration.cs index c72c24b..dbffd62 100644 --- a/src/GDShrapt.Reader/Declarations/GDVariableDeclaration.cs +++ b/src/GDShrapt.Reader/Declarations/GDVariableDeclaration.cs @@ -155,7 +155,7 @@ internal override void HandleChar(char c, GDReadingState state) state.PushAndPass(new GDSingleCharTokenResolver(this), c); break; case State.Initializer: - state.PushAndPass(new GDExpressionResolver(this), c); + state.PushAndPass(new GDExpressionResolver(this, Intendation), c); break; case State.FirstAccessorDeclarationNode: state.PushAndPass(new GDSetGetAccessorsResolver(this, true, Intendation + 1), c); diff --git a/src/GDShrapt.Reader/Expressions/GDArrayInitializerExpression.cs b/src/GDShrapt.Reader/Expressions/GDArrayInitializerExpression.cs index dc4b1cf..b7ab5c9 100644 --- a/src/GDShrapt.Reader/Expressions/GDArrayInitializerExpression.cs +++ b/src/GDShrapt.Reader/Expressions/GDArrayInitializerExpression.cs @@ -14,7 +14,7 @@ public GDSquareOpenBracket SquareOpenBracket } public GDExpressionsList Values { - get => _form.Token1 ?? (_form.Token1 = new GDExpressionsList()); + get => _form.Token1 ?? (_form.Token1 = new GDExpressionsList(_intendation)); set => _form.Token1 = value; } public GDSquareCloseBracket SquareCloseBracket @@ -31,9 +31,17 @@ public enum State Completed } + readonly int _intendation; readonly GDTokensForm _form; public override GDTokensForm Form => _form; public GDTokensForm TypedForm => _form; + + internal GDArrayInitializerExpression(int intendation) + { + _intendation = intendation; + _form = new GDTokensForm(this); + } + public GDArrayInitializerExpression() { _form = new GDTokensForm(this); diff --git a/src/GDShrapt.Reader/Expressions/GDAwaitExpression.cs b/src/GDShrapt.Reader/Expressions/GDAwaitExpression.cs index 6b3b2da..2464d41 100644 --- a/src/GDShrapt.Reader/Expressions/GDAwaitExpression.cs +++ b/src/GDShrapt.Reader/Expressions/GDAwaitExpression.cs @@ -22,7 +22,7 @@ public GDOpenBracket OpenBracket } public GDExpressionsList Parameters { - get => _form.Token2 ?? (_form.Token2 = new GDExpressionsList()); + get => _form.Token2 ?? (_form.Token2 = new GDExpressionsList(_intendation)); set => _form.Token2 = value; } public GDCloseBracket CloseBracket @@ -40,9 +40,17 @@ public enum State Completed } + readonly int _intendation; readonly GDTokensForm _form; public override GDTokensForm Form => _form; public GDTokensForm TypedForm => _form; + + internal GDAwaitExpression(int intendation) + { + _intendation = intendation; + _form = new GDTokensForm(this); + } + public GDAwaitExpression() { _form = new GDTokensForm(this); @@ -88,7 +96,7 @@ internal override void HandleNewLineChar(GDReadingState state) public override GDNode CreateEmptyInstance() { - return new GDYieldExpression(); + return new GDAwaitExpression(); } internal override void Visit(IGDVisitor visitor) diff --git a/src/GDShrapt.Reader/Expressions/GDBracketExpression.cs b/src/GDShrapt.Reader/Expressions/GDBracketExpression.cs index 756b32b..177dc0a 100644 --- a/src/GDShrapt.Reader/Expressions/GDBracketExpression.cs +++ b/src/GDShrapt.Reader/Expressions/GDBracketExpression.cs @@ -34,8 +34,16 @@ public enum State } readonly GDTokensForm _form; + readonly int _intendation; + public override GDTokensForm Form => _form; public GDTokensForm TypedForm => _form; + internal GDBracketExpression(int intendation) + { + _form = new GDTokensForm(this); + _intendation = intendation; + } + public GDBracketExpression() { _form = new GDTokensForm(this); @@ -51,7 +59,7 @@ internal override void HandleChar(char c, GDReadingState state) break; case State.Expression: if (!this.ResolveSpaceToken(c, state)) - this.ResolveExpression(c, state, this); + this.ResolveExpression(c, state, _intendation, this); break; case State.CloseBracket: if (!this.ResolveSpaceToken(c, state)) diff --git a/src/GDShrapt.Reader/Expressions/GDCallExpression.cs b/src/GDShrapt.Reader/Expressions/GDCallExpression.cs index 7d8eff7..216fb4a 100644 --- a/src/GDShrapt.Reader/Expressions/GDCallExpression.cs +++ b/src/GDShrapt.Reader/Expressions/GDCallExpression.cs @@ -44,8 +44,17 @@ public enum State } readonly GDTokensForm _form; + readonly int _intendation; + public override GDTokensForm Form => _form; public GDTokensForm TypedForm => _form; + + internal GDCallExpression(int intendation) + { + _form = new GDTokensForm(this); + _intendation = intendation; + } + public GDCallExpression() { _form = new GDTokensForm(this); @@ -57,7 +66,7 @@ internal override void HandleChar(char c, GDReadingState state) { case State.Caller: if (!this.ResolveSpaceToken(c, state)) - this.ResolveExpression(c, state); + this.ResolveExpression(c, state, _intendation); break; case State.OpenBracket: if (!this.ResolveSpaceToken(c, state)) diff --git a/src/GDShrapt.Reader/Expressions/GDDictionaryInitializerExpression.cs b/src/GDShrapt.Reader/Expressions/GDDictionaryInitializerExpression.cs index 9de878d..0a65741 100644 --- a/src/GDShrapt.Reader/Expressions/GDDictionaryInitializerExpression.cs +++ b/src/GDShrapt.Reader/Expressions/GDDictionaryInitializerExpression.cs @@ -13,7 +13,7 @@ public GDFigureOpenBracket FigureOpenBracket } public GDDictionaryKeyValueDeclarationList KeyValues { - get => _form.Token1 ?? (_form.Token1 = new GDDictionaryKeyValueDeclarationList()); + get => _form.Token1 ?? (_form.Token1 = new GDDictionaryKeyValueDeclarationList(_intendation)); set => _form.Token1 = value; } public GDFigureCloseBracket FigureCloseBracket @@ -31,8 +31,17 @@ public enum State } readonly GDTokensForm _form; + readonly int _intendation; + public override GDTokensForm Form => _form; public GDTokensForm TypedForm => _form; + + internal GDDictionaryInitializerExpression(int intendation) + { + _form = new GDTokensForm(this); + _intendation = intendation; + } + public GDDictionaryInitializerExpression() { _form = new GDTokensForm(this); diff --git a/src/GDShrapt.Reader/Expressions/GDDualOperatorExpression.cs b/src/GDShrapt.Reader/Expressions/GDDualOperatorExpression.cs index 1bf705c..e29cf09 100644 --- a/src/GDShrapt.Reader/Expressions/GDDualOperatorExpression.cs +++ b/src/GDShrapt.Reader/Expressions/GDDualOperatorExpression.cs @@ -38,18 +38,20 @@ public enum State Completed } + readonly int _intendation; readonly GDTokensForm _form; public bool AllowNewLines { get; } public override GDTokensForm Form => _form; public GDTokensForm TypedForm => _form; public GDDualOperatorExpression() - : this(true) + : this(0, true) { } - public GDDualOperatorExpression(bool allowNewLines) + public GDDualOperatorExpression(int intendation, bool allowNewLines) { + _intendation = intendation; _form = new GDTokensForm(this); AllowNewLines = allowNewLines; } @@ -60,7 +62,7 @@ internal override void HandleChar(char c, GDReadingState state) { case State.LeftExpression: if (!this.ResolveSpaceToken(c, state)) - this.ResolveExpression(c, state); + this.ResolveExpression(c, state, _intendation); break; case State.DualOperator: // Indicates that it isn't a normal expression. The parent should handle the state. @@ -76,7 +78,7 @@ internal override void HandleChar(char c, GDReadingState state) break; case State.RightExpression: if (!this.ResolveSpaceToken(c, state)) - this.ResolveExpression(c, state); + this.ResolveExpression(c, state, _intendation); break; default: state.PopAndPass(c); @@ -160,7 +162,7 @@ public override GDExpression SwapRight(GDExpression expression) public override GDNode CreateEmptyInstance() { - return new GDDualOperatorExpression(AllowNewLines); + return new GDDualOperatorExpression(0, AllowNewLines); } internal override void Visit(IGDVisitor visitor) diff --git a/src/GDShrapt.Reader/Expressions/GDGetUniqueNodeExpression.cs b/src/GDShrapt.Reader/Expressions/GDGetUniqueNodeExpression.cs index 081578c..be271ad 100644 --- a/src/GDShrapt.Reader/Expressions/GDGetUniqueNodeExpression.cs +++ b/src/GDShrapt.Reader/Expressions/GDGetUniqueNodeExpression.cs @@ -2,9 +2,9 @@ { public sealed class GDGetUniqueNodeExpression : GDExpression, ITokenOrSkipReceiver, - ITokenOrSkipReceiver + ITokenOrSkipReceiver { - public override int Priority => GDHelper.GetOperationPriority(GDOperationType.GetNode); + public override int Priority => GDHelper.GetOperationPriority(GDOperationType.GetUniqueNode); public GDPercent Percent { @@ -12,25 +12,25 @@ public GDPercent Percent set => _form.Token0 = value; } - public GDPathList Path + public GDExternalName Name { - get => _form.Token1 ?? (_form.Token1 = new GDPathList()); + get => _form.Token1; set => _form.Token1 = value; } public enum State { Percent, - Path, + Name, Completed } - readonly GDTokensForm _form; + readonly GDTokensForm _form; public override GDTokensForm Form => _form; - public GDTokensForm TypedForm => _form; + public GDTokensForm TypedForm => _form; public GDGetUniqueNodeExpression() { - _form = new GDTokensForm(this); + _form = new GDTokensForm(this); } internal override void HandleChar(char c, GDReadingState state) @@ -42,12 +42,10 @@ internal override void HandleChar(char c, GDReadingState state) return; this.ResolvePercent(c, state); break; - case State.Path: - _form.State = State.Completed; - + case State.Name: if (this.ResolveSpaceToken(c, state)) return; - state.PushAndPass(Path, c); + this.ResolveExternalName(c, state); break; default: state.PopAndPass(c); @@ -79,7 +77,7 @@ void ITokenReceiver.HandleReceivedToken(GDPercent token) { if (_form.IsOrLowerState(State.Percent)) { - _form.State = State.Path; + _form.State = State.Name; Percent = token; return; } @@ -91,30 +89,30 @@ void ITokenSkipReceiver.HandleReceivedTokenSkip() { if (_form.IsOrLowerState(State.Percent)) { - _form.State = State.Path; + _form.State = State.Name; return; } throw new GDInvalidStateException(); } - void ITokenReceiver.HandleReceivedToken(GDPathList token) + void ITokenReceiver.HandleReceivedToken(GDExternalName token) { - if (_form.IsOrLowerState(State.Path)) + if (_form.IsOrLowerState(State.Name)) { - _form.State = State.Path; - Path = token; + _form.State = State.Completed; + Name = token; return; } throw new GDInvalidStateException(); } - void ITokenSkipReceiver.HandleReceivedTokenSkip() + void ITokenSkipReceiver.HandleReceivedTokenSkip() { - if (_form.IsOrLowerState(State.Path)) + if (_form.IsOrLowerState(State.Name)) { - _form.State = State.Path; + _form.State = State.Completed; return; } diff --git a/src/GDShrapt.Reader/Expressions/GDIfExpression.cs b/src/GDShrapt.Reader/Expressions/GDIfExpression.cs index 8193347..b92e34f 100644 --- a/src/GDShrapt.Reader/Expressions/GDIfExpression.cs +++ b/src/GDShrapt.Reader/Expressions/GDIfExpression.cs @@ -49,6 +49,9 @@ public enum State readonly GDTokensForm _form; public override GDTokensForm Form => _form; public GDTokensForm TypedForm => _form; + + readonly int _intendation; + public bool AllowNewLines { get; } public GDIfExpression() @@ -56,8 +59,9 @@ public GDIfExpression() _form = new GDTokensForm(this); } - public GDIfExpression(bool allowNewLines) + public GDIfExpression(int intendation, bool allowNewLines) { + _intendation = intendation; AllowNewLines = allowNewLines; _form = new GDTokensForm(this); } @@ -69,7 +73,7 @@ internal override void HandleChar(char c, GDReadingState state) case State.True: if (!this.ResolveSpaceToken(c, state)) { - this.ResolveExpression(c, state, AllowNewLines ? this : null); + this.ResolveExpression(c, state, _intendation, AllowNewLines ? this : null); } break; case State.If: @@ -81,7 +85,7 @@ internal override void HandleChar(char c, GDReadingState state) case State.Condition: if (!this.ResolveSpaceToken(c, state)) { - this.ResolveExpression(c, state, AllowNewLines ? this : null); + this.ResolveExpression(c, state, _intendation, AllowNewLines ? this : null); } break; case State.Else: @@ -93,7 +97,7 @@ internal override void HandleChar(char c, GDReadingState state) case State.False: if (!this.ResolveSpaceToken(c, state)) { - this.ResolveExpression(c, state, AllowNewLines ? this : null); + this.ResolveExpression(c, state, _intendation, AllowNewLines ? this : null); } break; default: @@ -172,7 +176,7 @@ public override void RebuildBranchesOfPriorityIfNeeded() public override GDNode CreateEmptyInstance() { - return new GDIfExpression(AllowNewLines); + return new GDIfExpression(0, AllowNewLines); } internal override void Visit(IGDVisitor visitor) diff --git a/src/GDShrapt.Reader/Expressions/GDIndexerExpression.cs b/src/GDShrapt.Reader/Expressions/GDIndexerExpression.cs index e4d21cd..fb37989 100644 --- a/src/GDShrapt.Reader/Expressions/GDIndexerExpression.cs +++ b/src/GDShrapt.Reader/Expressions/GDIndexerExpression.cs @@ -1,4 +1,6 @@ -namespace GDShrapt.Reader +using System; + +namespace GDShrapt.Reader { public sealed class GDIndexerExpression : GDExpression, ITokenOrSkipReceiver, @@ -39,8 +41,17 @@ public enum State readonly GDTokensForm _form; + readonly int _intendation; + public override GDTokensForm Form => _form; public GDTokensForm TypedForm => _form; + + internal GDIndexerExpression(int intendation) + { + _form = new GDTokensForm(this); + _intendation = intendation; + } + public GDIndexerExpression() { _form = new GDTokensForm(this); @@ -52,7 +63,7 @@ internal override void HandleChar(char c, GDReadingState state) { case State.Caller: if (!this.ResolveSpaceToken(c, state)) - this.ResolveExpression(c, state); + this.ResolveExpression(c, state, _intendation); break; case State.SquareOpenBracket: if (!this.ResolveSpaceToken(c, state)) @@ -60,7 +71,7 @@ internal override void HandleChar(char c, GDReadingState state) break; case State.Inner: if (!this.ResolveSpaceToken(c, state)) - this.ResolveExpression(c, state); + this.ResolveExpression(c, state, _intendation); break; case State.SquareCloseBracket: if (!this.ResolveSpaceToken(c, state)) diff --git a/src/GDShrapt.Reader/Expressions/GDMemberOperatorExpression.cs b/src/GDShrapt.Reader/Expressions/GDMemberOperatorExpression.cs index d7a5836..e060da7 100644 --- a/src/GDShrapt.Reader/Expressions/GDMemberOperatorExpression.cs +++ b/src/GDShrapt.Reader/Expressions/GDMemberOperatorExpression.cs @@ -31,9 +31,17 @@ public enum State Completed } + readonly int _intendation; readonly GDTokensForm _form; public override GDTokensForm Form => _form; public GDTokensForm TypedForm => _form; + + internal GDMemberOperatorExpression(int intendation) + { + _intendation = intendation; + _form = new GDTokensForm(this); + } + public GDMemberOperatorExpression() { _form = new GDTokensForm(this); @@ -45,7 +53,7 @@ internal override void HandleChar(char c, GDReadingState state) { case State.CallerExpression: if (!this.ResolveSpaceToken(c, state)) - this.ResolveExpression(c, state); + this.ResolveExpression(c, state, _intendation); break; case State.Point: if (!this.ResolveSpaceToken(c, state)) diff --git a/src/GDShrapt.Reader/Expressions/GDMethodExpression.cs b/src/GDShrapt.Reader/Expressions/GDMethodExpression.cs index c38c890..fe78956 100644 --- a/src/GDShrapt.Reader/Expressions/GDMethodExpression.cs +++ b/src/GDShrapt.Reader/Expressions/GDMethodExpression.cs @@ -149,7 +149,7 @@ internal override void HandleChar(char c, GDReadingState state) break; case State.Expression: - this.ResolveExpression(c, state); + this.ResolveExpression(c, state, Intendation); break; case State.Statements: if (c.IsExpressionStopChar()) diff --git a/src/GDShrapt.Reader/Expressions/GDReturnExpression.cs b/src/GDShrapt.Reader/Expressions/GDReturnExpression.cs index bb4e200..fe25d0a 100644 --- a/src/GDShrapt.Reader/Expressions/GDReturnExpression.cs +++ b/src/GDShrapt.Reader/Expressions/GDReturnExpression.cs @@ -25,8 +25,16 @@ public enum State } readonly GDTokensForm _form; + readonly int _intendation; + public override GDTokensForm Form => _form; public GDTokensForm TypedForm => _form; + public GDReturnExpression(int intendation) + { + _form = new GDTokensForm(this); + _intendation = intendation; + } + public GDReturnExpression() { _form = new GDTokensForm(this); @@ -42,7 +50,7 @@ internal override void HandleChar(char c, GDReadingState state) break; case State.Expression: if (!this.ResolveSpaceToken(c, state)) - state.PushAndPass(new GDExpressionResolver(this), c); + state.PushAndPass(new GDExpressionResolver(this, _intendation), c); break; default: state.PopAndPass(c); diff --git a/src/GDShrapt.Reader/Expressions/GDSingleOperatorExpression.cs b/src/GDShrapt.Reader/Expressions/GDSingleOperatorExpression.cs index c4299db..edf318e 100644 --- a/src/GDShrapt.Reader/Expressions/GDSingleOperatorExpression.cs +++ b/src/GDShrapt.Reader/Expressions/GDSingleOperatorExpression.cs @@ -27,9 +27,17 @@ public enum State Completed } + readonly int _intendation; readonly GDTokensForm _form; public override GDTokensForm Form => _form; public GDTokensForm TypedForm => _form; + + internal GDSingleOperatorExpression(int intendation) + { + _intendation = intendation; + _form = new GDTokensForm(this); + } + public GDSingleOperatorExpression() { _form = new GDTokensForm(this); @@ -45,7 +53,7 @@ internal override void HandleChar(char c, GDReadingState state) break; case State.TargetExpression: if (!this.ResolveSpaceToken(c, state)) - this.ResolveExpression(c, state); + this.ResolveExpression(c, state, _intendation); break; default: state.PopAndPass(c); diff --git a/src/GDShrapt.Reader/Expressions/GDYieldExpression.cs b/src/GDShrapt.Reader/Expressions/GDYieldExpression.cs index 9f73e11..3c97557 100644 --- a/src/GDShrapt.Reader/Expressions/GDYieldExpression.cs +++ b/src/GDShrapt.Reader/Expressions/GDYieldExpression.cs @@ -22,7 +22,7 @@ public GDOpenBracket OpenBracket } public GDExpressionsList Parameters { - get => _form.Token2 ?? (_form.Token2 = new GDExpressionsList()); + get => _form.Token2 ?? (_form.Token2 = new GDExpressionsList(_intendation)); set => _form.Token2 = value; } public GDCloseBracket CloseBracket @@ -40,9 +40,17 @@ public enum State Completed } + readonly int _intendation; readonly GDTokensForm _form; public override GDTokensForm Form => _form; public GDTokensForm TypedForm => _form; + + internal GDYieldExpression(int intendation) + { + _intendation = intendation; + _form = new GDTokensForm(this); + } + public GDYieldExpression() { _form = new GDTokensForm(this); diff --git a/src/GDShrapt.Reader/GDScriptReader.cs b/src/GDShrapt.Reader/GDScriptReader.cs index ea1529a..c616ab0 100644 --- a/src/GDShrapt.Reader/GDScriptReader.cs +++ b/src/GDShrapt.Reader/GDScriptReader.cs @@ -70,7 +70,7 @@ public GDExpression ParseExpression(string content) var state = new GDReadingState(Settings); var receiver = new GDReceiver(); - state.Push(new GDStartTrimmingResolver(receiver, () => new GDExpressionResolver(receiver))); + state.Push(new GDStartTrimmingResolver(receiver, () => new GDExpressionResolver(receiver, 0))); var buffer = new char[Settings.ReadBufferSize]; int count = 0; diff --git a/src/GDShrapt.Reader/Lists/GDDictionaryKeyValueDeclarationList.cs b/src/GDShrapt.Reader/Lists/GDDictionaryKeyValueDeclarationList.cs index 3179d59..8915d21 100644 --- a/src/GDShrapt.Reader/Lists/GDDictionaryKeyValueDeclarationList.cs +++ b/src/GDShrapt.Reader/Lists/GDDictionaryKeyValueDeclarationList.cs @@ -3,9 +3,20 @@ public sealed class GDDictionaryKeyValueDeclarationList : GDCommaSeparatedList, ITokenReceiver { + readonly int _intendation; + + internal GDDictionaryKeyValueDeclarationList(int intendation) + { + _intendation = intendation; + } + + public GDDictionaryKeyValueDeclarationList() + { + } + internal override GDReader ResolveNode() { - var node = new GDDictionaryKeyValueDeclaration(); + var node = new GDDictionaryKeyValueDeclaration(_intendation); ListForm.AddToEnd(node); return node; } diff --git a/src/GDShrapt.Reader/Lists/GDExpressionsList.cs b/src/GDShrapt.Reader/Lists/GDExpressionsList.cs index 588edb3..1737c65 100644 --- a/src/GDShrapt.Reader/Lists/GDExpressionsList.cs +++ b/src/GDShrapt.Reader/Lists/GDExpressionsList.cs @@ -3,9 +3,20 @@ public sealed class GDExpressionsList : GDCommaSeparatedList, ITokenReceiver { + readonly int _intendation; + + internal GDExpressionsList(int intendation) + { + _intendation = intendation; + } + + public GDExpressionsList() + { + } + internal override GDReader ResolveNode() { - return new GDExpressionResolver(this); + return new GDExpressionResolver(this, _intendation); } internal override bool IsStopChar(char c) diff --git a/src/GDShrapt.Reader/Lists/GDStringPartsList.cs b/src/GDShrapt.Reader/Lists/GDStringPartsList.cs index 7a16dcb..663aaee 100644 --- a/src/GDShrapt.Reader/Lists/GDStringPartsList.cs +++ b/src/GDShrapt.Reader/Lists/GDStringPartsList.cs @@ -4,6 +4,7 @@ public class GDStringPartsList : GDSeparatedList, ITokenOrSkipReceiver { + bool _firstSlashChecking; bool _ended; readonly GDStringBoundingChar _bounder; @@ -35,6 +36,13 @@ internal override void HandleNewLineChar(GDReadingState state) internal override void HandleLeftSlashChar(GDReadingState state) { + if (Count == 0) + { + _firstSlashChecking = true; + this.ResolveStringPart('\\', state, _bounder); + return; + } + _ended = false; ListForm.AddToEnd(state.Push(new GDMultiLineSplitToken())); state.PassLeftSlashChar(); @@ -62,7 +70,10 @@ void ITokenReceiver.HandleReceivedToken(GDStringPart token) void ITokenSkipReceiver.HandleReceivedTokenSkip() { - _ended = true; + if (!_firstSlashChecking) + _ended = true; + else + _firstSlashChecking = false; } void ITokenReceiver.HandleReceivedToken(GDMultiLineSplitToken token) diff --git a/src/GDShrapt.Reader/Resolvers/GDExpressionResolver.cs b/src/GDShrapt.Reader/Resolvers/GDExpressionResolver.cs index 9247a0e..729cef9 100644 --- a/src/GDShrapt.Reader/Resolvers/GDExpressionResolver.cs +++ b/src/GDShrapt.Reader/Resolvers/GDExpressionResolver.cs @@ -9,24 +9,27 @@ internal class GDExpressionResolver : GDResolver, bool _ifExpressionChecked; bool _isCompleted; + readonly int _intendation; new ITokenReceiver Owner { get; } ITokenSkipReceiver OwnerWithSkip { get; } INewLineReceiver NewLineReceiver { get; } public bool IsCompleted => _isCompleted; - public GDExpressionResolver(ITokenOrSkipReceiver owner, INewLineReceiver newLineReceiver = null) + public GDExpressionResolver(ITokenOrSkipReceiver owner, int intendation, INewLineReceiver newLineReceiver = null) : base(owner) { Owner = owner; OwnerWithSkip = owner; NewLineReceiver = newLineReceiver; + _intendation = intendation; } - public GDExpressionResolver(ITokenReceiver owner) + public GDExpressionResolver(ITokenReceiver owner, int intendation) : base(owner) { Owner = owner; + _intendation = intendation; } internal override void HandleChar(char c, GDReadingState state) @@ -37,7 +40,7 @@ internal override void HandleChar(char c, GDReadingState state) _ifExpressionChecked = false; _nextIfKeyword = null; - var expr = new GDIfExpression(NewLineReceiver != null); + var expr = new GDIfExpression(_intendation, NewLineReceiver != null); PushAndSwap(state, expr); expr.Add(keyword); @@ -71,21 +74,21 @@ internal override void HandleChar(char c, GDReadingState state) { if (c == '[') { - PushAndSave(state, new GDArrayInitializerExpression()); + PushAndSave(state, new GDArrayInitializerExpression(_intendation)); state.PassChar(c); return; } if (c == '{') { - PushAndSave(state, new GDDictionaryInitializerExpression()); + PushAndSave(state, new GDDictionaryInitializerExpression(_intendation)); state.PassChar(c); return; } if (c == '(') { - PushAndSave(state, new GDBracketExpression()); + PushAndSave(state, new GDBracketExpression(_intendation)); state.PassChar(c); return; } @@ -127,14 +130,14 @@ internal override void HandleChar(char c, GDReadingState state) if (c == '.') { - PushAndSwap(state, new GDMemberOperatorExpression()); + PushAndSwap(state, new GDMemberOperatorExpression(_intendation)); state.PassChar(c); return; } if (c == '-' || c == '!' || c == '~') { - PushAndSave(state, new GDSingleOperatorExpression()); + PushAndSave(state, new GDSingleOperatorExpression(_intendation)); state.PassChar(c); return; } @@ -191,26 +194,26 @@ internal override void HandleChar(char c, GDReadingState state) if (c == '(') { - PushAndSwap(state, new GDCallExpression()); + PushAndSwap(state, new GDCallExpression(_intendation)); state.PassChar(c); return; } if (c == '[') { - PushAndSwap(state, new GDIndexerExpression()); + PushAndSwap(state, new GDIndexerExpression(_intendation)); state.PassChar(c); return; } if (c == '.') { - PushAndSwap(state, new GDMemberOperatorExpression()); + PushAndSwap(state, new GDMemberOperatorExpression(_intendation)); state.PassChar(c); return; } - PushAndSwap(state, new GDDualOperatorExpression(NewLineReceiver != null)); + PushAndSwap(state, new GDDualOperatorExpression(_intendation, NewLineReceiver != null)); state.PassChar(c); } } @@ -263,7 +266,7 @@ private bool CheckKeywords(GDReadingState state) return true; case "not": { - var e = new GDSingleOperatorExpression(); + var e = new GDSingleOperatorExpression(_intendation); e.Add(new GDSingleOperator() { OperatorType = GDSingleOperatorType.Not2 }); PushAndSave(state, e); return true; @@ -291,7 +294,7 @@ private bool CheckKeywords(GDReadingState state) } case "return": { - var e = new GDReturnExpression(); + var e = new GDReturnExpression(_intendation); e.Add(new GDReturnKeyword()); PushAndSave(state, e); return true; @@ -319,21 +322,21 @@ private bool CheckKeywords(GDReadingState state) } case "yield": { - var e = new GDYieldExpression(); + var e = new GDYieldExpression(_intendation); e.Add(new GDYieldKeyword()); PushAndSave(state, e); return true; } case "await": { - var e = new GDAwaitExpression(); + var e = new GDAwaitExpression(_intendation); e.Add(new GDAwaitKeyword()); PushAndSave(state, e); return true; } case "func": { - var e = new GDMethodExpression(); + var e = new GDMethodExpression(_intendation); e.Add(new GDFuncKeyword()); PushAndSave(state, e); return true; @@ -352,7 +355,7 @@ internal override void HandleNewLineChar(GDReadingState state) { if (_expression != null) { - PushAndSwap(state, new GDDualOperatorExpression(true)); + PushAndSwap(state, new GDDualOperatorExpression(_intendation, true)); state.PassNewLine(); } else @@ -381,7 +384,7 @@ internal override void HandleSharpChar(GDReadingState state) { if (_expression != null) { - PushAndSwap(state, new GDDualOperatorExpression(true)); + PushAndSwap(state, new GDDualOperatorExpression(_intendation, true)); state.PassSharpChar(); } else @@ -409,7 +412,7 @@ internal override void HandleLeftSlashChar(GDReadingState state) { if (_expression != null) { - PushAndSwap(state, new GDDualOperatorExpression(true)); + PushAndSwap(state, new GDDualOperatorExpression(_intendation, true)); state.PassLeftSlashChar(); } else diff --git a/src/GDShrapt.Reader/Resolvers/GDResolvingHelper.cs b/src/GDShrapt.Reader/Resolvers/GDResolvingHelper.cs index 5c35042..50a207b 100644 --- a/src/GDShrapt.Reader/Resolvers/GDResolvingHelper.cs +++ b/src/GDShrapt.Reader/Resolvers/GDResolvingHelper.cs @@ -290,10 +290,10 @@ public static bool ResolvePoint(this ITokenOrSkipReceiver receiver, cha return result; } - public static void ResolveExpression(this ITokenOrSkipReceiver receiver, char c, GDReadingState state, INewLineReceiver newLineReceiver = null) + public static void ResolveExpression(this ITokenOrSkipReceiver receiver, char c, GDReadingState state, int intendation, INewLineReceiver newLineReceiver = null) { if (!IsExpressionStopChar(c)) - state.Push(new GDExpressionResolver(receiver, newLineReceiver)); + state.Push(new GDExpressionResolver(receiver, intendation, newLineReceiver)); else receiver.HandleReceivedTokenSkip(); state.PassChar(c); @@ -313,6 +313,20 @@ public static bool ResolveIdentifier(this ITokenOrSkipReceiver rec return false; } + public static bool ResolveExternalName(this ITokenOrSkipReceiver receiver, char c, GDReadingState state) + { + if (IsExternalNameChar(c)) + { + receiver.HandleReceivedToken(state.Push(new GDExternalName())); + state.PassChar(c); + return true; + } + + receiver.HandleReceivedTokenSkip(); + state.PassChar(c); + return false; + } + public static bool ResolveNumber(this ITokenOrSkipReceiver receiver, char c, GDReadingState state) { if (IsNumberStartChar(c)) @@ -495,6 +509,7 @@ public static void ResolveTripleDoubleQuotas(this ITokenOrSkipReceiver c == '#'; public static bool IsSpace(this char c) => c == ' ' || c == '\t'; public static bool IsIdentifierStartChar(this char c) => c == '_' || char.IsLetter(c); + public static bool IsExternalNameChar(this char c) => c == '_' || char.IsLetter(c) || char.IsDigit(c); public static bool IsStringStartChar(this char c) => c == '\'' || c == '\"'; public static bool IsExpressionStopChar(this char c) => c == ',' || c == '}' || c == ')' || c == ']' || c == ':' || c == ';'; public static bool IsNumberStartChar(this char c) => char.IsDigit(c); diff --git a/src/GDShrapt.Reader/Resolvers/GDStringPartResolver.cs b/src/GDShrapt.Reader/Resolvers/GDStringPartResolver.cs index a7afdc7..411c8de 100644 --- a/src/GDShrapt.Reader/Resolvers/GDStringPartResolver.cs +++ b/src/GDShrapt.Reader/Resolvers/GDStringPartResolver.cs @@ -33,13 +33,13 @@ internal override void HandleChar(char c, GDReadingState state) case '\'': _stringBuilder.Append('\\').Append('\''); break; case '"': _stringBuilder.Append('\\').Append('"'); break; case '\\': _stringBuilder.Append('\\').Append('\\'); break; - case 'a': _stringBuilder.Append('\\').Append('\a'); break; - case 'b': _stringBuilder.Append('\\').Append('\b'); break; - case 'f': _stringBuilder.Append('\\').Append('\f'); break; - case 'n': _stringBuilder.Append('\\').Append('\n'); break; - case 'r': _stringBuilder.Append('\\').Append('\r'); break; - case 't': _stringBuilder.Append('\\').Append('\t'); break; - case 'v': _stringBuilder.Append('\\').Append('\v'); break; + case 'a': _stringBuilder.Append('\\').Append('a'); break; + case 'b': _stringBuilder.Append('\\').Append('b'); break; + case 'f': _stringBuilder.Append('\\').Append('f'); break; + case 'n': _stringBuilder.Append('\\').Append('n'); break; + case 'r': _stringBuilder.Append('\\').Append('r'); break; + case 't': _stringBuilder.Append('\\').Append('t'); break; + case 'v': _stringBuilder.Append('\\').Append('v'); break; case 'u': _stringBuilder.Append('\\').Append('u'); break; default: if (_stringBuilder.Length == 0) diff --git a/src/GDShrapt.Reader/SimpleTokens/GDExternalName.cs b/src/GDShrapt.Reader/SimpleTokens/GDExternalName.cs new file mode 100644 index 0000000..bfc7af8 --- /dev/null +++ b/src/GDShrapt.Reader/SimpleTokens/GDExternalName.cs @@ -0,0 +1,130 @@ +using System; +using System.Linq; +using System.Text; + +namespace GDShrapt.Reader +{ + public sealed class GDExternalName : GDNameToken, IEquatable + { + string _sequence; + public override string Sequence + { + get => _sequence; + set + { + CheckNameValue(value); + _sequence = value; + } + } + + private void CheckNameValue(string value) + { + if (value.IsNullOrWhiteSpace() || value.IsNullOrEmpty()) + throw new ArgumentException("Invalid name format"); + + if (char.IsNumber(value[0])) + throw new ArgumentException("Invalid name format"); + + if (value.Any(x => !char.IsLetter(x) && !char.IsDigit(x) && x != '_')) + throw new ArgumentException("Invalid name format"); + + } + + StringBuilder _builder = new StringBuilder(); + + internal override void HandleChar(char c, GDReadingState state) + { + if (c == '_' || char.IsLetterOrDigit(c)) + { + _builder.Append(c); + } + else + { + Sequence = _builder.ToString(); + state.PopAndPass(c); + } + } + + internal override void HandleNewLineChar(GDReadingState state) + { + if (_builder.Length > 0) + Sequence = _builder.ToString(); + + state.PopAndPassNewLine(); + } + + internal override void HandleSharpChar(GDReadingState state) + { + if (_builder.Length > 0) + Sequence = _builder.ToString(); + base.HandleSharpChar(state); + } + + internal override void ForceComplete(GDReadingState state) + { + if (_builder.Length > 0) + Sequence = _builder.ToString(); + base.ForceComplete(state); + } + + public override GDSyntaxToken Clone() + { + return new GDExternalName() + { + Sequence = Sequence + }; + } + + public static bool operator ==(GDExternalName one, GDExternalName two) + { + if (ReferenceEquals(one, null)) + return ReferenceEquals(two, null); + + if (ReferenceEquals(two, null)) + return false; + + return string.Equals(one.Sequence, two.Sequence, StringComparison.Ordinal); + } + + public static bool operator !=(GDExternalName one, GDExternalName two) + { + if (ReferenceEquals(one, null)) + return !ReferenceEquals(two, null); + + if (ReferenceEquals(two, null)) + return true; + + return !string.Equals(one.Sequence, two.Sequence, StringComparison.Ordinal); + } + + public static implicit operator GDExternalName(string id) + { + return new GDExternalName() + { + Sequence = id + }; + } + + public override int GetHashCode() + { + return Sequence?.GetHashCode() ?? base.GetHashCode(); + } + + public override bool Equals(object obj) + { + if (obj is GDExternalName identifier) + return ReferenceEquals(Sequence, identifier.Sequence) || string.Equals(Sequence, identifier.Sequence, StringComparison.Ordinal); + return base.Equals(obj); + } + + public bool Equals(GDExternalName other) + { + return string.Equals(Sequence, other.Sequence, StringComparison.Ordinal); + } + + public override string ToString() + { + return $"{Sequence}"; + } + } +} \ No newline at end of file diff --git a/src/GDShrapt.Reader/Statements/GDExpressionStatement.cs b/src/GDShrapt.Reader/Statements/GDExpressionStatement.cs index e806d1f..7820cf8 100644 --- a/src/GDShrapt.Reader/Statements/GDExpressionStatement.cs +++ b/src/GDShrapt.Reader/Statements/GDExpressionStatement.cs @@ -43,7 +43,7 @@ internal override void HandleChar(char c, GDReadingState state) { case State.Expression: if (!this.ResolveSpaceToken(c, state)) - this.ResolveExpression(c, state); + this.ResolveExpression(c, state, LineIntendation); break; case State.SemiColon: if (!this.ResolveSpaceToken(c, state)) diff --git a/src/GDShrapt.Reader/Statements/GDForStatement.cs b/src/GDShrapt.Reader/Statements/GDForStatement.cs index 8c050d5..70ded94 100644 --- a/src/GDShrapt.Reader/Statements/GDForStatement.cs +++ b/src/GDShrapt.Reader/Statements/GDForStatement.cs @@ -93,7 +93,7 @@ internal override void HandleChar(char c, GDReadingState state) state.PassChar(c); break; case State.Collection: - state.Push(new GDExpressionResolver(this)); + state.Push(new GDExpressionResolver(this, Intendation)); state.PassChar(c); break; case State.Colon: @@ -101,7 +101,7 @@ internal override void HandleChar(char c, GDReadingState state) state.PassChar(c); break; case State.Expression: - this.ResolveExpression(c, state); + this.ResolveExpression(c, state, Intendation); break; case State.Statements: this.HandleAsInvalidToken(c, state, x => x.IsSpace() || x.IsNewLine()); diff --git a/src/GDShrapt.Reader/Statements/GDMatchStatement.cs b/src/GDShrapt.Reader/Statements/GDMatchStatement.cs index 97c2454..8579230 100644 --- a/src/GDShrapt.Reader/Statements/GDMatchStatement.cs +++ b/src/GDShrapt.Reader/Statements/GDMatchStatement.cs @@ -66,7 +66,7 @@ internal override void HandleChar(char c, GDReadingState state) state.PushAndPass(new GDKeywordResolver(this), c); break; case State.Value: - state.PushAndPass(new GDExpressionResolver(this), c); + state.PushAndPass(new GDExpressionResolver(this, Intendation), c); break; case State.Colon: state.PushAndPass(new GDSingleCharTokenResolver(this), c); diff --git a/src/GDShrapt.Reader/Statements/GDVariableDeclarationStatement.cs b/src/GDShrapt.Reader/Statements/GDVariableDeclarationStatement.cs index 817f1a1..b073b1c 100644 --- a/src/GDShrapt.Reader/Statements/GDVariableDeclarationStatement.cs +++ b/src/GDShrapt.Reader/Statements/GDVariableDeclarationStatement.cs @@ -94,7 +94,7 @@ internal override void HandleChar(char c, GDReadingState state) this.ResolveAssign(c, state); break; case State.Initializer: - this.ResolveExpression(c, state); + this.ResolveExpression(c, state, LineIntendation); break; default: state.PopAndPass(c); diff --git a/src/GDShrapt.Reader/Statements/GDWhileStatement.cs b/src/GDShrapt.Reader/Statements/GDWhileStatement.cs index 5ea2bae..be5fc8c 100644 --- a/src/GDShrapt.Reader/Statements/GDWhileStatement.cs +++ b/src/GDShrapt.Reader/Statements/GDWhileStatement.cs @@ -78,7 +78,7 @@ internal override void HandleChar(char c, GDReadingState state) state.PassChar(c); break; case State.Condition: - state.Push(new GDExpressionResolver(this)); + state.Push(new GDExpressionResolver(this, Intendation)); state.PassChar(c); break; case State.Colon: @@ -86,7 +86,7 @@ internal override void HandleChar(char c, GDReadingState state) state.PassChar(c); break; case State.Expression: - this.ResolveExpression(c, state); + this.ResolveExpression(c, state, Intendation); break; case State.Statements: this.HandleAsInvalidToken(c, state, x => x.IsNewLine()); diff --git a/src/GDShrapt.Reader/Statements/IfStatement/GDElifBranch.cs b/src/GDShrapt.Reader/Statements/IfStatement/GDElifBranch.cs index 1f5bc5c..63896d4 100644 --- a/src/GDShrapt.Reader/Statements/IfStatement/GDElifBranch.cs +++ b/src/GDShrapt.Reader/Statements/IfStatement/GDElifBranch.cs @@ -43,7 +43,7 @@ public enum State Completed } - private readonly int _intendation; + readonly int _intendation; readonly GDTokensForm _form; public override GDTokensForm Form => _form; public GDTokensForm TypedForm => _form; @@ -74,7 +74,7 @@ internal override void HandleChar(char c, GDReadingState state) break; case State.Condition: case State.Expression: - this.ResolveExpression(c, state); + this.ResolveExpression(c, state, _intendation); break; case State.Statements: this.HandleAsInvalidToken(c, state, x => x.IsSpace() || x.IsNewLine()); diff --git a/src/GDShrapt.Reader/Statements/IfStatement/GDElseBranch.cs b/src/GDShrapt.Reader/Statements/IfStatement/GDElseBranch.cs index 76e77c2..7c4a717 100644 --- a/src/GDShrapt.Reader/Statements/IfStatement/GDElseBranch.cs +++ b/src/GDShrapt.Reader/Statements/IfStatement/GDElseBranch.cs @@ -66,7 +66,7 @@ internal override void HandleChar(char c, GDReadingState state) this.ResolveColon(c, state); break; case State.Expression: - this.ResolveExpression(c, state); + this.ResolveExpression(c, state, _intendation); break; case State.Statements: this.HandleAsInvalidToken(c, state, x => x.IsSpace() || x.IsNewLine()); diff --git a/src/GDShrapt.Reader/Statements/IfStatement/GDIfBranch.cs b/src/GDShrapt.Reader/Statements/IfStatement/GDIfBranch.cs index c2d2f0e..09e6559 100644 --- a/src/GDShrapt.Reader/Statements/IfStatement/GDIfBranch.cs +++ b/src/GDShrapt.Reader/Statements/IfStatement/GDIfBranch.cs @@ -73,7 +73,7 @@ internal override void HandleChar(char c, GDReadingState state) case State.Condition: case State.Expression: if (!this.ResolveSpaceToken(c, state)) - this.ResolveExpression(c, state); + this.ResolveExpression(c, state, _intendation); break; case State.Statements: _form.State = State.Completed;