Advertisement
Guest User

Untitled

a guest
Jun 19th, 2019
82
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 10.71 KB | None | 0 0
  1. #r "nuget:Theraot.Core/3.0.3"
  2.  
  3. // This file is for RoslynPad
  4.  
  5. using System;
  6. using System.Collections;
  7. using System.Collections.Generic;
  8. using System.Linq;
  9. using System.Text;
  10. using Theraot.Core;
  11.  
  12. public class ParseException : Exception
  13. {
  14. public ParseException(string message, string @string, int position, Pattern pattern)
  15. : base(message)
  16. {
  17. Pattern = pattern;
  18. String = @string;
  19. Position = position;
  20. }
  21.  
  22. public Pattern Pattern { get; }
  23.  
  24. public int Position { get; }
  25.  
  26. public string String { get; }
  27. }
  28.  
  29. public class Symbol : IEnumerable<Symbol>
  30. {
  31. public static readonly Symbol[] EmptySymbols = new Symbol[0];
  32.  
  33. public Symbol(Pattern pattern)
  34. {
  35. Pattern = pattern;
  36. }
  37.  
  38. public Pattern Pattern { get; }
  39.  
  40. public virtual IEnumerator<Symbol> GetEnumerator()
  41. {
  42. yield return this;
  43. }
  44.  
  45. IEnumerator IEnumerable.GetEnumerator()
  46. {
  47. return GetEnumerator();
  48. }
  49. }
  50.  
  51. public class TerminalSymbol : Symbol
  52. {
  53. public TerminalSymbol(Pattern pattern, string value)
  54. : base(pattern)
  55. {
  56. Value = value;
  57. }
  58.  
  59. public string Value { get; }
  60.  
  61. public override string ToString()
  62. {
  63. return Value;
  64. }
  65. }
  66.  
  67. public class CompositeSymbol : Symbol
  68. {
  69. public CompositeSymbol(Pattern pattern, IEnumerable<Symbol> symbols)
  70. : base(pattern)
  71. {
  72. Symbols = symbols;
  73. }
  74.  
  75. private IEnumerable<Symbol> Symbols { get; }
  76.  
  77. public override string ToString()
  78. {
  79. var builder = new StringBuilder();
  80. foreach (var symbol in Symbols)
  81. {
  82. builder.Append(symbol);
  83. }
  84. return builder.ToString();
  85. }
  86.  
  87. public override IEnumerator<Symbol> GetEnumerator()
  88. {
  89. return GraphHelper.ExploreBreadthFirstGraph(this, symbol => symbol is CompositeSymbol compositeSymbol ? compositeSymbol.Symbols : EmptySymbols, EqualityComparer<Symbol>.Default).GetEnumerator();
  90. }
  91. }
  92.  
  93. public sealed class Pattern
  94. {
  95. private Func<StringProcessor, Symbol> _parse;
  96.  
  97. private Pattern(string name)
  98. {
  99. Name = name;
  100. _parse = _ => new CompositeSymbol(this, Symbol.EmptySymbols);
  101. }
  102.  
  103. public string Name { get; }
  104.  
  105. public static Pattern Conjunction(params Pattern[] patterns)
  106. {
  107. return Conjunction("(" + string.Join(" + ", from subPattern in patterns select subPattern.Name) + ")", patterns);
  108. }
  109.  
  110. public static Pattern Conjunction(string name, params Pattern[] patterns)
  111. {
  112. var pattern = new Pattern(name);
  113. pattern._parse = processor => new CompositeSymbol(pattern, (from subPattern in patterns select subPattern.Parse(processor)).ToArray());
  114. return pattern;
  115. }
  116.  
  117. public static Pattern Custom(string name, Func<StringProcessor, string> callback)
  118. {
  119. if (callback == null)
  120. {
  121. throw new ArgumentNullException(nameof(callback));
  122. }
  123. var pattern = new Pattern(name);
  124. pattern._parse = processor =>
  125. {
  126. var position = processor.Position;
  127. var greedy = processor.Greedy;
  128. string? result = null;
  129. try
  130. {
  131. result = callback(processor);
  132. }
  133. finally
  134. {
  135. if (result == null)
  136. {
  137. processor.Position = position;
  138. processor.Greedy = greedy;
  139. throw new ParseException($"Expected {name}", processor.String, processor.Position, pattern);
  140. }
  141. }
  142. return new TerminalSymbol(pattern, result);
  143. };
  144. return pattern;
  145. }
  146.  
  147. public static Pattern Disjunction(params Pattern[] patterns)
  148. {
  149. return Disjunction("(" + string.Join(" | ", from subPattern in patterns select subPattern.Name) + ")", patterns);
  150. }
  151.  
  152. public static Pattern Disjunction(string name, params Pattern[] patterns)
  153. {
  154. var pattern = new Pattern(name);
  155. pattern._parse = processor =>
  156. {
  157. var position = processor.Position;
  158. var greedy = processor.Greedy;
  159. foreach (var subPattern in patterns)
  160. {
  161. Symbol? result = null;
  162. try
  163. {
  164. result = subPattern.Parse(processor);
  165. }
  166. catch (ParseException exception)
  167. {
  168. // swallow
  169. Theraot.No.Op(exception);
  170. }
  171. finally
  172. {
  173. if (result == null)
  174. {
  175. processor.Position = position;
  176. processor.Greedy = greedy;
  177. }
  178. }
  179. if (result != null)
  180. {
  181. return new CompositeSymbol(pattern, new[] { result });
  182. }
  183. }
  184. throw new ParseException($"Expected {name}", processor.String, processor.Position, pattern);
  185. };
  186. return pattern;
  187. }
  188.  
  189. public static Pattern Empty()
  190. {
  191. return Empty(string.Empty);
  192. }
  193.  
  194. public static Pattern Empty(string name)
  195. {
  196. return new Pattern(name);
  197. }
  198.  
  199. public static Pattern Literal(string literal)
  200. {
  201. return Literal("\"" + literal.Replace("\"", "\\\"") + "\"", literal);
  202. }
  203.  
  204. public static Pattern Literal(string name, string literal)
  205. {
  206. var pattern = new Pattern(name);
  207. pattern._parse = processor =>
  208. {
  209. if (processor.Read(literal))
  210. {
  211. return new TerminalSymbol(pattern, literal);
  212. }
  213. throw new ParseException($"Expected {name} ({literal})", processor.String, processor.Position, pattern);
  214. };
  215. return pattern;
  216. }
  217.  
  218. public static Pattern Literal(char literal)
  219. {
  220. return Literal("\"" + (literal == '"' ? "\\\"" : literal.ToString()) + "\"", literal);
  221. }
  222.  
  223. public static Pattern Literal(string name, char literal)
  224. {
  225. var pattern = new Pattern(name);
  226. pattern._parse = processor =>
  227. {
  228. if (processor.Read(literal))
  229. {
  230. return new TerminalSymbol(pattern, literal.ToString());
  231. }
  232. throw new ParseException($"Expected {name}", processor.String, processor.Position, pattern);
  233. };
  234. return pattern;
  235. }
  236.  
  237. public static Pattern Optional(Pattern subPattern)
  238. {
  239. return Optional("[" + subPattern.Name + "]", subPattern);
  240. }
  241.  
  242. public static Pattern Optional(string name, Pattern subPattern)
  243. {
  244. var pattern = new Pattern(name);
  245. pattern._parse = processor =>
  246. {
  247. var position = processor.Position;
  248. var greedy = processor.Greedy;
  249. try
  250. {
  251. return new CompositeSymbol(pattern, new[] { subPattern.Parse(processor) });
  252. }
  253. catch (ParseException)
  254. {
  255. processor.Position = position;
  256. processor.Greedy = greedy;
  257. return new CompositeSymbol(pattern, Symbol.EmptySymbols);
  258. }
  259. };
  260. return pattern;
  261. }
  262.  
  263. public static Pattern OptionalRepetition(Pattern subPattern)
  264. {
  265. return OptionalRepetition(subPattern.Name + "*", subPattern);
  266. }
  267.  
  268. public static Pattern OptionalRepetition(string name, Pattern subPattern)
  269. {
  270. var pattern = new Pattern(name);
  271. pattern._parse = processor =>
  272. {
  273. var symbols = new List<Symbol>();
  274. while (!processor.EndOfString)
  275. {
  276. var position = processor.Position;
  277. var greedy = processor.Greedy;
  278. Symbol? result = null;
  279. try
  280. {
  281. result = subPattern.Parse(processor);
  282. }
  283. catch (ParseException exception)
  284. {
  285. // swallow
  286. Theraot.No.Op(exception);
  287. }
  288. finally
  289. {
  290. if (result == null)
  291. {
  292. processor.Position = position;
  293. processor.Greedy = greedy;
  294. }
  295. }
  296. if (result == null)
  297. {
  298. break;
  299. }
  300. symbols.Add(result);
  301. }
  302. return new CompositeSymbol(pattern, symbols);
  303. };
  304. return pattern;
  305. }
  306.  
  307. public static Pattern Repetition(Pattern subPattern)
  308. {
  309. return Repetition(subPattern.Name + "+", subPattern);
  310. }
  311.  
  312. public static Pattern Repetition(string name, Pattern subPattern)
  313. {
  314. var pattern = new Pattern(name);
  315. pattern._parse = processor =>
  316. {
  317. var symbols = new List<Symbol>();
  318. while (!processor.EndOfString)
  319. {
  320. var position = processor.Position;
  321. var greedy = processor.Greedy;
  322. Symbol? result = null;
  323. try
  324. {
  325. result = subPattern.Parse(processor);
  326. }
  327. catch (ParseException exception)
  328. {
  329. // swallow
  330. Theraot.No.Op(exception);
  331. }
  332. finally
  333. {
  334. if (result == null)
  335. {
  336. processor.Position = position;
  337. processor.Greedy = greedy;
  338. }
  339. }
  340. if (result == null)
  341. {
  342. break;
  343. }
  344. symbols.Add(result);
  345. }
  346. if (symbols.Count == 0)
  347. {
  348. throw new ParseException($"Expected {pattern.Name}", processor.String, processor.Position, pattern);
  349. }
  350. return new CompositeSymbol(pattern, symbols);
  351. };
  352. return pattern;
  353. }
  354.  
  355. public Symbol Parse(string str)
  356. {
  357. var processor = new StringProcessor(str);
  358. return Parse(processor);
  359. }
  360.  
  361. private Symbol Parse(StringProcessor processor)
  362. {
  363. return _parse?.Invoke(processor);
  364. }
  365. }
  366.  
  367. const string input = "\"hello \" + \"world \" + \" + \" + \"hello\"";
  368.  
  369. var quoteSymbol = Pattern.Literal("QuoteSymbol", '"');
  370. var nonQuoteSymbol = Pattern.Custom("NonQuoteSymbol", s => s.ReadUntil('"'));
  371. var String = Pattern.Conjunction("String", quoteSymbol, nonQuoteSymbol, quoteSymbol);
  372.  
  373. var whiteSpace = Pattern.Custom("WhiteSpace", s => s.ReadWhile(char.IsWhiteSpace));
  374. var plusSymbol = Pattern.Literal("PlusSymbol", '+');
  375. var document = Pattern.Repetition(Pattern.Conjunction(whiteSpace, String, whiteSpace, plusSymbol));
  376.  
  377. var results = from symbol in document.Parse(input) where symbol.Pattern == String select symbol.ToString();
  378.  
  379. foreach (var v in results.ToArray())
  380. {
  381. Console.WriteLine(v);
  382. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement