Created
September 14, 2010 19:51
-
-
Save agross/579654 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using Magnum.CommandLineParser; | |
using Magnum.Monads.Parser; | |
using SearchQueryParser; | |
namespace ParserCombinator | |
{ | |
internal class Program | |
{ | |
static void Main(string[] args) | |
{ | |
Parse("in:h 123, in:h 123,"); | |
Parse("in:h 123, in:h 123"); | |
Parse("in:h 123, in:hans, name:peter-pan öäß, #blah"); | |
Parse("in:h 123, in:hans, name:peter-pan öäß, #blah, bla"); | |
Parse("in:h 123, in:hans, name:peter-pan öäß, #blah, #bla"); | |
Parse("in:h #123 in:hans name:peter-pan öäß #blah"); | |
Parse("in:h #123 in:hans name:peter-pan öäß,#blah"); | |
Parse(" in:h.123,in:hans jsdfg,name:peter-pan öäß,#blah "); | |
Parse("abc \"sdl kjd\" s:dl ök_sd"); | |
Parse("abc \"sdl #kjd\" s:dl ök_sd"); | |
Console.ReadKey(); | |
} | |
static void Parse(string line) | |
{ | |
Console.WriteLine("\nQUERY: " + line); | |
CreateCommands(line); | |
} | |
public static void CreateCommands(string query) | |
{ | |
var cmd = new MonadicSearchQueryParser().Parse(query).ToArray(); | |
foreach (var element in cmd) | |
{ | |
Console.WriteLine("{0}", element); | |
} | |
} | |
} | |
} | |
namespace SearchQueryParser | |
{ | |
public abstract class TextSearchQueryParser<TInput> : | |
AbstractCharacterParser<TInput> | |
{ | |
protected TextSearchQueryParser() | |
{ | |
Whitespace = Rep(Char(',').Or(Char(' ').Or(Char('\t').Or(Char('\n')).Or(Char('\r'))))); | |
Key = from c in Char(char.IsLetter) | |
from cs in Rep(Char(char.IsLetterOrDigit)) | |
from eq in Char(':') | |
select cs.Aggregate(c.ToString(), (s, ch) => s + ch); | |
Value = from symbol in Rep(Char(x => x != ',')) | |
select symbol.Aggregate("", (s, ch) => s + ch); | |
Definition = | |
from ws in Whitespace | |
from key in Key | |
from value in Value | |
select DefinitionElement.New(key, value); | |
Switch = | |
from ws in Whitespace | |
from c in Char('#') | |
from arg in Rep(Char(char.IsLetterOrDigit)) | |
select SwitchElement.New(arg.Aggregate("", (s, ch) => s + ch)); | |
Unknown = from w in Whitespace | |
from rest in Rep(Char(x => true)) | |
where rest.Length != 0 | |
select UnknownElement.New(rest.Aggregate("", (s, ch) => s + ch)); | |
All = | |
(from element in Definition select element) | |
.Or(from element in Switch select element) | |
.Or(from element in Unknown select element); | |
} | |
public Parser<TInput, ICommandLineElement> Unknown | |
{ | |
get; | |
private set; | |
} | |
public Parser<TInput, char[]> Whitespace | |
{ | |
get; | |
private set; | |
} | |
public Parser<TInput, string> Key | |
{ | |
get; | |
private set; | |
} | |
public Parser<TInput, string> Value | |
{ | |
get; | |
private set; | |
} | |
public Parser<TInput, ICommandLineElement> Definition | |
{ | |
get; | |
private set; | |
} | |
public Parser<TInput, ICommandLineElement> Switch | |
{ | |
get; | |
private set; | |
} | |
public Parser<TInput, ICommandLineElement> All | |
{ | |
get; | |
private set; | |
} | |
} | |
public class UnknownElement : ICommandLineElement | |
{ | |
readonly string _unknown; | |
UnknownElement(string unknown) | |
{ | |
_unknown = unknown; | |
} | |
public static ICommandLineElement New(string unknown) | |
{ | |
return new UnknownElement(unknown); | |
} | |
public override string ToString() | |
{ | |
return "UNKNOWN: " + _unknown; | |
} | |
} | |
public class StringQueryParser : | |
TextSearchQueryParser<string> | |
{ | |
public override Parser<string, char> AnyChar | |
{ | |
get { return input => input.Length > 0 ? new Result<string, char>(input[0], input.Substring(1)) : null; } | |
} | |
} | |
public class MonadicSearchQueryParser : | |
ICommandLineParser | |
{ | |
public IEnumerable<ICommandLineElement> Parse(string commandLine) | |
{ | |
var parser = new StringQueryParser(); | |
Result<string, ICommandLineElement> result = parser.All(commandLine); | |
while (result != null) | |
{ | |
yield return result.Value; | |
result = parser.All(result.Rest); | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment