Skip to content

Commit

Permalink
Second try.
Browse files Browse the repository at this point in the history
  • Loading branch information
varndellwagglebee committed Nov 4, 2024
1 parent 245e3d2 commit 5554bd0
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 31 deletions.
6 changes: 4 additions & 2 deletions src/Hyperbee.Templating/Text/TemplateParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -494,11 +494,13 @@ public FrameStack.Frame CurrentFrame() =>

internal sealed class FrameStack
{
public record Frame( TokenDefinition Token, bool Truthy, IEnumerator<string> Enumerator, int StartPos = -1 );
// Updated Frame to include an IEnumerator<string>
public record Frame( TokenDefinition Token, bool Truthy, IEnumerator<string> Enumerator = null, int StartPos = -1 );

private readonly Stack<Frame> _stack = new();

public void Push( TokenDefinition token, bool truthy, IEnumerator<string> enumerator, int startPos = -1 )
// Updated Push method to accept an IEnumerator<string> parameter
public void Push( TokenDefinition token, bool truthy, IEnumerator<string> enumerator = null, int startPos = -1 )
=> _stack.Push( new Frame( token, truthy, enumerator, startPos ) );

public Frame Peek() => _stack.Peek();
Expand Down
51 changes: 22 additions & 29 deletions src/Hyperbee.Templating/Text/TokenProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ public TokenAction ProcessToken( TokenDefinition token, TemplateState state, out

// Resolve value

ResolveValue( token, out value, out var defined, out var ifResult, out IEnumerable<string> iterator, out var expressionError );
ResolveValue( token, out value, out var defined, out var ifResult, out IEnumerable<string> enumerator, out var expressionError );

// Frame handling: post-value processing

Expand All @@ -100,8 +100,11 @@ public TokenAction ProcessToken( TokenDefinition token, TemplateState state, out
}
case TokenType.Each:
{
var result = enumerator.GetEnumerator();
var startPos = token.TokenType == TokenType.Each ? state.CurrentPos : -1;
frames.Push( token, false, null, startPos );

frames.Push( token, true, result, startPos );

return TokenAction.Ignore;
}
}
Expand Down Expand Up @@ -134,7 +137,7 @@ private static TokenAction ProcessElseToken( FrameStack frames, TokenDefinition
if ( !frames.IsTokenType( TokenType.If ) )
throw new TemplateException( "Syntax error. Invalid `else` without matching `if`." );

frames.Push( token, !frames.IsTruthy, null );
frames.Push( token, !frames.IsTruthy );
return TokenAction.Ignore;
}

Expand Down Expand Up @@ -182,42 +185,32 @@ private TokenAction ProcessEndEachToken( FrameStack frames )
throw new TemplateException( "Syntax error. Invalid `/each` without matching `each`. " );

var eachToken = frames.Peek().Token;

var currentFrame = frames.Peek();
if ( currentFrame.Enumerator == null )
{
string expressionError = null;
var values = eachToken.TokenEvaluation switch
{
TokenEvaluation.Expression when TryInvokeTokenExpression( eachToken, out var expressionResult, out expressionError ) =>
expressionResult.ToString()!.Split( ',' ).Select( v => v.Trim() ),
TokenEvaluation.Expression => throw new TemplateException( $"{_tokenLeft}Error ({eachToken.Id}):{expressionError ?? "Error in each condition."}{_tokenRight}" ),
_ => _members[eachToken.Name].Split( ',' ).Select( v => v.Trim() )
};

currentFrame = currentFrame with { Enumerator = values.GetEnumerator() };
frames.Push( currentFrame.Token, true, currentFrame.Enumerator, currentFrame.StartPos );
return TokenAction.ContinueLoop;

}
string expressionError = null;

// Iterate over the collection
var items = currentFrame.Enumerator;
while ( items.MoveNext() )
var conditionIsTrue = eachToken.TokenEvaluation switch
{
var item = items.Current;
_members.Add( "x", item );
frames.Push( currentFrame.Token, true, currentFrame.Enumerator, currentFrame.StartPos );
TokenEvaluation.Expression when TryInvokeTokenExpression( eachToken, out var expressionResult, out expressionError ) =>
expressionResult.ToString()!.Split( ',' ).Select( v => v.Trim() ).Any(),
TokenEvaluation.Expression => throw new TemplateException( $"{_tokenLeft}Error ({eachToken.Id}):{expressionError ?? "Error in while condition."}{_tokenRight}" ),
_ => Truthy( _members[eachToken.Name] ) // Re-evaluate the condition
};

if ( conditionIsTrue && currentFrame.Enumerator.MoveNext() && currentFrame.Enumerator.Current != null )
{
_members["x"] = currentFrame.Enumerator.Current;
return TokenAction.ContinueLoop;
}



//Otherwise, pop the frame and exit the loop
frames.Pop();
return TokenAction.Ignore;
}



private TokenAction ProcessDefineToken( TokenDefinition token )
{
// ReSharper disable once RedundantAssignment
Expand All @@ -234,12 +227,12 @@ TokenEvaluation.Expression when TryInvokeTokenExpression( token, out var express
return TokenAction.Ignore;
}

private void ResolveValue( TokenDefinition token, out string value, out bool defined, out bool ifResult, out IEnumerable<string> iterator, out string expressionError )
private void ResolveValue( TokenDefinition token, out string value, out bool defined, out bool ifResult, out IEnumerable<string> enumerator, out string expressionError )
{
value = default;
defined = false;
ifResult = false;
iterator = null;
enumerator = null;
expressionError = null;

switch ( token.TokenType )
Expand Down Expand Up @@ -280,7 +273,7 @@ private void ResolveValue( TokenDefinition token, out string value, out bool def
if ( TryInvokeTokenExpression( token, out var eachExprResult, out var errorEach ) )
{
var results = (string) eachExprResult;
iterator = results.Split( ',' ).Select( v => v.Trim() );
enumerator = results.Split( ',' ).Select( v => v.Trim() );
}
else
throw new TemplateException( $"{_tokenLeft}Error ({token.Id}):{errorEach ?? "Error in each condition."}{_tokenRight}" );
Expand Down

0 comments on commit 5554bd0

Please sign in to comment.