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

@@ -1,17 +1,19 @@
namespace ZelWiki.Engine.Function
{
/// <summary>
/// Contains information about an actual function call, its supplied parameters, and is matched with a defined function.
/// 包含有关实际函数调用及其提供的参数的信息,并与定义的函数相匹配。
/// </summary>
public class FunctionCall
{
/// <summary>
/// The name of the function being called.
///
/// </summary>
public string Name { get; private set; }
public FunctionPrototype Prototype { get; set; }
/// <summary>
/// The arguments supplied by the caller.
/// T
/// </summary>
public FunctionParameters Parameters { get; private set; }
@@ -25,7 +27,7 @@
{
if (arg.StartsWith(':') && arg.Contains('='))
{
var parsed = arg.Substring(1); //Skip the colon.
var parsed = arg.Substring(1);
int index = parsed.IndexOf('=');
var name = parsed.Substring(0, index).Trim().ToLower();
var value = parsed.Substring(index + 1).Trim();
@@ -42,9 +44,9 @@
}
/// <summary>
/// Checks the passed value against the function prototype to ensure that the variable is the correct type, value, etc.
/// 对照函数原型检查传递的值,以确保变量的类型,值等正确
/// </summary>
/// <param name="segment"></param>
/// <param name="param"></param>
/// <param name="value"></param>
/// <exception cref="Exception"></exception>
private void EnforcePrototypeParamValue(PrototypeParameter param, string value)
@@ -53,21 +55,25 @@
{
if (bool.TryParse(value, out bool _) == false)
{
throw new Exception($"Function [{Name}], the value [{value}] passed to parameter [{param.Name}] could not be converted to boolean.");
throw new Exception(
$"函数 [{Name}] 传递给 [{param.Name}] 的值 [{value}] 无法转化成布尔");
}
}
if (param.Type == "integer")
{
if (int.TryParse(value, out int _) == false)
{
throw new Exception($"Function [{Name}], the value [{value}] passed to parameter [{param.Name}] could not be converted to integer.");
throw new Exception(
$"函数 [{Name}] 传递给 [{param.Name}] 的值 [{value}] 无法转化成整数.");
}
}
else if (param.Type == "float")
{
if (double.TryParse(value, out double _) == false)
{
throw new Exception($"Function [{Name}], the value [{value}] passed to parameter [{param.Name}] could not be converted to float.");
throw new Exception(
$"函数 [{Name}] 传递给 [{param.Name}] 的值 [{value}] 无法转化成小数.");
}
}
@@ -75,24 +81,22 @@
{
if (param.AllowedValues.Contains(value.ToLower()) == false)
{
throw new Exception($"Function [{Name}], the value [{value}] passed to parameter [{param.Name}] is not allowed. Allowed values are [{string.Join(",", param.AllowedValues)}].");
throw new Exception(
$"函数 [{Name}] 传递给 [{param.Name}] 的值 [{value}] 为非法数据. 合法值为 [{string.Join(",", param.AllowedValues)}].");
}
}
}
/// <summary>
/// Rolls through the supplied arguments and applies them to the prototype. Also identifies which supplied arguments are associated with each
/// prototype argument and adds the ordinal based arguments to the name based collection. Ensures that each argument conforms with the prototype.
///
/// </summary>
/// <exception cref="Exception"></exception>
private void ApplyPrototype()
{
int index = 0;
var index = 0;
//Keep a list of the arguments as they are associated with the prototype so that we can later reference them by name.
var namedToAddLater = new List<NamedParameter>();
//Handle non-infinite ordinal based required parameters:
for (; index < Prototype.Parameters.Count; index++)
{
var param = Prototype.Parameters[index];
@@ -101,15 +105,15 @@
{
break;
}
if (param.IsInfinite == true)
if (param.IsInfinite)
{
break;
}
if (Parameters.Ordinals.Count > index)
{
//Good, we have a value.
string value = Parameters.Ordinals[index].Value;
var value = Parameters.Ordinals[index].Value;
Parameters.Ordinals[index].AssociateWithPrototypeParam(param.Name);
EnforcePrototypeParamValue(param, value.ToLower());
@@ -123,33 +127,30 @@
bool hasEncounteredOptionalParameter = false;
//Handle remaining optional parameters:
for (; index < Prototype.Parameters.Count; index++)
{
var param = Prototype.Parameters[index];
if (param.IsInfinite == true)
if (param.IsInfinite)
{
if (param.IsRequired == true)
if (param.IsRequired)
{
//Make sure we have at least one of these required infinite parameters passed.
if (Parameters.Ordinals.Count > index)
{
//Good, we have a value.
string value = Parameters.Ordinals[index].Value;
var value = Parameters.Ordinals[index].Value;
Parameters.Ordinals[index].AssociateWithPrototypeParam(param.Name);
EnforcePrototypeParamValue(param, value.ToLower());
}
else
{
throw new Exception($"Function [{Name}], the required infinite parameter [{param.Name}] was not passed.");
throw new Exception(
$"函数 [{Name}], 参数 [{param.Name}] 未通过.");
}
}
//Now that we have encountered an infinite parameter, it will swallow up all other ordinal based arguments. Might as well check the types and exit the loop.
for (; index < Parameters.Ordinals.Count; index++)
{
string value = Parameters.Ordinals[index].Value;
var value = Parameters.Ordinals[index].Value;
Parameters.Ordinals[index].AssociateWithPrototypeParam(param.Name);
EnforcePrototypeParamValue(param, value.ToLower());
namedToAddLater.Add(new NamedParameter(param.Name, value));
@@ -163,18 +164,20 @@
hasEncounteredOptionalParameter = true;
}
if (param.IsRequired == true && hasEncounteredOptionalParameter)
if (param.IsRequired && hasEncounteredOptionalParameter)
{
throw new Exception($"Function [{Name}], the required parameter [{param.Name}] was found after other optional parameters.");
throw new Exception(
$"函数 [{Name}], 所必参数 [{param.Name}] 在其他可选参数之后找到.");
}
else if (param.IsInfinite == true)
else if (param.IsInfinite)
{
throw new Exception($"Function [{Name}], encountered an unexpected number of infinite parameters in prototype for [{param.Name}].");
throw new Exception(
$"函数 [{Name}], 参数溢出 [{param.Name}].");
}
if (Parameters.Ordinals.Count > index)
{
string value = Parameters.Ordinals[index].Value;
var value = Parameters.Ordinals[index].Value;
Parameters.Ordinals[index].AssociateWithPrototypeParam(param.Name);
EnforcePrototypeParamValue(param, value.ToLower());
namedToAddLater.Add(new NamedParameter(param.Name, value));
@@ -183,8 +186,10 @@
foreach (var named in Parameters.Named)
{
var param = Prototype.Parameters.Where(o => o.Name.Equals(named.Name, StringComparison.InvariantCultureIgnoreCase)).FirstOrDefault()
?? throw new Exception($"Function [{Name}], the named parameter [{named.Name}] is not defined in the function prototype.");
var param = Prototype.Parameters
.FirstOrDefault(o => o.Name.Equals(named.Name, StringComparison.InvariantCultureIgnoreCase))
?? throw new Exception(
$"函数 [{Name}], 命名参数 [{named.Name}] 未在函数原型中定义.");
EnforcePrototypeParamValue(param, named.Value);
}
@@ -194,17 +199,20 @@
var unmatchedParams = Parameters.Ordinals.Where(o => o.IsMatched == false).ToList();
if (unmatchedParams.Count != 0)
{
throw new Exception($"Function [{Name}], unmatched parameter value [{unmatchedParams.First().Value}].");
throw new Exception($"函数 [{Name}], 不匹配的参数值 [{unmatchedParams.First().Value}].");
}
var nonInfiniteParams = Prototype.Parameters.Where(o => o.IsInfinite == false).Select(o => o.Name.ToLower());
var groups = Parameters.Named.Where(o => nonInfiniteParams.Contains(o.Name.ToLower())).GroupBy(o => o.Name.ToLower()).Where(o => o.Count() > 1);
var nonInfiniteParams =
Prototype.Parameters.Where(o => o.IsInfinite == false).Select(o => o.Name.ToLower());
var groups = Parameters.Named.Where(o => nonInfiniteParams.Contains(o.Name.ToLower()))
.GroupBy(o => o.Name.ToLower()).Where(o => o.Count() > 1);
if (groups.Any())
{
var group = groups.First();
throw new Exception($"Function [{Name}], non-infinite parameter specified more than once: [{group.Key}].");
throw new Exception(
$"函数 [{Name}], 多次指定参数: [{group.Key}].");
}
}
}
}
}

View File

@@ -4,38 +4,42 @@ namespace ZelWiki.Engine.Function
{
public class FunctionParameters
{
/// <summary>
/// Variables set by ordinal.
/// </summary>
public List<OrdinalParameter> Ordinals { get; set; } = new();
/// <summary>
/// Variables set by name.
/// </summary>
public List<NamedParameter> Named { get; private set; } = new();
private readonly FunctionCall _owner;
public FunctionParameters(FunctionCall owner)
{
_owner = owner;
}
/// <summary>
///
/// </summary>
public List<OrdinalParameter> Ordinals { get; set; } = new();
/// <summary>
///
/// </summary>
public List<NamedParameter> Named { get; private set; } = new();
public T Get<T>(string name)
{
try
{
var value = Named.Where(o => o.Name.Equals(name, StringComparison.InvariantCultureIgnoreCase)).FirstOrDefault()?.Value;
var value = Named
.FirstOrDefault(o => o.Name.Equals(name, StringComparison.InvariantCultureIgnoreCase))?.Value;
if (value == null)
{
var prototype = _owner.Prototype.Parameters.Where(o => o.Name.Equals(name, StringComparison.InvariantCultureIgnoreCase)).First();
return Converters.ConvertTo<T>(prototype.DefaultValue) ?? throw new Exception("Value cannot be null");
var prototype = _owner.Prototype.Parameters.First(o => o.Name.Equals(name, StringComparison.InvariantCultureIgnoreCase));
return Converters.ConvertTo<T>(prototype.DefaultValue) ??
throw new Exception("值不能为空");
}
return Converters.ConvertTo<T>(value) ?? throw new Exception("Value cannot be null");
return Converters.ConvertTo<T>(value) ?? throw new Exception("值不能为空");
}
catch (Exception ex)
{
throw new Exception($"Function [{_owner.Name}], {ex.Message}");
throw new Exception($"函数 [{_owner.Name}], {ex.Message}");
}
}
@@ -43,17 +47,18 @@ namespace ZelWiki.Engine.Function
{
try
{
var value = Named.Where(o => o.Name.Equals(name, StringComparison.InvariantCultureIgnoreCase)).FirstOrDefault()?.Value;
var value = Named
.FirstOrDefault(o => o.Name.Equals(name, StringComparison.InvariantCultureIgnoreCase))?.Value;
if (value == null)
{
return defaultValue;
}
return Converters.ConvertTo<T>(value) ?? throw new Exception("Value cannot be null");
return Converters.ConvertTo<T>(value) ?? throw new Exception("值不能为空");
}
catch (Exception ex)
{
throw new Exception($"Function [{_owner.Name}], {ex.Message}");
throw new Exception($"函数 [{_owner.Name}], {ex.Message}");
}
}
@@ -62,14 +67,15 @@ namespace ZelWiki.Engine.Function
try
{
var values = Named.Where(o => o.Name.Equals(name, StringComparison.InvariantCultureIgnoreCase))?
.Select(o => Converters.ConvertTo<T>(o.Value) ?? throw new Exception("Value cannot be null"))?.ToList();
.Select(o => Converters.ConvertTo<T>(o.Value) ?? throw new Exception("值不能为空"))
?.ToList();
return values ?? new List<T>();
}
catch (Exception ex)
{
throw new Exception($"Function [{_owner.Name}], {ex.Message}");
throw new Exception($"函数 [{_owner.Name}], {ex.Message}");
}
}
}
}
}

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;
}
}
}
}

