Skip to content

Commit

Permalink
Latest update.
Browse files Browse the repository at this point in the history
Renamed "*Element*" to "*Argument*"  ("ReadElementGroup" is now named as "ReadArgumentGroup".
The "ReadArgumentGroup" can now read an escape sequence of letters or a character(this is extremely useful for the "*\\left*" and "*\\right*" commands, etc).
It also fixes issue #158.
  • Loading branch information
B3zaleel authored and ForNeVeR committed Jan 3, 2020
1 parent 9733f84 commit 4e20411
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 121 deletions.
2 changes: 1 addition & 1 deletion src/WpfMath.Example/MainWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ private void Window_Loaded(object sender, RoutedEventArgs e)

var testFormula1 = "\\int_0^{\\infty}{x^{2n} e^{-a x^2} dx} = \\frac{2n-1}{2a} \\int_0^{\\infty}{x^{2(n-1)} e^{-a x^2} dx} = \\frac{(2n-1)!!}{2^{n+1}} \\sqrt{\\frac{\\pi}{a^{2n+1}}}";
var testFormula2 = "\\int_a^b{f(x) dx} = (b - a) \\sum_{n = 1}^{\\infty} {\\sum_{m = 1}^{2^n - 1} { ( { - 1} )^{m + 1} } } 2^{ - n} f(a + m ( {b - a} )2^{-n} )";
var testFormula3 = @"L = \int_a^b \sqrt[4]{ \left| \sum_{i,j=1}^ng_{ij}\left(\gamma(t)\right) \left[\frac{d}{dt}x^i\circ\gamma(t) \right] \left{\frac{d}{dt}x^j\circ\gamma(t) \right} \right|}dt";
var testFormula3 = @"L = \int_a^\infty \sqrt[4]{ \left\vert \sum_{i,j=1}^ng_{ij}\left\(\gamma(t)\right\) \left\[\frac{d}{dt}x^i\circ\gamma(t) \right\] \left\{\frac{d}{dt}x^j\circ\gamma(t) \right\} \right\|}dt";
//matrix examples
var testFormula4 = @"\matrix{4&78&3 \\ 5 & 9 & 82 }";
var testFormula5 = @"\cases{x,&if x > 0;\cr -x,& otherwise.}";
Expand Down
2 changes: 1 addition & 1 deletion src/WpfMath/Parsers/Matrices/MatrixCommandParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public CommandProcessingResult ProcessCommand(CommandContext context)
if (position == source.Length)
throw new TexParseException("illegal end!");

var cellsSource = TexFormulaParser.ReadElement(source, ref position);
var cellsSource = TexFormulaParser.ReadArgument(source, ref position);
var matrixSource = context.CommandSource.Segment(
context.CommandNameStartPosition,
position - context.CommandNameStartPosition);
Expand Down
6 changes: 3 additions & 3 deletions src/WpfMath/Parsers/StandardCommands.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public CommandProcessingResult ProcessCommand(CommandContext context)
var source = context.CommandSource;
var position = context.ArgumentsStartPosition;
var underlineFormula = context.Parser.Parse(
TexFormulaParser.ReadElement(source, ref position),
TexFormulaParser.ReadArgument(source, ref position),
context.Formula.TextStyle,
context.Environment);
var start = context.CommandNameStartPosition;
Expand All @@ -30,11 +30,11 @@ public CommandProcessingResult ProcessCommand(CommandContext context)
var source = context.CommandSource;
var position = context.ArgumentsStartPosition;
var topFormula = context.Parser.Parse(
TexFormulaParser.ReadElement(source, ref position),
TexFormulaParser.ReadArgument(source, ref position),
context.Formula.TextStyle,
context.Environment.CreateChildEnvironment());
var bottomFormula = context.Parser.Parse(
TexFormulaParser.ReadElement(source, ref position),
TexFormulaParser.ReadArgument(source, ref position),
context.Formula.TextStyle,
context.Environment.CreateChildEnvironment());
var start = context.CommandNameStartPosition;
Expand Down
177 changes: 61 additions & 116 deletions src/WpfMath/TexFormulaParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ internal static string GetDelimeterMapping(char character)
}
catch (KeyNotFoundException)
{
throw new DelimiterMappingNotFoundException(character);
throw new TexParseException(new DelimiterMappingNotFoundException(character).Message);
}
}

