|
@@ -64,6 +64,7 @@ public ref struct Parser
|
|
|
|
|
|
|
|
return ParseAssignmentStatement(firstExpression, ref enumerator);
|
|
return ParseAssignmentStatement(firstExpression, ref enumerator);
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
break;
|
|
break;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -168,7 +169,7 @@ public ref struct Parser
|
|
|
var doToken = enumerator.Current;
|
|
var doToken = enumerator.Current;
|
|
|
|
|
|
|
|
// parse statements
|
|
// parse statements
|
|
|
- var statements = ParseStatementList(ref enumerator, SyntaxTokenType.End);
|
|
|
|
|
|
|
+ var statements = ParseStatementList(ref enumerator, SyntaxTokenType.End, out _);
|
|
|
|
|
|
|
|
return new DoStatementNode(statements, doToken.Position);
|
|
return new DoStatementNode(statements, doToken.Position);
|
|
|
}
|
|
}
|
|
@@ -208,6 +209,7 @@ public ref struct Parser
|
|
|
enumerator.MovePrevious();
|
|
enumerator.MovePrevious();
|
|
|
return new AssignmentStatementNode(leftNodes.AsSpan().ToArray(), [], firstExpression.Position);
|
|
return new AssignmentStatementNode(leftNodes.AsSpan().ToArray(), [], firstExpression.Position);
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
MoveNextWithValidation(ref enumerator);
|
|
MoveNextWithValidation(ref enumerator);
|
|
|
|
|
|
|
|
// parse expressions
|
|
// parse expressions
|
|
@@ -227,6 +229,7 @@ public ref struct Parser
|
|
|
enumerator.MovePrevious();
|
|
enumerator.MovePrevious();
|
|
|
return new LocalAssignmentStatementNode(identifiers, [], localToken.Position);
|
|
return new LocalAssignmentStatementNode(identifiers, [], localToken.Position);
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
MoveNextWithValidation(ref enumerator);
|
|
MoveNextWithValidation(ref enumerator);
|
|
|
|
|
|
|
|
// parse expressions
|
|
// parse expressions
|
|
@@ -353,7 +356,7 @@ public ref struct Parser
|
|
|
CheckCurrent(ref enumerator, SyntaxTokenType.Do);
|
|
CheckCurrent(ref enumerator, SyntaxTokenType.Do);
|
|
|
|
|
|
|
|
// parse statements
|
|
// parse statements
|
|
|
- var statements = ParseStatementList(ref enumerator, SyntaxTokenType.End);
|
|
|
|
|
|
|
+ var statements = ParseStatementList(ref enumerator, SyntaxTokenType.End, out _);
|
|
|
|
|
|
|
|
return new WhileStatementNode(condition, statements, whileToken.Position);
|
|
return new WhileStatementNode(condition, statements, whileToken.Position);
|
|
|
}
|
|
}
|
|
@@ -365,7 +368,7 @@ public ref struct Parser
|
|
|
var repeatToken = enumerator.Current;
|
|
var repeatToken = enumerator.Current;
|
|
|
|
|
|
|
|
// parse statements
|
|
// parse statements
|
|
|
- var statements = ParseStatementList(ref enumerator, SyntaxTokenType.Until);
|
|
|
|
|
|
|
+ var statements = ParseStatementList(ref enumerator, SyntaxTokenType.Until, out _);
|
|
|
|
|
|
|
|
// skip 'until keyword'
|
|
// skip 'until keyword'
|
|
|
CheckCurrentAndSkip(ref enumerator, SyntaxTokenType.Until, out _);
|
|
CheckCurrentAndSkip(ref enumerator, SyntaxTokenType.Until, out _);
|
|
@@ -418,11 +421,12 @@ public ref struct Parser
|
|
|
|
|
|
|
|
// skip 'do' keyword
|
|
// skip 'do' keyword
|
|
|
CheckCurrent(ref enumerator, SyntaxTokenType.Do);
|
|
CheckCurrent(ref enumerator, SyntaxTokenType.Do);
|
|
|
|
|
+ var doToken = enumerator.Current;
|
|
|
|
|
|
|
|
// parse statements
|
|
// parse statements
|
|
|
- var statements = ParseStatementList(ref enumerator, SyntaxTokenType.End);
|
|
|
|
|
|
|
+ var statements = ParseStatementList(ref enumerator, SyntaxTokenType.End, out _);
|
|
|
|
|
|
|
|
- return new NumericForStatementNode(varName, initialValueNode, limitNode, stepNode, statements, forToken.Position);
|
|
|
|
|
|
|
+ return new NumericForStatementNode(varName, initialValueNode, limitNode, stepNode, statements, forToken.Position, doToken.Position);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
GenericForStatementNode ParseGenericForStatement(ref SyntaxTokenEnumerator enumerator, SyntaxToken forToken)
|
|
GenericForStatementNode ParseGenericForStatement(ref SyntaxTokenEnumerator enumerator, SyntaxToken forToken)
|
|
@@ -433,33 +437,33 @@ public ref struct Parser
|
|
|
// skip 'in' keyword
|
|
// skip 'in' keyword
|
|
|
CheckCurrentAndSkip(ref enumerator, SyntaxTokenType.In, out _);
|
|
CheckCurrentAndSkip(ref enumerator, SyntaxTokenType.In, out _);
|
|
|
enumerator.SkipEoL();
|
|
enumerator.SkipEoL();
|
|
|
-
|
|
|
|
|
|
|
+ var iteratorToken = enumerator.Current;
|
|
|
var expressions = ParseExpressionList(ref enumerator);
|
|
var expressions = ParseExpressionList(ref enumerator);
|
|
|
MoveNextWithValidation(ref enumerator);
|
|
MoveNextWithValidation(ref enumerator);
|
|
|
enumerator.SkipEoL();
|
|
enumerator.SkipEoL();
|
|
|
|
|
|
|
|
// skip 'do' keyword
|
|
// skip 'do' keyword
|
|
|
CheckCurrent(ref enumerator, SyntaxTokenType.Do);
|
|
CheckCurrent(ref enumerator, SyntaxTokenType.Do);
|
|
|
-
|
|
|
|
|
|
|
+ var doToken = enumerator.Current;
|
|
|
// parse statements
|
|
// parse statements
|
|
|
- var statements = ParseStatementList(ref enumerator, SyntaxTokenType.End);
|
|
|
|
|
|
|
+ var statements = ParseStatementList(ref enumerator, SyntaxTokenType.End, out var endToken);
|
|
|
|
|
|
|
|
- return new GenericForStatementNode(identifiers, expressions, statements, forToken.Position);
|
|
|
|
|
|
|
+ return new GenericForStatementNode(identifiers, expressions, statements, iteratorToken.Position, doToken.Position, endToken.Position);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
FunctionDeclarationStatementNode ParseFunctionDeclarationStatement(ref SyntaxTokenEnumerator enumerator, SyntaxToken functionToken)
|
|
FunctionDeclarationStatementNode ParseFunctionDeclarationStatement(ref SyntaxTokenEnumerator enumerator, SyntaxToken functionToken)
|
|
|
{
|
|
{
|
|
|
- var (Name, Identifiers, Statements, HasVariableArgments) = ParseFunctionDeclarationCore(ref enumerator, false);
|
|
|
|
|
- return new FunctionDeclarationStatementNode(Name, Identifiers, Statements, HasVariableArgments, functionToken.Position);
|
|
|
|
|
|
|
+ var (Name, Identifiers, Statements, HasVariableArgments, LineDefined, LastLineDefined) = ParseFunctionDeclarationCore(ref enumerator, false);
|
|
|
|
|
+ return new FunctionDeclarationStatementNode(Name, Identifiers, Statements, HasVariableArgments, functionToken.Position, LineDefined, LastLineDefined);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
LocalFunctionDeclarationStatementNode ParseLocalFunctionDeclarationStatement(ref SyntaxTokenEnumerator enumerator, SyntaxToken functionToken)
|
|
LocalFunctionDeclarationStatementNode ParseLocalFunctionDeclarationStatement(ref SyntaxTokenEnumerator enumerator, SyntaxToken functionToken)
|
|
|
{
|
|
{
|
|
|
- var (Name, Identifiers, Statements, HasVariableArgments) = ParseFunctionDeclarationCore(ref enumerator, false);
|
|
|
|
|
- return new LocalFunctionDeclarationStatementNode(Name, Identifiers, Statements, HasVariableArgments, functionToken.Position);
|
|
|
|
|
|
|
+ var (Name, Identifiers, Statements, HasVariableArgments, LineDefined, LastLineDefined) = ParseFunctionDeclarationCore(ref enumerator, false);
|
|
|
|
|
+ return new LocalFunctionDeclarationStatementNode(Name, Identifiers, Statements, HasVariableArgments, functionToken.Position, LineDefined, LastLineDefined);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- (ReadOnlyMemory<char> Name, IdentifierNode[] Identifiers, StatementNode[] Statements, bool HasVariableArgments) ParseFunctionDeclarationCore(ref SyntaxTokenEnumerator enumerator, bool isAnonymous)
|
|
|
|
|
|
|
+ (ReadOnlyMemory<char> Name, IdentifierNode[] Identifiers, StatementNode[] Statements, bool HasVariableArgments, int LineDefined, int LastLineDefined) ParseFunctionDeclarationCore(ref SyntaxTokenEnumerator enumerator, bool isAnonymous)
|
|
|
{
|
|
{
|
|
|
ReadOnlyMemory<char> name;
|
|
ReadOnlyMemory<char> name;
|
|
|
|
|
|
|
@@ -478,7 +482,7 @@ public ref struct Parser
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// skip '('
|
|
// skip '('
|
|
|
- CheckCurrentAndSkip(ref enumerator, SyntaxTokenType.LParen, out _);
|
|
|
|
|
|
|
+ CheckCurrentAndSkip(ref enumerator, SyntaxTokenType.LParen, out var leftParenToken);
|
|
|
enumerator.SkipEoL();
|
|
enumerator.SkipEoL();
|
|
|
|
|
|
|
|
// parse parameters
|
|
// parse parameters
|
|
@@ -494,16 +498,16 @@ public ref struct Parser
|
|
|
CheckCurrent(ref enumerator, SyntaxTokenType.RParen);
|
|
CheckCurrent(ref enumerator, SyntaxTokenType.RParen);
|
|
|
|
|
|
|
|
// parse statements
|
|
// parse statements
|
|
|
- var statements = ParseStatementList(ref enumerator, SyntaxTokenType.End);
|
|
|
|
|
|
|
+ var statements = ParseStatementList(ref enumerator, SyntaxTokenType.End, out var endToken);
|
|
|
|
|
|
|
|
- return (name, identifiers, statements, hasVarArg);
|
|
|
|
|
|
|
+ return (name, identifiers, statements, hasVarArg, leftParenToken.Position.Line, endToken.Position.Line);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
TableMethodDeclarationStatementNode ParseTableMethodDeclarationStatement(ref SyntaxTokenEnumerator enumerator, SyntaxToken functionToken)
|
|
TableMethodDeclarationStatementNode ParseTableMethodDeclarationStatement(ref SyntaxTokenEnumerator enumerator, SyntaxToken functionToken)
|
|
|
{
|
|
{
|
|
|
using var names = new PooledList<IdentifierNode>(32);
|
|
using var names = new PooledList<IdentifierNode>(32);
|
|
|
var hasSelfParameter = false;
|
|
var hasSelfParameter = false;
|
|
|
-
|
|
|
|
|
|
|
+ SyntaxToken leftParenToken;
|
|
|
while (true)
|
|
while (true)
|
|
|
{
|
|
{
|
|
|
CheckCurrent(ref enumerator, SyntaxTokenType.Identifier);
|
|
CheckCurrent(ref enumerator, SyntaxTokenType.Identifier);
|
|
@@ -517,6 +521,7 @@ public ref struct Parser
|
|
|
{
|
|
{
|
|
|
LuaParseException.UnexpectedToken(ChunkName, enumerator.Current.Position, enumerator.Current);
|
|
LuaParseException.UnexpectedToken(ChunkName, enumerator.Current.Position, enumerator.Current);
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
hasSelfParameter = enumerator.Current.Type is SyntaxTokenType.Colon;
|
|
hasSelfParameter = enumerator.Current.Type is SyntaxTokenType.Colon;
|
|
|
|
|
|
|
|
MoveNextWithValidation(ref enumerator);
|
|
MoveNextWithValidation(ref enumerator);
|
|
@@ -524,6 +529,7 @@ public ref struct Parser
|
|
|
}
|
|
}
|
|
|
else if (enumerator.Current.Type is SyntaxTokenType.LParen)
|
|
else if (enumerator.Current.Type is SyntaxTokenType.LParen)
|
|
|
{
|
|
{
|
|
|
|
|
+ leftParenToken = enumerator.Current;
|
|
|
// skip '('
|
|
// skip '('
|
|
|
MoveNextWithValidation(ref enumerator);
|
|
MoveNextWithValidation(ref enumerator);
|
|
|
enumerator.SkipEoL();
|
|
enumerator.SkipEoL();
|
|
@@ -544,9 +550,9 @@ public ref struct Parser
|
|
|
CheckCurrent(ref enumerator, SyntaxTokenType.RParen);
|
|
CheckCurrent(ref enumerator, SyntaxTokenType.RParen);
|
|
|
|
|
|
|
|
// parse statements
|
|
// parse statements
|
|
|
- var statements = ParseStatementList(ref enumerator, SyntaxTokenType.End);
|
|
|
|
|
|
|
+ var statements = ParseStatementList(ref enumerator, SyntaxTokenType.End, out var endToken);
|
|
|
|
|
|
|
|
- return new TableMethodDeclarationStatementNode(names.AsSpan().ToArray(), identifiers, statements, hasVarArg, hasSelfParameter, functionToken.Position);
|
|
|
|
|
|
|
+ return new TableMethodDeclarationStatementNode(names.AsSpan().ToArray(), identifiers, statements, hasVarArg, hasSelfParameter, functionToken.Position, leftParenToken.Position.Line, endToken.Position.Line);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
bool TryParseExpression(ref SyntaxTokenEnumerator enumerator, OperatorPrecedence precedence, [NotNullWhen(true)] out ExpressionNode? result)
|
|
bool TryParseExpression(ref SyntaxTokenEnumerator enumerator, OperatorPrecedence precedence, [NotNullWhen(true)] out ExpressionNode? result)
|
|
@@ -579,7 +585,7 @@ public ref struct Parser
|
|
|
// nested table access & function call
|
|
// nested table access & function call
|
|
|
RECURSIVE:
|
|
RECURSIVE:
|
|
|
enumerator.SkipEoL();
|
|
enumerator.SkipEoL();
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
var nextType = enumerator.GetNext().Type;
|
|
var nextType = enumerator.GetNext().Type;
|
|
|
if (nextType is SyntaxTokenType.LSquare or SyntaxTokenType.Dot or SyntaxTokenType.Colon)
|
|
if (nextType is SyntaxTokenType.LSquare or SyntaxTokenType.Dot or SyntaxTokenType.Colon)
|
|
|
{
|
|
{
|
|
@@ -851,9 +857,9 @@ public ref struct Parser
|
|
|
// skip 'function' keyword
|
|
// skip 'function' keyword
|
|
|
CheckCurrentAndSkip(ref enumerator, SyntaxTokenType.Function, out var functionToken);
|
|
CheckCurrentAndSkip(ref enumerator, SyntaxTokenType.Function, out var functionToken);
|
|
|
enumerator.SkipEoL();
|
|
enumerator.SkipEoL();
|
|
|
-
|
|
|
|
|
- var (_, Identifiers, Statements, HasVariableArgments) = ParseFunctionDeclarationCore(ref enumerator, true);
|
|
|
|
|
- return new FunctionDeclarationExpressionNode(Identifiers, Statements, HasVariableArgments, functionToken.Position);
|
|
|
|
|
|
|
+
|
|
|
|
|
+ var (_, Identifiers, Statements, HasVariableArgments, LineDefined, LastLineDefined) = ParseFunctionDeclarationCore(ref enumerator, true);
|
|
|
|
|
+ return new FunctionDeclarationExpressionNode(Identifiers, Statements, HasVariableArgments, functionToken.Position, LineDefined, LastLineDefined);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
ExpressionNode[] ParseCallFunctionArguments(ref SyntaxTokenEnumerator enumerator)
|
|
ExpressionNode[] ParseCallFunctionArguments(ref SyntaxTokenEnumerator enumerator)
|
|
@@ -946,20 +952,22 @@ public ref struct Parser
|
|
|
return buffer.AsSpan().ToArray();
|
|
return buffer.AsSpan().ToArray();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- StatementNode[] ParseStatementList(ref SyntaxTokenEnumerator enumerator, SyntaxTokenType endToken)
|
|
|
|
|
|
|
+ StatementNode[] ParseStatementList(ref SyntaxTokenEnumerator enumerator, SyntaxTokenType endTokenType, out SyntaxToken endToken)
|
|
|
{
|
|
{
|
|
|
using var statements = new PooledList<StatementNode>(64);
|
|
using var statements = new PooledList<StatementNode>(64);
|
|
|
|
|
|
|
|
// parse statements
|
|
// parse statements
|
|
|
while (enumerator.MoveNext())
|
|
while (enumerator.MoveNext())
|
|
|
{
|
|
{
|
|
|
- if (enumerator.Current.Type == endToken) break;
|
|
|
|
|
|
|
+ if (enumerator.Current.Type == endTokenType) break;
|
|
|
if (enumerator.Current.Type is SyntaxTokenType.EndOfLine or SyntaxTokenType.SemiColon) continue;
|
|
if (enumerator.Current.Type is SyntaxTokenType.EndOfLine or SyntaxTokenType.SemiColon) continue;
|
|
|
|
|
|
|
|
var node = ParseStatement(ref enumerator);
|
|
var node = ParseStatement(ref enumerator);
|
|
|
statements.Add(node);
|
|
statements.Add(node);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ endToken = enumerator.Current;
|
|
|
|
|
+
|
|
|
return statements.AsSpan().ToArray();
|
|
return statements.AsSpan().ToArray();
|
|
|
}
|
|
}
|
|
|
|
|
|