View File

@@ -2,14 +2,19 @@
{
public class FunctionPrototype
{
public string FunctionPrefix { get; set; } = string.Empty;
public string ProperName { get; set; } = string.Empty;
public string FunctionName { get; set; } = string.Empty;
public List<PrototypeParameter> Parameters { get; set; }
/// <summary>
///
/// </summary>
public FunctionPrototype()
{
Parameters = new List<PrototypeParameter>();
FunctionPrefix = string.Empty;
ProperName = string.Empty;
FunctionName = string.Empty;
Parameters = new();
}
public string FunctionPrefix { get; set; }
public string ProperName { get; set; }
public string FunctionName { get; set; }
public List<PrototypeParameter> Parameters { get; set; }
}
}

View File

@@ -14,6 +14,10 @@ namespace ZelWiki.Engine.Function
public WikiFunctionType FunctionTypes { get; private set; }
public List<PrototypeSet> Items { get; set; } = new();
/// <summary>
///
/// </summary>
/// <param name="functionTypes"></param>
public FunctionPrototypeCollection(WikiFunctionType functionTypes)
{
FunctionTypes = functionTypes;
@@ -36,40 +40,40 @@ namespace ZelWiki.Engine.Function
{
functionName = functionName.ToLower();
//$$ are scope functions and are not called by prefix, we only have prefixes to make it easier to parse
// the functions in the wikiText and scope functions are easy enough since they start with curly braces.
return Items.Any(o => (o.FunctionPrefix == functionPrefix || o.FunctionPrefix == "$$") && o.FunctionName == functionName);
return Items.Any(o =>
(o.FunctionPrefix == functionPrefix || o.FunctionPrefix == "$$") && o.FunctionName == functionName);
}
public FunctionPrototype Get(string functionPrefix, string functionName)
{
functionName = functionName.ToLower();
//$$ are scope functions and are not called by prefix, we only have prefixes to make it easier to parse
// the functions in the wikiText and scope functions are easy enough since they start with curly braces.
var functionPrototype = Items.Where(o => (o.FunctionPrefix == functionPrefix || o.FunctionPrefix == "$$") && o.FunctionName == functionName).FirstOrDefault()?.Value;
var functionPrototype = Items.FirstOrDefault(o =>
(o.FunctionPrefix == functionPrefix || o.FunctionPrefix == "$$") && o.FunctionName == functionName)
?.Value;
return functionPrototype
?? throw new WikiFunctionPrototypeNotDefinedException($"Function ({functionName}) does not have a defined prototype.");
?? throw new WikiFunctionPrototypeNotDefinedException(
$"函数 ({functionName}) 没有定义的原型.");
}
#region Private
private FunctionPrototype ParsePrototype(string prototypeString)
{
int nameStartIndex = prototypeString.TakeWhile(c => char.IsLetterOrDigit(c) == false).Count();
int nameEndIndex = prototypeString.IndexOf(':');
string properName = prototypeString.Substring(nameStartIndex, nameEndIndex - nameStartIndex).Trim();
string functionName = properName.ToLower();
string functionPrefix = prototypeString.Substring(0, nameStartIndex).Trim();
var nameStartIndex = prototypeString.TakeWhile(c => char.IsLetterOrDigit(c) == false).Count();
var nameEndIndex = prototypeString.IndexOf(':');
var properName = prototypeString.Substring(nameStartIndex, nameEndIndex - nameStartIndex).Trim();
var functionName = properName.ToLower();
var functionPrefix = prototypeString.Substring(0, nameStartIndex).Trim();
prototypeString = prototypeString.Substring(nameEndIndex + 1).Trim();
var prototype = new FunctionPrototype() { FunctionPrefix = functionPrefix, ProperName = properName, FunctionName = functionName };
var prototype = new FunctionPrototype()
{ FunctionPrefix = functionPrefix, ProperName = properName, FunctionName = functionName };
if (prototypeString.Length == 0)
{
//No parameters.
return prototype;
}
var segments = prototypeString.Trim().Split('|').Select(o => o.Trim());
@@ -77,13 +81,13 @@ namespace ZelWiki.Engine.Function
{
var prototypeSegment = new PrototypeParameter();
int index = 0;
var index = 0;
if (segment[index] == '<')
{
index++; //Skip the '<'
index++;
prototypeSegment.Type = Tok(segment, ref index);
index++; //Skip the '>'
index++;
if (prototypeSegment.Type.Contains(':'))
{
@@ -94,12 +98,14 @@ namespace ZelWiki.Engine.Function
prototypeSegment.IsInfinite = true;
if (prototype.Parameters.Any(o => o.IsInfinite))
{
throw new Exception($"Function [{functionName}], prototype error: cannot contain more than one [infinite] parameter.");
throw new Exception(
$"函数 [{functionName}], 原型错误: cannot contain more than one [infinite] parameter.");
}
}
else
{
throw new Exception($"Function [{functionName}], prototype error: expected [infinite] got [{splitSeg[1]}].");
throw new Exception(
$"函数 [{functionName}], 原型错误: expected [infinite] got [{splitSeg[1]}].");
}
}
@@ -112,41 +118,42 @@ namespace ZelWiki.Engine.Function
prototypeSegment.IsRequired = true;
}
index++; //Skip the '[' or '{'
index++;
prototypeSegment.Name = Tok(segment, ref index);
if (index < segment.Length && segment[index] == '(') //Parse allowed values.
if (index < segment.Length && segment[index] == '(')
{
int allowedValueEndIndex = segment.IndexOf(')', index);
string roteRequiredValues = segment.Substring(index + 1, allowedValueEndIndex - index - 1);
prototypeSegment.AllowedValues = roteRequiredValues.Trim().Split(',').Select(o => o.Trim().ToLower()).ToList();
prototypeSegment.AllowedValues = roteRequiredValues.Trim().Split(',')
.Select(o => o.Trim().ToLower()).ToList();
index = allowedValueEndIndex;
index++; //Skip the ')'
index++;
SkipWhiteSpace(segment, ref index);
}
index++; //Skip the ']' or '}'
index++;
}
else
{
throw new Exception($"Function [{functionName}], prototype error: expected [{{] or [[].");
throw new Exception($"函数 [{functionName}], 原型错误: expected [{{] or [[].");
}
SkipWhiteSpace(segment, ref index);
if (index < segment.Length && segment[index] == '=')
{
index++; //Skip the '='
index++;
SkipWhiteSpace(segment, ref index);
if (segment[index] != '\'')
{
throw new Exception($"Function [{functionName}], prototype error: expected [\'].");
throw new Exception($"函数 [{functionName}], 原型错误: expected [\'].");
}
index++; //Skip the '''
index++;
prototypeSegment.DefaultValue = segment.Substring(index, (segment.Length - index) - 1);
@@ -154,13 +161,13 @@ namespace ZelWiki.Engine.Function
if (index < segment.Length && segment[index] != '\'')
{
throw new Exception($"Function [{functionName}], prototype error: expected [\'].");
throw new Exception($"函数 [{functionName}], 原型错误: expected [\'].");
}
}
}
else
{
throw new Exception($"Function [{functionName}], prototype error: expected [<].");
throw new Exception($"函数 [{functionName}], 原型错误: expected [<].");
}
prototype.Parameters.Add(prototypeSegment);
@@ -168,9 +175,8 @@ namespace ZelWiki.Engine.Function
return prototype;
}
/// <summary>
/// Gets the next token in a string.
///
/// </summary>
/// <param name="str"></param>
/// <param name="index"></param>
@@ -203,5 +209,7 @@ namespace ZelWiki.Engine.Function
index++;
}
}
#endregion
}
}
}

