diff --git a/src/WpfMath.Example/MainWindow.xaml.cs b/src/WpfMath.Example/MainWindow.xaml.cs
index a91ce77f..d42822f6 100644
--- a/src/WpfMath.Example/MainWindow.xaml.cs
+++ b/src/WpfMath.Example/MainWindow.xaml.cs
@@ -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.}";
diff --git a/src/WpfMath/Parsers/Matrices/MatrixCommandParser.cs b/src/WpfMath/Parsers/Matrices/MatrixCommandParser.cs
index 00ac207b..7b0e7883 100644
--- a/src/WpfMath/Parsers/Matrices/MatrixCommandParser.cs
+++ b/src/WpfMath/Parsers/Matrices/MatrixCommandParser.cs
@@ -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);
diff --git a/src/WpfMath/Parsers/StandardCommands.cs b/src/WpfMath/Parsers/StandardCommands.cs
index 546ef2e1..fe2daede 100644
--- a/src/WpfMath/Parsers/StandardCommands.cs
+++ b/src/WpfMath/Parsers/StandardCommands.cs
@@ -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;
@@ -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;
diff --git a/src/WpfMath/TexFormulaParser.cs b/src/WpfMath/TexFormulaParser.cs
index 9b92e36f..c6e38821 100644
--- a/src/WpfMath/TexFormulaParser.cs
+++ b/src/WpfMath/TexFormulaParser.cs
@@ -104,7 +104,7 @@ internal static string GetDelimeterMapping(char character)
}
catch (KeyNotFoundException)
{
- throw new DelimiterMappingNotFoundException(character);
+ throw new TexParseException(new DelimiterMappingNotFoundException(character).Message);
}
}
@@ -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(
@@ -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 + "'!");
@@ -356,24 +356,55 @@ private static SourceSpan ReadElementGroupOptional(
if (value[position] != openChar)
return null;
- return ReadElementGroup(value, ref position, openChar, closeChar);
+ return ReadArgumentGroup(value, ref position, openChar, closeChar);
}
- /// Reads an element: typically, a curly brace-enclosed value group or a singular value.
+ /// Reads an argument: typically, a curly brace-enclosed value group, a singular value or an escaped sequence of letters/a character.
/// Will be thrown for ill-formed groups.
- 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(
@@ -381,7 +412,7 @@ private TexFormula ReadScript(
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());
/// May return null for commands that produce no atoms.
private Atom ProcessCommand(
@@ -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);
@@ -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;
@@ -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}");
@@ -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);
@@ -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)
@@ -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}");
@@ -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());
@@ -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);
@@ -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);
@@ -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)
@@ -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);