Skip to content

Commit

Permalink
#236 - Rework parser (remove RPN)
Browse files Browse the repository at this point in the history
  • Loading branch information
sys27 committed Jul 31, 2019
1 parent 14a1c29 commit 206a250
Show file tree
Hide file tree
Showing 5 changed files with 831 additions and 171 deletions.
22 changes: 16 additions & 6 deletions xFunc.DotnetTool/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using xFunc.Maths.Analyzers.TypeAnalyzers;
using xFunc.Maths.Expressions;
using xFunc.Maths.Expressions.Collections;
using xFunc.Maths.Tokenization;

namespace xFunc.DotnetTool
{
Expand Down Expand Up @@ -141,12 +142,21 @@ private static void PrintError(DebugInfoOptions options, Exception e)

public static void Main(string[] args)
{
CommandLine.Parser.Default
.ParseArguments<TokenizeOptions, ParseOptions, SolveOptions, InteractiveOptions>(args)
.WithParsed<TokenizeOptions>(Tokenize)
.WithParsed<ParseOptions>(Parse)
.WithParsed<SolveOptions>(Solve)
.WithParsed<InteractiveOptions>(Interactive);
//CommandLine.Parser.Default
// .ParseArguments<TokenizeOptions, ParseOptions, SolveOptions, InteractiveOptions>(args)
// .WithParsed<TokenizeOptions>(Tokenize)
// .WithParsed<ParseOptions>(Parse)
// .WithParsed<SolveOptions>(Solve)
// .WithParsed<InteractiveOptions>(Interactive);

var l = new Lexer();
var p = new Maths.Parser();

var tokens = l.Tokenize("true || false & false");
var exp = p.Parse(tokens);

Console.WriteLine(exp);
Console.WriteLine(exp.Execute());
}
}
}
245 changes: 122 additions & 123 deletions xFunc.Maths/Parser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,128 +22,127 @@

