Reworked diagnostics, saves line positions in memory, instead of calculating later.
This commit is contained in:
parent
b5bfb7997b
commit
1d6b5673d6
|
@ -107,11 +107,9 @@ namespace Upsilon.BaseTypes.ScriptFunction
|
||||||
// if we haven't found a method, we throw an exception
|
// if we haven't found a method, we throw an exception
|
||||||
if (method == null)
|
if (method == null)
|
||||||
{
|
{
|
||||||
var (i, pos) = diagnostics.ScriptString.GetLinePosition(span.Start);
|
|
||||||
var line = diagnostics.ScriptString.GetLine(i);
|
|
||||||
throw new ScriptRuntimeException(
|
throw new ScriptRuntimeException(
|
||||||
$"Can't find method {_method.Name} with parameter types {string.Join(", ", convertedTypes.Select(x => x.Name))} on type {_object.GetType().Name}",
|
$"Can't find method {_method.Name} with parameter types {string.Join(", ", convertedTypes.Select(x => x.Name))} on type {_object.GetType().Name}",
|
||||||
i, pos, line);
|
span, diagnostics.ScriptString.GetSpan(span));
|
||||||
}
|
}
|
||||||
// get the method parameters
|
// get the method parameters
|
||||||
var parameters = method.GetParameters();
|
var parameters = method.GetParameters();
|
||||||
|
|
|
@ -51,11 +51,9 @@ namespace Upsilon.BaseTypes.UserData
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var (i, pos) = diagnostics.ScriptString.GetLinePosition(span.Start);
|
|
||||||
var line = diagnostics.ScriptString.GetLine(i);
|
|
||||||
throw new ScriptRuntimeException(
|
throw new ScriptRuntimeException(
|
||||||
$"Tried indexing a CSharp list with a value that's not an integer. Value: {scriptIndex.ToCSharpObject()}",
|
$"Tried indexing a CSharp list with a value that's not an integer. Value: {scriptIndex.ToCSharpObject()}",
|
||||||
i, pos, line);
|
span, diagnostics.ScriptString.GetSpan(span));
|
||||||
}
|
}
|
||||||
|
|
||||||
index--;
|
index--;
|
||||||
|
|
|
@ -17,18 +17,18 @@ namespace Upsilon.Binder
|
||||||
}
|
}
|
||||||
|
|
||||||
public override BoundKind Kind => BoundKind.BoundBinaryExpression;
|
public override BoundKind Kind => BoundKind.BoundBinaryExpression;
|
||||||
public override IEnumerable<BoundNode> GetNodeAtPosition(int characterPosition)
|
public override IEnumerable<BoundNode> GetNodeAtPosition(int line, int character)
|
||||||
{
|
{
|
||||||
if (characterPosition >= LeftExpression.Span.Start && characterPosition <= LeftExpression.Span.End)
|
if (LeftExpression.Span.Contains(line, character))
|
||||||
{
|
{
|
||||||
foreach (var exp in LeftExpression.GetNodeAtPosition(characterPosition))
|
foreach (var exp in LeftExpression.GetNodeAtPosition(line, character))
|
||||||
{
|
{
|
||||||
yield return exp;
|
yield return exp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (characterPosition >= RightExpression.Span.Start && characterPosition <= RightExpression.Span.End)
|
if (RightExpression.Span.Contains(line, character))
|
||||||
{
|
{
|
||||||
foreach (var exp in RightExpression.GetNodeAtPosition(characterPosition))
|
foreach (var exp in RightExpression.GetNodeAtPosition(line, character))
|
||||||
{
|
{
|
||||||
yield return exp;
|
yield return exp;
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,20 +19,25 @@ namespace Upsilon.Binder
|
||||||
}
|
}
|
||||||
|
|
||||||
public override BoundKind Kind => BoundKind.BoundFunctionCallExpression;
|
public override BoundKind Kind => BoundKind.BoundFunctionCallExpression;
|
||||||
public override IEnumerable<BoundNode> GetNodeAtPosition(int characterPosition)
|
public override IEnumerable<BoundNode> GetNodeAtPosition(int line, int character)
|
||||||
{
|
{
|
||||||
if (characterPosition >= Identifier.Span.Start && characterPosition <= Identifier.Span.End)
|
if (Identifier.Span.Contains(line, character))
|
||||||
{
|
{
|
||||||
foreach (var exp in Identifier.GetNodeAtPosition(characterPosition))
|
foreach (var exp in Identifier.GetNodeAtPosition(line, character))
|
||||||
{
|
{
|
||||||
yield return exp;
|
yield return exp;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
foreach (var parameter in Parameters)
|
foreach (var parameter in Parameters)
|
||||||
{
|
{
|
||||||
if (characterPosition >= parameter.Span.Start && characterPosition <= parameter.Span.End)
|
if (parameter.Span.Contains(line, character))
|
||||||
{
|
{
|
||||||
foreach (var boundNode in parameter.GetNodeAtPosition(characterPosition)) yield return boundNode;
|
foreach (var exp in parameter.GetNodeAtPosition(line, character))
|
||||||
|
{
|
||||||
|
yield return exp;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
yield return this;
|
yield return this;
|
||||||
|
|
|
@ -20,17 +20,21 @@ namespace Upsilon.Binder
|
||||||
}
|
}
|
||||||
|
|
||||||
public override BoundKind Kind => BoundKind.BoundFunctionExpression;
|
public override BoundKind Kind => BoundKind.BoundFunctionExpression;
|
||||||
public override IEnumerable<BoundNode> GetNodeAtPosition(int characterPosition)
|
public override IEnumerable<BoundNode> GetNodeAtPosition(int linePosition, int characterPosition)
|
||||||
{
|
{
|
||||||
foreach (var parameter in Parameters)
|
foreach (var parameter in Parameters)
|
||||||
{
|
{
|
||||||
if (characterPosition >= parameter.Span.Start && characterPosition <= parameter.Span.End)
|
if (parameter.Span.Contains(linePosition, characterPosition))
|
||||||
foreach (var boundNode in parameter.GetNodeAtPosition(characterPosition))
|
{
|
||||||
|
foreach (var boundNode in parameter.GetNodeAtPosition(linePosition, characterPosition))
|
||||||
yield return boundNode;
|
yield return boundNode;
|
||||||
}
|
}
|
||||||
if (characterPosition >= Block.Span.Start && characterPosition <= Block.Span.End)
|
}
|
||||||
foreach (var boundNode in Block.GetNodeAtPosition(characterPosition))
|
if (Block.Span.Contains(linePosition, characterPosition))
|
||||||
|
{
|
||||||
|
foreach (var boundNode in Block.GetNodeAtPosition(linePosition, characterPosition))
|
||||||
yield return boundNode;
|
yield return boundNode;
|
||||||
|
}
|
||||||
yield return this;
|
yield return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,16 +18,18 @@ namespace Upsilon.Binder
|
||||||
public BoundExpression Index { get; }
|
public BoundExpression Index { get; }
|
||||||
|
|
||||||
public override BoundKind Kind => BoundKind.BoundIndexExpression;
|
public override BoundKind Kind => BoundKind.BoundIndexExpression;
|
||||||
public override IEnumerable<BoundNode> GetNodeAtPosition(int characterPosition)
|
public override IEnumerable<BoundNode> GetNodeAtPosition(int linePosition, int characterPosition)
|
||||||
{
|
{
|
||||||
if (characterPosition >= Identifier.Span.Start && characterPosition <= Identifier.Span.End)
|
if (Identifier.Span.Contains(linePosition, characterPosition))
|
||||||
foreach (var boundNode in Identifier.GetNodeAtPosition(characterPosition))
|
{
|
||||||
|
foreach (var boundNode in Identifier.GetNodeAtPosition(linePosition, characterPosition))
|
||||||
yield return boundNode;
|
yield return boundNode;
|
||||||
|
}
|
||||||
if (characterPosition >= Index.Span.Start && characterPosition <= Index.Span.End)
|
if (Index.Span.Contains(linePosition, characterPosition))
|
||||||
foreach (var boundNode in Index.GetNodeAtPosition(characterPosition))
|
{
|
||||||
|
foreach (var boundNode in Index.GetNodeAtPosition(linePosition, characterPosition))
|
||||||
yield return boundNode;
|
yield return boundNode;
|
||||||
|
}
|
||||||
yield return this;
|
yield return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,12 +49,15 @@ namespace Upsilon.Binder
|
||||||
}
|
}
|
||||||
|
|
||||||
public override BoundKind Kind => BoundKind.BoundFullstopIndexExpression;
|
public override BoundKind Kind => BoundKind.BoundFullstopIndexExpression;
|
||||||
public override IEnumerable<BoundNode> GetNodeAtPosition(int characterPosition)
|
public override IEnumerable<BoundNode> GetNodeAtPosition(int linePosition, int characterPosition)
|
||||||
{
|
{
|
||||||
if (characterPosition >= Expression.Span.Start && characterPosition <= Expression.Span.End)
|
if (Expression.Span.Contains(linePosition, characterPosition))
|
||||||
foreach (var boundNode in Expression.GetNodeAtPosition(characterPosition))
|
{
|
||||||
|
foreach (var boundNode in Expression.GetNodeAtPosition(linePosition, characterPosition))
|
||||||
yield return boundNode;
|
yield return boundNode;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
yield return this;
|
yield return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@ namespace Upsilon.Binder
|
||||||
}
|
}
|
||||||
|
|
||||||
public override BoundKind Kind => BoundKind.BoundLiteralExpression;
|
public override BoundKind Kind => BoundKind.BoundLiteralExpression;
|
||||||
public override IEnumerable<BoundNode> GetNodeAtPosition(int characterPosition)
|
public override IEnumerable<BoundNode> GetNodeAtPosition(int line, int character)
|
||||||
{
|
{
|
||||||
yield return this;
|
yield return this;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,16 +17,16 @@ namespace Upsilon.Binder
|
||||||
}
|
}
|
||||||
|
|
||||||
public override BoundKind Kind => BoundKind.BoundTableExpression;
|
public override BoundKind Kind => BoundKind.BoundTableExpression;
|
||||||
public override IEnumerable<BoundNode> GetNodeAtPosition(int characterPosition)
|
public override IEnumerable<BoundNode> GetNodeAtPosition(int linePosition, int characterPosition)
|
||||||
{
|
{
|
||||||
foreach (var statement in Statements)
|
foreach (var statement in Statements)
|
||||||
{
|
{
|
||||||
if (characterPosition >= statement.Span.Start && characterPosition <= statement.Span.End)
|
if (statement.Span.Contains(linePosition, characterPosition))
|
||||||
foreach (var boundNode in statement.GetNodeAtPosition(characterPosition))
|
{
|
||||||
yield return boundNode;
|
yield return statement;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
yield return this;
|
yield return this;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Type Type => Type.Table;
|
public override Type Type => Type.Table;
|
||||||
|
|
|
@ -7,12 +7,13 @@ namespace Upsilon.Binder
|
||||||
public class BoundUnaryExpression : BoundExpression
|
public class BoundUnaryExpression : BoundExpression
|
||||||
{
|
{
|
||||||
public override BoundKind Kind => BoundKind.BoundUnaryExpression;
|
public override BoundKind Kind => BoundKind.BoundUnaryExpression;
|
||||||
public override IEnumerable<BoundNode> GetNodeAtPosition(int characterPosition)
|
public override IEnumerable<BoundNode> GetNodeAtPosition(int linePosition, int characterPosition)
|
||||||
{
|
{
|
||||||
if (characterPosition >= InExpression.Span.Start && characterPosition <= InExpression.Span.End)
|
if (InExpression.Span.Contains(linePosition, characterPosition))
|
||||||
foreach (var boundNode in InExpression.GetNodeAtPosition(characterPosition))
|
{
|
||||||
|
foreach (var boundNode in InExpression.GetNodeAtPosition(linePosition, characterPosition))
|
||||||
yield return boundNode;
|
yield return boundNode;
|
||||||
|
}
|
||||||
yield return this;
|
yield return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ namespace Upsilon.Binder
|
||||||
|
|
||||||
public BoundVariableSymbol Variable { get; }
|
public BoundVariableSymbol Variable { get; }
|
||||||
public override BoundKind Kind => BoundKind.VariableExpression;
|
public override BoundKind Kind => BoundKind.VariableExpression;
|
||||||
public override IEnumerable<BoundNode> GetNodeAtPosition(int characterPosition)
|
public override IEnumerable<BoundNode> GetNodeAtPosition(int linePosition, int characterPosition)
|
||||||
{
|
{
|
||||||
yield return Variable;
|
yield return Variable;
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,6 @@ namespace Upsilon.Binder
|
||||||
public abstract BoundKind Kind { get; }
|
public abstract BoundKind Kind { get; }
|
||||||
public TextSpan Span { get; }
|
public TextSpan Span { get; }
|
||||||
|
|
||||||
public abstract IEnumerable<BoundNode> GetNodeAtPosition(int characterPosition);
|
public abstract IEnumerable<BoundNode> GetNodeAtPosition(int linePosition, int characterPosition);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -13,13 +13,17 @@ namespace Upsilon.Binder
|
||||||
}
|
}
|
||||||
|
|
||||||
public override BoundKind Kind => BoundKind.BoundBlockStatement;
|
public override BoundKind Kind => BoundKind.BoundBlockStatement;
|
||||||
public override IEnumerable<BoundNode> GetNodeAtPosition(int characterPosition)
|
public override IEnumerable<BoundNode> GetNodeAtPosition(int linePosition, int characterPosition)
|
||||||
{
|
{
|
||||||
foreach (var statement in Statements)
|
foreach (var statement in Statements)
|
||||||
{
|
{
|
||||||
if (characterPosition >= statement.Span.Start && characterPosition <= statement.Span.End)
|
if (statement.Span.Contains(linePosition, characterPosition))
|
||||||
foreach (var boundNode in statement.GetNodeAtPosition(characterPosition))
|
{
|
||||||
yield return boundNode;
|
foreach (var node in statement.GetNodeAtPosition(linePosition, characterPosition))
|
||||||
|
{
|
||||||
|
yield return node;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
yield return this;
|
yield return this;
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,11 +10,9 @@ namespace Upsilon.Binder
|
||||||
}
|
}
|
||||||
|
|
||||||
public override BoundKind Kind => BoundKind.BoundBreakStatement;
|
public override BoundKind Kind => BoundKind.BoundBreakStatement;
|
||||||
public override IEnumerable<BoundNode> GetNodeAtPosition(int characterPosition)
|
public override IEnumerable<BoundNode> GetNodeAtPosition(int linePosition, int characterPosition)
|
||||||
{
|
{
|
||||||
if (characterPosition >= Span.Start && characterPosition <= Span.End)
|
|
||||||
yield return this;
|
yield return this;
|
||||||
yield return null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -7,13 +7,11 @@ namespace Upsilon.Binder
|
||||||
{
|
{
|
||||||
public BoundExpression Expression { get; }
|
public BoundExpression Expression { get; }
|
||||||
public override BoundKind Kind => BoundKind.BoundExpressionStatement;
|
public override BoundKind Kind => BoundKind.BoundExpressionStatement;
|
||||||
public override IEnumerable<BoundNode> GetNodeAtPosition(int characterPosition)
|
public override IEnumerable<BoundNode> GetNodeAtPosition(int linePosition, int characterPosition)
|
||||||
{
|
{
|
||||||
if (characterPosition >= Span.Start && characterPosition <= Span.End)
|
foreach (var boundNode in Expression.GetNodeAtPosition(linePosition, characterPosition))
|
||||||
foreach (var boundNode in Expression.GetNodeAtPosition(characterPosition))
|
|
||||||
yield return boundNode;
|
yield return boundNode;
|
||||||
|
|
||||||
yield return this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public BoundExpressionStatement(BoundExpression expression, TextSpan span):base(span)
|
public BoundExpressionStatement(BoundExpression expression, TextSpan span):base(span)
|
||||||
|
|
|
@ -16,10 +16,10 @@ namespace Upsilon.Binder
|
||||||
}
|
}
|
||||||
|
|
||||||
public override BoundKind Kind => BoundKind.BoundFunctionAssignmentStatement;
|
public override BoundKind Kind => BoundKind.BoundFunctionAssignmentStatement;
|
||||||
public override IEnumerable<BoundNode> GetNodeAtPosition(int characterPosition)
|
public override IEnumerable<BoundNode> GetNodeAtPosition(int linePosition, int characterPosition)
|
||||||
{
|
{
|
||||||
if (characterPosition >= Func.Span.Start && characterPosition <= Func.Span.End)
|
if (Func.Span.Contains(linePosition, characterPosition))
|
||||||
foreach (var boundNode in Func.GetNodeAtPosition(characterPosition))
|
foreach (var boundNode in Func.GetNodeAtPosition(linePosition, characterPosition))
|
||||||
yield return boundNode;
|
yield return boundNode;
|
||||||
|
|
||||||
yield return this;
|
yield return this;
|
||||||
|
|
|
@ -20,16 +20,18 @@ namespace Upsilon.Binder
|
||||||
}
|
}
|
||||||
|
|
||||||
public override BoundKind Kind => BoundKind.BoundGenericForStatement;
|
public override BoundKind Kind => BoundKind.BoundGenericForStatement;
|
||||||
public override IEnumerable<BoundNode> GetNodeAtPosition(int characterPosition)
|
public override IEnumerable<BoundNode> GetNodeAtPosition(int linePosition, int characterPosition)
|
||||||
{
|
{
|
||||||
if (characterPosition >= BoundEnumerableExpression.Span.Start && characterPosition <= BoundEnumerableExpression.Span.End)
|
if (BoundEnumerableExpression.Span.Contains(linePosition, characterPosition))
|
||||||
foreach (var boundNode in BoundEnumerableExpression.GetNodeAtPosition(characterPosition))
|
{
|
||||||
|
foreach (var boundNode in BoundEnumerableExpression.GetNodeAtPosition(linePosition, characterPosition))
|
||||||
yield return boundNode;
|
yield return boundNode;
|
||||||
|
}
|
||||||
if (characterPosition >= Block.Span.Start && characterPosition <= Block.Span.End)
|
if (Block.Span.Contains(linePosition, characterPosition))
|
||||||
foreach (var boundNode in Block.GetNodeAtPosition(characterPosition))
|
{
|
||||||
|
foreach (var boundNode in Block.GetNodeAtPosition(linePosition, characterPosition))
|
||||||
yield return boundNode;
|
yield return boundNode;
|
||||||
|
}
|
||||||
yield return this;
|
yield return this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,24 +25,28 @@ namespace Upsilon.Binder
|
||||||
}
|
}
|
||||||
|
|
||||||
public override BoundKind Kind => BoundKind.BoundIfStatement;
|
public override BoundKind Kind => BoundKind.BoundIfStatement;
|
||||||
public override IEnumerable<BoundNode> GetNodeAtPosition(int characterPosition)
|
public override IEnumerable<BoundNode> GetNodeAtPosition(int linePosition, int characterPosition)
|
||||||
{
|
{
|
||||||
if (characterPosition >= Condition.Span.Start && characterPosition <= Condition.Span.End)
|
if (Condition.Span.Contains(linePosition, characterPosition))
|
||||||
foreach (var boundNode in Condition.GetNodeAtPosition(characterPosition))
|
{
|
||||||
|
foreach (var boundNode in Condition.GetNodeAtPosition(linePosition, characterPosition))
|
||||||
yield return boundNode;
|
yield return boundNode;
|
||||||
|
}
|
||||||
if (characterPosition >= Block.Span.Start && characterPosition <= Block.Span.End)
|
if (Block.Span.Contains(linePosition, characterPosition))
|
||||||
foreach (var boundNode in Block.GetNodeAtPosition(characterPosition))
|
{
|
||||||
|
foreach (var boundNode in Block.GetNodeAtPosition(linePosition, characterPosition))
|
||||||
yield return boundNode;
|
yield return boundNode;
|
||||||
|
}
|
||||||
if (NextElseIf != null && characterPosition >= NextElseIf.Span.Start && characterPosition <= NextElseIf.Span.End)
|
if (NextElseIf != null && NextElseIf.Span.Contains(linePosition, characterPosition))
|
||||||
foreach (var boundNode in NextElseIf.GetNodeAtPosition(characterPosition))
|
{
|
||||||
|
foreach (var boundNode in NextElseIf.GetNodeAtPosition(linePosition, characterPosition))
|
||||||
yield return boundNode;
|
yield return boundNode;
|
||||||
|
}
|
||||||
if (ElseStatement != null && characterPosition >= ElseStatement.Span.Start && characterPosition <= ElseStatement.Span.End)
|
if (ElseStatement != null && ElseStatement.Span.Contains(linePosition, characterPosition))
|
||||||
foreach (var boundNode in ElseStatement.GetNodeAtPosition(characterPosition))
|
{
|
||||||
|
foreach (var boundNode in ElseStatement.GetNodeAtPosition(linePosition, characterPosition))
|
||||||
yield return boundNode;
|
yield return boundNode;
|
||||||
|
}
|
||||||
yield return this;
|
yield return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,12 +66,13 @@ namespace Upsilon.Binder
|
||||||
}
|
}
|
||||||
|
|
||||||
public override BoundKind Kind => BoundKind.BoundElseStatement;
|
public override BoundKind Kind => BoundKind.BoundElseStatement;
|
||||||
public override IEnumerable<BoundNode> GetNodeAtPosition(int characterPosition)
|
public override IEnumerable<BoundNode> GetNodeAtPosition(int linePosition, int characterPosition)
|
||||||
{
|
{
|
||||||
if (Block != null && characterPosition >= Block.Span.Start && characterPosition <= Block.Span.End)
|
if (Block.Span.Contains(linePosition, characterPosition))
|
||||||
foreach (var boundNode in Block.GetNodeAtPosition(characterPosition))
|
{
|
||||||
|
foreach (var boundNode in Block.GetNodeAtPosition(linePosition, characterPosition))
|
||||||
yield return boundNode;
|
yield return boundNode;
|
||||||
|
}
|
||||||
yield return this;
|
yield return this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,14 +18,13 @@ namespace Upsilon.Binder
|
||||||
}
|
}
|
||||||
|
|
||||||
public override BoundKind Kind => BoundKind.BoundMultiAssignmentStatement;
|
public override BoundKind Kind => BoundKind.BoundMultiAssignmentStatement;
|
||||||
public override IEnumerable<BoundNode> GetNodeAtPosition(int characterPosition)
|
public override IEnumerable<BoundNode> GetNodeAtPosition(int linePosition, int characterPosition)
|
||||||
{
|
{
|
||||||
if (characterPosition >= Assignment.Span.Start && characterPosition <= Assignment.Span.End)
|
if (Assignment.Span.Contains(linePosition, characterPosition))
|
||||||
foreach (var boundNode in Assignment.GetNodeAtPosition(characterPosition))
|
foreach (var boundNode in Assignment.GetNodeAtPosition(linePosition, characterPosition))
|
||||||
yield return boundNode;
|
yield return boundNode;
|
||||||
|
|
||||||
yield return this;
|
yield return this;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -23,26 +23,21 @@ namespace Upsilon.Binder
|
||||||
}
|
}
|
||||||
|
|
||||||
public override BoundKind Kind => BoundKind.BoundNumericForStatement;
|
public override BoundKind Kind => BoundKind.BoundNumericForStatement;
|
||||||
public override IEnumerable<BoundNode> GetNodeAtPosition(int characterPosition)
|
public override IEnumerable<BoundNode> GetNodeAtPosition(int linePosition, int characterPosition)
|
||||||
{
|
{
|
||||||
if (characterPosition >= BoundStart.Span.Start && characterPosition <= BoundStart.Span.End)
|
if (BoundStart.Span.Contains(linePosition, characterPosition))
|
||||||
foreach (var boundNode in BoundStart.GetNodeAtPosition(characterPosition))
|
foreach (var boundNode in BoundStart.GetNodeAtPosition(linePosition, characterPosition))
|
||||||
yield return boundNode;
|
yield return boundNode;
|
||||||
|
if (BoundStop.Span.Contains(linePosition, characterPosition))
|
||||||
if (characterPosition >= BoundStop.Span.Start && characterPosition <= BoundStop.Span.End)
|
foreach (var boundNode in BoundStop.GetNodeAtPosition(linePosition, characterPosition))
|
||||||
foreach (var boundNode in BoundStop.GetNodeAtPosition(characterPosition))
|
|
||||||
yield return boundNode;
|
yield return boundNode;
|
||||||
|
if (BoundStep.Span.Contains(linePosition, characterPosition))
|
||||||
if (characterPosition >= BoundStep.Span.Start && characterPosition <= BoundStep.Span.End)
|
foreach (var boundNode in BoundStep.GetNodeAtPosition(linePosition, characterPosition))
|
||||||
foreach (var boundNode in BoundStep.GetNodeAtPosition(characterPosition))
|
|
||||||
yield return boundNode;
|
yield return boundNode;
|
||||||
|
if (Block.Span.Contains(linePosition, characterPosition))
|
||||||
if (characterPosition >= Block.Span.Start && characterPosition <= Block.Span.End)
|
foreach (var boundNode in Block.GetNodeAtPosition(linePosition, characterPosition))
|
||||||
foreach (var boundNode in Block.GetNodeAtPosition(characterPosition))
|
|
||||||
yield return boundNode;
|
yield return boundNode;
|
||||||
|
|
||||||
yield return this;
|
yield return this;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -12,12 +12,11 @@ namespace Upsilon.Binder
|
||||||
|
|
||||||
public BoundExpression Expression { get; }
|
public BoundExpression Expression { get; }
|
||||||
public override BoundKind Kind => BoundKind.BoundReturnStatement;
|
public override BoundKind Kind => BoundKind.BoundReturnStatement;
|
||||||
public override IEnumerable<BoundNode> GetNodeAtPosition(int characterPosition)
|
public override IEnumerable<BoundNode> GetNodeAtPosition(int linePosition, int characterPosition)
|
||||||
{
|
{
|
||||||
if (characterPosition >= Expression.Span.Start && characterPosition <= Expression.Span.End)
|
if (Expression.Span.Contains(linePosition, characterPosition))
|
||||||
foreach (var boundNode in Expression.GetNodeAtPosition(characterPosition))
|
foreach (var boundNode in Expression.GetNodeAtPosition(linePosition, characterPosition))
|
||||||
yield return boundNode;
|
yield return boundNode;
|
||||||
|
|
||||||
yield return this;
|
yield return this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,9 +18,9 @@ namespace Upsilon.Binder
|
||||||
|
|
||||||
public string FileName { get; set; }
|
public string FileName { get; set; }
|
||||||
public override BoundKind Kind => BoundKind.BoundScript;
|
public override BoundKind Kind => BoundKind.BoundScript;
|
||||||
public override IEnumerable<BoundNode> GetNodeAtPosition(int characterPosition)
|
public override IEnumerable<BoundNode> GetNodeAtPosition(int linePosition, int characterPosition)
|
||||||
{
|
{
|
||||||
foreach (var boundNode in Statement.GetNodeAtPosition(characterPosition)) yield return boundNode;
|
foreach (var boundNode in Statement.GetNodeAtPosition(linePosition, characterPosition)) yield return boundNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BoundBlockStatement Statement { get; }
|
public BoundBlockStatement Statement { get; }
|
||||||
|
|
|
@ -16,18 +16,15 @@ namespace Upsilon.Binder
|
||||||
}
|
}
|
||||||
|
|
||||||
public override BoundKind Kind => BoundKind.BoundTableAssigmentStatement;
|
public override BoundKind Kind => BoundKind.BoundTableAssigmentStatement;
|
||||||
public override IEnumerable<BoundNode> GetNodeAtPosition(int characterPosition)
|
public override IEnumerable<BoundNode> GetNodeAtPosition(int linePosition, int characterPosition)
|
||||||
{
|
{
|
||||||
if (characterPosition >= TableIndexExpression.Span.Start && characterPosition <= TableIndexExpression.Span.End)
|
if (TableIndexExpression.Span.Contains(linePosition, characterPosition))
|
||||||
foreach (var boundNode in TableIndexExpression.GetNodeAtPosition(characterPosition))
|
foreach (var boundNode in TableIndexExpression.GetNodeAtPosition(linePosition, characterPosition))
|
||||||
yield return boundNode;
|
yield return boundNode;
|
||||||
|
if (Value.Span.Contains(linePosition, characterPosition))
|
||||||
if (characterPosition >= Value.Span.Start && characterPosition <= Value.Span.End)
|
foreach (var boundNode in Value.GetNodeAtPosition(linePosition, characterPosition))
|
||||||
foreach (var boundNode in Value.GetNodeAtPosition(characterPosition))
|
|
||||||
yield return boundNode;
|
yield return boundNode;
|
||||||
|
|
||||||
yield return this;
|
yield return this;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -18,16 +18,15 @@ namespace Upsilon.Binder
|
||||||
}
|
}
|
||||||
|
|
||||||
public override BoundKind Kind => BoundKind.BoundAssignmentStatement;
|
public override BoundKind Kind => BoundKind.BoundAssignmentStatement;
|
||||||
public override IEnumerable<BoundNode> GetNodeAtPosition(int characterPosition)
|
public override IEnumerable<BoundNode> GetNodeAtPosition(int linePosition, int characterPosition)
|
||||||
{
|
{
|
||||||
if (characterPosition >= Variable.Span.Start && characterPosition <= Variable.Span.End)
|
if (Variable.Span.Contains(linePosition, characterPosition))
|
||||||
yield return Variable;
|
yield return Variable;
|
||||||
if (characterPosition >= BoundExpression.Span.Start && characterPosition <= BoundExpression.Span.End)
|
if (BoundExpression.Span.Contains(linePosition, characterPosition))
|
||||||
foreach (var boundNode in BoundExpression.GetNodeAtPosition(characterPosition))
|
foreach (var boundNode in BoundExpression.GetNodeAtPosition(linePosition, characterPosition))
|
||||||
yield return boundNode;
|
yield return boundNode;
|
||||||
|
|
||||||
yield return this;
|
yield return this;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -17,16 +17,14 @@ namespace Upsilon.Binder
|
||||||
}
|
}
|
||||||
|
|
||||||
public override BoundKind Kind => BoundKind.BoundWhileStatement;
|
public override BoundKind Kind => BoundKind.BoundWhileStatement;
|
||||||
public override IEnumerable<BoundNode> GetNodeAtPosition(int characterPosition)
|
public override IEnumerable<BoundNode> GetNodeAtPosition(int linePosition, int characterPosition)
|
||||||
{
|
{
|
||||||
if (characterPosition >= Condition.Span.Start && characterPosition <= Condition.Span.End)
|
if (Condition.Span.Contains(linePosition, characterPosition))
|
||||||
foreach (var boundNode in Condition.GetNodeAtPosition(characterPosition))
|
foreach (var boundNode in Condition.GetNodeAtPosition(linePosition, characterPosition))
|
||||||
yield return boundNode;
|
yield return boundNode;
|
||||||
|
if (Block.Span.Contains(linePosition, characterPosition))
|
||||||
if (characterPosition >= Block.Span.Start && characterPosition <= Block.Span.End)
|
foreach (var boundNode in Block.GetNodeAtPosition(linePosition, characterPosition))
|
||||||
foreach (var boundNode in Block.GetNodeAtPosition(characterPosition))
|
|
||||||
yield return boundNode;
|
yield return boundNode;
|
||||||
|
|
||||||
yield return this;
|
yield return this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,19 +19,19 @@ namespace Upsilon.Binder
|
||||||
|
|
||||||
public BlockStatementSyntax UnboundBlock { get; }
|
public BlockStatementSyntax UnboundBlock { get; }
|
||||||
|
|
||||||
public override IEnumerable<BoundNode> GetNodeAtPosition(int characterPosition)
|
public override IEnumerable<BoundNode> GetNodeAtPosition(int linePosition, int characterPosition)
|
||||||
{
|
{
|
||||||
foreach (var parameter in Parameters)
|
foreach (var parameter in Parameters)
|
||||||
{
|
{
|
||||||
if (characterPosition >= parameter.Span.Start && characterPosition <= parameter.Span.End)
|
if (parameter.Span.Contains(linePosition, characterPosition))
|
||||||
foreach (var boundNode in parameter.GetNodeAtPosition(characterPosition))
|
foreach (var boundNode in parameter.GetNodeAtPosition(linePosition, characterPosition))
|
||||||
yield return boundNode;
|
yield return boundNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Block != null)
|
if (Block != null)
|
||||||
{
|
{
|
||||||
if (characterPosition >= Block.Span.Start && characterPosition <= Block.Span.End)
|
if (Block.Span.Contains(linePosition, characterPosition))
|
||||||
foreach (var boundNode in Block.GetNodeAtPosition(characterPosition))
|
foreach (var boundNode in Block.GetNodeAtPosition(linePosition, characterPosition))
|
||||||
yield return boundNode;
|
yield return boundNode;
|
||||||
}
|
}
|
||||||
yield return this;
|
yield return this;
|
||||||
|
|
|
@ -17,7 +17,7 @@ namespace Upsilon.Binder
|
||||||
|
|
||||||
public bool IsCreation { get; }
|
public bool IsCreation { get; }
|
||||||
public override BoundKind Kind => BoundKind.BoundVariableSymbol;
|
public override BoundKind Kind => BoundKind.BoundVariableSymbol;
|
||||||
public override IEnumerable<BoundNode> GetNodeAtPosition(int characterPosition)
|
public override IEnumerable<BoundNode> GetNodeAtPosition(int characterPosition, int i)
|
||||||
{
|
{
|
||||||
yield return this;
|
yield return this;
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,9 +33,8 @@ namespace Upsilon
|
||||||
{
|
{
|
||||||
if (ThrowsOnError)
|
if (ThrowsOnError)
|
||||||
{
|
{
|
||||||
var linePos = ScriptString.GetLinePosition(location.Start);
|
var text = ScriptString.GetSpan(location);
|
||||||
var line = ScriptString.GetLine(linePos.Line);
|
throw new ParseException(FileName, message, location.StartLine, location.StartPosition, text);
|
||||||
throw new ParseException(FileName, message, linePos.Line, linePos.Pos, line);
|
|
||||||
}
|
}
|
||||||
Log(DiagnosticLevel.Error, message, location);
|
Log(DiagnosticLevel.Error, message, location);
|
||||||
}
|
}
|
||||||
|
@ -122,39 +121,24 @@ namespace Upsilon
|
||||||
Span = span;
|
Span = span;
|
||||||
}
|
}
|
||||||
|
|
||||||
public (int Position, int PositionOnLine) GetStartLine()
|
|
||||||
{
|
|
||||||
return Diagnostics.ScriptString.GetLinePosition(Span.Start);
|
|
||||||
}
|
|
||||||
|
|
||||||
public (int Position, int PositionOnLine) GetEndLine()
|
|
||||||
{
|
|
||||||
return Diagnostics.ScriptString.GetLinePosition(Span.End);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
var linePos = Diagnostics.ScriptString.GetLinePosition(Span.Start);
|
return $"{Message} at ({Span.StartLine}, {Span.StartPosition})\n{Diagnostics.ScriptString.GetSpan(Span)}";
|
||||||
return $"{Message} at ({linePos.Line}, {linePos.Pos})\n{Diagnostics.ScriptString.GetSpan(Span)}";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetDiagnosticPosition()
|
public string GetDiagnosticPosition()
|
||||||
{
|
{
|
||||||
var linePos = Diagnostics.ScriptString.GetLinePosition(Span.Start);
|
return $"({Span.StartLine},{Span.StartPosition})";
|
||||||
return $"({linePos.Line},{linePos.Pos})";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public string LineBeforeError()
|
public string LineBeforeError()
|
||||||
{
|
{
|
||||||
var linePos = Diagnostics.ScriptString.GetLinePosition(Span.Start);
|
return Diagnostics.ScriptString.GetSpan(Span.StartLine, 0, Span.StartLine, Span.StartPosition);
|
||||||
var lineIndex = Diagnostics.ScriptString.GetLineStartPos(linePos.Line);
|
|
||||||
return Diagnostics.ScriptString.GetSpan(lineIndex, linePos.Pos);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public string BeforeError(int i = 5)
|
public string BeforeError(int i = 5)
|
||||||
{
|
{
|
||||||
return Diagnostics.ScriptString.GetSpan(Span.Start - i, i);
|
return Diagnostics.ScriptString.GetSpan(Span.StartLine, Span.StartPosition - i, Span.StartLine, Span.StartPosition);
|
||||||
}
|
}
|
||||||
|
|
||||||
public string AtError()
|
public string AtError()
|
||||||
|
@ -164,15 +148,12 @@ namespace Upsilon
|
||||||
|
|
||||||
public string LineAfterError()
|
public string LineAfterError()
|
||||||
{
|
{
|
||||||
var linePos = Diagnostics.ScriptString.GetLinePosition(Span.Start);
|
return Diagnostics.ScriptString.GetSpan(Span.EndLine, Span.EndPosition, Span.EndLine, 10000);
|
||||||
var lineInfo = Diagnostics.ScriptString.GetLineInfo(linePos.Line);
|
|
||||||
|
|
||||||
return Diagnostics.ScriptString.GetSpan(Span.End, lineInfo.End - Span.End);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public string AfterError(int i = 5)
|
public string AfterError(int i = 5)
|
||||||
{
|
{
|
||||||
return Diagnostics.ScriptString.GetSpan(Span.Start + Span.Length, i);
|
return Diagnostics.ScriptString.GetSpan(Span.EndLine, Span.EndPosition, Span.EndLine, Span.EndPosition + i);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,5 +10,6 @@ namespace Upsilon.Evaluator.Debugging
|
||||||
public class Breakpoint
|
public class Breakpoint
|
||||||
{
|
{
|
||||||
public int Line { get; set; }
|
public int Line { get; set; }
|
||||||
|
public int Position { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -67,8 +67,7 @@ namespace Upsilon.Evaluator
|
||||||
{
|
{
|
||||||
foreach (var breakpoint in file.Breakpoints)
|
foreach (var breakpoint in file.Breakpoints)
|
||||||
{
|
{
|
||||||
var lineStart = _script.ScriptString.GetLineInfo(breakpoint.Line).Start;
|
var debugStatement = e.GetBottomStatementAtPosition(breakpoint.Line, breakpoint.Position);
|
||||||
var debugStatement = e.GetBottomStatementAtPosition(lineStart);
|
|
||||||
debugStatement.HasBreakpoint = true;
|
debugStatement.HasBreakpoint = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -436,9 +435,7 @@ namespace Upsilon.Evaluator
|
||||||
|
|
||||||
private void ThrowException(string message, TextSpan location)
|
private void ThrowException(string message, TextSpan location)
|
||||||
{
|
{
|
||||||
var (i, pos) = _script.ScriptString.GetLinePosition(location.Start);
|
throw new ScriptRuntimeException(message, location, _diagnostics.ScriptString.GetSpan(location));
|
||||||
var line = _script.ScriptString.GetLine(i);
|
|
||||||
throw new ScriptRuntimeException(message, i, pos, line);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void EvaluateAssignmentStatement(BoundVariableAssignment e)
|
private void EvaluateAssignmentStatement(BoundVariableAssignment e)
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using System;
|
using System;
|
||||||
|
using Upsilon.Text;
|
||||||
|
|
||||||
namespace Upsilon.Exceptions
|
namespace Upsilon.Exceptions
|
||||||
{
|
{
|
||||||
|
@ -9,11 +10,11 @@ namespace Upsilon.Exceptions
|
||||||
public int Character { get; }
|
public int Character { get; }
|
||||||
public string ErrorLine { get; }
|
public string ErrorLine { get; }
|
||||||
|
|
||||||
public ScriptRuntimeException(string errorMessage, int line, int character, string errorLine)
|
public ScriptRuntimeException(string errorMessage, TextSpan position, string errorLine)
|
||||||
{
|
{
|
||||||
ErrorMessage = errorMessage;
|
ErrorMessage = errorMessage;
|
||||||
Line = line;
|
Line = position.StartLine;
|
||||||
Character = character;
|
Character = position.StartPosition;
|
||||||
ErrorLine = errorLine;
|
ErrorLine = errorLine;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ namespace Upsilon.Parser
|
||||||
Left = left;
|
Left = left;
|
||||||
Operator = @operator;
|
Operator = @operator;
|
||||||
Right = right;
|
Right = right;
|
||||||
Span = new TextSpan(left.Span.Start, right.Span.End - left.Span.Start);
|
Span = TextSpan.Between(left.Span, right.Span);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override SyntaxKind Kind => SyntaxKind.BinaryExpression;
|
public override SyntaxKind Kind => SyntaxKind.BinaryExpression;
|
||||||
|
|
|
@ -18,7 +18,7 @@ namespace Upsilon.Parser
|
||||||
OpenParenthesis = openParenthesis;
|
OpenParenthesis = openParenthesis;
|
||||||
Parameters = parameters;
|
Parameters = parameters;
|
||||||
CloseParenthesis = closeParenthesis;
|
CloseParenthesis = closeParenthesis;
|
||||||
Span = new TextSpan(Identifier.Span.Start, CloseParenthesis.Span.End - Identifier.Span.Start);
|
Span = TextSpan.Between(Identifier.Span, CloseParenthesis.Span);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override SyntaxKind Kind => SyntaxKind.FunctionCallExpression;
|
public override SyntaxKind Kind => SyntaxKind.FunctionCallExpression;
|
||||||
|
|
|
@ -23,7 +23,7 @@ namespace Upsilon.Parser
|
||||||
CloseParenthesis = closeParenthesis;
|
CloseParenthesis = closeParenthesis;
|
||||||
Block = block;
|
Block = block;
|
||||||
EndToken = endToken;
|
EndToken = endToken;
|
||||||
Span = new TextSpan(FunctionToken.Span.Start, EndToken.Span.End - FunctionToken.Span.Start);
|
Span = TextSpan.Between(FunctionToken.Span, endToken.Span);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override SyntaxKind Kind => SyntaxKind.FunctionExpression;
|
public override SyntaxKind Kind => SyntaxKind.FunctionExpression;
|
||||||
|
|
|
@ -17,7 +17,7 @@ namespace Upsilon.Parser
|
||||||
OpenBracket = openBracket;
|
OpenBracket = openBracket;
|
||||||
Index = index;
|
Index = index;
|
||||||
CloseBracket = closeBracket;
|
CloseBracket = closeBracket;
|
||||||
Span = new TextSpan(expression.Span.Start, CloseBracket.Span.End - expression.Span.Start);
|
Span = TextSpan.Between(expression.Span, closeBracket.Span);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override SyntaxKind Kind => SyntaxKind.IndexExpression;
|
public override SyntaxKind Kind => SyntaxKind.IndexExpression;
|
||||||
|
@ -41,7 +41,7 @@ namespace Upsilon.Parser
|
||||||
Expression = expression;
|
Expression = expression;
|
||||||
FullStop = fullStop;
|
FullStop = fullStop;
|
||||||
Index = index;
|
Index = index;
|
||||||
Span = new TextSpan(expression.Span.Start, Index.Span.End - expression.Span.Start);
|
Span = TextSpan.Between(expression.Span, Index.Span);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override SyntaxKind Kind => SyntaxKind.FullStopIndexExpression;
|
public override SyntaxKind Kind => SyntaxKind.FullStopIndexExpression;
|
||||||
|
|
|
@ -10,7 +10,7 @@ namespace Upsilon.Parser
|
||||||
OpenParenthesis = openParenthesis;
|
OpenParenthesis = openParenthesis;
|
||||||
Expression = expression;
|
Expression = expression;
|
||||||
CloseParenthesis = closeParenthesis;
|
CloseParenthesis = closeParenthesis;
|
||||||
Span = new TextSpan(OpenParenthesis.Span.Start, CloseParenthesis.Span.End - OpenParenthesis.Span.Start);
|
Span = TextSpan.Between(OpenParenthesis.Span, CloseParenthesis.Span);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override SyntaxKind Kind => SyntaxKind.ParenthesizedExpression;
|
public override SyntaxKind Kind => SyntaxKind.ParenthesizedExpression;
|
||||||
|
|
|
@ -11,7 +11,7 @@ namespace Upsilon.Parser
|
||||||
Expressions = expressions;
|
Expressions = expressions;
|
||||||
OpenBrace = openBrace;
|
OpenBrace = openBrace;
|
||||||
CloseBrace = closeBrace;
|
CloseBrace = closeBrace;
|
||||||
Span = new TextSpan(OpenBrace.Span.Start, CloseBrace.Span.End - OpenBrace.Span.Start);
|
Span = TextSpan.Between(OpenBrace.Span, CloseBrace.Span);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override SyntaxKind Kind => SyntaxKind.TableExpression;
|
public override SyntaxKind Kind => SyntaxKind.TableExpression;
|
||||||
|
|
|
@ -9,7 +9,7 @@ namespace Upsilon.Parser
|
||||||
{
|
{
|
||||||
Operator = @operator;
|
Operator = @operator;
|
||||||
Expression = expression;
|
Expression = expression;
|
||||||
Span = new TextSpan(Operator.Span.Start, expression.Span.End - Operator.Span.Start);
|
Span = TextSpan.Between(Operator.Span, expression.Span);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override SyntaxKind Kind => SyntaxKind.UnaryExpression;
|
public override SyntaxKind Kind => SyntaxKind.UnaryExpression;
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using Upsilon.Text;
|
||||||
|
|
||||||
namespace Upsilon.Parser
|
namespace Upsilon.Parser
|
||||||
{
|
{
|
||||||
public class IdentifierToken : SyntaxToken
|
public class IdentifierToken : SyntaxToken
|
||||||
{
|
{
|
||||||
public IdentifierToken(string name, int position)
|
public IdentifierToken(string name, TextSpan position)
|
||||||
: base(SyntaxKind.Identifier, position, name, null)
|
: base(SyntaxKind.Identifier, position, name, null)
|
||||||
{
|
{
|
||||||
Name = name;
|
Name = name;
|
||||||
|
|
|
@ -9,14 +9,15 @@ namespace Upsilon.Parser
|
||||||
public class Lexer
|
public class Lexer
|
||||||
{
|
{
|
||||||
private bool SaveComments { get; }
|
private bool SaveComments { get; }
|
||||||
private readonly string _text;
|
private readonly string[] _text;
|
||||||
private readonly Diagnostics _diagnostics;
|
private readonly Diagnostics _diagnostics;
|
||||||
|
private int _linePosition;
|
||||||
private int _position;
|
private int _position;
|
||||||
|
|
||||||
private Lexer(string text, Diagnostics diagnostics, bool saveComments)
|
private Lexer(string text, Diagnostics diagnostics, bool saveComments)
|
||||||
{
|
{
|
||||||
SaveComments = saveComments;
|
SaveComments = saveComments;
|
||||||
_text = text;
|
_text = text.Split('\n');
|
||||||
_diagnostics = diagnostics;
|
_diagnostics = diagnostics;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,8 +27,29 @@ namespace Upsilon.Parser
|
||||||
return lexer.Lex();
|
return lexer.Lex();
|
||||||
}
|
}
|
||||||
|
|
||||||
private char Current => _position >= _text.Length ? '\0' : _text[_position];
|
private char Current
|
||||||
private char Next => _position + 1 >= _text.Length ? '\0' : _text[_position + 1];
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var linePos = _linePosition;
|
||||||
|
var pos = _position;
|
||||||
|
if (linePos >= _text.Length) return '\0';
|
||||||
|
if (pos >= _text[linePos].Length) return '\n';
|
||||||
|
return _text[linePos][pos];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private char Next
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var linePos = _linePosition;
|
||||||
|
var pos = _position + 1;
|
||||||
|
if (linePos >= _text.Length) return '\0';
|
||||||
|
if (pos >= _text[linePos].Length) return '\n';
|
||||||
|
return _text[linePos][pos];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private readonly List<string> _activeComments = new List<string>();
|
private readonly List<string> _activeComments = new List<string>();
|
||||||
private ImmutableArray<SyntaxToken> Lex()
|
private ImmutableArray<SyntaxToken> Lex()
|
||||||
|
@ -66,46 +88,53 @@ namespace Upsilon.Parser
|
||||||
switch (Current)
|
switch (Current)
|
||||||
{
|
{
|
||||||
case '\0':
|
case '\0':
|
||||||
return new SyntaxToken(SyntaxKind.EndOfFile, _position, "\0", null);
|
return new SyntaxToken(SyntaxKind.EndOfFile, new TextSpan(_linePosition, _position, _linePosition, _position + 1), "\0", null);
|
||||||
case ' ': case '\t': case '\r': case '\n':
|
case ' ': case '\t': case '\r':
|
||||||
return new SyntaxToken(SyntaxKind.WhiteSpace, _position, Current.ToString(), null);
|
return new SyntaxToken(SyntaxKind.WhiteSpace, new TextSpan(_linePosition, _position, _linePosition, _position + 1), Current.ToString(), null);
|
||||||
|
case '\n':
|
||||||
|
{
|
||||||
|
_linePosition++;
|
||||||
|
var pos = _position;
|
||||||
|
_position = -1;
|
||||||
|
return new SyntaxToken(SyntaxKind.WhiteSpace, new TextSpan(_linePosition, pos, _linePosition, pos + 1), "\n", null);
|
||||||
|
}
|
||||||
case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
|
case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
|
||||||
return LexNumber();
|
return LexNumber();
|
||||||
case '+':
|
case '+':
|
||||||
return new SyntaxToken(SyntaxKind.Plus, _position, "+", null);
|
return new SyntaxToken(SyntaxKind.Plus, new TextSpan(_linePosition, _position, _linePosition, _position + 1), "+", null);
|
||||||
case '-':
|
case '-':
|
||||||
if (Next == '-')
|
if (Next == '-')
|
||||||
{
|
{
|
||||||
_position++;
|
_position++;
|
||||||
return LexComments();
|
return LexComments();
|
||||||
}
|
}
|
||||||
return new SyntaxToken(SyntaxKind.Minus, _position, "-", null);
|
return new SyntaxToken(SyntaxKind.Minus, new TextSpan(_linePosition, _position, _linePosition, _position + 1), "-", null);
|
||||||
case '*':
|
case '*':
|
||||||
return new SyntaxToken(SyntaxKind.Star, _position, "*", null);
|
return new SyntaxToken(SyntaxKind.Star, new TextSpan(_linePosition, _position, _linePosition, _position + 1), "*", null);
|
||||||
case '/':
|
case '/':
|
||||||
return new SyntaxToken(SyntaxKind.Slash, _position, "/", null);
|
return new SyntaxToken(SyntaxKind.Slash, new TextSpan(_linePosition, _position, _linePosition, _position + 1), "/", null);
|
||||||
case '(':
|
case '(':
|
||||||
return new SyntaxToken(SyntaxKind.OpenParenthesis, _position, "(", null);
|
return new SyntaxToken(SyntaxKind.OpenParenthesis, new TextSpan(_linePosition, _position, _linePosition, _position + 1), "(", null);
|
||||||
case ')':
|
case ')':
|
||||||
return new SyntaxToken(SyntaxKind.CloseParenthesis, _position, ")", null);
|
return new SyntaxToken(SyntaxKind.CloseParenthesis, new TextSpan(_linePosition, _position, _linePosition, _position + 1), ")", null);
|
||||||
case '{':
|
case '{':
|
||||||
return new SyntaxToken(SyntaxKind.OpenBrace, _position, "{", null);
|
return new SyntaxToken(SyntaxKind.OpenBrace, new TextSpan(_linePosition, _position, _linePosition, _position + 1), "{", null);
|
||||||
case '}':
|
case '}':
|
||||||
return new SyntaxToken(SyntaxKind.CloseBrace, _position, "}", null);
|
return new SyntaxToken(SyntaxKind.CloseBrace, new TextSpan(_linePosition, _position, _linePosition, _position + 1), "}", null);
|
||||||
case '[':
|
case '[':
|
||||||
return new SyntaxToken(SyntaxKind.OpenBracket, _position, "[", null);
|
return new SyntaxToken(SyntaxKind.OpenBracket, new TextSpan(_linePosition, _position, _linePosition, _position + 1), "[", null);
|
||||||
case ']':
|
case ']':
|
||||||
return new SyntaxToken(SyntaxKind.CloseBracket, _position, "]", null);
|
return new SyntaxToken(SyntaxKind.CloseBracket, new TextSpan(_linePosition, _position, _linePosition, _position + 1), "]", null);
|
||||||
case '.':
|
case '.':
|
||||||
return new SyntaxToken(SyntaxKind.FullStop, _position, ".", null);
|
return new SyntaxToken(SyntaxKind.FullStop, new TextSpan(_linePosition, _position, _linePosition, _position + 1), ".", null);
|
||||||
case ',':
|
case ',':
|
||||||
return new SyntaxToken(SyntaxKind.Comma, _position, ",", null);
|
return new SyntaxToken(SyntaxKind.Comma, new TextSpan(_linePosition, _position, _linePosition, _position + 1), ",", null);
|
||||||
case '#':
|
case '#':
|
||||||
return new SyntaxToken(SyntaxKind.PoundSign, _position, "#", null);
|
return new SyntaxToken(SyntaxKind.PoundSign, new TextSpan(_linePosition, _position, _linePosition, _position + 1), "#", null);
|
||||||
case '%':
|
case '%':
|
||||||
return new SyntaxToken(SyntaxKind.PercentSign, _position, "%", null);
|
return new SyntaxToken(SyntaxKind.PercentSign, new TextSpan(_linePosition, _position, _linePosition, _position + 1), "%", null);
|
||||||
case '^':
|
case '^':
|
||||||
return new SyntaxToken(SyntaxKind.RoofSign, _position, "^", null);
|
return new SyntaxToken(SyntaxKind.RoofSign, new TextSpan(_linePosition, _position, _linePosition, _position + 1), "^", null);
|
||||||
case '"':
|
case '"':
|
||||||
case '\'':
|
case '\'':
|
||||||
return LexString(Current);
|
return LexString(Current);
|
||||||
|
@ -113,35 +142,35 @@ namespace Upsilon.Parser
|
||||||
if (Next == '=')
|
if (Next == '=')
|
||||||
{
|
{
|
||||||
_position++;
|
_position++;
|
||||||
return new SyntaxToken(SyntaxKind.EqualsEquals, _position - 1, "==", null);
|
return new SyntaxToken(SyntaxKind.EqualsEquals, new TextSpan(_linePosition, _position - 1, _linePosition, _position + 1), "==", null);
|
||||||
}
|
}
|
||||||
return new SyntaxToken(SyntaxKind.Equals, _position, "=", null);
|
return new SyntaxToken(SyntaxKind.Equals, new TextSpan(_linePosition, _position, _linePosition, _position + 1), "=", null);
|
||||||
case '~':
|
case '~':
|
||||||
if (Next == '=')
|
if (Next == '=')
|
||||||
{
|
{
|
||||||
_position++;
|
_position++;
|
||||||
return new SyntaxToken(SyntaxKind.TildeEquals, _position - 1, "~=", null);
|
return new SyntaxToken(SyntaxKind.TildeEquals, new TextSpan(_linePosition, _position - 1, _linePosition, _position + 1), "~=", null);
|
||||||
}
|
}
|
||||||
return new SyntaxToken(SyntaxKind.Tilde, _position, "~", null);
|
return new SyntaxToken(SyntaxKind.Tilde, new TextSpan(_linePosition, _position, _linePosition, _position + 1), "~", null);
|
||||||
case '<':
|
case '<':
|
||||||
if (Next == '=')
|
if (Next == '=')
|
||||||
{
|
{
|
||||||
_position++;
|
_position++;
|
||||||
return new SyntaxToken(SyntaxKind.LessEquals, _position - 1, "<=", null);
|
return new SyntaxToken(SyntaxKind.LessEquals, new TextSpan(_linePosition, _position - 1, _linePosition, _position + 1), "<=", null);
|
||||||
}
|
}
|
||||||
return new SyntaxToken(SyntaxKind.Less, _position, "<", null);
|
return new SyntaxToken(SyntaxKind.Less, new TextSpan(_linePosition, _position, _linePosition, _position + 1), "<", null);
|
||||||
case '>':
|
case '>':
|
||||||
if (Next == '=')
|
if (Next == '=')
|
||||||
{
|
{
|
||||||
_position++;
|
_position++;
|
||||||
return new SyntaxToken(SyntaxKind.GreaterEquals, _position - 1, ">=", null);
|
return new SyntaxToken(SyntaxKind.GreaterEquals, new TextSpan(_linePosition, _position - 1, _linePosition, _position + 1), ">=", null);
|
||||||
}
|
}
|
||||||
return new SyntaxToken(SyntaxKind.Greater, _position, ">", null);
|
return new SyntaxToken(SyntaxKind.Greater, new TextSpan(_linePosition, _position, _linePosition, _position + 1), ">", null);
|
||||||
default:
|
default:
|
||||||
if (char.IsLetter(Current) || Current == '_')
|
if (char.IsLetter(Current) || Current == '_')
|
||||||
return LexIdentifierOrKeyword();
|
return LexIdentifierOrKeyword();
|
||||||
_diagnostics.LogBadCharacter(new TextSpan(_position, 1), SyntaxKind.Identifier);
|
_diagnostics.LogBadCharacter(new TextSpan(_linePosition, _position, _linePosition, _position + 1), SyntaxKind.Identifier);
|
||||||
return new SyntaxToken(SyntaxKind.BadToken, _position, "", null);
|
return new SyntaxToken(SyntaxKind.BadToken, new TextSpan(_linePosition, _position, _linePosition, _position + 1), "", null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -157,8 +186,8 @@ namespace Upsilon.Parser
|
||||||
{
|
{
|
||||||
if (hasDecimalPoint)
|
if (hasDecimalPoint)
|
||||||
{
|
{
|
||||||
_diagnostics.LogBadCharacter(new TextSpan(_position, 1), SyntaxKind.Number);
|
_diagnostics.LogBadCharacter(new TextSpan(_linePosition, _position, _linePosition, _position + 1), SyntaxKind.Number);
|
||||||
return new SyntaxToken(SyntaxKind.BadToken, _position, "", null);
|
return new SyntaxToken(SyntaxKind.BadToken, new TextSpan(_linePosition, _position, _linePosition, _position + 1), "", null);
|
||||||
}
|
}
|
||||||
hasDecimalPoint = true;
|
hasDecimalPoint = true;
|
||||||
}
|
}
|
||||||
|
@ -172,16 +201,18 @@ namespace Upsilon.Parser
|
||||||
o = double.Parse(numStr.ToString());
|
o = double.Parse(numStr.ToString());
|
||||||
else
|
else
|
||||||
o = long.Parse(numStr.ToString());
|
o = long.Parse(numStr.ToString());
|
||||||
return new SyntaxToken(SyntaxKind.Number, start, numStr.ToString(), o);
|
return new SyntaxToken(SyntaxKind.Number, new TextSpan(_linePosition, start, _linePosition, _position + 1), numStr.ToString(), o);
|
||||||
}
|
}
|
||||||
|
|
||||||
private SyntaxToken LexString(char current)
|
private SyntaxToken LexString(char current)
|
||||||
{
|
{
|
||||||
var start = _position;
|
var start = _position;
|
||||||
var sb = new StringBuilder();
|
var sb = new StringBuilder();
|
||||||
while (_position < _text.Length)
|
while (true)
|
||||||
{
|
{
|
||||||
_position++;
|
_position++;
|
||||||
|
if (Current == '\0')
|
||||||
|
break;
|
||||||
if (Current == '\\' && Next == current)
|
if (Current == '\\' && Next == current)
|
||||||
{
|
{
|
||||||
sb.Append(current);
|
sb.Append(current);
|
||||||
|
@ -194,15 +225,18 @@ namespace Upsilon.Parser
|
||||||
|
|
||||||
if (Current != current)
|
if (Current != current)
|
||||||
{
|
{
|
||||||
_diagnostics.LogBadCharacter(new TextSpan(_position, 1), current, Current);
|
_diagnostics.LogBadCharacter(new TextSpan(_linePosition, _position, _linePosition, _position + 1),
|
||||||
|
current, Current);
|
||||||
}
|
}
|
||||||
|
|
||||||
var res = sb.ToString();
|
var res = sb.ToString();
|
||||||
return new SyntaxToken(SyntaxKind.String, start, $"\"{res}\"", res);
|
return new SyntaxToken(SyntaxKind.String, new TextSpan(_linePosition, start, _linePosition, _position + 1),
|
||||||
|
$"\"{res}\"", res);
|
||||||
}
|
}
|
||||||
|
|
||||||
private SyntaxToken LexIdentifierOrKeyword()
|
private SyntaxToken LexIdentifierOrKeyword()
|
||||||
{
|
{
|
||||||
|
var startLine = _linePosition;
|
||||||
var start = _position;
|
var start = _position;
|
||||||
var stringBuilder = new StringBuilder();
|
var stringBuilder = new StringBuilder();
|
||||||
stringBuilder.Append(Current);
|
stringBuilder.Append(Current);
|
||||||
|
@ -216,19 +250,20 @@ namespace Upsilon.Parser
|
||||||
var str = stringBuilder.ToString();
|
var str = stringBuilder.ToString();
|
||||||
if (kind == SyntaxKind.Identifier)
|
if (kind == SyntaxKind.Identifier)
|
||||||
{
|
{
|
||||||
return new IdentifierToken(str, start);
|
return new IdentifierToken(str, new TextSpan(startLine, start, _linePosition, _position));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (kind == SyntaxKind.ReturnKeyword)
|
if (kind == SyntaxKind.ReturnKeyword)
|
||||||
{
|
{
|
||||||
return new ReturnSyntaxToken(start, Next == Environment.NewLine[0]);
|
return new ReturnSyntaxToken(new TextSpan(_linePosition, start, _linePosition, _position + 1), Next == Environment.NewLine[0]);
|
||||||
}
|
}
|
||||||
return new SyntaxToken(kind, start, str, null);
|
return new SyntaxToken(kind, new TextSpan(_linePosition, start, _linePosition, _position + 1), str, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private SyntaxToken LexComments()
|
private SyntaxToken LexComments()
|
||||||
{
|
{
|
||||||
_position++;
|
_position++;
|
||||||
|
var startLine = _linePosition;
|
||||||
var start = _position;
|
var start = _position;
|
||||||
StringBuilder stringBuilder = null;
|
StringBuilder stringBuilder = null;
|
||||||
if (SaveComments)
|
if (SaveComments)
|
||||||
|
@ -244,7 +279,7 @@ namespace Upsilon.Parser
|
||||||
}
|
}
|
||||||
var str = stringBuilder?.ToString();
|
var str = stringBuilder?.ToString();
|
||||||
_position++;
|
_position++;
|
||||||
return new SyntaxToken(SyntaxKind.Comment, start, _position - start, str);
|
return new SyntaxToken(SyntaxKind.Comment, new TextSpan(startLine, start, _linePosition, _position + 1), _position - start, str);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -9,9 +9,9 @@ namespace Upsilon.Parser
|
||||||
{
|
{
|
||||||
TypeName = typeName;
|
TypeName = typeName;
|
||||||
IdentifierName = identifierName;
|
IdentifierName = identifierName;
|
||||||
var start = identifierName.Span.Start;
|
var start = identifierName.Span;
|
||||||
if (typeName != null) start = typeName.Span.Start;
|
if (typeName != null) start = typeName.Span;
|
||||||
Span = new TextSpan(start, identifierName.Span.End - start);
|
Span = TextSpan.Between(start, identifierName.Span);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IdentifierToken TypeName { get; }
|
public IdentifierToken TypeName { get; }
|
||||||
|
|
|
@ -29,7 +29,7 @@ namespace Upsilon.Parser
|
||||||
private SyntaxToken Get(int offset)
|
private SyntaxToken Get(int offset)
|
||||||
{
|
{
|
||||||
if (_position + offset >= _tokens.Length)
|
if (_position + offset >= _tokens.Length)
|
||||||
return new SyntaxToken(SyntaxKind.EndOfFile, _position + offset, "\0", null);
|
return new SyntaxToken(SyntaxKind.EndOfFile, _tokens.Last().Span, "\0", null);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return _tokens[_position + offset];
|
return _tokens[_position + offset];
|
||||||
|
@ -49,7 +49,7 @@ namespace Upsilon.Parser
|
||||||
return NextToken();
|
return NextToken();
|
||||||
|
|
||||||
_diagnostics.LogBadCharacter(Current.Span, kind, Current.Kind);
|
_diagnostics.LogBadCharacter(Current.Span, kind, Current.Kind);
|
||||||
return new SyntaxToken(kind, Current.Span.Start, "", null);
|
return new SyntaxToken(kind, Current.Span, "", null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private StatementSyntax ParseScriptSyntax()
|
private StatementSyntax ParseScriptSyntax()
|
||||||
|
@ -515,7 +515,7 @@ namespace Upsilon.Parser
|
||||||
// We'll still want to return a index expression, but we just express that the identifier is empty.
|
// We'll still want to return a index expression, but we just express that the identifier is empty.
|
||||||
// This is helpful for tools, etc
|
// This is helpful for tools, etc
|
||||||
return new FullStopIndexExpressionSyntax(expression, fullStop,
|
return new FullStopIndexExpressionSyntax(expression, fullStop,
|
||||||
new IdentifierToken(string.Empty, fullStop.Span.End));
|
new IdentifierToken(string.Empty, fullStop.Span));
|
||||||
}
|
}
|
||||||
|
|
||||||
private ExpressionSyntax ParseParenthesizedExpression()
|
private ExpressionSyntax ParseParenthesizedExpression()
|
||||||
|
|
|
@ -12,8 +12,8 @@ namespace Upsilon.Parser
|
||||||
Identifier = identifyExpression;
|
Identifier = identifyExpression;
|
||||||
EqualsToken = equalsToken;
|
EqualsToken = equalsToken;
|
||||||
Expression = expression;
|
Expression = expression;
|
||||||
var start = LocalToken?.Span.Start ?? Identifier.Span.Start;
|
var start = LocalToken?.Span ?? Identifier.Span;
|
||||||
Span = new TextSpan(start, Expression.Span.End - start);
|
Span = TextSpan.Between(start, expression.Span);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override SyntaxKind Kind => SyntaxKind.AssignmentStatement;
|
public override SyntaxKind Kind => SyntaxKind.AssignmentStatement;
|
||||||
|
|
|
@ -13,7 +13,7 @@ namespace Upsilon.Parser
|
||||||
var first = statements.FirstOrDefault();
|
var first = statements.FirstOrDefault();
|
||||||
var last = statements.LastOrDefault();
|
var last = statements.LastOrDefault();
|
||||||
if (first != null && last != null)
|
if (first != null && last != null)
|
||||||
Span = new TextSpan(first.Span.Start, last.Span.End - first.Span.Start);
|
Span = TextSpan.Between(first.Span, last.Span);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ImmutableArray<StatementSyntax> Statements { get; }
|
public ImmutableArray<StatementSyntax> Statements { get; }
|
||||||
|
|
|
@ -10,9 +10,9 @@ namespace Upsilon.Parser
|
||||||
LocalToken = localToken;
|
LocalToken = localToken;
|
||||||
Identifier = identifier;
|
Identifier = identifier;
|
||||||
FunctionExpression = functionExpression;
|
FunctionExpression = functionExpression;
|
||||||
var start = Identifier.Span.Start;
|
var start = Identifier.Span;
|
||||||
if (localToken != null) start = localToken.Span.Start;
|
if (localToken != null) start = localToken.Span;
|
||||||
Span = new TextSpan(start, FunctionExpression.Span.End - start);
|
Span = TextSpan.Between(start, functionExpression.Span);
|
||||||
}
|
}
|
||||||
|
|
||||||
public SyntaxToken LocalToken { get; }
|
public SyntaxToken LocalToken { get; }
|
||||||
|
|
|
@ -24,7 +24,7 @@ namespace Upsilon.Parser
|
||||||
DoKeyword = doKeyword;
|
DoKeyword = doKeyword;
|
||||||
Block = block;
|
Block = block;
|
||||||
EndKeyword = endKeyword;
|
EndKeyword = endKeyword;
|
||||||
Span = new TextSpan(forKeyword.Span.Start, endKeyword.Span.End - forKeyword.Span.Start);
|
Span = TextSpan.Between(forKeyword.Span, endKeyword.Span);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override SyntaxKind Kind => SyntaxKind.GenericForStatement;
|
public override SyntaxKind Kind => SyntaxKind.GenericForStatement;
|
||||||
|
|
|
@ -16,9 +16,9 @@ namespace Upsilon.Parser
|
||||||
ThenToken = thenToken;
|
ThenToken = thenToken;
|
||||||
Block = block;
|
Block = block;
|
||||||
EndToken = endToken;
|
EndToken = endToken;
|
||||||
var end = Block.Span.End;
|
var end = Block.Span;
|
||||||
if (EndToken != null) end = EndToken.Span.End;
|
if (EndToken != null) end = EndToken.Span;
|
||||||
Span = new TextSpan(IfToken.Span.Start, end - IfToken.Span.Start);
|
Span = TextSpan.Between(ifToken.Span, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IfStatementSyntax(SyntaxToken ifToken, ExpressionStatementSyntax condition, SyntaxToken thenToken,
|
public IfStatementSyntax(SyntaxToken ifToken, ExpressionStatementSyntax condition, SyntaxToken thenToken,
|
||||||
|
@ -29,7 +29,7 @@ namespace Upsilon.Parser
|
||||||
ThenToken = thenToken;
|
ThenToken = thenToken;
|
||||||
Block = block;
|
Block = block;
|
||||||
ElseStatement = elseStatement;
|
ElseStatement = elseStatement;
|
||||||
Span = new TextSpan(IfToken.Span.Start, ElseStatement.Span.End - IfToken.Span.Start);
|
Span = TextSpan.Between(ifToken.Span, elseStatement.Span);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IfStatementSyntax(SyntaxToken ifToken, ExpressionStatementSyntax condition, SyntaxToken thenToken,
|
public IfStatementSyntax(SyntaxToken ifToken, ExpressionStatementSyntax condition, SyntaxToken thenToken,
|
||||||
|
@ -40,7 +40,7 @@ namespace Upsilon.Parser
|
||||||
ThenToken = thenToken;
|
ThenToken = thenToken;
|
||||||
Block = block;
|
Block = block;
|
||||||
NextElseIfStatement = nextElseIfStatement;
|
NextElseIfStatement = nextElseIfStatement;
|
||||||
Span = new TextSpan(IfToken.Span.Start, NextElseIfStatement.Span.End - IfToken.Span.Start);
|
Span = TextSpan.Between(ifToken.Span, nextElseIfStatement.Span);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -79,7 +79,7 @@ namespace Upsilon.Parser
|
||||||
yield return Condition;
|
yield return Condition;
|
||||||
yield return ThenToken;
|
yield return ThenToken;
|
||||||
yield return Block;
|
yield return Block;
|
||||||
Span = new TextSpan(ElseIfToken.Span.Start, Block.Span.End - ElseIfToken.Span.Start);
|
Span = TextSpan.Between(ElseIfToken.Span, Block.Span);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ElseIfStatementSyntax(IfStatementSyntax s)
|
public ElseIfStatementSyntax(IfStatementSyntax s)
|
||||||
|
@ -119,7 +119,7 @@ namespace Upsilon.Parser
|
||||||
ElseToken = elseToken;
|
ElseToken = elseToken;
|
||||||
Block = block;
|
Block = block;
|
||||||
EndToken = endToken;
|
EndToken = endToken;
|
||||||
Span = new TextSpan(ElseToken.Span.Start, EndToken.Span.End - ElseToken.Span.Start);
|
Span = TextSpan.Between(elseToken.Span, endToken.Span);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override SyntaxKind Kind => SyntaxKind.ElseStatement;
|
public override SyntaxKind Kind => SyntaxKind.ElseStatement;
|
||||||
|
|
|
@ -19,9 +19,9 @@ namespace Upsilon.Parser
|
||||||
Identifiers = identifiers.ToImmutableArray();
|
Identifiers = identifiers.ToImmutableArray();
|
||||||
AssignmentToken = assignmentToken;
|
AssignmentToken = assignmentToken;
|
||||||
Expression = expression;
|
Expression = expression;
|
||||||
var start = Identifiers.First().Span.Start;
|
var start = Identifiers.First().Span;
|
||||||
if (localKeyword != null) start = localKeyword.Span.Start;
|
if (localKeyword != null) start = localKeyword.Span;
|
||||||
Span = new TextSpan(start, expression.Span.End - start);
|
Span = TextSpan.Between(start, expression.Span);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override SyntaxKind Kind => SyntaxKind.MultiAssignmentStatement;
|
public override SyntaxKind Kind => SyntaxKind.MultiAssignmentStatement;
|
||||||
|
|
|
@ -32,7 +32,7 @@ namespace Upsilon.Parser
|
||||||
DoToken = doToken;
|
DoToken = doToken;
|
||||||
Block = block;
|
Block = block;
|
||||||
EndToken = endToken;
|
EndToken = endToken;
|
||||||
Span = new TextSpan(ForToken.Span.Start, EndToken.Span.End - ForToken.Span.Start);
|
Span = TextSpan.Between(forToken.Span, endToken.Span);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override SyntaxKind Kind => SyntaxKind.NumericForStatement;
|
public override SyntaxKind Kind => SyntaxKind.NumericForStatement;
|
||||||
|
|
|
@ -9,9 +9,9 @@ namespace Upsilon.Parser
|
||||||
{
|
{
|
||||||
ReturnToken = returnToken;
|
ReturnToken = returnToken;
|
||||||
Expression = expression;
|
Expression = expression;
|
||||||
var end = returnToken.Span.End;
|
var end = returnToken.Span;
|
||||||
if (expression != null) end = expression.Span.End;
|
if (expression != null) end = expression.Span;
|
||||||
Span = new TextSpan(returnToken.Span.Start, end - returnToken.Span.Start);
|
Span = TextSpan.Between(returnToken.Span, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
public SyntaxToken ReturnToken { get; }
|
public SyntaxToken ReturnToken { get; }
|
||||||
|
|
|
@ -15,7 +15,7 @@ namespace Upsilon.Parser
|
||||||
TableExpression = tableExpression;
|
TableExpression = tableExpression;
|
||||||
AssignmentToken = assignmentToken;
|
AssignmentToken = assignmentToken;
|
||||||
Expression = expression;
|
Expression = expression;
|
||||||
Span = new TextSpan(tableExpression.Span.Start, expression.Span.End - tableExpression.Span.Start);
|
Span = TextSpan.Between(tableExpression.Span, expression.Span);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override SyntaxKind Kind => SyntaxKind.TableAssignmentStatement;
|
public override SyntaxKind Kind => SyntaxKind.TableAssignmentStatement;
|
||||||
|
|
|
@ -21,7 +21,7 @@ namespace Upsilon.Parser
|
||||||
Block = block;
|
Block = block;
|
||||||
EndKeyword = endKeyword;
|
EndKeyword = endKeyword;
|
||||||
|
|
||||||
Span = new TextSpan(whileToken.Span.Start, endKeyword.Span.End);
|
Span = TextSpan.Between(whileToken.Span, endKeyword.Span);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override SyntaxKind Kind => SyntaxKind.WhileStatement;
|
public override SyntaxKind Kind => SyntaxKind.WhileStatement;
|
||||||
|
|
|
@ -5,17 +5,17 @@ namespace Upsilon.Parser
|
||||||
{
|
{
|
||||||
public class SyntaxToken : SyntaxNode
|
public class SyntaxToken : SyntaxNode
|
||||||
{
|
{
|
||||||
public SyntaxToken(SyntaxKind kind, int position, string text, object value)
|
public SyntaxToken(SyntaxKind kind, TextSpan position, string text, object value)
|
||||||
{
|
{
|
||||||
Kind = kind;
|
Kind = kind;
|
||||||
Span = new TextSpan(position, text.Length);
|
Span = position;
|
||||||
Value = value;
|
Value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SyntaxToken(SyntaxKind kind, int position, int length, object value)
|
public SyntaxToken(SyntaxKind kind, TextSpan position, int length, object value)
|
||||||
{
|
{
|
||||||
Kind = kind;
|
Kind = kind;
|
||||||
Span = new TextSpan(position, length);
|
Span = position;
|
||||||
Value = value;
|
Value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@ namespace Upsilon.Parser
|
||||||
{
|
{
|
||||||
public bool FollowedByLineBreak { get; }
|
public bool FollowedByLineBreak { get; }
|
||||||
|
|
||||||
public ReturnSyntaxToken(int position, bool followedByLineBreak)
|
public ReturnSyntaxToken(TextSpan position, bool followedByLineBreak)
|
||||||
: base(SyntaxKind.ReturnKeyword, position, "return", null)
|
: base(SyntaxKind.ReturnKeyword, position, "return", null)
|
||||||
{
|
{
|
||||||
FollowedByLineBreak = followedByLineBreak;
|
FollowedByLineBreak = followedByLineBreak;
|
||||||
|
|
|
@ -1,109 +1,45 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
namespace Upsilon.Text
|
namespace Upsilon.Text
|
||||||
{
|
{
|
||||||
public class SourceText
|
public class SourceText
|
||||||
{
|
{
|
||||||
private readonly string _text;
|
private readonly string[] _text;
|
||||||
private readonly SourceTextLine[] _lines;
|
|
||||||
|
|
||||||
public SourceText(string text)
|
public SourceText(string text)
|
||||||
{
|
{
|
||||||
_text = text;
|
_text = text.Split('\n');
|
||||||
if (string.IsNullOrEmpty(text))
|
|
||||||
{
|
|
||||||
_lines = new SourceTextLine[0];
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var lines = text.Split(new[] {Environment.NewLine}, StringSplitOptions.None);
|
|
||||||
_lines = new SourceTextLine[lines.Length];
|
|
||||||
var linePos = 0;
|
|
||||||
for (var index = 0; index < lines.Length; index++)
|
|
||||||
{
|
|
||||||
var line = lines[index];
|
|
||||||
_lines[index] = new SourceTextLine(linePos, line.Length + Environment.NewLine.Length);
|
|
||||||
linePos += line.Length + Environment.NewLine.Length;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetSpan(int start, int length)
|
public string GetSpan(int startLine, int startPosition, int endLine, int endPosition)
|
||||||
{
|
{
|
||||||
if (start < 0)
|
if (startPosition < 0) startPosition = 0;
|
||||||
|
if (startLine == endLine)
|
||||||
{
|
{
|
||||||
length += start;
|
return _text[startLine].Substring(startPosition, endPosition - startPosition);
|
||||||
start = 0;
|
}
|
||||||
};
|
var sb = new StringBuilder();
|
||||||
if (start >= _text.Length)
|
sb.Append(_text[startLine].Substring(startPosition));
|
||||||
return string.Empty;
|
for (var i = startLine + 1; i < endLine; i++)
|
||||||
if (start + length >= _text.Length) length = _text.Length - start;
|
{
|
||||||
return _text.Substring(start, length);
|
sb.Append(_text[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public (int Line, int Pos) GetLinePosition(int spanPos)
|
if (endPosition > _text[endLine].Length) endPosition = _text[endLine].Length;
|
||||||
{
|
sb.Append(_text[endLine].Substring(0, endPosition));
|
||||||
var min = 0;
|
return sb.ToString();
|
||||||
var max = _lines.Length - 1;
|
|
||||||
while (min <= max)
|
|
||||||
{
|
|
||||||
var mid = (min + max) / 2 ;
|
|
||||||
if (mid >= _lines.Length)
|
|
||||||
{
|
|
||||||
max = _lines.Length - 1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
var midLine = _lines[mid];
|
|
||||||
if (midLine.Start <= spanPos && midLine.End > spanPos)
|
|
||||||
{
|
|
||||||
var pos = spanPos - midLine.Start;
|
|
||||||
return (mid, pos);
|
|
||||||
}
|
|
||||||
if (spanPos >= midLine.End)
|
|
||||||
{
|
|
||||||
min = mid + 1;
|
|
||||||
}
|
|
||||||
else if (spanPos < midLine.Start)
|
|
||||||
{
|
|
||||||
max = mid - 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (min >= _lines.Length)
|
|
||||||
{
|
|
||||||
min = _lines.Length - 1;
|
|
||||||
}
|
|
||||||
var newPos = spanPos - _lines[min].Start;
|
|
||||||
return (min, newPos);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int GetLineStartPos(int lineIndex)
|
|
||||||
{
|
|
||||||
return _lines[lineIndex].Start;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int GetLineCount()
|
|
||||||
{
|
|
||||||
return _lines.Length;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int GetTextLength()
|
|
||||||
{
|
|
||||||
return _text.Length;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetLine(int linePosition)
|
public string GetLine(int linePosition)
|
||||||
{
|
{
|
||||||
var line = _lines[linePosition];
|
return _text[linePosition];
|
||||||
return GetSpan(line.Start, line.LineLength);
|
|
||||||
}
|
|
||||||
|
|
||||||
public SourceTextLine GetLineInfo(int lineIndex)
|
|
||||||
{
|
|
||||||
return _lines[lineIndex];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetSpan(TextSpan span)
|
public string GetSpan(TextSpan span)
|
||||||
{
|
{
|
||||||
return GetSpan(span.Start, span.Length);
|
return GetSpan(span.StartLine, span.StartPosition, span.EndLine, span.EndPosition);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -2,19 +2,33 @@ namespace Upsilon.Text
|
||||||
{
|
{
|
||||||
public struct TextSpan
|
public struct TextSpan
|
||||||
{
|
{
|
||||||
public TextSpan(int start, int length)
|
public int StartLine { get; }
|
||||||
{
|
public int StartPosition { get; }
|
||||||
Start = start;
|
public int EndLine { get; }
|
||||||
Length = length;
|
public int EndPosition { get; }
|
||||||
}
|
|
||||||
|
|
||||||
public int Start { get; }
|
public TextSpan(int startLine, int startPosition, int endLine, int endPosition)
|
||||||
public int Length { get; }
|
{
|
||||||
public int End => Start + Length;
|
StartLine = startLine;
|
||||||
|
StartPosition = startPosition;
|
||||||
|
EndLine = endLine;
|
||||||
|
EndPosition = endPosition;
|
||||||
|
}
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
return $"{Start} - {End}";
|
return $"({StartLine}, {StartPosition}) - ({EndLine}, {EndPosition})";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TextSpan Between(TextSpan start, TextSpan end)
|
||||||
|
{
|
||||||
|
return new TextSpan(start.StartLine, start.StartPosition, end.EndLine, end.EndPosition);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Contains(int linePosition, int characterPosition)
|
||||||
|
{
|
||||||
|
return StartLine >= linePosition && EndLine <= linePosition && characterPosition >= StartPosition &&
|
||||||
|
characterPosition <= EndPosition;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -7,9 +7,9 @@ namespace Upsilon.Utilities
|
||||||
{
|
{
|
||||||
public static class SearchHelper
|
public static class SearchHelper
|
||||||
{
|
{
|
||||||
public static BoundScope GetScopeAt(this BoundScript script, int characterPosition)
|
public static BoundScope GetScopeAt(this BoundScript script, int linePosition, int characterPosition)
|
||||||
{
|
{
|
||||||
foreach (var node in script.GetNodeAtPosition(characterPosition))
|
foreach (var node in script.GetNodeAtPosition(linePosition, characterPosition))
|
||||||
{
|
{
|
||||||
if (node is IBoundNodeScopeOwner scopeOwner && scopeOwner.Scope != null)
|
if (node is IBoundNodeScopeOwner scopeOwner && scopeOwner.Scope != null)
|
||||||
{
|
{
|
||||||
|
@ -19,14 +19,14 @@ namespace Upsilon.Utilities
|
||||||
return script.Scope;
|
return script.Scope;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static BoundNode GetBottomNodeAtPosition(this BoundNode node, int characterPosition)
|
public static BoundNode GetBottomNodeAtPosition(this BoundNode node, int linePosition, int characterPosition)
|
||||||
{
|
{
|
||||||
return node.GetNodeAtPosition(characterPosition).First();
|
return node.GetNodeAtPosition(linePosition, characterPosition).First();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static BoundStatement GetBottomStatementAtPosition(this BoundNode node, int characterPosition)
|
public static BoundStatement GetBottomStatementAtPosition(this BoundNode node, int linePosition, int characterPosition)
|
||||||
{
|
{
|
||||||
return (BoundStatement) node.GetNodeAtPosition(characterPosition).First(x => x is BoundStatement);
|
return (BoundStatement) node.GetNodeAtPosition(linePosition, characterPosition).First(x => x is BoundStatement);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Dictionary<string, VariableSymbol> GetBoundScopeVisibleVariables(this BoundScope scope)
|
public static Dictionary<string, VariableSymbol> GetBoundScopeVisibleVariables(this BoundScope scope)
|
||||||
|
|
Loading…
Reference in New Issue