Skip to content

Commit 01d92a4

Browse files
committed
Allow for all functions to be called, case-insensitive
1 parent 120830e commit 01d92a4

File tree

2 files changed

+148
-228
lines changed

2 files changed

+148
-228
lines changed

MathConverter/Parser.cs

Lines changed: 147 additions & 227 deletions
Original file line numberDiff line numberDiff line change
@@ -297,241 +297,161 @@ private AbstractSyntaxTree Primary()
297297
Func<double, double> formula1 = null;
298298
Func<object, object, object> formula2 = null;
299299
Func<IEnumerable<object>, object> formulaN = null;
300-
switch (lex)
300+
switch (lex.ToLower())
301301
{
302302
case "null":
303303
return new NullNode();
304304
case "true":
305305
return new ValueNode(true);
306306
case "false":
307307
return new ValueNode(false);
308-
case "NOW":
309-
case "Now":
310-
case "now":
311-
formula0 = () => DateTime.Now;
312-
break;
313-
case "COS":
314-
case "Cos":
315-
case "cos":
316-
formula1 = Math.Cos;
317-
break;
318-
case "SIN":
319-
case "Sin":
320-
case "sin":
321-
formula1 = Math.Sin;
322-
break;
323-
case "TAN":
324-
case "Tan":
325-
case "tan":
326-
formula1 = Math.Tan;
327-
break;
328-
case "ABS":
329-
case "Abs":
330-
case "abs":
331-
formula1 = Math.Abs;
332-
break;
333-
case "ACOS":
334-
case "ACos":
335-
case "Acos":
336-
case "acos":
337-
case "ARCCOS":
338-
case "ArcCos":
339-
case "Arccos":
340-
case "arccos":
341-
formula1 = Math.Acos;
342-
break;
343-
case "ASIN":
344-
case "ASin":
345-
case "Asin":
346-
case "asin":
347-
case "ARCSIN":
348-
case "ArcSin":
349-
case "Arcsin":
350-
case "arcsin":
351-
formula1 = Math.Asin;
352-
break;
353-
case "ATAN":
354-
case "ATan":
355-
case "Atan":
356-
case "atan":
357-
case "ARCTAN":
358-
case "ArcTan":
359-
case "Arctan":
360-
case "arctan":
361-
formula1 = Math.Atan;
362-
break;
363-
case "CEIL":
364-
case "Ceil":
365-
case "ceil":
366-
case "CEILING":
367-
case "Ceiling":
368-
case "ceiling":
369-
formula1 = Math.Ceiling;
370-
break;
371-
case "FLOOR":
372-
case "Floor":
373-
case "floor":
374-
formula1 = Math.Floor;
375-
break;
376-
case "SQRT":
377-
case "Sqrt":
378-
case "sqrt":
379-
formula1 = Math.Sqrt;
380-
break;
381-
case "DEGREES":
382-
case "Degrees":
383-
case "degrees":
384-
case "DEG":
385-
case "Deg":
386-
case "deg":
387-
formula1 = x => x / Math.PI * 180;
388-
break;
389-
case "RADIANS":
390-
case "Radians":
391-
case "radians":
392-
case "RAD":
393-
case "Rad":
394-
case "rad":
395-
formula1 = x => x / 180 * Math.PI;
396-
break;
397-
case "ROUND":
398-
case "Round":
399-
case "round":
400-
formula2 = (x, y) =>
401-
{
402-
var a = MathConverter.ConvertToDouble(x);
403-
var b = MathConverter.ConvertToDouble(y);
404-
if (a.HasValue && b.HasValue)
405-
{
406-
if (b.Value == (int)b.Value)
407-
return Math.Round(a.Value, (int)b.Value);
408-
else
409-
throw new Exception(string.Format("Error calling Math.Round({0}, {1}):\r\n{1} is not an integer.", a, y));
410-
}
411-
else
412-
{
413-
return null;
414-
}
415-
};
416-
break;
417-
case "ATAN2":
418-
case "ATan2":
419-
case "Atan2":
420-
case "atan2":
421-
case "ARCTAN2":
422-
case "ArcTan2":
423-
case "Arctan2":
424-
case "arctan2":
425-
formula2 = (x, y) =>
426-
{
427-
var a = MathConverter.ConvertToDouble(x);
428-
var b = MathConverter.ConvertToDouble(y);
429-
if (a.HasValue && b.HasValue)
430-
return Math.Atan2(a.Value, b.Value);
431-
else
432-
return null;
433-
};
434-
break;
435-
case "LOG":
436-
case "Log":
437-
case "log":
438-
formula2 = (x, y) =>
439-
{
440-
var a = MathConverter.ConvertToDouble(x);
441-
var b = MathConverter.ConvertToDouble(y);
442-
if (a.HasValue && b.HasValue)
443-
return Math.Log(a.Value, b.Value);
444-
else
445-
return null;
446-
};
447-
448-
break;
449-
case "ISNULL":
450-
case "IsNull":
451-
case "Isnull":
452-
case "isnull":
453-
case "IFNULL":
454-
case "IfNull":
455-
case "Ifnull":
456-
case "ifnull":
457-
formula2 = (x, y) => ReferenceEquals(x, null) ? y : x;
458-
break;
459-
case "AND":
460-
case "And":
461-
case "and":
462-
formulaN = FormulaNodeN.And;
463-
break;
464-
case "NOR":
465-
case "Nor":
466-
case "nor":
467-
formulaN = FormulaNodeN.Nor;
468-
break;
469-
case "OR":
470-
case "Or":
471-
case "or":
472-
formulaN = FormulaNodeN.Or;
473-
break;
474-
case "MAX":
475-
case "Max":
476-
case "max":
477-
formulaN = FormulaNodeN.Max;
478-
break;
479-
case "MIN":
480-
case "Min":
481-
case "min":
482-
formulaN = FormulaNodeN.Min;
483-
break;
484-
case "AVG":
485-
case "Avg":
486-
case "avg":
487-
case "AVERAGE":
488-
case "Average":
489-
case "average":
490-
formulaN = FormulaNodeN.Average;
491-
break;
492-
case "PI":
493-
case "pi":
494-
return new ConstantNumberNode(Math.PI);
495-
case "E":
496-
case "e":
497-
return new ConstantNumberNode(Math.E);
498-
case "FORMAT":
499-
case "Format":
500-
case "format":
501-
formulaN = FormulaNodeN.Format;
502-
break;
503-
case "CONCAT":
504-
case "Concat":
505-
case "concat":
506-
formulaN = FormulaNodeN.Concat;
507-
break;
508-
case "JOIN":
509-
case "Join":
510-
case "join":
511-
formulaN = FormulaNodeN.Join;
512-
break;
513-
case "CONTAINS":
514-
case "Contains":
515-
case "contains":
516-
formula2 = (x, y) =>
308+
default:
309+
switch (lex.ToLower())
517310
{
518-
if (x is IEnumerable<dynamic>)
519-
{
520-
return (x as IEnumerable<dynamic>).Contains(y);
521-
}
522-
else if (x is string)
523-
{
524-
return (x as string).Contains(y as dynamic);
525-
}
526-
else
527-
{
528-
return null;
529-
}
530-
};
311+
case "now":
312+
formula0 = () => DateTime.Now;
313+
break;
314+
case "cos":
315+
formula1 = Math.Cos;
316+
break;
317+
case "sin":
318+
formula1 = Math.Sin;
319+
break;
320+
case "tan":
321+
formula1 = Math.Tan;
322+
break;
323+
case "abs":
324+
formula1 = Math.Abs;
325+
break;
326+
case "acos":
327+
case "arccos":
328+
formula1 = Math.Acos;
329+
break;
330+
case "asin":
331+
case "arcsin":
332+
formula1 = Math.Asin;
333+
break;
334+
case "atan":
335+
case "arctan":
336+
formula1 = Math.Atan;
337+
break;
338+
case "ceil":
339+
case "ceiling":
340+
formula1 = Math.Ceiling;
341+
break;
342+
case "floor":
343+
formula1 = Math.Floor;
344+
break;
345+
case "sqrt":
346+
formula1 = Math.Sqrt;
347+
break;
348+
case "degrees":
349+
case "deg":
350+
formula1 = x => x / Math.PI * 180;
351+
break;
352+
case "radians":
353+
case "rad":
354+
formula1 = x => x / 180 * Math.PI;
355+
break;
356+
case "round":
357+
formula2 = (x, y) =>
358+
{
359+
var a = MathConverter.ConvertToDouble(x);
360+
var b = MathConverter.ConvertToDouble(y);
361+
if (a.HasValue && b.HasValue)
362+
{
363+
if (b.Value == (int)b.Value)
364+
return Math.Round(a.Value, (int)b.Value);
365+
else
366+
throw new Exception(string.Format("Error calling Math.Round({0}, {1}):\r\n{1} is not an integer.", a, y));
367+
}
368+
else
369+
{
370+
return null;
371+
}
372+
};
373+
break;
374+
case "atan2":
375+
case "arctan2":
376+
formula2 = (x, y) =>
377+
{
378+
var a = MathConverter.ConvertToDouble(x);
379+
var b = MathConverter.ConvertToDouble(y);
380+
if (a.HasValue && b.HasValue)
381+
return Math.Atan2(a.Value, b.Value);
382+
else
383+
return null;
384+
};
385+
break;
386+
case "log":
387+
formula2 = (x, y) =>
388+
{
389+
var a = MathConverter.ConvertToDouble(x);
390+
var b = MathConverter.ConvertToDouble(y);
391+
if (a.HasValue && b.HasValue)
392+
return Math.Log(a.Value, b.Value);
393+
else
394+
return null;
395+
};
396+
break;
397+
case "isnull":
398+
case "ifnull":
399+
formula2 = (x, y) => ReferenceEquals(x, null) ? y : x;
400+
break;
401+
case "and":
402+
formulaN = FormulaNodeN.And;
403+
break;
404+
case "nor":
405+
formulaN = FormulaNodeN.Nor;
406+
break;
407+
case "or":
408+
formulaN = FormulaNodeN.Or;
409+
break;
410+
case "max":
411+
formulaN = FormulaNodeN.Max;
412+
break;
413+
case "min":
414+
formulaN = FormulaNodeN.Min;
415+
break;
416+
case "avg":
417+
case "average":
418+
formulaN = FormulaNodeN.Average;
419+
break;
420+
case "pi":
421+
return new ConstantNumberNode(Math.PI);
422+
case "e":
423+
return new ConstantNumberNode(Math.E);
424+
case "format":
425+
formulaN = FormulaNodeN.Format;
426+
break;
427+
case "concat":
428+
formulaN = FormulaNodeN.Concat;
429+
break;
430+
case "join":
431+
formulaN = FormulaNodeN.Join;
432+
break;
433+
case "contains":
434+
formula2 = (x, y) =>
435+
{
436+
if (x is IEnumerable<dynamic>)
437+
{
438+
return (x as IEnumerable<dynamic>).Contains(y);
439+
}
440+
else if (x is string)
441+
{
442+
return (x as string).Contains(y as dynamic);
443+
}
444+
else
445+
{
446+
return null;
447+
}
448+
};
449+
break;
450+
default:
451+
var err = $"{lex} is an invalid formula name";
452+
throw new ParsingException(scanner.Position, err, new NotSupportedException(err));
453+
}
531454
break;
532-
default:
533-
var err = lex + " is an invalid formula name";
534-
throw new ParsingException(scanner.Position, err, new NotSupportedException(err));
535455
}
536456

537457
if (formula0 != null)
@@ -609,7 +529,7 @@ private AbstractSyntaxTree Primary()
609529

610530
break;
611531
case TokenType.RParen:
612-
if (lex == "round")
532+
if (lex.ToLower() == "round")
613533
{
614534
return new FormulaNode2(lex, formula2, arg1, new ConstantNumberNode(0));
615535
}

0 commit comments

Comments
 (0)