rfc2822.treetop - mail-2.5.4 Documentation

module Mail

    grammar RFC2822

      include RFC2822Obsolete

      rule ALPHA
        [a-zA-Z]
      end

      rule DIGIT
        [0-9]
      end

      rule DQUOTE
        '"'
      end

      rule LF
        "\n"
      end

      rule CR
        "\r"
      end

      rule CRLF
        "\r\n"
      end

      rule WSP
        [\x09\x20]
      end

      rule FWS    # Folding white space
        (WSP* CRLF WSP+) / (CRLF WSP+) / obs_FWS
      end

      rule CFWS
        (FWS* comment)* FWS?
      end

      rule NO_WS_CTL
        [\x01-\x08]   /         # US-ASCII control characters
        [\x0B-\x0C]   /         #  that do not include the
        [\x0E-\x1F]   /         #  carriage return, line feed,
        [\x7f]                  #  and white space characters
      end

      rule specials
        "(" / ")" /     # Special characters used in
        "<" / ">" /     #  other parts of the syntax
        "[" / "]" /
        ":" / ";" /
        "@" / '\' /
        "," / "." /
        DQUOTE
      end

      rule ctext
        NO_WS_CTL   /    # Non white space controls
        [\x21-\x27] /    # The rest of the US-ASCII
        [\x2a-\x5b] /    #  characters not including "(",
        [\x5d-\x7e]      #  ")", or "\"
      end

      rule ccontent
        ctext / quoted_pair / comment
      end

      rule comment
        "(" ( FWS? ccontent )* FWS? ")"
      end

      rule atext
        ALPHA / DIGIT / # Any character except controls,
        "!" / "#" /     #  SP, and specials.
        "$" / "%" /     #  Used for atoms
        "&" / "'" /
        "*" / "+" /
        "-" / "/" /
        "=" / "?" /
        "^" / "_" /
        "`" / "{" /
        "|" / "}" /
        "~"
      end

      rule mtext
        (atext / ".")+
      end

      rule atom
        CFWS? atext+ CFWS?
      end

      rule dot_atom
        CFWS? dot_atom_text CFWS?
      end

      rule local_dot_atom
        CFWS? local_dot_atom_text CFWS?
      end

      rule message_id_text
        mtext+
      end

      rule dot_atom_text
        (domain_text "."?)+
      end

      rule local_dot_atom_text
        ("."* domain_text "."*)+
      end

      rule domain_text
        (DQUOTE (FWS? quoted_domain)+ FWS? DQUOTE) / atext+
      end

      rule quoted_domain
        qdcontent / "\\" text
      end

      rule qdcontent
        NO_WS_CTL /     # Non white space controls
        [\x21] /        # The rest of the US-ASCII
        [\x23-\x45] /   # characters not including "\"
        [\x47-\x5b] /   # or the "." or the
        [\x5d-\x7e]     # double quote character
      end

      rule phrase
        obs_phrase / word+
      end

      rule word
        atom / quoted_string
      end

      rule phrase_list
        first_phrase:phrase other_phrases:("," FWS* phrase_value:phrase)*
      end

      rule domain_literal
        CFWS? "[" (FWS? dcontent)* FWS? "]" CFWS?
      end

      rule dcontent
        dtext / quoted_pair
      end

      rule dtext
        NO_WS_CTL    /  # Non white space controls
        [\x21-\x5a]  /  # The rest of the US-ASCII characters
        [\x5e-\x7e]     #  not including "[", "]", or "\"
      end

      rule angle_addr
        CFWS? "<" addr_spec ">" CFWS? / obs_angle_addr
      end

      rule addr_spec
        (local_part "@" domain) / local_part
      end

      rule local_part
        local_dot_atom / quoted_string / obs_local_part
      end

      rule domain
        dot_atom / domain_literal / obs_domain
      end

      rule group
        group_name:display_name ":" group_list:(mailbox_list_group / CFWS)? ";" CFWS?
      end

      rule mailbox_list_group
        mailbox_list {
          def addresses
            [first_addr] + other_addr.elements.map { |o| o.addr_value }
          end
        }
      end

      rule quoted_string
        CFWS? DQUOTE quoted_content:(FWS? qcontent)* FWS? DQUOTE CFWS?
      end

      rule qcontent
        qtext / quoted_pair
      end

      rule quoted_pair
        ("\\" text) / obs_qp
      end

      rule qtext
        NO_WS_CTL /     # Non white space controls
        [\x21] /        # The rest of the US-ASCII
        [\x23-\x5b] /   #  characters not including "\"
        [\x5d-\x7e]     #  or the quote character
      end

      rule text
        [\x01-\x09]     /       # Characters excluding CR and LF
        [\x0b-\x0c]     /
        [\x0e-\x7e]     /
        obs_text
      end

      rule display_name
        phrase
      end

      rule name_addr
        display_name angle_addr / angle_addr
      end

      rule mailbox_list
        (first_addr:mailbox other_addr:(("," / ";") addr_value:mailbox)*) / obs_mbox_list
      end

      rule mailbox
        (name_addr / addr_spec) {
          def dig_comments(comments, elements)
            elements.each { |elem|
              if elem.respond_to?(:comment)
                comments << elem.comment
              end
              dig_comments(comments, elem.elements) if elem.elements
             }
          end

          def comments
            comments = []
            dig_comments(comments, elements)
            comments
          end
        }
      end

      rule address
        group {

          def dig_comments(comments, elements)
            elements.each { |elem|
              if elem.respond_to?(:comment)
                comments << elem.comment
              end
              dig_comments(comments, elem.elements) if elem.elements
             }
          end

          def comments
            comments = []
            dig_comments(comments, elements)
            comments
          end

        } /
        mailbox
      end

      rule address_list
        first_addr:address? other_addr:(FWS* ("," / ";") FWS* addr_value:address?)*
      end

      rule date_time
        ( day_of_week ",")? date FWS time CFWS?
      end

      rule day_of_week
        (FWS? day_name) / obs_day_of_week
      end

      rule day_name
        "Mon" / "Tue" / "Wed" / "Thu" /
        "Fri" / "Sat" / "Sun"
      end

      rule date
        day month year
      end

      rule year
        DIGIT DIGIT DIGIT DIGIT / obs_year
      end

      rule month
        (FWS month_name FWS) / obs_month
      end

      rule month_name
        "Jan" / "Feb" / "Mar" / "Apr" /
        "May" / "Jun" / "Jul" / "Aug" /
        "Sep" / "Oct" / "Nov" / "Dec"
      end

      rule day
        (FWS? DIGIT DIGIT?) / obs_day
      end

      rule time
        time_of_day FWS zone
      end

      rule time_of_day
        hour ":" minute ( ":" second )?
      end

      rule hour
        DIGIT DIGIT / obs_hour
      end

      rule minute
        DIGIT DIGIT / obs_minute
      end

      rule second
        DIGIT DIGIT / obs_second
      end

      rule zone
        (( "+" / "-" ) DIGIT DIGIT DIGIT DIGIT) / obs_zone
      end

      rule return
        path CRLF
      end

      rule path
        ((CFWS)? "<" ((CFWS)? / addr_spec) ">" (CFWS)?) / obs_path
      end

      rule received
        name_val_list ";" date_time CRLF
      end

      rule name_val_list
        (CFWS)? (name_val_pair (CFWS name_val_pair)*)?
      end

      rule name_val_pair
        item_name CFWS item_value
      end

      rule item_name
        ALPHA (("-")? (ALPHA / DIGIT))*
      end

      rule item_value
        (angle_addr)+ / addr_spec / atom / domain / msg_id
      end

      rule message_ids
        first_msg_id:msg_id other_msg_ids:( CFWS msg_id_value:msg_id )*
      end

      rule msg_id
        (CFWS)? "<" msg_id_value ">" (CFWS)?
      end

      rule msg_id_value
        id_left "@" id_right
      end

      rule id_left
        message_id_text / no_fold_quote / obs_id_left
      end

      rule id_right
        msg_id_dot_atom_text / no_fold_literal / obs_id_right
      end

      rule msg_id_dot_atom_text
        (msg_id_domain_text "."?)+
      end

      rule msg_id_domain_text
        (DQUOTE (FWS? quoted_domain)+ FWS? DQUOTE) / msg_id_atext+
      end

      rule msg_id_atext
        ALPHA / DIGIT / # Any character except controls,
        "!" / "#" /     #  SP, and specials.
        "$" / "%" /     #  Used for atoms
        "&" / "'" /
        "*" / "+" /
        "-" / "/" /
        "=" / "?" /
        "^" / "_" /
        "`" / "{" /
        "|" / "}" /
        "~" / "@"
      end

      rule no_fold_quote
        DQUOTE (qtext / quoted_pair)+ DQUOTE
      end

      rule no_fold_literal
        "[" (dtext / quoted_pair)+ "]"
      end

    end

end