View File

@@ -5,6 +5,11 @@
public string Name { get; set; }
public string Value { get; set; }
/// <summary>
///
/// </summary>
/// <param name="name"></param>
/// <param name="value"></param>
public NamedParameter(string name, string value)
{
Name = name;

View File

@@ -2,27 +2,32 @@
{
public class OrdinalParameter
{
public string Value { get; set; }
/// <summary>
/// Has been matched to a prototype parameter?
///
/// </summary>
public bool IsMatched { get; set; } = false;
/// <summary>
/// If matched to a prototype parameter, this is the name of the parameter.
/// </summary>
public string ParameterName { get; set; } = string.Empty;
/// <param name="value"></param>
public OrdinalParameter(string value)
{
Value = value;
IsMatched = false;
ParameterName = string.Empty;
}
public string Value { get; set; }
/// <summary>
///
/// </summary>
public bool IsMatched { get; set; }
/// <summary>
///
/// </summary>
public string ParameterName { get; set; }
public void AssociateWithPrototypeParam(string paramName)
{
IsMatched = true;
ParameterName = paramName;
}
}
}
}

View File

@@ -2,11 +2,13 @@
{
public class ParsedFunctionCall
{
public string Prefix { get; set; } = string.Empty;
public string Name { get; set; } = string.Empty;
public int EndIndex { get; set; }
public List<string> RawArguments { get; set; } = new List<string>();
/// <summary>
///
/// </summary>
/// <param name="prefix"></param>
/// <param name="name"></param>
/// <param name="endIndex"></param>
/// <param name="rawArguments"></param>
public ParsedFunctionCall(string prefix, string name, int endIndex, List<string> rawArguments)
{
Prefix = prefix;
@@ -14,5 +16,9 @@
EndIndex = endIndex;
RawArguments = rawArguments;
}
public string Prefix { get; set; }
public string Name { get; set; }
public int EndIndex { get; set; }
public List<string> RawArguments { get; set; }
}
}

