This repository has been archived on 2025-10-18. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
RDTKEditor/RhythmBaseCore/Components/RDLang/RDLangParser.cs
T

188 lines
7.4 KiB
C#

using sly.lexer;
using sly.parser.generator;
namespace RhythmBase.Components.RDLang
{
internal class RDLangParser
{
internal const string PlainString = "";
private static List<Token<RDExpressionToken>> TokenList { get; set; } = [];
public required RDVariables Variables { get; set; }
[NodeName("integer")]
[Production("primary: Number")]
public static float Primary(Token<RDExpressionToken> intToken) => float.Parse(intToken.Value);
[NodeName("boolean")]
[Production("primary: True")]
[Production("primary: False")]
public static float Boolean(Token<RDExpressionToken> token) => token.TokenID switch
{
RDExpressionToken.True => 1.0f,
RDExpressionToken.False => 0.0f,
_ => throw new InvalidOperationException("Invalid boolean token")
};
[NodeName("group")]
[Production("primary: LeftParenthesis [d] expression RightParenthesis [d]")]
public static float Group(float groupValue) => groupValue;
[NodeName("addOrSubstract")]
[Production("expression : term Add expression")]
[Production("expression : term Subtract expression")]
public static float Expression(float left, Token<RDExpressionToken> operatorToken, float right) => operatorToken.TokenID switch
{
RDExpressionToken.Add => left + right,
RDExpressionToken.Subtract => left - right,
_ => throw new InvalidOperationException("Invalid operator")
};
[NodeName("expression")]
[Production("expression : term")]
public static float Expression_Term(float termValue) => termValue;
[NodeName("multOrDivide")]
[Production("term : factor Multiply term")]
[Production("term : factor Divide term")]
public static float Term(float left, Token<RDExpressionToken> operatorToken, float right) => operatorToken.TokenID switch
{
RDExpressionToken.Multiply => left * right,
RDExpressionToken.Divide => left / right,
_ => throw new InvalidOperationException("Invalid operator")
};
[NodeName("term")]
[Production("term : factor")]
public static float TermFactor(float factorValue) => factorValue;
[NodeName("primary")]
[Production("factor : primary")]
public static float PrimaryFactor(float primValue) => primValue;
[NodeName("negate")]
[Production("factor : Add factor")]
[Production("factor : Subtract factor")]
public static float Factor(Token<RDExpressionToken> symbolToken, float factorValue) => symbolToken.TokenID switch
{
RDExpressionToken.Add => factorValue,
RDExpressionToken.Subtract => -factorValue,
_ => throw new InvalidOperationException("Invalid operator")
};
[NodeName("primary")]
[Production("primary: VariableInt")]
[Production("primary: VariableFloat")]
[Production("primary: VariableBoolean")]
[Production("primary: PlainString")]
public float PrimaryVariable(Token<RDExpressionToken> variableToken)
{
return variableToken.TokenID switch
{
RDExpressionToken.VariableInt => Variables.i[int.Parse(variableToken.Value[1..])],
RDExpressionToken.VariableFloat => Variables.f[int.Parse(variableToken.Value[1..])],
RDExpressionToken.VariableBoolean => Variables.b[int.Parse(variableToken.Value[1..])] ? 1.0f : 0.0f,
RDExpressionToken.PlainString => (float)Variables[variableToken.Value],
_ => throw new InvalidOperationException("Invalid variable type"),
};
}
[NodeName("string")]
[Production("argument: String")]
public static float String(Token<RDExpressionToken> stringToken)
{
TokenList.Add(new(RDExpressionToken.String,
stringToken.Value switch
{
['s', 't', 'r', ':', ..] => stringToken.Value[4..],
['"', .., '"'] => stringToken.Value[1..^1],
_ => stringToken.Value,
},
new()));
return 1;
}
[NodeName("compare")]
[Production("expression: term GreaterThanOrEqual expression")]
[Production("expression: term GreaterThan expression")]
[Production("expression: term LessThanOrEqual expression")]
[Production("expression: term LessThan expression")]
public static float Compare(float left, Token<RDExpressionToken> operatorToken, float right)
{
var result = operatorToken.TokenID switch
{
RDExpressionToken.GreaterThan => left > right,
RDExpressionToken.GreaterThanOrEqual => left >= right,
RDExpressionToken.LessThan => left < right,
RDExpressionToken.LessThanOrEqual => left <= right,
_ => throw new InvalidOperationException("Invalid operator")
};
return result ? 1.0f : 0.0f;
}
[NodeName("assignment")]
[Production("primary: VariableInt Assignment expression")]
[Production("primary: VariableFloat Assignment expression")]
[Production("primary: VariableBoolean Assignment expression")]
[Production("primary: PlainString Assignment expression")]
public float Assignment(Token<RDExpressionToken> nameToken, Token<RDExpressionToken> _, float expression)
{
var variableName = nameToken.Value;
switch (variableName[0])
{
case 'i':
Variables.i[int.Parse(variableName[1..])] = (int)expression;
break;
case 'f':
Variables.f[int.Parse(variableName[1..])] = expression;
break;
case 'b':
Variables.b[int.Parse(variableName[1..])] = expression != 0.0f;
break;
default:
Variables[variableName] = expression;
break;
}
return expression;
}
[NodeName("function_call")]
[Production("primary: Identifier LeftParenthesis [d] functionRight")]
public static float FunctionCallWithArguments(Token<RDExpressionToken> identifierToken, float _) => EvaluateFunction(identifierToken.Value, TokenList);
[NodeName("function_right")]
[Production("functionRight: RightParenthesis [d]")]
public static float FunctionCall() => 0;
[NodeName("function_right")]
[Production("functionRight: Number RightParenthesis [d]")]
[Production("functionRight: PlainString RightParenthesis [d]")]
public static float FunctionEnd(Token<RDExpressionToken> valueToken)
{
TokenList.Add(valueToken);
return 1;
}
[NodeName("arguments")]
[Production("functionRight: Number Comma [d] functionRight")]
[Production("functionRight: String Comma [d] functionRight")]
[Production("functionRight: PlainString Comma [d] functionRight")]
public static float ArgumentListWithComma(Token<RDExpressionToken> valueToken, float argument)
{
TokenList.Add(valueToken);
return 1 + argument;
}
[NodeName("arguments")]
[Production("functionRight: expression Comma [d] functionRight")]
public static float ArgumentListWithComma2(float arg, float argument)
{
TokenList.Add(new(RDExpressionToken.Number,arg.ToString(),new()));
return 1 + argument;
}
private static float EvaluateFunction(string functionName, List<Token<RDExpressionToken>> tokenList)
{
return functionName switch
{
"Rand" => (float)(TokenList.Count == 1
? int.TryParse(tokenList[0].Value, out int result)
? RDVariables.Rand(result)
: throw new ArgumentException("Invalid argument type for Rand function")
: throw new ArgumentException("Invalid argument count for Rand function")),
"atLeastRank" => (TokenList.Count == 1
? RDVariables.atLeastRank(tokenList[0].Value)
? 1.0f
: 0.0f
: throw new ArgumentException("Invalid argument count for atLeastRank function")),
"atLeastNPerfects" => (TokenList.Count == 2
? RDVariables.atLeastNPerfects(int.Parse(tokenList[0].Value), int.Parse(tokenList[1].Value))
? 1.0f
: 0.0f
: throw new ArgumentException("Invalid argument count for atLeastNPerfects function")),
_ => throw new InvalidOperationException($"Unknown function: {functionName}"),
};
}
}
}