public PathParserResult <Index> ParseIndex() { var state = _pos; try { try { var b = ParseBoolean(); return(PathParserResult <Index> .Success(new Index { Boolean = b.Result, Type = IndexType.Boolean })); } catch { } try { var h = ParseNodes(); return(PathParserResult <Index> .Success(new Index { Path = h.Result, Type = IndexType.Path })); } catch { } try { var str = ParseStringLiteral(); return(PathParserResult <Index> .Success(new Index { String = str.Result, Type = IndexType.String })); } catch { } var n = ParseNumber(); return(PathParserResult <Index> .Success(new Index { Number = n.Result, Type = IndexType.Number })); } catch (ParserException) { _pos = state; throw; } }
public PathParserResult <List <BindingPathNode> > ParseNodes() { var state = _pos; try { var fst = ParseNode(true); var list = new List <BindingPathNode> { fst.Result }; while (true) { try { ParseChar(x => x == '.'); } catch (ParserException) { return(PathParserResult <List <BindingPathNode> > .Success(list)); } var node = ParseNode(false); list.Add(node.Result); } } catch (ParserException) { _pos = state; throw; } }
public PathParserResult <string> ParseIdentifier() { var state = _pos; try { var first = ParseChar(x => char.IsLetter(x) || x == '_'); var sb = new StringBuilder(); sb.Append(first.Result); while (true) { try { var chr = ParseChar(x => char.IsLetterOrDigit(x) || x == '_'); sb.Append(chr.Result); } catch (ParserException) { break; } } return(PathParserResult <string> .Success(sb.ToString())); } catch (ParserException) { _pos = state; throw; } }
public PathParserResult <List <Index> > ParseIndices(bool failOnAbsence) { var state = _pos; try { try { ParseChar(x => x == '['); } catch (ParserException) { if (failOnAbsence) { throw; } return (PathParserResult <List <Index> > .Success( new List <Index>())); } var fst = ParseIndex(); var list = new List <Index> { fst.Result }; while (true) { try { ParseChar(x => x == ','); } catch (ParserException) { break; } var index = ParseIndex(); list.Add(index.Result); } ParseChar(x => x == ']'); return(PathParserResult <List <Index> > .Success(list)); } catch (ParserException) { _pos = state; throw; } }
public PathParserResult <BindingPathNode> ParseNode(bool first) { var state = _pos; try { string id; try { id = ParseIdentifier().Result; } catch (ParserException) { id = null; } List <Index> indices; try { indices = ParseIndices(id == null).Result; } catch { indices = null; } if ((indices == null && id == null) || (!first && id == null)) { throw new ParserException(); } return(PathParserResult <BindingPathNode> .Success(new BindingPathNode { Property = id, Indices = indices })); } catch (ParserException) { _pos = state; throw; } }
public PathParserResult <bool> ParseBoolean() { var state = _pos; try { var id = ParseIdentifier().Result; if (id == "true") { return(PathParserResult <bool> .Success(true)); } if (id == "false") { return(PathParserResult <bool> .Success(false)); } throw new ParserException(); } catch (ParserException) { _pos = state; throw; } }
public PathParserResult <char> ParseChar(Predicate <char> predicate) { var state = _pos; try { if (_pos == _input.Length) { throw new ParserException(); } var ch = _input[_pos++]; var succ = predicate(ch); if (!succ) { throw new ParserException(); } return(PathParserResult <char> .Success(ch)); } catch (ParserException) { _pos = state; throw; } }
public PathParserResult <string> ParseStringLiteral() { var state = _pos; try { var delim = ParseChar(x => x == '"' || x == '\'').Result; var str = new StringBuilder(); var escape = false; const string hexLetters = "abcdef"; Predicate <char> isHex = c => char.IsDigit(c) || hexLetters.IndexOf(char.ToLower(c)) > 0; while (true) { var chr = ParseChar(x => true).Result; if (escape) { switch (chr) { case '\\': str.Append('\\'); break; case '\'': str.Append('\''); break; case '"': str.Append('"'); break; case 'n': str.Append('\n'); break; case 'r': str.Append('\r'); break; case 't': str.Append('\t'); break; case 'x': var x1 = ParseChar(isHex); var x2 = ParseChar(isHex); str.Append((char)int.Parse($"{x1}{x2}", NumberStyles.HexNumber)); break; case 'u': var u1 = ParseChar(isHex); var u2 = ParseChar(isHex); var u3 = ParseChar(isHex); var u4 = ParseChar(isHex); str.Append((char)int.Parse($"{u1}{u2}{u3}{u4}", NumberStyles.HexNumber)); break; default: throw new ParserException(); } escape = false; } else if (chr == delim) { return(PathParserResult <string> .Success(str.ToString())); } else if (chr == '\\') { escape = true; } else { str.Append(chr); } } } catch (ParserException) { _pos = state; throw; } }
public PathParserResult <decimal> ParseNumber() { var state = _pos; try { var str = new StringBuilder(); try { ParseChar(x => x == '-'); str.Append('-'); } catch { } var hasDot = false; try { ParseChar(x => x == '.'); str.Append('.'); hasDot = true; while (true) { try { var chr = ParseChar(char.IsDigit); str.Append(chr.Result); } catch { break; } } goto exponentPart; } catch { } while (true) { try { var chr = ParseChar(char.IsDigit); str.Append(chr.Result); } catch { break; } } if (!hasDot) { try { ParseChar(x => x == '.'); str.Append('.'); while (true) { try { var chr = ParseChar(char.IsDigit); str.Append(chr.Result); } catch { break; } } } catch { } } exponentPart: try { ParseChar(x => x == 'e' || x == 'E'); str.Append('e'); try { ParseChar(x => x == '-'); str.Append('-'); } catch { } while (true) { try { var chr = ParseChar(char.IsDigit); str.Append(chr.Result); } catch { break; } } } catch { } decimal number; if (!decimal.TryParse(str.ToString(), NumberStyles.Float, CultureInfo.InvariantCulture, out number)) { throw new ParserException(); } return(PathParserResult <decimal> .Success(number)); } catch (ParserException) { _pos = state; throw; } }