Skip to content

Commit

Permalink
Updates
Browse files Browse the repository at this point in the history
  • Loading branch information
gregli-msft committed Mar 7, 2025
1 parent 3fc069c commit 592c57f
Show file tree
Hide file tree
Showing 6 changed files with 52 additions and 32 deletions.
6 changes: 3 additions & 3 deletions src/libraries/Microsoft.PowerFx.Core/Binding/BinderUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1505,6 +1505,9 @@ public static bool TryGetConstantValue(CheckTypesContext context, TexlNode node,
nodeValue = null;
switch (node.Kind)
{
case NodeKind.StrLit:
nodeValue = node.AsStrLit().Value;
return true;
case NodeKind.StrInterp:
var strInterpNode = node.AsStrInterp();
var segments = new List<string>();
Expand All @@ -1527,9 +1530,6 @@ public static bool TryGetConstantValue(CheckTypesContext context, TexlNode node,
}

break;
case NodeKind.StrLit:
nodeValue = node.AsStrLit().Value;
return true;
case NodeKind.BinaryOp:
var binaryOpNode = node.AsBinaryOp();
if (binaryOpNode.Op == BinaryOp.Concat)
Expand Down
31 changes: 23 additions & 8 deletions src/libraries/Microsoft.PowerFx.Core/Texl/Builtins/Match.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,21 @@ public MatchAllFunction(RegexTypeCache regexTypeCache)
: base("MatchAll", TexlStrings.AboutMatchAll, DType.EmptyTable, regexTypeCache)
{
}
}

// These start with the codes that can come after a regular expression definition in Perl/JavaScript with "/a+/misx" and can also be used in "(?misx)a+".
// If possible, do not add lower case letters that are Power Fx specific to avoid future conflicts with the industry. We added ^, $, and N as Power Fx specific.
public class MatchOptionCodes
{
public const char BeginsWith = '^'; // invented by us, adds a '^' at the front of the regex
public const char EndsWith = '$'; // invented by us, adds a '$' at the end of the regex
public const char IgnoreCase = 'i';
public const char Multiline = 'm';
public const char FreeSpacing = 'x'; // we don't support the double 'xx' mode
public const char DotAll = 's'; // otherwise known as "singleline" in other flavors, hence the 's', but note is not the opposite of "multiline"
public const char ExplicitCapture = 'n'; // default for Power Fx, can be asserted too for compatibility
public const char NumberedSubMatches = 'N'; // invented by us, opposite of ExplicitCapture and can't be used together
public const char Contains = 'c'; // invented by us, something to wrap ^ and $ around
}

internal class BaseMatchFunction : BuiltinFunction
Expand Down Expand Up @@ -100,7 +115,7 @@ public override bool HasSuggestionsForParam(int index)
Contracts.Assert(index >= 0);

return index <= 2;
}
}