namespace xFunc.Maths
{

/// <summary>
/// The parser for mathematical expressions.
/// </summary>
public class Parser : IParser
{

/// <summary>
/// Initializes a new instance of the <see cref="Parser"/> class with default implementations of <see cref="IExpressionFactory"/>.
/// </summary>
public Parser() : this(new ExpressionFactory(new Differentiator(), new Simplifier())) { }

/// <summary>
/// Initializes a new instance of the <see cref="Parser" /> class.
/// </summary>
/// <param name="factory">The factory.</param>
public Parser(IExpressionFactory factory)
{
ExpressionFactory = factory;
}

/// <summary>
/// Parses the specified function.
/// </summary>
/// <param name="tokens">The list of tokens.</param>
/// <returns>The parsed expression.</returns>
public IExpression Parse(IEnumerable<IToken> tokens)
{
if (tokens == null)
throw new ArgumentNullException(nameof(tokens));

var tokensArray = tokens as IToken[] ?? tokens.ToArray();
if (!tokensArray.Any())
throw new ArgumentException(nameof(tokens));

var rpn = ConvertToReversePolishNotation(tokensArray);

var arguments = new LinkedList<IExpression>();
foreach (var token in rpn)
{
var expression = ExpressionFactory.Create(token, arguments);

if (expression is IFunctionExpression functionExpression)
for (var i = 0; i < functionExpression.ParametersCount; i++)
arguments.RemoveLast();

arguments.AddLast(expression);
}

if (arguments.Count > 1)
throw new ParseException(Resource.MoreParams);

return arguments.Last.Value;
}

private IEnumerable<IToken> ConvertToReversePolishNotation(IToken[] tokens)
{
var output = new List<IToken>(tokens.Length);
var stack = new Stack<IToken>();

var openBracketToken = new SymbolToken(Symbols.OpenBracket);
var openBraceToken = new SymbolToken(Symbols.OpenBrace);
foreach (var token in tokens)
{
IToken stackToken;
if (token is SymbolToken t)
{
switch (t.Symbol)
{
case Symbols.OpenBracket:
case Symbols.OpenBrace:
stack.Push(token);
break;
case Symbols.CloseBracket:
case Symbols.CloseBrace:
stackToken = stack.Pop();
while (!stackToken.Equals(openBracketToken) && !stackToken.Equals(openBraceToken))
{
output.Add(stackToken);
stackToken = stack.Pop();
}
break;
case Symbols.Comma:
stackToken = stack.Pop();

while (!stackToken.Equals(openBracketToken) && !stackToken.Equals(openBraceToken))
{
output.Add(stackToken);
stackToken = stack.Pop();
}

stack.Push(stackToken);
break;
}
}
else
{
while (stack.Count != 0 && (stackToken = stack.Peek()).Priority >= token.Priority)
{
if (stackToken.Equals(openBracketToken) || stackToken.Equals(openBraceToken))
break;
output.Add(stack.Pop());
}

stack.Push(token);
}
}

if (stack.Count != 0)
output.AddRange(stack);

return output;
}

/// <summary>
/// Gets or sets the expression factory.
/// </summary>
/// <value>
/// The expression factory.
/// </value>
public IExpressionFactory ExpressionFactory { get; set; }

}
///// <summary>
///// The parser for mathematical expressions.
///// </summary>
//public class Parser : IParser
//{

// /// <summary>
// /// Initializes a new instance of the <see cref="Parser"/> class with default implementations of <see cref="IExpressionFactory"/>.
// /// </summary>
// public Parser() : this(new ExpressionFactory(new Differentiator(), new Simplifier())) { }

// /// <summary>
// /// Initializes a new instance of the <see cref="Parser" /> class.
// /// </summary>
// /// <param name="factory">The factory.</param>
// public Parser(IExpressionFactory factory)
// {
// ExpressionFactory = factory;
// }

// /// <summary>
// /// Parses the specified function.
// /// </summary>
// /// <param name="tokens">The list of tokens.</param>
// /// <returns>The parsed expression.</returns>
// public IExpression Parse(IEnumerable<IToken> tokens)
// {
// if (tokens == null)
// throw new ArgumentNullException(nameof(tokens));

// var tokensArray = tokens as IToken[] ?? tokens.ToArray();
// if (!tokensArray.Any())
// throw new ArgumentException(nameof(tokens));

// var rpn = ConvertToReversePolishNotation(tokensArray);

// var arguments = new LinkedList<IExpression>();
// foreach (var token in rpn)
// {
// var expression = ExpressionFactory.Create(token, arguments);

// if (expression is IFunctionExpression functionExpression)
// for (var i = 0; i < functionExpression.ParametersCount; i++)
// arguments.RemoveLast();

// arguments.AddLast(expression);
// }

// if (arguments.Count > 1)
// throw new ParseException(Resource.MoreParams);

// return arguments.Last.Value;
// }

// private IEnumerable<IToken> ConvertToReversePolishNotation(IToken[] tokens)
// {
// var output = new List<IToken>(tokens.Length);
// var stack = new Stack<IToken>();

// var openBracketToken = new SymbolToken(Symbols.OpenBracket);
// var openBraceToken = new SymbolToken(Symbols.OpenBrace);
// foreach (var token in tokens)
// {
// IToken stackToken;
// if (token is SymbolToken t)
// {
// switch (t.Symbol)
// {
// case Symbols.OpenBracket:
// case Symbols.OpenBrace:
// stack.Push(token);
// break;
// case Symbols.CloseBracket:
// case Symbols.CloseBrace:
// stackToken = stack.Pop();
// while (!stackToken.Equals(openBracketToken) && !stackToken.Equals(openBraceToken))
// {
// output.Add(stackToken);
// stackToken = stack.Pop();
// }
// break;
// case Symbols.Comma:
// stackToken = stack.Pop();

// while (!stackToken.Equals(openBracketToken) && !stackToken.Equals(openBraceToken))
// {
// output.Add(stackToken);
// stackToken = stack.Pop();
// }

// stack.Push(stackToken);
// break;
// }
// }
// else
// {
// while (stack.Count != 0 && (stackToken = stack.Peek()).Priority >= token.Priority)
// {
// if (stackToken.Equals(openBracketToken) || stackToken.Equals(openBraceToken))
// break;
// output.Add(stack.Pop());
// }

// stack.Push(token);
// }
// }

// if (stack.Count != 0)
// output.AddRange(stack);

// return output;
// }

// /// <summary>
// /// Gets or sets the expression factory.
// /// </summary>
// /// <value>
// /// The expression factory.
// /// </value>
// public IExpressionFactory ExpressionFactory { get; set; }

//}

}

0 comments on commit 206a250

Please sign in to comment.