This commit is contained in:
Zel
2025-02-23 18:47:21 +08:00
parent eaaffeeccb
commit e46a7ca31c
104 changed files with 2630 additions and 2516 deletions

View File

@@ -10,13 +10,15 @@ namespace ZelWiki.Engine.Function
private static partial Regex FunctionCallParser();
/// <summary>
/// Parsed a function call, its parameters and matches it to a defined function and its prototype.
/// 解析函数调用及其参数,并将其与已定义的函数及其原型进行匹配
/// </summary>
/// <param name="prototypes"></param>
/// <param name="functionCall"></param>
/// <param name="parseEndIndex"></param>
/// <returns></returns>
/// <exception cref="Exception"></exception>
public static FunctionCall ParseAndGetFunctionCall(FunctionPrototypeCollection prototypes, string functionCall, out int parseEndIndex)
/// <exception cref="WikiFunctionPrototypeNotDefinedException"></exception>
public static FunctionCall ParseAndGetFunctionCall(FunctionPrototypeCollection prototypes, string functionCall,
out int parseEndIndex)
{
var rawArguments = new List<string>();
@@ -25,7 +27,8 @@ namespace ZelWiki.Engine.Function
var prototype = prototypes.Get(parsed.Prefix, parsed.Name);
if (prototype == null)
{
throw new WikiFunctionPrototypeNotDefinedException($"Function ({parsed.Name}) does not have a defined prototype.");
throw new WikiFunctionPrototypeNotDefinedException(
$"函数 ({parsed.Name}) 没有定义的原型.");
}
parseEndIndex = parsed.EndIndex;
@@ -35,18 +38,18 @@ namespace ZelWiki.Engine.Function
public static ParsedFunctionCall ParseFunctionCall(FunctionPrototypeCollection prototypes, string functionCall)
{
string functionName = string.Empty;
int parseEndIndex = 0;
var functionName = string.Empty;
var parseEndIndex = 0;
var rawArguments = new List<string>();
var firstLine = functionCall.Split('\n')?.FirstOrDefault();
if (firstLine == null || firstLine.Where(x => x == '(').Count() != firstLine.Where(x => x == ')').Count())
if (firstLine == null || firstLine.Count(x => x == '(') != firstLine.Count(x => x == ')'))
{
throw new WikiFunctionPrototypeSyntaxError($"Function parentheses mismatch.");
throw new WikiFunctionPrototypeSyntaxError($"函数括号不匹配.");
}
string functionPrefix = functionCall.Substring(0, 2);
var functionPrefix = functionCall.Substring(0, 2);
var parameterMatches = FunctionCallParser().Matches(firstLine);
if (parameterMatches.Count > 0)
@@ -57,12 +60,15 @@ namespace ZelWiki.Engine.Function
functionName = match.Value[..paramStartIndex].ToLower().TrimStart(['{', '#', '@']).Trim();
parseEndIndex = match.Index + match.Length;
string rawArgTrimmed = match.ToString().Substring(paramStartIndex, (match.ToString().Length - paramStartIndex));
string rawArgTrimmed = match.ToString()
.Substring(paramStartIndex, (match.ToString().Length - paramStartIndex));
rawArguments = ParseRawArguments(rawArgTrimmed);
}
else //The function call has no parameters.
else //函数调用没有参数.
{
int endOfLine = functionCall.Substring(2).TakeWhile(c => char.IsLetterOrDigit(c)).Count(); //Find the first non-alphanumeric after the function identifier (##, @@, etc).
var endOfLine =
functionCall.Substring(2).TakeWhile(c => char.IsLetterOrDigit(c))
.Count();
functionName = functionCall.Substring(2, endOfLine).ToLower().TrimStart(['{', '#', '@']).Trim();
parseEndIndex = endOfLine + 2;
}
@@ -71,12 +77,11 @@ namespace ZelWiki.Engine.Function
}
/// <summary>
/// Parses function parameters into a list of arguments based on comma separation.
/// String do not need to be enclosed in double-quotes unless they contain commas.
///
/// </summary>
/// <param name="paramString"></param>
/// <returns></returns>
/// <exception cref="Exception"></exception>
/// <exception cref="WikiFunctionPrototypeSyntaxError"></exception>
public static List<string> ParseRawArgumentsAddParenthesis(string paramString)
{
if (paramString.StartsWith('(') || paramString.EndsWith(')'))
@@ -88,17 +93,16 @@ namespace ZelWiki.Engine.Function
}
/// <summary>
/// Parses function parameters into a list of arguments based on comma separation.
/// String do not need to be enclosed in double-quotes unless they contain commas.
///
/// </summary>
/// <param name="paramString"></param>
/// <returns></returns>
/// <exception cref="Exception"></exception>
/// <exception cref="WikiFunctionPrototypeSyntaxError"></exception>
public static List<string> ParseRawArguments(string paramString)
{
List<string> ps = new();
int readPos = 0;
var readPos = 0;
var singleParam = new StringBuilder();
@@ -109,7 +113,7 @@ namespace ZelWiki.Engine.Function
int parenNest = 1;
readPos++; //Skip the (
readPos++;
while (readPos < paramString.Length && char.IsWhiteSpace(paramString[readPos])) readPos++;
@@ -130,7 +134,7 @@ namespace ZelWiki.Engine.Function
}
else if (paramString[readPos] == ')' && parenNest == 0)
{
readPos++; //Skip the )
readPos++;
if (parenNest == 0 && readPos != paramString.Length)
{
@@ -141,6 +145,7 @@ namespace ZelWiki.Engine.Function
{
ps.Add(singleParam.ToString());
}
singleParam.Clear();
if (parenNest == 0)
@@ -150,10 +155,10 @@ namespace ZelWiki.Engine.Function
}
else if (paramString[readPos] == '\"')
{
readPos++; //Skip the ".
readPos++;
bool escapeChar = false;
for (; ; readPos++)
var escapeChar = false;
for (;; readPos++)
{
if (readPos == paramString.Length)
{
@@ -166,14 +171,14 @@ namespace ZelWiki.Engine.Function
}
else if (paramString[readPos] == '\"' && escapeChar == false)
{
//Found the end of the string:
readPos++; //Skip the ".
readPos++;
break;
}
else
{
singleParam.Append(paramString[readPos]);
}
escapeChar = false;
}
@@ -181,7 +186,7 @@ namespace ZelWiki.Engine.Function
}
else if (paramString[readPos] == ',')
{
readPos++; //Skip the ,
readPos++;
while (readPos < paramString.Length && char.IsWhiteSpace(paramString[readPos])) readPos++;
ps.Add(singleParam.ToString());
@@ -209,7 +214,7 @@ namespace ZelWiki.Engine.Function
}
}
for (int i = 0; i < ps.Count; i++)
for (var i = 0; i < ps.Count; i++)
{
ps[i] = ps[i].Trim();
}
@@ -217,4 +222,4 @@ namespace ZelWiki.Engine.Function
return ps;
}
}
}
}