diff options
-rw-r--r-- | src/dmarc_lexer.xrl | 18 | ||||
-rw-r--r-- | src/dmarc_parser.yrl | 31 |
2 files changed, 35 insertions, 14 deletions
diff --git a/src/dmarc_lexer.xrl b/src/dmarc_lexer.xrl index 29bc778..77dadde 100644 --- a/src/dmarc_lexer.xrl +++ b/src/dmarc_lexer.xrl @@ -8,14 +8,14 @@ LOST_MAILTO = mailto Rules. -{KEY} : {token, {key, TokenLine, list_to_atom(TokenChars)}}. -{MAILTO_EMAIL} : {token, {mailto, TokenLine, TokenChars}}. -= : {token, {equals, TokenLine}}. -: : {token, {colon, TokenLine}}. -; : {token, {semicolon, TokenLine}}. -, : {token, {comma, TokenLine}}. -{LOST_MAILTO} : {error, invalid_mailto}. -{VALUE} : {token, {string, TokenLine, TokenChars}}. -{WHITESPACE}+ : skip_token. +{KEY} : {token, {key, TokenLine, list_to_atom(TokenChars)}}. +{MAILTO_EMAIL} : {token, {mailto, TokenLine, TokenChars}}. += : {token, {equals, TokenLine}}. +: : {token, {colon, TokenLine}}. +; : {token, {semicolon, TokenLine}}. +, : {token, {comma, TokenLine}}. +{LOST_MAILTO} : {error, invalid_mailto}. +{VALUE} : {token, {string, TokenLine, TokenChars}}. +{WHITESPACE}+ : skip_token. Erlang code. diff --git a/src/dmarc_parser.yrl b/src/dmarc_parser.yrl index c1f4e1d..14c375b 100644 --- a/src/dmarc_parser.yrl +++ b/src/dmarc_parser.yrl @@ -1,12 +1,14 @@ Nonterminals - record property_list property optional_semicolon value. + record property_list property optional_semicolon value invalid_property. Terminals key equals semicolon string comma colon mailto. Rootsymbol record. -record -> property_list optional_semicolon : '$1'. +record -> property_list optional_semicolon : + {Valid, Invalid} = separate_properties('$1'), + #{valid => maps:from_list(Valid), invalid => maps:from_list(Invalid)}. optional_semicolon -> semicolon : []. optional_semicolon -> '$empty' : []. @@ -14,8 +16,13 @@ optional_semicolon -> '$empty' : []. property_list -> property : ['$1']. property_list -> property property_list : ['$1' | '$2']. -property -> key equals value semicolon : {value('$1'), process_value(value('$1'), value_to_list('$3'))}. -property -> key equals value : {value('$1'), process_value(value('$1'), value_to_list('$3'))}. +property -> key equals value semicolon : {valid, {value('$1'), process_value(value('$1'), value_to_list('$3'))}}. +property -> key equals value : {valid, {value('$1'), process_value(value('$1'), value_to_list('$3'))}}. + +property -> invalid_property : {invalid, '$1'}. + +invalid_property -> string equals value semicolon : {value('$1'), value_to_list('$3')}. +invalid_property -> string equals value : {value('$1'), value_to_list('$3')}. value -> mailto : '$1'. value -> mailto comma value : join_values('$1', '$3'). @@ -23,7 +30,7 @@ value -> mailto comma value : join_values('$1', '$3'). value -> string : '$1'. value -> string colon value : join_values('$1', '$3'). -Expect 1. +Expect 2. Erlang code. @@ -45,3 +52,17 @@ process_value(_Key, [Value]) -> value(Value); process_value(_Key, Values) -> [value(V) || V <- Values]. + +separate_properties(Properties) -> + separate_properties(Properties, [], []). + +separate_properties([], ValidAcc, InvalidAcc) -> + {lists:reverse(ValidAcc), lists:reverse(InvalidAcc)}; +separate_properties([{valid, Property} | Rest], ValidAcc, InvalidAcc) -> + separate_properties(Rest, [Property | ValidAcc], InvalidAcc); +separate_properties([{invalid, {Key, Values}} | Rest], ValidAcc, InvalidAcc) -> + ProcessedValues = case Values of + [SingleValue] -> value(SingleValue); + MultipleValues -> [value(V) || V <- MultipleValues] + end, + separate_properties(Rest, ValidAcc, [{Key, ProcessedValues} | InvalidAcc]). |