public static bool TryParseStreetAddress(string input, out StreetAddressSyntaxNode result) { var tokens = Tokenizer.Tokenize(input).Reverse().ToImmutableArray(); var state = new ParserState(tokens); var success = TryParseStreetAddress(ref state, out var syntax) && state.Current.IsNone; result = success ? syntax : null; return(success); }
private static bool TryParseStreetAddress(ref ParserState state, out StreetAddressSyntaxNode result) { result = default; var snapshot = state; TryParseSecondaryAddress(ref state, out var secondaryAddress); if (!TryParseSecondaryAddress(ref state, out _)) { var gotPostDirectional = TryParseDirectional(ref state, out var postDirectional); var gotSuffix = TryParseStreetSuffix(ref state, out var suffix); var primaryNameTokens = state.Tokens.Skip(state.Index).ToImmutableArray(); state = new ParserState(state.Tokens, state.Tokens.Length); if (TryParseFromEnd <RangeSyntaxNode>(ref primaryNameTokens, out var addressNumber, TryParseRange) && addressNumber.Components.Any(c => c.IsNumeric)) { var gotPreDirectional = TryParseFromEnd <DirectionalSyntaxNode>(ref primaryNameTokens, out var preDirectional, TryParseDirectional); primaryNameTokens = primaryNameTokens.Reverse().ToImmutableArray(); if (primaryNameTokens.All(t => t.IsWhiteSpace)) { if (gotSuffix && !gotPreDirectional) { primaryNameTokens = suffix.Tokens.ToImmutableArray(); suffix = null; } else if (gotPostDirectional) { primaryNameTokens = postDirectional.Tokens.ToImmutableArray(); postDirectional = null; } else if (gotPreDirectional) { primaryNameTokens = preDirectional.Tokens.ToImmutableArray(); preDirectional = null; } } if (primaryNameTokens.Length >= 3) { var token0 = primaryNameTokens[0]; var token2 = primaryNameTokens[2]; if (token0.Matches("CO") || token0.Matches("CTY") || token0.Matches("COUNTY")) { if (token2.Matches("RD") || token2.Matches("ROAD")) { primaryNameTokens = primaryNameTokens .SetItem(0, token0.WithValue("COUNTY")) .SetItem(2, token0.WithValue("ROAD")); } } } if (!primaryNameTokens.IsEmpty) { result = new StreetAddressSyntaxNode( addressNumber, preDirectional, primaryNameTokens, suffix, postDirectional, secondaryAddress); return(true); } } } state = snapshot; return(false); }