Skip to content
This repository has been archived by the owner on Dec 22, 2023. It is now read-only.

Commit

Permalink
Fix trailing value handling
Browse files Browse the repository at this point in the history
Allow for tag couples to hold values for trailing value parsing

Simplify negative value detection
  • Loading branch information
louistakepillz committed Apr 2, 2015
1 parent 3befeb4 commit 8733649
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 52 deletions.
118 changes: 83 additions & 35 deletions ArgumentParser/Parser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Reflection;
Expand Down Expand Up @@ -364,18 +365,22 @@ public static IEnumerable<IPairable> GetParameters(String input, ParserOptions o
RegexOptions.Singleline);

var matchElements =
matches.OfType<Match>().SelectMany(x => x.Groups["tag"].Captures
.OfType<Capture>()
.GroupBy(c => c.Value, (c, e) => new RawParameter(
prefix: x.Groups["prefix"].Value,
tag: c,
value: x.Groups["value"].Success
? (options.Detokenize
? DetokenizeValue(options, x.Groups["value"].Value)
: x.Groups["value"].Value)
: null,
count: e.Count())))
.ToArray();
matches.OfType<Match>().SelectMany(x =>
{
var captures = x.Groups["tag"].Captures.OfType<Capture>().ToArray();
return captures
.GroupBy(c => c.Value, (c, e) => new RawParameter(
prefix: x.Groups["prefix"].Value,
tag: c,
value: x.Groups["value"].Success
? (options.Detokenize
? DetokenizeValue(options, x.Groups["value"].Value)
: x.Groups["value"].Value)
: null,
count: e.Count(),
totalCount: captures.Length));
}).ToArray();

List<UnboundValue> unboundValues = new List<UnboundValue>();

Expand All @@ -388,23 +393,14 @@ public static IEnumerable<IPairable> GetParameters(String input, ParserOptions o
{
var parameters = p.ToArray();
var flag = a as IFlag;
String[][] trailingValues;
if (flag != null)
return GetFlagPair(options, flag, parameters);
if (a.AllowCompositeValues)
return new ParameterPair(a, parameters.Select(x => x.Value == null ? null : ParseValue(options, a, x.Value)));
var values = parameters
.Select(x => x.Value == null
? null
: x.Value.Split(new[] { '\x20' }, StringSplitOptions.RemoveEmptyEntries))
.ToArray();
var pair = new ParameterPair(a, values.Select(x => ParseValue(options, a, x.First())));
var pair = flag != null
? GetFlagPair(options, flag, parameters, out trailingValues)
: GetParameterPair(options, a, parameters, out trailingValues);
unboundValues.AddRange(values
.Where(x => x.Any())
unboundValues.AddRange(trailingValues
.Where(x => x != null && x.Any())
.SelectMany(x => x.Skip(1))
.Select(x => new UnboundValue(pair, x)));
Expand Down Expand Up @@ -462,24 +458,59 @@ private static String GetParameterPattern(ParameterTokenStyle tokenStyle)
}
}

private static FlagPair GetFlagPair(ParserOptions options, IFlag flag, RawParameter[] parameters)
private static ParameterPair GetParameterPair(ParserOptions options, IArgument argument, RawParameter[] parameters, out String[][] trailingValues)
{
if (argument.AllowCompositeValues)
{
trailingValues = new String[0][];
return new ParameterPair(
argument: argument,
values: parameters
.Where(x => x != null)
.Select(x => x.Value == null || x.TotalCount > 1
? null
: ParseValue(options, argument, x.Value)));
}

trailingValues = GetCompositeValueParts(parameters);

return new ParameterPair(
argument: argument,
values: trailingValues.Select(x => x == null ? null : ParseValue(options, argument, x.First())));
}

private static FlagPair GetFlagPair(ParserOptions options, IFlag flag, RawParameter[] parameters, out String[][] trailingValues)
{
if (!parameters.Any())
{
trailingValues = new String[0][];
return new FlagPair(flag, new Object[0], 0);
}

bool isBoolean = flag.Type == typeof (Boolean);

var values = parameters.Select(x => new
{
Parameter = x,
Value = x.Value == null ? 1 : ValueConverter.GetFlagValue(options.Culture, isBoolean, x.Value)
}).ToArray();
var values = parameters.Where(x => x != null).Select(x => new
{
Parameter = x,
Value = x.Value == null || x.TotalCount > 1
? 1
: ValueConverter.GetFlagValue(options.Culture, isBoolean, x.Value)
}).ToArray();

// Skip special flag logic for booleans, as such operations can not be done on single bits.
if (isBoolean)
{
bool? defaultValue = flag.DefaultValue as Boolean?;
bool invertDefault = defaultValue.HasValue && defaultValue.Value;
return new FlagPair(flag, values.Select(x => (Object) x.Value), values.Last().Value == 0 ^ invertDefault ? 1 : 0);

var flagPair = new FlagPair(
argument: flag,
values: values.Select(x => (Object) x.Value),
count: values.Last().Value == 0 ^ invertDefault ? 1 : 0);

trailingValues = flag.AllowCompositeValues ? new String[0][] : GetCompositeValueParts(parameters);

return flagPair;
}

bool aggregateImplicit = (flag.Options & FlagOptions.AggregateImplicit) != 0,
Expand Down Expand Up @@ -526,7 +557,13 @@ private static FlagPair GetFlagPair(ParserOptions options, IFlag flag, RawParame
explicitCount = bitFieldExplicit ? GetFlagValue(explicitParameter.Parameter.Count) : explicitParameter.Parameter.Count;
}

return new FlagPair(flag, values.Select(x => (Object) x.Value), implicitCount + explicitCount);
{
var flagPair = new FlagPair(flag, values.Select(x => (Object) x.Value), implicitCount + explicitCount);

trailingValues = flag.AllowCompositeValues ? new String[0][] : GetCompositeValueParts(parameters);

return flagPair;
}
}

private static Int32 GetFlagValue(Int32 value)
Expand All @@ -537,6 +574,17 @@ private static Int32 GetFlagValue(Int32 value)
return 1 << (value - 1);
}

