aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Joe Banks <[email protected]>2025-05-29 00:44:01 +0100
committerGravatar Joe Banks <[email protected]>2025-05-29 00:44:01 +0100
commite96205d7968f87e70d02f96eaf14aa73def8e4c0 (patch)
tree36e5d912980df3960fbefcde9a8acebf13244468
parentDMARC get_dmarc_policy/1 does everything now (diff)
Parser should not fail for unrecognised tags, store them aside
-rw-r--r--src/dmarc_lexer.xrl18
-rw-r--r--src/dmarc_parser.yrl31
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]).