mirror of
https://github.com/ZuneDev/ZuneUIXTools.git
synced 2026-07-27 13:11:59 -07:00
Add UIXA string literals
This commit is contained in:
@@ -87,17 +87,30 @@ partial class Lexer
|
||||
if (!typeNameResult.WasSuccessful)
|
||||
return Result.Failure<IDirective>(input, "Invalid constant directive", ["Expected qualified name of type to construct"]);
|
||||
|
||||
Markup.MarkupConstantPersistMode? persistMode = null;
|
||||
string content = "";
|
||||
|
||||
var encodingMarkerResult = Parse.Char('.')(input);
|
||||
input = encodingMarkerResult.Remainder;
|
||||
if (!encodingMarkerResult.WasSuccessful)
|
||||
{
|
||||
// Support defining constants from string literals
|
||||
var stringLiteralResult = ExpressionInBraces(StringLiteral)(input);
|
||||
input = stringLiteralResult.Remainder;
|
||||
if (!stringLiteralResult.WasSuccessful)
|
||||
return Result.Failure<IDirective>(input, "Invalid constant directive", ["Expected '.', followed by the persist mode."]);
|
||||
|
||||
persistMode = Markup.MarkupConstantPersistMode.FromString;
|
||||
content = stringLiteralResult.Value[1..^1].Unescape();
|
||||
}
|
||||
else
|
||||
{
|
||||
var persistModeResult = Parse.CharExcept('(').AtLeastOnce().Text().Token()(input);
|
||||
input = persistModeResult.Remainder;
|
||||
if (!persistModeResult.WasSuccessful)
|
||||
return Result.Failure<IDirective>(input, "Invalid constant directive", ["No persist mode was specified."]);
|
||||
|
||||
Markup.MarkupConstantPersistMode? persistMode = persistModeResult.Value.ToLowerInvariant() switch
|
||||
persistMode = persistModeResult.Value.ToLowerInvariant() switch
|
||||
{
|
||||
"bin" => Markup.MarkupConstantPersistMode.Binary,
|
||||
"str" => Markup.MarkupConstantPersistMode.FromString,
|
||||
@@ -110,22 +123,23 @@ partial class Lexer
|
||||
if (!openBracketResult.WasSuccessful)
|
||||
return Result.Failure<IDirective>(input, "Invalid constant directive", ["Expected '('"]);
|
||||
|
||||
var contentResult = Parse.CharExcept(')').AtLeastOnce().Text().Token()(input);
|
||||
var contentResult = Parse.AnyChar.Until(StatementEnd).Text().Token()(input);
|
||||
input = contentResult.Remainder;
|
||||
if (!contentResult.WasSuccessful)
|
||||
return Result.Failure<IDirective>(input, "Invalid constant directive", ["Expected constant value"]);
|
||||
|
||||
var closeBracketResult = Parse.Char(')').Token()(input);
|
||||
input = closeBracketResult.Remainder;
|
||||
if (!closeBracketResult.WasSuccessful)
|
||||
content = contentResult.Value;
|
||||
if (content.Length <= 1 || content[^1] != ')')
|
||||
return Result.Failure<IDirective>(input, "Invalid constant directive", ["Expected ')'"]);
|
||||
content = content[..^1];
|
||||
}
|
||||
|
||||
var constantName = constNameResult.Value;
|
||||
var typeName = typeNameResult.Value;
|
||||
|
||||
if (persistMode == Markup.MarkupConstantPersistMode.FromString)
|
||||
{
|
||||
directive = new StringEncodedConstantDirective(constantName, typeName, contentResult.Value)
|
||||
directive = new StringEncodedConstantDirective(constantName, typeName, content)
|
||||
{
|
||||
Line = line,
|
||||
Column = column,
|
||||
@@ -133,7 +147,7 @@ partial class Lexer
|
||||
}
|
||||
else if (persistMode == Markup.MarkupConstantPersistMode.Canonical)
|
||||
{
|
||||
directive = new CanonicalInstanceConstantDirective(constantName, typeName, contentResult.Value)
|
||||
directive = new CanonicalInstanceConstantDirective(constantName, typeName, content)
|
||||
{
|
||||
Line = line,
|
||||
Column = column,
|
||||
@@ -142,7 +156,7 @@ partial class Lexer
|
||||
else if (persistMode == Markup.MarkupConstantPersistMode.Binary)
|
||||
{
|
||||
byte[] constantBytes;
|
||||
var byteParts = contentResult.Value.Split(',');
|
||||
var byteParts = content.Split(',');
|
||||
if (byteParts.Length == 1)
|
||||
{
|
||||
var constantStr = byteParts[0].Trim();
|
||||
@@ -167,7 +181,7 @@ partial class Lexer
|
||||
}
|
||||
else
|
||||
{
|
||||
return Result.Failure<IDirective>(input, "Invalid constant directive", [$"Expected a 1, 2, or 4 hex number, or a list of bytes."]);
|
||||
return Result.Failure<IDirective>(input, "Invalid constant directive", [$"Expected a 1-, 2-, or 4-digit hex number, or a list of bytes"]);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -185,7 +199,7 @@ partial class Lexer
|
||||
}
|
||||
else
|
||||
{
|
||||
return Result.Failure<IDirective>(input, "Invalid constant directive", [$"'{persistModeResult.Value}' is not a valid persist mode."]);
|
||||
return Result.Failure<IDirective>(input, "Invalid constant directive", [$"Invalid persist mode"]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -16,6 +16,16 @@ public static partial class Lexer
|
||||
|
||||
public static readonly Parser<string> Uri = Parse.LetterOrDigit.Or(Parse.Chars(":/!._-")).AtLeastOnce().Text();
|
||||
|
||||
// https://github.com/apexsharp/apexparser/blob/4eb5983c657b0e6c49ed47bc42a0346e80f9e26d/ApexSharp.ApexParser/Parser/ApexGrammar.cs#L360C9-L367C64
|
||||
public static readonly Parser<string> StringLiteral =
|
||||
from leading in Parse.WhiteSpace.Many()
|
||||
from openQuote in Parse.Char('"')
|
||||
from fragments in Parse.Char('\\').Then(_ => Parse.AnyChar.Select(c => $"\\{c}"))
|
||||
.Or(Parse.CharExcept("\\\"").Many().Text()).Many()
|
||||
from closeQuote in Parse.Char('"')
|
||||
from trailing in Parse.WhiteSpace.Many()
|
||||
select $"\"{string.Join(string.Empty, fragments)}\"";
|
||||
|
||||
public static readonly Parser<string> StatementEnd = Parse.Char(';').Return(";").Or(Parse.LineTerminator);
|
||||
|
||||
public static readonly Parser<QualifiedTypeName> QualifiedTypeName = ParseQualifiedTypeName;
|
||||
@@ -70,4 +80,10 @@ public static partial class Lexer
|
||||
|
||||
return Result.Success(qualifiedName, input);
|
||||
}
|
||||
|
||||
private static Parser<string> ExpressionInBraces(Parser<string> parser, char open = '(', char close = ')') =>
|
||||
from openBrace in Parse.Char(open).Token()
|
||||
from expression in parser.Optional()
|
||||
from closeBrace in Parse.Char(close).Token()
|
||||
select expression.GetOrElse(string.Empty).Trim();
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ public record ConstantDirective : Directive
|
||||
public record StringEncodedConstantDirective : ConstantDirective
|
||||
{
|
||||
public StringEncodedConstantDirective(string name, QualifiedTypeName typeName, string content)
|
||||
: base(name, typeName, $"{typeName}.str({content})")
|
||||
: base(name, typeName, $"{typeName}(\"{content.Escape()}\")")
|
||||
{
|
||||
Content = content;
|
||||
PersistMode = MarkupConstantPersistMode.FromString;
|
||||
|
||||
@@ -45,6 +45,8 @@ public class Assembly
|
||||
.constant const3 = Color.str(255, 0, 0, 255)
|
||||
.constant const4 = Font.str(JetBrains Mono)
|
||||
.constant const5 = String.str(This is some blue text)
|
||||
.constant const3255 = String.str(({0:X8}))
|
||||
.constant const3256 = String("Content\nOn a new line")
|
||||
.section object
|
||||
|
||||
Default_cont:
|
||||
@@ -77,7 +79,7 @@ Alt_locl:
|
||||
_output.WriteLine(ast.ToString());
|
||||
|
||||
Assert.NotNull(ast);
|
||||
Assert.Equal(20, ast.Directives.Count());
|
||||
Assert.Equal(22, ast.Directives.Count());
|
||||
Assert.Equal(24, ast.Code.Count());
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user