private static String[][] GetCompositeValueParts(RawParameter[] parameters)
{
var values = parameters
.Where(x => x != null)
.Select(x => x.Value == null || x.TotalCount > 1
? null
: x.Value.Split(new[] { '\x20' }, StringSplitOptions.RemoveEmptyEntries))
.ToArray();
return values;
}

private static String DetokenizeValue(ParserOptions options, String value)
{
try
Expand Down
25 changes: 12 additions & 13 deletions ArgumentParser/Patterns/POSIXParameterPattern.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,29 +28,28 @@ public static partial class Parser
(
(?<prefix>--)
(
(?<tag>(?!-)[\-\w-[\d]]+)\s+
(?<value>
(
(?<tag>(?!-)\w+)
(
\s+
(?<value>
("" (?> \\. | [^""])* "")|
(' (?> \\. | [^'])* ')|
(?> \\. | [^\-""'] | (?<!\s) \d+ )*|
(?> \-\d [\,\.\d]* )
(?> \-\d [\,\.\w]* )
)
)|
(?<tag>(?!-)[\w\-]+)
)?
)|
(?<prefix>-)
(?<tag>\w)\s+
(?<value>
(
(?<tag>\w)+
(
\s+
(?<value>
("" (?> \\. | [^""])* "")|
(' (?> \\. | [^'])* ')|
(?> \\. | [^\-""'] | (?<!\s) \d+ )*|
(?> \-\d[\,\.\d]* )
(?> \-\d [\,\.\w]* )
)
)|
(?<prefix>-)
(?<tag>\w)+
)?
)(?=\s|$)";
#else
private const String UNIX_PARAMETERS_PATTERN = @"(?<=^|\s)((?<prefix>--)((?<tag>(?!-)[\-\w-[\d]]+)\s+(?<value>((""(?>\\.|[^""])*"")|('(?>\\.|[^'])*')|(?>\\.|[^\-""']|(?<!\s)\d+)*|(?>\-\d[\,\.\d]*)))|(?<tag>(?!-)[\w\-]+))|(?<prefix>-)(?<tag>\w)\s+(?<value>((""(?>\\.|[^""])*"")|('(?>\\.|[^'])*')|(?>\\.|[^\-""']|(?<!\s)\d+)*|(?>\-\d[\,\.\d]*)))|(?<prefix>-)(?<tag>\w)+)(?=\s|$)";
Expand Down
13 changes: 10 additions & 3 deletions ArgumentParser/RawParameter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,12 @@ public RawParameter(String prefix, String tag, String value)
/// <param name="prefix">The prefix of the parameter.</param>
/// <param name="tag">The tag that defines the parameter.</param>
/// <param name="value">The value of the parameter.</param>
/// <param name="count">The tag couple count.</param>
public RawParameter(String prefix, String tag, String value, Int32 count)
/// <param name="totalCount">The total tag couple count.</param>
/// <param name="count">The count of identical tags.</param>
public RawParameter(String prefix, String tag, String value, Int32 totalCount, Int32 count)
: this(prefix, tag, value)
{
this.TotalCount = totalCount;
this.Count = count;
}

Expand All @@ -56,10 +58,15 @@ public RawParameter(String prefix, String tag, String value, Int32 count)
public Key Key { get; private set; }

/// <summary>
/// Gets the tag couple count.
/// Gets the count of identical tags within the same couple.
/// </summary>
public Int32 Count { get; private set; }

/// <summary>
/// Gets the total tag couple count.
/// </summary>
public Int32 TotalCount { get; private set; }

/// <summary>
/// Gets the value of the parameter.
/// </summary>
Expand Down
2 changes: 1 addition & 1 deletion ArgumentParserTest/ContextTestUnit.cs
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ public void Init(String[] verbs)

public void HandleParameter(RawParameter parameter)
{
Debug.WriteLine("{0} #{1}: \"{2}\"", parameter.Key, parameter.Count, parameter.Value);
Debug.WriteLine("{0} #{1}: \"{2}\" (Compound: {3})", parameter.Key, parameter.Count, parameter.Value, parameter.TotalCount > 1);
}

public void HandleValue(UnboundValue value)
Expand Down

0 comments on commit 8733649

Please sign in to comment.