public override bool CheckTypes(CheckTypesContext context, TexlNode[] args, DType[] argTypes, IErrorContainer errors, out DType returnType, out Dictionary<TexlNode, DType> nodeToCoercedTypeMap)
{
Expand Down Expand Up @@ -133,7 +148,7 @@ public override bool CheckTypes(CheckTypesContext context, TexlNode[] args, DTyp
if (!context.Features.PowerFxV1CompatibilityRules)
{
// only used for the following analysis and type creation, not modified in the IR
regularExpressionOptions += "N";
regularExpressionOptions += MatchOptionCodes.NumberedSubMatches;
}

string alteredOptions = regularExpressionOptions;
Expand Down Expand Up @@ -176,7 +191,7 @@ private bool TryCreateReturnType(TexlNode regExNode, string regexPattern, string
try
{
var regexDotNetOptions = RegexOptions.None;
if (alteredOptions.Contains("x"))
if (alteredOptions.Contains(MatchOptionCodes.FreeSpacing))
{
regexDotNetOptions |= RegexOptions.IgnorePatternWhitespace;

Expand Down Expand Up @@ -218,7 +233,7 @@ private bool TryCreateReturnType(TexlNode regExNode, string regexPattern, string
propertyNames.Add(new TypedName(DType.String, ColumnName_FullMatch));
}

if (!subMatchesHidden && alteredOptions.Contains("N"))
if (!subMatchesHidden && alteredOptions.Contains(MatchOptionCodes.NumberedSubMatches))
{
propertyNames.Add(new TypedName(DType.CreateTable(new TypedName(DType.String, ColumnName_Value)), ColumnName_SubMatches));
}
Expand Down Expand Up @@ -303,8 +318,8 @@ private void AddWarnings(TexlNode regExNode, IErrorContainer errors, bool hidesF

private bool IsSupportedRegularExpression(TexlNode regExNode, string regexPattern, string regexOptions, out string alteredOptions, IErrorContainer errors)
{
bool freeSpacing = regexOptions.Contains("x"); // can also be set with inline mode modifier
bool numberedCpature = regexOptions.Contains("N"); // can only be set here, no inline mode modifier
bool freeSpacing = regexOptions.Contains(MatchOptionCodes.FreeSpacing); // can also be set with inline mode modifier
bool numberedCpature = regexOptions.Contains(MatchOptionCodes.NumberedSubMatches); // can only be set here, no inline mode modifier

alteredOptions = regexOptions;

Expand Down Expand Up @@ -735,13 +750,13 @@ void CCRegExError(ErrorResourceKey errKey)
return false;
}

if (inlineOptions.Contains("n") && numberedCpature)
if (inlineOptions.Contains(MatchOptionCodes.ExplicitCapture) && numberedCpature)
{
RegExError(TexlStrings.ErrInvalidRegExInlineOptionConflictsWithNumberedSubMatches);
return false;
}

if (inlineOptions.Contains("x"))
if (inlineOptions.Contains(MatchOptionCodes.FreeSpacing))
{
freeSpacing = true;
}
Expand Down
18 changes: 9 additions & 9 deletions src/libraries/Microsoft.PowerFx.Core/Types/Enums/BuiltInEnums.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,15 +81,15 @@ internal static class BuiltInEnums
DType.String,
new Dictionary<string, object>()
{
{ "BeginsWith", "^c" },
{ "EndsWith", "$c" },
{ "Complete", "^c$" },
{ "Contains", "c" },
{ "IgnoreCase", "i" },
{ "Multiline", "m" },
{ "FreeSpacing", "x" },
{ "DotAll", "s" },
{ "NumberedSubMatches", "N" }
{ "BeginsWith", MatchOptionCodes.BeginsWith + MatchOptionCodes.Contains },
{ "EndsWith", MatchOptionCodes.Contains + MatchOptionCodes.EndsWith },
{ "Complete", MatchOptionCodes.BeginsWith + MatchOptionCodes.Contains + MatchOptionCodes.EndsWith },
{ "Contains", MatchOptionCodes.Contains },
{ "IgnoreCase", MatchOptionCodes.IgnoreCase },
{ "Multiline", MatchOptionCodes.Multiline },
{ "FreeSpacing", MatchOptionCodes.FreeSpacing },
{ "DotAll", MatchOptionCodes.DotAll },
{ "NumberedSubMatches", MatchOptionCodes.NumberedSubMatches }
},
canConcatenateStronglyTyped: true);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
using Microsoft.PowerFx.Core.Utils;
using Microsoft.PowerFx.Interpreter.Localization;
using Microsoft.PowerFx.Types;
using static Microsoft.PowerFx.Core.Texl.Builtins.BaseMatchFunction;

namespace Microsoft.PowerFx.Functions
{
Expand Down Expand Up @@ -227,13 +228,13 @@ public Task<FormulaValue> InvokeAsync(FormulaValue[] args, CancellationToken can
index = inlineOptions.Length;
}

bool freeSpacing = options.Contains("x");
bool multiline = options.Contains("m");
bool ignoreCase = options.Contains("i");
bool dotAll = options.Contains("s");
bool matchStart = options.Contains("^");
bool matchEnd = options.Contains("$");
bool numberedSubMatches = options.Contains("N");
bool freeSpacing = options.Contains(MatchOptionCodes.FreeSpacing);
bool multiline = options.Contains(MatchOptionCodes.Multiline);
bool ignoreCase = options.Contains(MatchOptionCodes.IgnoreCase);
bool dotAll = options.Contains(MatchOptionCodes.DotAll);
bool matchStart = options.Contains(MatchOptionCodes.BeginsWith);
bool matchEnd = options.Contains(MatchOptionCodes.EndsWith);
bool numberedSubMatches = options.Contains(MatchOptionCodes.NumberedSubMatches);

// Can't add options ^ and $ too early as there may be freespacing comments, centralize the logic here and call subfunctions
string AlterStart()
Expand Down Expand Up @@ -331,8 +332,8 @@ string AlterEnd()
}
}

// multiline is not included as it is handled with the definitions of ^ and $ above
RegexOptions alteredOptions = RegexOptions.CultureInvariant |
(multiline ? RegexOptions.Multiline : 0) |
(ignoreCase ? RegexOptions.IgnoreCase : 0) |
(dotAll ? RegexOptions.Singleline : 0) |
(freeSpacing ? RegexOptions.IgnorePatternWhitespace : 0) |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,8 @@ Errors: Error 27-44: Regular expression must be a constant value.|Error 0-7: The
>> IsMatch("Hello 123 world", $"Hello {Sqrt(1)}{Sqrt(4)}{Sqrt(9)} world")
Errors: Error 27-69: Regular expression must be a constant value.|Error 0-7: The function 'IsMatch' has some invalid arguments.

>> IsMatch("Hello 123 world", $"Hello")
Errors: Error 27-35: Regular expression must be a constant value.|Error 0-7: The function 'IsMatch' has some invalid arguments.
>> IsMatch("Hello 123 world", $"Hello", MatchOptions.Contains)
true

>> IsMatch("Hello", "Hello", MatchOptions.IgnoreCase)
true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -214,15 +214,19 @@ Errors: Error 0-4: The function 'Text' has some invalid arguments.|Warning 15-37

// The thousands separator in the fi-FI locale is the no-break space (U+00A0)
>> Text(12345.6789, $"[$-fi-FI]#{Char(160)}##0.00", "en-US")
Error({Kind:ErrorKind.InvalidArgument})
Errors: Error 0-4: The function 'Text' has some invalid arguments.|Warning 17-47: Incorrect format specifier for 'Text'.

>> Text(12345.6789, $"[$-fi-FI]#{Char(160)}##0.00", "fi-FI")
Error({Kind:ErrorKind.InvalidArgument})
Errors: Error 0-4: The function 'Text' has some invalid arguments.|Warning 17-47: Incorrect format specifier for 'Text'.

// The thousands separator in the fr-FR locale is the narrow no-break space (U+202F)
>> Text(12345.6789, $"[$-fr-FR]#{ParseJSON("""\u202F""")}##0.00", "en-US")
Error({Kind:ErrorKind.InvalidArgument})

// The thousands separator in the fr-FR locale is the narrow no-break space (U+202F)
>> Text(12345.6789, $"[$-fr-FR]#{UniChar(8239)}##0.00", "en-US")
Errors: Error 0-4: The function 'Text' has some invalid arguments.|Warning 17-51: Incorrect format specifier for 'Text'.

>> Text(1234.5678, "[$-en-US]", "en-US")
Errors: Error 0-4: The function 'Text' has some invalid arguments.|Warning 16-27: Incorrect format specifier for 'Text'.

Expand Down

0 comments on commit 592c57f

Please sign in to comment.