Skip to content

Instantly share code, notes, and snippets.

@agross
Created September 14, 2010 19:51
Show Gist options
  • Save agross/579654 to your computer and use it in GitHub Desktop.
Save agross/579654 to your computer and use it in GitHub Desktop.
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