using Lua.Internal; namespace Lua.CodeAnalysis.Syntax; public readonly struct SyntaxToken(SyntaxTokenType type, ReadOnlyMemory text, SourcePosition position) : IEquatable { public static SyntaxToken EndOfLine(SourcePosition position) => new(SyntaxTokenType.EndOfLine, Keywords.LF.AsMemory(), position); public static SyntaxToken LParen(SourcePosition position) => new(SyntaxTokenType.LParen, Keywords.LParen.AsMemory(), position); public static SyntaxToken RParen(SourcePosition position) => new(SyntaxTokenType.RParen, Keywords.RParen.AsMemory(), position); public static SyntaxToken LCurly(SourcePosition position) => new(SyntaxTokenType.LCurly, Keywords.LCurly.AsMemory(), position); public static SyntaxToken RCurly(SourcePosition position) => new(SyntaxTokenType.RCurly, Keywords.RCurly.AsMemory(), position); public static SyntaxToken LSquare(SourcePosition position) => new(SyntaxTokenType.LSquare, Keywords.LSquare.AsMemory(), position); public static SyntaxToken RSquare(SourcePosition position) => new(SyntaxTokenType.RSquare, Keywords.RSquare.AsMemory(), position); public static SyntaxToken Nil(SourcePosition position) => new(SyntaxTokenType.Nil, Keywords.Nil.AsMemory(), position); public static SyntaxToken True(SourcePosition position) => new(SyntaxTokenType.True, Keywords.True.AsMemory(), position); public static SyntaxToken False(SourcePosition position) => new(SyntaxTokenType.False, Keywords.False.AsMemory(), position); public static SyntaxToken Addition(SourcePosition position) => new(SyntaxTokenType.Addition, Keywords.Addition.AsMemory(), position); public static SyntaxToken Subtraction(SourcePosition position) => new(SyntaxTokenType.Subtraction, Keywords.Subtraction.AsMemory(), position); public static SyntaxToken Multiplication(SourcePosition position) => new(SyntaxTokenType.Multiplication, Keywords.Multiplication.AsMemory(), position); public static SyntaxToken Division(SourcePosition position) => new(SyntaxTokenType.Division, Keywords.Division.AsMemory(), position); public static SyntaxToken Modulo(SourcePosition position) => new(SyntaxTokenType.Modulo, Keywords.Modulo.AsMemory(), position); public static SyntaxToken Exponentiation(SourcePosition position) => new(SyntaxTokenType.Exponentiation, Keywords.Exponentiation.AsMemory(), position); public static SyntaxToken Equality(SourcePosition position) => new(SyntaxTokenType.Equality, Keywords.Equality.AsMemory(), position); public static SyntaxToken Inequality(SourcePosition position) => new(SyntaxTokenType.Inequality, Keywords.Inequality.AsMemory(), position); public static SyntaxToken GreaterThan(SourcePosition position) => new(SyntaxTokenType.GreaterThan, Keywords.GreaterThan.AsMemory(), position); public static SyntaxToken GreaterThanOrEqual(SourcePosition position) => new(SyntaxTokenType.GreaterThanOrEqual, Keywords.GreaterThanOrEqual.AsMemory(), position); public static SyntaxToken LessThan(SourcePosition position) => new(SyntaxTokenType.LessThan, Keywords.LessThan.AsMemory(), position); public static SyntaxToken LessThanOrEqual(SourcePosition position) => new(SyntaxTokenType.LessThanOrEqual, Keywords.LessThanOrEqual.AsMemory(), position); public static SyntaxToken Length(SourcePosition position) => new(SyntaxTokenType.Length, Keywords.Length.AsMemory(), position); public static SyntaxToken Concat(SourcePosition position) => new(SyntaxTokenType.Concat, Keywords.Concat.AsMemory(), position); public static SyntaxToken VarArg(SourcePosition position) => new(SyntaxTokenType.VarArg, "...".AsMemory(), position); public static SyntaxToken Assignment(SourcePosition position) => new(SyntaxTokenType.Assignment, Keywords.Assignment.AsMemory(), position); public static SyntaxToken And(SourcePosition position) => new(SyntaxTokenType.And, Keywords.And.AsMemory(), position); public static SyntaxToken Or(SourcePosition position) => new(SyntaxTokenType.Or, Keywords.Or.AsMemory(), position); public static SyntaxToken Not(SourcePosition position) => new(SyntaxTokenType.Not, Keywords.Not.AsMemory(), position); public static SyntaxToken End(SourcePosition position) => new(SyntaxTokenType.End, Keywords.End.AsMemory(), position); public static SyntaxToken Then(SourcePosition position) => new(SyntaxTokenType.Then, Keywords.Then.AsMemory(), position); public static SyntaxToken If(SourcePosition position) => new(SyntaxTokenType.If, Keywords.If.AsMemory(), position); public static SyntaxToken ElseIf(SourcePosition position) => new(SyntaxTokenType.ElseIf, Keywords.ElseIf.AsMemory(), position); public static SyntaxToken Else(SourcePosition position) => new(SyntaxTokenType.Else, Keywords.Else.AsMemory(), position); public static SyntaxToken Local(SourcePosition position) => new(SyntaxTokenType.Local, Keywords.Local.AsMemory(), position); public static SyntaxToken Return(SourcePosition position) => new(SyntaxTokenType.Return, Keywords.Return.AsMemory(), position); public static SyntaxToken Goto(SourcePosition position) => new(SyntaxTokenType.Goto, Keywords.Goto.AsMemory(), position); public static SyntaxToken Comma(SourcePosition position) => new(SyntaxTokenType.Comma, ",".AsMemory(), position); public static SyntaxToken Dot(SourcePosition position) => new(SyntaxTokenType.Dot, ".".AsMemory(), position); public static SyntaxToken SemiColon(SourcePosition position) => new(SyntaxTokenType.SemiColon, ";".AsMemory(), position); public static SyntaxToken Colon(SourcePosition position) => new(SyntaxTokenType.Colon, ":".AsMemory(), position); public static SyntaxToken Do(SourcePosition position) => new(SyntaxTokenType.Do, Keywords.Do.AsMemory(), position); public static SyntaxToken While(SourcePosition position) => new(SyntaxTokenType.While, Keywords.While.AsMemory(), position); public static SyntaxToken Repeat(SourcePosition position) => new(SyntaxTokenType.Repeat, Keywords.Repeat.AsMemory(), position); public static SyntaxToken Until(SourcePosition position) => new(SyntaxTokenType.Until, Keywords.Until.AsMemory(), position); public static SyntaxToken Break(SourcePosition position) => new(SyntaxTokenType.Break, Keywords.Break.AsMemory(), position); public static SyntaxToken Function(SourcePosition position) => new(SyntaxTokenType.Function, Keywords.Function.AsMemory(), position); public static SyntaxToken For(SourcePosition position) => new(SyntaxTokenType.For, Keywords.For.AsMemory(), position); public static SyntaxToken In(SourcePosition position) => new(SyntaxTokenType.In, Keywords.In.AsMemory(), position); public SyntaxTokenType Type { get; } = type; public ReadOnlyMemory Text { get; } = text; public SourcePosition Position { get; } = position; public static SyntaxToken Number(string text, SourcePosition position) { return new(SyntaxTokenType.Number, text.AsMemory(), position); } public static SyntaxToken Number(ReadOnlyMemory text, SourcePosition position) { return new(SyntaxTokenType.Number, text, position); } public static SyntaxToken Identifier(string text, SourcePosition position) { return new(SyntaxTokenType.Identifier, text.AsMemory(), position); } public static SyntaxToken Identifier(ReadOnlyMemory text, SourcePosition position) { return new(SyntaxTokenType.Identifier, text, position); } public static SyntaxToken String(ReadOnlyMemory text, SourcePosition position) { return new(SyntaxTokenType.String, text, position); } public static SyntaxToken RawString(ReadOnlyMemory text, SourcePosition position) { return new(SyntaxTokenType.RawString, text, position); } public static SyntaxToken Label(ReadOnlyMemory text, SourcePosition position) { return new(SyntaxTokenType.Label, text, position); } public override string ToString() { return $"{Position} {Type}:{Text}"; } public string ToDisplayString() { return Type switch { SyntaxTokenType.EndOfLine => Keywords.LF, SyntaxTokenType.LParen => Keywords.LParen, SyntaxTokenType.RParen => Keywords.RParen, SyntaxTokenType.LCurly => Keywords.LCurly, SyntaxTokenType.RCurly => Keywords.RCurly, SyntaxTokenType.LSquare => Keywords.LSquare, SyntaxTokenType.RSquare => Keywords.RSquare, SyntaxTokenType.SemiColon => ";", SyntaxTokenType.Comma => ",", SyntaxTokenType.Number => Text.ToString(), SyntaxTokenType.String => $"\"{Text}\"", SyntaxTokenType.RawString => $"[[{Text}]]", SyntaxTokenType.Nil => Keywords.Nil, SyntaxTokenType.True => Keywords.True, SyntaxTokenType.False => Keywords.False, SyntaxTokenType.Identifier => Text.ToString(), SyntaxTokenType.Addition => Keywords.Addition, SyntaxTokenType.Subtraction => Keywords.Subtraction, SyntaxTokenType.Multiplication => Keywords.Multiplication, SyntaxTokenType.Division => Keywords.Division, SyntaxTokenType.Modulo => Keywords.Modulo, SyntaxTokenType.Exponentiation => Keywords.Exponentiation, SyntaxTokenType.Equality => Keywords.Equality, SyntaxTokenType.Inequality => Keywords.Inequality, SyntaxTokenType.GreaterThan => Keywords.GreaterThan, SyntaxTokenType.LessThan => Keywords.LessThan, SyntaxTokenType.GreaterThanOrEqual => Keywords.GreaterThanOrEqual, SyntaxTokenType.LessThanOrEqual => Keywords.LessThanOrEqual, SyntaxTokenType.And => Keywords.And, SyntaxTokenType.Not => Keywords.Not, SyntaxTokenType.Or => Keywords.Or, SyntaxTokenType.Assignment => Keywords.Assignment, SyntaxTokenType.Concat => Keywords.Concat, SyntaxTokenType.Length => Keywords.Length, SyntaxTokenType.Break => Keywords.Break, SyntaxTokenType.Do => Keywords.Do, SyntaxTokenType.For => Keywords.For, SyntaxTokenType.Goto => Keywords.Goto, SyntaxTokenType.If => Keywords.If, SyntaxTokenType.ElseIf => Keywords.ElseIf, SyntaxTokenType.Else => Keywords.Else, SyntaxTokenType.Function => Keywords.Function, SyntaxTokenType.End => Keywords.End, SyntaxTokenType.Then => Keywords.Then, SyntaxTokenType.In => Keywords.In, SyntaxTokenType.Local => Keywords.Local, SyntaxTokenType.Repeat => Keywords.Repeat, SyntaxTokenType.Return => Keywords.Return, SyntaxTokenType.Until => Keywords.Until, SyntaxTokenType.While => Keywords.While, _ => "", }; } public bool Equals(SyntaxToken other) { return other.Type == Type && other.Text.Span.SequenceEqual(Text.Span) && other.Position == Position; } public override bool Equals(object? obj) { if (obj is SyntaxToken token) return Equals(token); return false; } public override int GetHashCode() { return HashCode.Combine(Type, Utf16StringMemoryComparer.Default.GetHashCode(Text), Position); } public static bool operator ==(SyntaxToken left, SyntaxToken right) { return left.Equals(right); } public static bool operator !=(SyntaxToken left, SyntaxToken right) { return !(left == right); } } public enum SyntaxTokenType { /// /// Invalid token /// Invalid, /// /// End of line /// EndOfLine, /// /// Left parenthesis '(' /// LParen, /// /// Right parenthesis ')' /// RParen, /// /// Left curly bracket '{' /// LCurly, /// /// Right curly bracket '}' /// RCurly, /// /// Left square bracket '[' /// LSquare, /// /// Right square bracket ']' /// RSquare, /// /// Semi colon (;) /// SemiColon, /// /// Colon (:) /// Colon, /// /// Comma (,) /// Comma, /// /// Dot (.) /// Dot, /// /// Numeric literal (e.g. 1, 2, 1.0, 2.0, ...) /// Number, /// /// String literal (e.g. "foo", "bar", ...) /// String, /// /// Raw string literal (e.g. [[Hello, World!]]) /// RawString, /// /// Nil literal (nil) /// Nil, /// /// Boolean literal (true) /// True, /// /// Boolean literal (false) /// False, /// /// Identifier /// Identifier, /// /// Label /// Label, /// /// Addition operator (+) /// Addition, /// /// Subtraction operator (-) /// Subtraction, /// /// Multiplication operator (*) /// Multiplication, /// /// Division operator (/) /// Division, /// /// Modulo operator (%) /// Modulo, /// /// Exponentiation operator (^) /// Exponentiation, Equality, // == Inequality, // ~= GreaterThan, // > LessThan, // < GreaterThanOrEqual, // >= LessThanOrEqual, // <= And, // and Not, // not Or, // or /// /// Assignment operator (=) /// Assignment, Concat, // .. Length, // # VarArg, // ... Break, // break Do, // do For, // for Goto, // goto If, // if ElseIf, // elseif Else, // else Function, // function End, // end Then, // then In, // in Local, // local Repeat, // repeat Return, // return Until, // until While, // while }