View File

@@ -2,11 +2,24 @@
{
public class PrototypeParameter
{
public string Type { get; set; } = string.Empty;
public string Name { get; set; } = string.Empty;
public string DefaultValue { get; set; } = string.Empty;
public bool IsRequired { get; set; } = false;
public bool IsInfinite { get; set; } = false;
public List<string> AllowedValues { get; set; } = new();
/// <summary>
///
/// </summary>
public PrototypeParameter()
{
Type = string.Empty;
Name = string.Empty;
DefaultValue = string.Empty;
IsRequired = false;
IsInfinite = false;
AllowedValues = new();
}
public string Type { get; set; }
public string Name { get; set; }
public string DefaultValue { get; set; }
public bool IsRequired { get; set; }
public bool IsInfinite { get; set; }
public List<string> AllowedValues { get; set; }
}
}
}

View File

@@ -2,9 +2,19 @@
{
public class PrototypeSet
{
public string FunctionPrefix { get; set; } = string.Empty;
public string ProperName { get; set; } = string.Empty;
public string FunctionName { get; set; } = string.Empty;
public FunctionPrototype Value { get; set; } = new();
/// <summary>
///
/// </summary>
public PrototypeSet()
{
FunctionPrefix = string.Empty;
ProperName = string.Empty;
FunctionName = string.Empty;
Value = new();
}
public string FunctionPrefix { get; set; }
public string ProperName { get; set; }
public string FunctionName { get; set; }
public FunctionPrototype Value { get; set; }
}
}

View File

@@ -1,10 +1,12 @@
namespace ZelWiki.Engine.Function
{
[Obsolete("弃用了")]
public static class SelfDocument
{
/// <summary>
/// Don't ever look at this. :(
///
/// </summary>
[Obsolete("弃用了")]
public static void CreateNotExisting()
{
/*