initial commit
This commit is contained in:
79
Upsilon/Evaluator/Evaluator.cs
Normal file
79
Upsilon/Evaluator/Evaluator.cs
Normal file
@@ -0,0 +1,79 @@
|
||||
using System;
|
||||
using Upsilon.Parser;
|
||||
|
||||
namespace Upsilon.Evaluator
|
||||
{
|
||||
public static class Evaluator
|
||||
{
|
||||
public static object Evaluate(this ScriptSyntax e)
|
||||
{
|
||||
return EvaluateExpression(e.Statement);
|
||||
}
|
||||
|
||||
public static object Evaluate(this ExpressionSyntax e)
|
||||
{
|
||||
return EvaluateExpression(e);
|
||||
}
|
||||
|
||||
private static object EvaluateExpression(ExpressionSyntax e)
|
||||
{
|
||||
switch (e.Kind)
|
||||
{
|
||||
case SyntaxKind.UnaryExpression:
|
||||
return EvaluateUnaryExpression((UnaryExpressionSyntax) e);
|
||||
case SyntaxKind.BinaryExpression:
|
||||
return EvaluateBinaryExpression((BinaryExpressionSyntax) e);
|
||||
case SyntaxKind.LiteralExpression:
|
||||
return ((LiteralExpressionSyntax) e).Value;
|
||||
case SyntaxKind.ParenthesizedExpression:
|
||||
return ((ParenthesizedExpressionSyntax) e).Expression.Evaluate();
|
||||
default:
|
||||
throw new Exception("Invalid expression: " + e.Kind);
|
||||
}
|
||||
}
|
||||
|
||||
private static object EvaluateUnaryExpression(UnaryExpressionSyntax e)
|
||||
{
|
||||
var operand = EvaluateExpression(e.Expression);
|
||||
switch (e.Operator.Kind)
|
||||
{
|
||||
case SyntaxKind.Plus:
|
||||
return operand;
|
||||
case SyntaxKind.Minus:
|
||||
return -(double) operand;
|
||||
case SyntaxKind.NotKeyword:
|
||||
return !(bool)operand;
|
||||
default:
|
||||
throw new Exception("Invalid Unary Operator: " + e.Operator.Kind);
|
||||
}
|
||||
}
|
||||
|
||||
private static object EvaluateBinaryExpression(BinaryExpressionSyntax e)
|
||||
{
|
||||
var left = EvaluateExpression(e.Left);
|
||||
var right = EvaluateExpression(e.Right);
|
||||
switch (e.Operator.Kind)
|
||||
{
|
||||
case SyntaxKind.Plus:
|
||||
return (double)left + (double)right;
|
||||
case SyntaxKind.Minus:
|
||||
return (double)left - (double)right;
|
||||
case SyntaxKind.Star:
|
||||
return (double)left * (double)right;
|
||||
case SyntaxKind.Slash:
|
||||
return (double)left / (double)right;
|
||||
case SyntaxKind.AndKeyword:
|
||||
return (bool)left && (bool)right;
|
||||
case SyntaxKind.OrKeyword:
|
||||
return (bool)left || (bool)right;
|
||||
case SyntaxKind.EqualsEquals:
|
||||
return Equals(left, right);
|
||||
case SyntaxKind.TildeEquals:
|
||||
return !Equals(left, right);
|
||||
default:
|
||||
throw new Exception("Invalid Binary Operator: " + e.Operator.Kind);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
27
Upsilon/Parser/ExpressionSyntax/BinaryExpressionSyntax.cs
Normal file
27
Upsilon/Parser/ExpressionSyntax/BinaryExpressionSyntax.cs
Normal file
@@ -0,0 +1,27 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Upsilon.Parser
|
||||
{
|
||||
public class BinaryExpressionSyntax : ExpressionSyntax
|
||||
{
|
||||
public BinaryExpressionSyntax(ExpressionSyntax left, SyntaxToken @operator, ExpressionSyntax right)
|
||||
{
|
||||
Left = left;
|
||||
Operator = @operator;
|
||||
Right = right;
|
||||
}
|
||||
|
||||
public override SyntaxKind Kind => SyntaxKind.BinaryExpression;
|
||||
|
||||
public ExpressionSyntax Left { get; }
|
||||
public SyntaxToken Operator { get; }
|
||||
public ExpressionSyntax Right { get; }
|
||||
|
||||
public override IEnumerable<SyntaxNode> ChildNodes()
|
||||
{
|
||||
yield return Left;
|
||||
yield return Operator;
|
||||
yield return Right;
|
||||
}
|
||||
}
|
||||
}
|
||||
7
Upsilon/Parser/ExpressionSyntax/ExpressionSyntax.cs
Normal file
7
Upsilon/Parser/ExpressionSyntax/ExpressionSyntax.cs
Normal file
@@ -0,0 +1,7 @@
|
||||
namespace Upsilon.Parser
|
||||
{
|
||||
public abstract class ExpressionSyntax : SyntaxNode
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
22
Upsilon/Parser/ExpressionSyntax/LiteralExpressionSyntax.cs
Normal file
22
Upsilon/Parser/ExpressionSyntax/LiteralExpressionSyntax.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Upsilon.Parser
|
||||
{
|
||||
public class LiteralExpressionSyntax : ExpressionSyntax
|
||||
{
|
||||
public LiteralExpressionSyntax(SyntaxToken literal, object value)
|
||||
{
|
||||
Literal = literal;
|
||||
Value = value;
|
||||
}
|
||||
|
||||
public override SyntaxKind Kind => SyntaxKind.LiteralExpression;
|
||||
public SyntaxToken Literal { get; }
|
||||
public object Value { get; }
|
||||
|
||||
public override IEnumerable<SyntaxNode> ChildNodes()
|
||||
{
|
||||
yield return Literal;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Upsilon.Parser
|
||||
{
|
||||
public class ParenthesizedExpressionSyntax : ExpressionSyntax
|
||||
{
|
||||
public ParenthesizedExpressionSyntax(SyntaxToken openParenthesis, ExpressionSyntax expression, SyntaxToken closeParenthesis)
|
||||
{
|
||||
OpenParenthesis = openParenthesis;
|
||||
Expression = expression;
|
||||
CloseParenthesis = closeParenthesis;
|
||||
}
|
||||
|
||||
public override SyntaxKind Kind => SyntaxKind.ParenthesizedExpression;
|
||||
|
||||
public SyntaxToken OpenParenthesis { get; }
|
||||
public ExpressionSyntax Expression { get; }
|
||||
public SyntaxToken CloseParenthesis { get; }
|
||||
|
||||
public override IEnumerable<SyntaxNode> ChildNodes()
|
||||
{
|
||||
yield return OpenParenthesis;
|
||||
yield return Expression;
|
||||
yield return CloseParenthesis;
|
||||
}
|
||||
}
|
||||
}
|
||||
24
Upsilon/Parser/ExpressionSyntax/ScriptSyntax.cs
Normal file
24
Upsilon/Parser/ExpressionSyntax/ScriptSyntax.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Upsilon.Parser
|
||||
{
|
||||
public class ScriptSyntax : SyntaxNode
|
||||
{
|
||||
public ScriptSyntax(ExpressionSyntax statement, SyntaxToken endOfFileToken)
|
||||
{
|
||||
Statement = statement;
|
||||
EndOfFileToken = endOfFileToken;
|
||||
}
|
||||
|
||||
public override SyntaxKind Kind => SyntaxKind.ScriptUnit;
|
||||
|
||||
public ExpressionSyntax Statement { get; }
|
||||
public SyntaxToken EndOfFileToken { get; }
|
||||
|
||||
public override IEnumerable<SyntaxNode> ChildNodes()
|
||||
{
|
||||
yield return Statement;
|
||||
yield return EndOfFileToken;
|
||||
}
|
||||
}
|
||||
}
|
||||
24
Upsilon/Parser/ExpressionSyntax/UnaryExpressionSyntax.cs
Normal file
24
Upsilon/Parser/ExpressionSyntax/UnaryExpressionSyntax.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Upsilon.Parser
|
||||
{
|
||||
public class UnaryExpressionSyntax : ExpressionSyntax
|
||||
{
|
||||
public UnaryExpressionSyntax(SyntaxToken @operator, ExpressionSyntax expression)
|
||||
{
|
||||
Operator = @operator;
|
||||
Expression = expression;
|
||||
}
|
||||
|
||||
public override SyntaxKind Kind => SyntaxKind.UnaryExpression;
|
||||
|
||||
public SyntaxToken Operator { get; }
|
||||
public ExpressionSyntax Expression { get; }
|
||||
|
||||
public override IEnumerable<SyntaxNode> ChildNodes()
|
||||
{
|
||||
yield return Operator;
|
||||
yield return Expression;
|
||||
}
|
||||
}
|
||||
}
|
||||
142
Upsilon/Parser/Lexer.cs
Normal file
142
Upsilon/Parser/Lexer.cs
Normal file
@@ -0,0 +1,142 @@
|
||||
using System;
|
||||
using System.Collections.Immutable;
|
||||
using System.Text;
|
||||
|
||||
namespace Upsilon.Parser
|
||||
{
|
||||
public class Lexer
|
||||
{
|
||||
private readonly string _text;
|
||||
private int _position;
|
||||
|
||||
private Lexer(string text)
|
||||
{
|
||||
_text = text;
|
||||
}
|
||||
|
||||
public static ImmutableArray<SyntaxToken> Lex(string text)
|
||||
{
|
||||
var lexer = new Lexer(text);
|
||||
return lexer.Lex();
|
||||
}
|
||||
|
||||
private char Current
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_position >= _text.Length)
|
||||
return '\0';
|
||||
return _text[_position];
|
||||
}
|
||||
}
|
||||
|
||||
private char Next
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_position + 1 >= _text.Length)
|
||||
return '\0';
|
||||
return _text[_position + 1];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private ImmutableArray<SyntaxToken> Lex()
|
||||
{
|
||||
var array = ImmutableArray.CreateBuilder<SyntaxToken>();
|
||||
while (true)
|
||||
{
|
||||
var next = LexNext();
|
||||
if (next.Kind != SyntaxKind.WhiteSpace)
|
||||
{
|
||||
array.Add(next);
|
||||
if (next.Kind == SyntaxKind.EndOfFile)
|
||||
break;
|
||||
}
|
||||
_position++;
|
||||
}
|
||||
return array.ToImmutable();
|
||||
}
|
||||
|
||||
private SyntaxToken LexNext()
|
||||
{
|
||||
switch (Current)
|
||||
{
|
||||
case '\0':
|
||||
return new SyntaxToken(SyntaxKind.EndOfFile, _position, "\0", null);
|
||||
case ' ': case '\t': case '\r': case '\n':
|
||||
return new SyntaxToken(SyntaxKind.WhiteSpace, _position, Current.ToString(), null);
|
||||
case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
|
||||
return LexNumber();
|
||||
case '+':
|
||||
return new SyntaxToken(SyntaxKind.Plus, _position, "+", null);
|
||||
case '-':
|
||||
return new SyntaxToken(SyntaxKind.Minus, _position, "-", null);
|
||||
case '*':
|
||||
return new SyntaxToken(SyntaxKind.Star, _position, "*", null);
|
||||
case '/':
|
||||
return new SyntaxToken(SyntaxKind.Slash, _position, "/", null);
|
||||
case '(':
|
||||
return new SyntaxToken(SyntaxKind.OpenParenthesis, _position, "(", null);
|
||||
case ')':
|
||||
return new SyntaxToken(SyntaxKind.CloseParenthesis, _position, ")", null);
|
||||
case '=':
|
||||
if (Next == '=')
|
||||
{
|
||||
_position++;
|
||||
return new SyntaxToken(SyntaxKind.EqualsEquals, _position - 1, "==", null);
|
||||
}
|
||||
return new SyntaxToken(SyntaxKind.Equals, _position, "=", null);
|
||||
case '~':
|
||||
if (Next == '=')
|
||||
{
|
||||
_position++;
|
||||
return new SyntaxToken(SyntaxKind.TildeEquals, _position - 1, "~=", null);
|
||||
}
|
||||
return new SyntaxToken(SyntaxKind.Tilde, _position, "~", null);
|
||||
default:
|
||||
if (char.IsLetter(Current))
|
||||
return LexIdentifierOrKeyword();
|
||||
throw new Exception("Unknown token character: " + Current);
|
||||
}
|
||||
}
|
||||
|
||||
private SyntaxToken LexNumber()
|
||||
{
|
||||
var start = _position;
|
||||
var hasDecimalPoint = false;
|
||||
var numStr = new StringBuilder();
|
||||
numStr.Append(Current);
|
||||
while (char.IsDigit(Next) || Next == '.' || Next == '_')
|
||||
{
|
||||
if (Next == '.')
|
||||
{
|
||||
if (hasDecimalPoint)
|
||||
{
|
||||
throw new Exception("No second decimal allowed there");
|
||||
}
|
||||
hasDecimalPoint = true;
|
||||
}
|
||||
numStr.Append(Next);
|
||||
_position++;
|
||||
}
|
||||
var i = double.Parse(numStr.ToString());
|
||||
return new SyntaxToken(SyntaxKind.Number, start, numStr.ToString(), i);
|
||||
}
|
||||
|
||||
private SyntaxToken LexIdentifierOrKeyword()
|
||||
{
|
||||
var start = _position;
|
||||
var numStr = new StringBuilder();
|
||||
numStr.Append(Current);
|
||||
while (char.IsLetterOrDigit(Next) || Next == '_')
|
||||
{
|
||||
numStr.Append(Next);
|
||||
_position++;
|
||||
}
|
||||
|
||||
var kind = SyntaxKeyWords.GetSyntaxKind(numStr.ToString());
|
||||
return new SyntaxToken(kind, start, numStr.ToString(), null);
|
||||
}
|
||||
}
|
||||
}
|
||||
126
Upsilon/Parser/Parser.cs
Normal file
126
Upsilon/Parser/Parser.cs
Normal file
@@ -0,0 +1,126 @@
|
||||
using System;
|
||||
using System.Collections.Immutable;
|
||||
|
||||
namespace Upsilon.Parser
|
||||
{
|
||||
public class Parser
|
||||
{
|
||||
private readonly ImmutableArray<SyntaxToken> _tokens;
|
||||
private int _position;
|
||||
|
||||
private Parser(ImmutableArray<SyntaxToken> tokens)
|
||||
{
|
||||
_tokens = tokens;
|
||||
}
|
||||
|
||||
public static ScriptSyntax Parse(string text)
|
||||
{
|
||||
var tokens = Lexer.Lex(text);
|
||||
return new Parser(tokens).ParseScriptSyntax();
|
||||
}
|
||||
|
||||
private SyntaxToken Current => Get(0);
|
||||
private SyntaxToken Next => Get(1);
|
||||
|
||||
private SyntaxToken Get(int offset)
|
||||
{
|
||||
if (_position + offset >= _tokens.Length)
|
||||
return new SyntaxToken(SyntaxKind.EndOfFile, _position + offset, "\0", null);
|
||||
return _tokens[_position + offset];
|
||||
}
|
||||
|
||||
private SyntaxToken NextToken()
|
||||
{
|
||||
var current = Current;
|
||||
_position++;
|
||||
return current;
|
||||
}
|
||||
|
||||
private SyntaxToken MatchToken(SyntaxKind kind)
|
||||
{
|
||||
if (Current.Kind == kind)
|
||||
return NextToken();
|
||||
|
||||
return new SyntaxToken(kind, Current.Span.Start, "", null);
|
||||
}
|
||||
|
||||
public ScriptSyntax ParseScriptSyntax()
|
||||
{
|
||||
var expression = ParseExpression();
|
||||
var eof = MatchToken(SyntaxKind.EndOfFile);
|
||||
return new ScriptSyntax(expression, eof);
|
||||
}
|
||||
|
||||
public ExpressionSyntax ParseExpression()
|
||||
{
|
||||
return ParseBinaryExpression();
|
||||
}
|
||||
|
||||
private ExpressionSyntax ParseBinaryExpression(SyntaxKindPrecedence.Precedence parentPrecedence = SyntaxKindPrecedence.Precedence.None)
|
||||
{
|
||||
ExpressionSyntax left;
|
||||
var unaryOperatorPrecedence = Current.Kind.UnaryOperatorPrecedence();
|
||||
if (unaryOperatorPrecedence != SyntaxKindPrecedence.Precedence.None
|
||||
&& unaryOperatorPrecedence >= parentPrecedence)
|
||||
{
|
||||
var operatorToken = NextToken();
|
||||
var operand = ParseBinaryExpression(unaryOperatorPrecedence);
|
||||
left = new UnaryExpressionSyntax(operatorToken, operand);
|
||||
}
|
||||
else
|
||||
{
|
||||
left = ParsePrimaryExpression();
|
||||
}
|
||||
|
||||
while (true)
|
||||
{
|
||||
var precedence = Current.Kind.BinaryOperatorPrecedence();
|
||||
if (precedence == SyntaxKindPrecedence.Precedence.None || precedence <= parentPrecedence)
|
||||
break;
|
||||
|
||||
var op = NextToken();
|
||||
var right = ParseBinaryExpression(precedence);
|
||||
left = new BinaryExpressionSyntax(left, op, right);
|
||||
}
|
||||
return left;
|
||||
}
|
||||
|
||||
private ExpressionSyntax ParsePrimaryExpression()
|
||||
{
|
||||
switch (Current.Kind)
|
||||
{
|
||||
case SyntaxKind.OpenParenthesis:
|
||||
return ParseParenthesizedExpression();
|
||||
case SyntaxKind.Number:
|
||||
return ParseNumber();
|
||||
case SyntaxKind.TrueKeyword:
|
||||
case SyntaxKind.FalseKeyword:
|
||||
return ParseBoolean();
|
||||
default:
|
||||
throw new Exception("Unknown primary expression type: " + Current.Kind);
|
||||
}
|
||||
}
|
||||
|
||||
private ExpressionSyntax ParseParenthesizedExpression()
|
||||
{
|
||||
var l = MatchToken(SyntaxKind.OpenParenthesis);
|
||||
var e = ParseExpression();
|
||||
var r = MatchToken(SyntaxKind.CloseParenthesis);
|
||||
return new ParenthesizedExpressionSyntax(l, e, r);
|
||||
}
|
||||
|
||||
private ExpressionSyntax ParseNumber()
|
||||
{
|
||||
var numberToken = MatchToken(SyntaxKind.Number);
|
||||
return new LiteralExpressionSyntax(numberToken, numberToken.Value);
|
||||
}
|
||||
|
||||
private ExpressionSyntax ParseBoolean()
|
||||
{
|
||||
var isTrue = Current.Kind == SyntaxKind.TrueKeyword;
|
||||
var token = MatchToken(isTrue ? SyntaxKind.TrueKeyword : SyntaxKind.FalseKeyword);
|
||||
return new LiteralExpressionSyntax(token, isTrue);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
24
Upsilon/Parser/SyntaxKeyWords.cs
Normal file
24
Upsilon/Parser/SyntaxKeyWords.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
namespace Upsilon.Parser
|
||||
{
|
||||
public static class SyntaxKeyWords
|
||||
{
|
||||
public static SyntaxKind GetSyntaxKind(string s)
|
||||
{
|
||||
switch (s)
|
||||
{
|
||||
case "true":
|
||||
return SyntaxKind.TrueKeyword;
|
||||
case "false":
|
||||
return SyntaxKind.FalseKeyword;
|
||||
case "not":
|
||||
return SyntaxKind.NotKeyword;
|
||||
case "and":
|
||||
return SyntaxKind.AndKeyword;
|
||||
case "or":
|
||||
return SyntaxKind.OrKeyword;
|
||||
default:
|
||||
return SyntaxKind.Identifier;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
39
Upsilon/Parser/SyntaxKind.cs
Normal file
39
Upsilon/Parser/SyntaxKind.cs
Normal file
@@ -0,0 +1,39 @@
|
||||
namespace Upsilon.Parser
|
||||
{
|
||||
public enum SyntaxKind
|
||||
{
|
||||
// tokens
|
||||
EndOfFile,
|
||||
WhiteSpace,
|
||||
|
||||
Number,
|
||||
Plus,
|
||||
Minus,
|
||||
Star,
|
||||
Slash,
|
||||
OpenParenthesis,
|
||||
CloseParenthesis,
|
||||
Equals,
|
||||
EqualsEquals,
|
||||
Tilde,
|
||||
TildeEquals,
|
||||
|
||||
// key words
|
||||
TrueKeyword,
|
||||
FalseKeyword,
|
||||
NotKeyword,
|
||||
AndKeyword,
|
||||
OrKeyword,
|
||||
|
||||
Identifier,
|
||||
|
||||
// Expressions
|
||||
UnaryExpression,
|
||||
BinaryExpression,
|
||||
LiteralExpression,
|
||||
ParenthesizedExpression,
|
||||
|
||||
// script unit
|
||||
ScriptUnit,
|
||||
}
|
||||
}
|
||||
53
Upsilon/Parser/SyntaxKindPrecedence.cs
Normal file
53
Upsilon/Parser/SyntaxKindPrecedence.cs
Normal file
@@ -0,0 +1,53 @@
|
||||
namespace Upsilon.Parser
|
||||
{
|
||||
public static class SyntaxKindPrecedence
|
||||
{
|
||||
public enum Precedence
|
||||
{
|
||||
None = 0,
|
||||
Or,
|
||||
And,
|
||||
Equality,
|
||||
PlusMinus,
|
||||
StarSlash,
|
||||
Unary,
|
||||
}
|
||||
|
||||
public static Precedence UnaryOperatorPrecedence(this SyntaxKind kind)
|
||||
{
|
||||
switch (kind)
|
||||
{
|
||||
case SyntaxKind.Plus:
|
||||
case SyntaxKind.Minus:
|
||||
case SyntaxKind.NotKeyword:
|
||||
return Precedence.Unary;
|
||||
default:
|
||||
return Precedence.None;
|
||||
}
|
||||
}
|
||||
|
||||
public static Precedence BinaryOperatorPrecedence(this SyntaxKind kind)
|
||||
{
|
||||
switch (kind)
|
||||
{
|
||||
case SyntaxKind.EqualsEquals:
|
||||
return Precedence.Equality;
|
||||
case SyntaxKind.TildeEquals:
|
||||
return Precedence.Equality;
|
||||
case SyntaxKind.AndKeyword:
|
||||
return Precedence.And;
|
||||
case SyntaxKind.OrKeyword:
|
||||
return Precedence.Or;
|
||||
case SyntaxKind.Plus:
|
||||
case SyntaxKind.Minus:
|
||||
return Precedence.PlusMinus;
|
||||
case SyntaxKind.Star:
|
||||
case SyntaxKind.Slash:
|
||||
return Precedence.StarSlash;
|
||||
default:
|
||||
return Precedence.None;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
15
Upsilon/Parser/SyntaxNode.cs
Normal file
15
Upsilon/Parser/SyntaxNode.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using System.Collections.Generic;
|
||||
using Upsilon.Text;
|
||||
|
||||
namespace Upsilon.Parser
|
||||
{
|
||||
public abstract class SyntaxNode
|
||||
{
|
||||
public abstract SyntaxKind Kind { get; }
|
||||
|
||||
|
||||
public virtual TextSpan Span { get; set; }
|
||||
|
||||
public abstract IEnumerable<SyntaxNode> ChildNodes();
|
||||
}
|
||||
}
|
||||
23
Upsilon/Parser/SyntaxToken.cs
Normal file
23
Upsilon/Parser/SyntaxToken.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
using System.Collections.Generic;
|
||||
using Upsilon.Text;
|
||||
|
||||
namespace Upsilon.Parser
|
||||
{
|
||||
public sealed class SyntaxToken : SyntaxNode
|
||||
{
|
||||
public SyntaxToken(SyntaxKind kind, int position, string text, object value)
|
||||
{
|
||||
Kind = kind;
|
||||
Span = new TextSpan(position, text.Length);
|
||||
Value = value;
|
||||
}
|
||||
|
||||
public override SyntaxKind Kind { get; }
|
||||
public object Value { get; }
|
||||
|
||||
public override IEnumerable<SyntaxNode> ChildNodes()
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
}
|
||||
}
|
||||
15
Upsilon/Text/TextSpan.cs
Normal file
15
Upsilon/Text/TextSpan.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
namespace Upsilon.Text
|
||||
{
|
||||
public struct TextSpan
|
||||
{
|
||||
public TextSpan(int start, int length)
|
||||
{
|
||||
Start = start;
|
||||
Length = length;
|
||||
}
|
||||
|
||||
public int Start { get; }
|
||||
public int Length { get; }
|
||||
public int End => Start + End;
|
||||
}
|
||||
}
|
||||
13
Upsilon/Upsilon.csproj
Normal file
13
Upsilon/Upsilon.csproj
Normal file
@@ -0,0 +1,13 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="System.Collections.Immutable, Version=1.2.3.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<HintPath>..\..\..\..\..\usr\share\dotnet\sdk\NuGetFallbackFolder\microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Collections.Immutable.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
2
Upsilon/Upsilon.csproj.DotSettings
Normal file
2
Upsilon/Upsilon.csproj.DotSettings
Normal file
@@ -0,0 +1,2 @@
|
||||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=parser_005Cexpressionsyntax/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
|
||||
27
Upsilon/Utilities/NodeStringFormatter.cs
Normal file
27
Upsilon/Utilities/NodeStringFormatter.cs
Normal file
@@ -0,0 +1,27 @@
|
||||
using System.Text;
|
||||
using Upsilon.Parser;
|
||||
|
||||
namespace Upsilon.Utilities
|
||||
{
|
||||
public static class NodeStringFormatter
|
||||
{
|
||||
public static string Print(this SyntaxNode token, int depth = 0)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
var tabs = depth - 1;
|
||||
for (var i = 0; i < tabs; i++)
|
||||
sb.Append("\t");
|
||||
if (depth > 0)
|
||||
{
|
||||
sb.Append("|-- ");
|
||||
}
|
||||
sb.Append(token.Kind);
|
||||
foreach (var syntaxNode in token.ChildNodes())
|
||||
{
|
||||
sb.Append("\n");
|
||||
sb.Append(syntaxNode.Print(depth + 1));
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user