Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 25 additions & 1 deletion src/RCParsing/Building/ParserElementBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1389,7 +1389,16 @@ public T Empty()
{
return Token(new EmptyTokenPattern());
}


/// <summary>
/// Adds an any character token to the current sequence. It matches any single character, and returns it as intermediate value.
/// </summary>
/// <returns>Current instance for method chaining.</returns>
public T AnyChar()
{
return Token(new AnyCharTokenPattern());
}

/// <summary>
/// Adds a fail token to the current sequence. It always fails.
/// </summary>
Expand Down Expand Up @@ -2005,5 +2014,20 @@ public T TextUntil(params string[] forbidden)
{
return Token(EscapedTextTokenPattern.CreateUntil(forbidden));
}

// The pizdec

/// <summary>
/// Adds a token pattern that uses an entire parser for matching.
/// The parser will be invoked as a token in the current sequence.
/// </summary>
/// <param name="matchParser">The parser to use for matching.</param>
/// <param name="ruleAlias">The alias for the rule to parse. If null, uses the main rule of the parser.</param>
/// <param name="tokenAlias">Optional token alias to match instead of a rule. If both this and ruleAlias are null, uses main rule.</param>
/// <returns>Current instance for method chaining.</returns>
public T Parser(Parser matchParser, string? ruleAlias = null, string? tokenAlias = null)
{
return Token(new ParserTokenPattern(matchParser, ruleAlias, tokenAlias));
}
}
}
77 changes: 66 additions & 11 deletions src/RCParsing/ParsedRuleResultBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -198,14 +198,16 @@ IEnumerator IEnumerable.GetEnumerator()
/// </summary>
/// <typeparam name="T">The type of value to retrieve.</typeparam>
/// <returns>The intermediate value associated with this AST node.</returns>
public T GetIntermediateValue<T>() => (T)IntermediateValue;
public T GetIntermediateValue<T>() => IntermediateValue is T res ? res :
throw new SemanticException(this, $"Expected an intermediate value of type {typeof(T).Name} but got {IntermediateValue?.GetType().Name ?? "null"}.");

/// <summary>
/// Gets the intermediate value associated with child AST node at the specific index as an instance of type <typeparamref name="T"/>.
/// </summary>
/// <typeparam name="T">The type of value to retrieve.</typeparam>
/// <returns>The intermediate value associated with child AST node.</returns>
public T GetIntermediateValue<T>(int index) => (T)this[index].IntermediateValue;
public T GetIntermediateValue<T>(int index) => this[index].IntermediateValue is T res ? res :
throw new SemanticException(this[index], $"Expected an intermediate value of type {typeof(T).Name} but got {IntermediateValue?.GetType().Name ?? "null"}.");

/// <summary>
/// Tries to get the intermediate value associated with this AST node as an instance of type <typeparamref name="T"/>.
Expand All @@ -227,40 +229,72 @@ IEnumerator IEnumerable.GetEnumerator()
/// </summary>
/// <typeparam name="T">The type of value to retrieve.</typeparam>
/// <returns>The intermediate value associated with this AST node.</returns>
public T ConvertIntermediateValue<T>() => (T)Convert.ChangeType(IntermediateValue, typeof(T));
public T ConvertIntermediateValue<T>()
{
try
{
return (T)Convert.ChangeType(IntermediateValue, typeof(T));
}
catch (Exception ex)
{
throw new SemanticException(this, $"Failed to convert intermediate value to {typeof(T).Name}: {ex.Message}", ex);
}
}

/// <summary>
/// Gets the intermediate value associated with child AST node at the specific index converted to type <typeparamref name="T"/>.
/// </summary>
/// <typeparam name="T">The type of value to retrieve.</typeparam>
/// <returns>The intermediate value associated with child AST node.</returns>
public T ConvertIntermediateValue<T>(int index) => (T)Convert.ChangeType(this[index].IntermediateValue, typeof(T));
public T ConvertIntermediateValue<T>(int index)
{
try
{
return (T)Convert.ChangeType(this[index].IntermediateValue, typeof(T));
}
catch (Exception ex)
{
throw new SemanticException(this[index], $"Failed to convert intermediate value to {typeof(T).Name}: {ex.Message}", ex);
}
}

/// <summary>
/// Gets the value associated with this AST node as not-null object. If the value is null, throws an exception.
/// </summary>
/// <returns>The value associated with this AST node.</returns>
public object GetValue() => Value ?? throw new InvalidOperationException("ParsedRuleResult.Value is null");
public object GetValue() => Value ?? throw new SemanticException(this, "ParsedRuleResult.Value is null");

/// <summary>
/// Gets the value associated with child AST node at the specific index as not-null object. If the value is null, throws an exception.
/// </summary>
/// <returns>The value associated with child AST node.</returns>
public object GetValue(int index) => this[index].Value ?? throw new InvalidOperationException("ParsedRuleResult.Value is null");
public object GetValue(int index) => this[index].Value ?? throw new SemanticException(this[index], "ParsedRuleResult[index].Value is null");

/// <summary>
/// Gets the value associated with this AST node as an instance of type <typeparamref name="T"/>.
/// </summary>
/// <typeparam name="T">The type of value to retrieve.</typeparam>
/// <returns>The value associated with this AST node.</returns>
public T GetValue<T>() => (T)Value;
public T GetValue<T>()
{
var value = Value;
return value is T res ? res :
throw new SemanticException(this,
$"Expected a value of type {typeof(T).Name} but got {value?.GetType().Name ?? "null"}.");
}

/// <summary>
/// Gets the value associated with child AST node at the specific index as an instance of type <typeparamref name="T"/>.
/// </summary>
/// <typeparam name="T">The type of value to retrieve.</typeparam>
/// <returns>The value associated with child AST node.</returns>
public T GetValue<T>(int index) => (T)this[index].Value;
public T GetValue<T>(int index)
{
var value = this[index].Value;
return value is T res ? res :
throw new SemanticException(this[index],
$"Expected a value of type {typeof(T).Name} but got {value?.GetType().Name ?? "null"}.");
}

/// <summary>
/// Tries to get the value associated with this AST node as an instance of type <typeparamref name="T"/> or <see langword="default"/> value.
Expand Down Expand Up @@ -302,7 +336,17 @@ IEnumerator IEnumerable.GetEnumerator()
/// </remarks>
/// <typeparam name="T">The type of value to retrieve.</typeparam>
/// <returns>The value associated with this AST node.</returns>
public T ConvertValue<T>() => (T)Convert.ChangeType(Value, typeof(T));
public T ConvertValue<T>()
{
try
{
return (T)Convert.ChangeType(Value, typeof(T));
}
catch (Exception ex)
{
throw new SemanticException(this, $"Failed to convert value to {typeof(T).Name}: {ex.Message}", ex);
}
}

/// <summary>
/// Gets the value associated with child AST node at the specific index converted to type <typeparamref name="T"/>.
Expand All @@ -312,14 +356,25 @@ IEnumerator IEnumerable.GetEnumerator()
/// </remarks>
/// <typeparam name="T">The type of value to retrieve.</typeparam>
/// <returns>The value associated with child AST node.</returns>
public T ConvertValue<T>(int index) => (T)Convert.ChangeType(this[index].Value, typeof(T));
public T ConvertValue<T>(int index)
{
try
{
return (T)Convert.ChangeType(this[index].Value, typeof(T));
}
catch (Exception ex)
{
throw new SemanticException(this[index], $"Failed to convert value to {typeof(T).Name}: {ex.Message}", ex);
}
}

/// <summary>
/// Gets the parsing parameter associated with parser context as an instance of type <typeparamref name="T"/>.
/// </summary>
/// <typeparam name="T">The type of parsing parameter to retrieve.</typeparam>
/// <returns>The parsing parameter associated with the parser context.</returns>
public T GetParsingParameter<T>() => (T)ParsingParameter;
public T GetParsingParameter<T>() => ParsingParameter is T res ? res :
throw new SemanticException(this, $"Expected a parsing parameter of type {typeof(T).Name} but got {ParsingParameter?.GetType().Name ?? "null"}.");

/// <summary>
/// Tries to get the parsing parameter associated with parser context as an instance of type <typeparamref name="T"/> or <see langword="default"/> value.
Expand Down
Loading
Loading