Expand Down Expand Up @@ -253,7 +253,7 @@ private TexFormula Parse(
}
else if (ch == leftGroupChar)
{
var groupValue = ReadElement(value, ref position);
var groupValue = ReadArgument(value, ref position);
var parsedGroup = Parse(groupValue, textStyle, environment.CreateChildEnvironment());
var innerGroupAtom = parsedGroup.RootAtom ?? new RowAtom(groupValue);
var groupAtom = new TypedAtom(
Expand Down Expand Up @@ -318,7 +318,7 @@ private static TexFormula ConvertRawText(SourceSpan value, string textStyle)
return formula;
}

internal static SourceSpan ReadElementGroup(SourceSpan value, ref int position, char openChar, char closeChar)
internal static SourceSpan ReadArgumentGroup(SourceSpan value, ref int position, char openChar, char closeChar)
{
if (position == value.Length || value[position] != openChar)
throw new TexParseException("missing '" + openChar + "'!");
Expand Down Expand Up @@ -356,32 +356,63 @@ private static SourceSpan ReadElementGroupOptional(
if (value[position] != openChar)
return null;

return ReadElementGroup(value, ref position, openChar, closeChar);
return ReadArgumentGroup(value, ref position, openChar, closeChar);
}

/// <summary>Reads an element: typically, a curly brace-enclosed value group or a singular value.</summary>
/// <summary>Reads an argument: typically, a curly brace-enclosed value group, a singular value or an escaped sequence of letters/a character.</summary>
/// <exception cref="TexParseException">Will be thrown for ill-formed groups.</exception>
internal static SourceSpan ReadElement(SourceSpan value, ref int position)
internal static SourceSpan ReadArgument(SourceSpan value, ref int position)
{
SkipWhiteSpace(value, ref position);

if (position == value.Length)
throw new TexParseException("An element is missing");

if (value[position] == leftGroupChar)
if (position < value.Length)
{
return ReadElementGroup(value, ref position, leftGroupChar, rightGroupChar);
}
if (value[position] == leftGroupChar)
return ReadArgumentGroup(value, ref position, leftGroupChar, rightGroupChar);
else if (value[position] == escapeChar)
{
position++;
var start = position;

return value.Segment(position++, 1);
if (position < value.Length)
{
if (!Char.IsLetter(value[position]))
{
position++;
return value.Segment(start, 1);
}
else
{
bool elementfound = false;
while (position < value.Length && elementfound == false)
{
if (!Char.IsLetter(value[position]))
{
elementfound = true;
position--;
}
position++;
}
if (elementfound)
return value.Segment(start-1, position - start+1);
else
throw new TexParseException("An argument is missing");
}
}
else
throw new TexParseException("An argument is missing");
}
else
return value.Segment(position++, 1);
}
else
throw new TexParseException("An argument is missing");
}

private TexFormula ReadScript(
TexFormula formula,
SourceSpan value,
ref int position,
ICommandEnvironment environment) =>
Parse(ReadElement(value, ref position), formula.TextStyle, environment.CreateChildEnvironment());
Parse(ReadArgument(value, ref position), formula.TextStyle, environment.CreateChildEnvironment());

/// <remarks>May return <c>null</c> for commands that produce no atoms.</remarks>
private Atom ProcessCommand(
Expand All @@ -401,11 +432,11 @@ private Atom ProcessCommand(
case "frac":
{
var numeratorFormula = Parse(
ReadElement(value, ref position),
ReadArgument(value, ref position),
formula.TextStyle,
environment.CreateChildEnvironment());
var denominatorFormula = Parse(
ReadElement(value, ref position),
ReadArgument(value, ref position),
formula.TextStyle,
environment.CreateChildEnvironment());
source = value.Segment(start, position - start);
Expand All @@ -417,50 +448,7 @@ private Atom ProcessCommand(
if (position == value.Length)
throw new TexParseException("`left` command should be passed a delimiter");

string delimiter = "";
if (value[position] == escapeChar)
{
position++;
if (position == value.Length)
throw new TexParseException("`left` command should be passed a delimiter");

if (Char.IsLetter(value[position]) == false)
{
delimiter = value[position].ToString();
position++;
}
else
{
StringBuilder sb = new StringBuilder();
bool leftSymbolFound = false;
while (position < value.Length && leftSymbolFound == false)
{
if (IsWhiteSpace(value[position]) || Char.IsLetter(value[position]) == false)
{
leftSymbolFound = true;
}
if (leftSymbolFound == false)
{
sb.Append(value[position].ToString());
position++;
}
}
if (leftSymbolFound == true)
{
var grouplength = sb.Length;
delimiter = value.Segment(position - grouplength, grouplength).ToString();
}
else
{
throw new TexParseException("left symbol is incomplete");
}
}
}
else
{
delimiter = value[position].ToString();
position++;
}
string delimiter = ReadArgument(value, ref position).ToString().Trim();

var left = position;

Expand All @@ -476,7 +464,7 @@ private Atom ProcessCommand(
if (delimiter.Length > 1)
{
opening = GetDelimiterSymbol(
delimiter, value.Segment(start, left - start));
delimiter.Replace('\\', ' ').Trim(), value.Segment(start, left - start));
}
if (opening == null)
throw new TexParseException($"Cannot find delimiter named {delimiter}");
Expand All @@ -488,7 +476,7 @@ private Atom ProcessCommand(
case "overline":
{
var overlineFormula = Parse(
ReadElement(value, ref position),
ReadArgument(value, ref position),
formula.TextStyle,
environment.CreateChildEnvironment());
source = value.Segment(start, position - start);
Expand All @@ -503,50 +491,7 @@ private Atom ProcessCommand(
if (position == value.Length)
throw new TexParseException("`right` command should be passed a delimiter");

string delimiter = "";
if (value[position] == escapeChar)
{
position++;
if (position == value.Length)
throw new TexParseException("`right` command should be passed a delimiter");

if (Char.IsLetter(value[position]) == false)
{
delimiter = value[position].ToString();
position++;
}
else
{
StringBuilder sb = new StringBuilder();
bool rightSymbolFound = false;
while (position < value.Length && rightSymbolFound == false)
{
if (IsWhiteSpace(value[position]) || Char.IsLetter(value[position]) == false)
{
rightSymbolFound = true;
}
if (rightSymbolFound == false)
{
sb.Append(value[position].ToString());
position++;
}
}
if (rightSymbolFound)
{
var grouplength = sb.Length;
delimiter = value.Segment(position - grouplength, grouplength).ToString();
}
else
{
throw new TexParseException("right symbol is incomplete");
}
}
}
else
{
delimiter = value[position].ToString();
position++;
}
string delimiter = ReadArgument(value, ref position).ToString().Trim();

SymbolAtom closing = null;
if (delimiter.Length == 1)
Expand All @@ -558,7 +503,7 @@ private Atom ProcessCommand(
if (delimiter.Length > 1)
{
closing = GetDelimiterSymbol(
delimiter, value.Segment(start, position - start));
delimiter.Replace('\\', ' ').Trim(), value.Segment(start, position - start));
}
if (closing == null)
throw new TexParseException($"Cannot find delimiter named {delimiter}");
Expand All @@ -576,13 +521,13 @@ private Atom ProcessCommand(
{
// Degree of radical is specified.
degreeFormula = Parse(
ReadElementGroup(value, ref position, leftBracketChar, rightBracketChar),
ReadArgumentGroup(value, ref position, leftBracketChar, rightBracketChar),
formula.TextStyle,
environment.CreateChildEnvironment());
}

var sqrtFormula = this.Parse(
ReadElement(value, ref position),
ReadArgument(value, ref position),
formula.TextStyle,
environment.CreateChildEnvironment());

Expand All @@ -593,7 +538,7 @@ private Atom ProcessCommand(
{
var color = ReadColorModelData(value, ref position);

var bodyValue = ReadElement(value, ref position);
var bodyValue = ReadArgument(value, ref position);
var bodyFormula = Parse(bodyValue, formula.TextStyle, environment.CreateChildEnvironment());
source = value.Segment(start, position - start);

Expand All @@ -603,7 +548,7 @@ private Atom ProcessCommand(
{
var color = ReadColorModelData(value, ref position);

var bodyValue = ReadElement(value, ref position);
var bodyValue = ReadArgument(value, ref position);
var bodyFormula = Parse(bodyValue, formula.TextStyle, environment.CreateChildEnvironment());
source = value.Segment(start, position - start);

Expand Down Expand Up @@ -637,7 +582,7 @@ private Color ReadColorModelData(SourceSpan value, ref int position)
ref position,
leftBracketChar,
rightBracketChar)?.ToString();
var colorDefinition = ReadElement(value, ref position).ToString();
var colorDefinition = ReadArgument(value, ref position).ToString();
var colorComponents = colorDefinition.Split(',').Select(c => c.Trim());

var colorParser = string.IsNullOrEmpty(colorModelName)
Expand Down Expand Up @@ -727,8 +672,8 @@ private void ProcessEscapeSequence(TexFormula formula,
SkipWhiteSpace(value, ref position);

var styledFormula = command == TexUtilities.TextStyleName
? ConvertRawText(ReadElement(value, ref position), command)
: Parse(ReadElement(value, ref position), command, environment.CreateChildEnvironment());
? ConvertRawText(ReadArgument(value, ref position), command)
: Parse(ReadArgument(value, ref position), command, environment.CreateChildEnvironment());

var source = value.Segment(start, position - start);
var atom = styledFormula.RootAtom ?? new NullAtom(source);
Expand Down

0 comments on commit 4e20411

Please # to comment.