1 6 package tests.jfun.parsec.rfc822; 7 import jfun.parsec.Map; 8 import jfun.parsec.Map2; 9 import jfun.parsec.Parser; 10 import jfun.parsec.Parsers; 11 import jfun.parsec.Mapn; 12 import jfun.parsec.Map3; 13 import jfun.parsec.Map4; 14 import jfun.parsec.Scanners; 15 import jfun.parsec.pattern.Patterns; 16 17 22 public final class MessageParser { 23 private static Parser keyword(String name){ 24 return LexicalRules.keyword(name); 25 } 26 private final AddressParser aparser = new AddressParser(); 27 private final DateTimeParser dparser = new DateTimeParser(); 28 private final Parser addr_spec = aparser.addr_spec; 29 private final Parser phrase = aparser.phrase; 30 public final Parser msg_id = Parsers.between( 32 LexicalRules.isChar('<'), 33 LexicalRules.isChar('>'), 34 addr_spec); 35 private static final Parser colon = LexicalRules.isChar(':'); 36 private static Parser namedField(String name, Parser p){ 37 return LexicalRules.keyword(name).and(p, 38 new Map2(){ 39 public Object map(final Object o1, final Object o2){ 40 return new NamedObject((String )o1, o2); 41 } 42 }); 43 } 44 private static Parser field(String name, Parser p){ 45 return namedField(name, colon.seq(p) 46 .followedBy(LexicalRules.crlf)); 47 } 48 private static Parser extField(Parser name, Parser p){ 49 return name.and(colon.seq(p).followedBy(LexicalRules.crlf), 50 new Map2(){ 51 public Object map(final Object o1, final Object o2){ 52 return new NamedObject((String )o1, o2); 53 } 54 }); 55 } 56 private static Parser foldedText(final Parser p){ 57 return LexicalRules.toStringLexer( 58 Parsers.plus( 59 LexicalRules.lwsp, p 60 ).many() 61 ); 62 } 63 private final Parser line =foldedText( 64 LexicalRules.crlf.not().seq(LexicalRules.chr) 65 ); 66 public final Parser many_phrase_msg_id = 67 Parsers.sum(phrase, msg_id).many(Object .class); 68 public final Parser texts = foldedText(LexicalRules.text); 69 public final Parser optional_field = Parsers.sum(new Parser[]{ 71 field("Message-ID", msg_id), 72 field("Resent-Message-ID", msg_id), 73 field("In-Reply-To",many_phrase_msg_id), 74 field("References", many_phrase_msg_id), 75 field("Keywords", 76 LexicalRules.list(phrase, String [].class)), 77 field("Subject", texts), 78 field("Comments", texts), 79 field("Encrypted", 80 aparser.word.some(String .class, 1,2)), 81 extField(LexicalRules.s_atom, line) 82 } 83 ); 84 public final Parser address_list1 = 85 LexicalRules.list1(aparser.address, Address.class); 86 public final Parser address_list = 87 LexicalRules.list(aparser.address, Address.class); 88 public final Parser destination = Parsers.sum(new Parser[]{ 89 field("To", address_list1), 90 field("Resent-To", address_list1), 91 field("cc", address_list1), 92 field("Resent-cc", address_list1), 93 field("bcc", address_list), 94 field("Resent-bcc", address_list) 95 }); 96 public final Parser resent_date = 97 field("Resent-Date", dparser.pdatetime); 98 public final Parser orig_date = 99 field("Date", dparser.pdatetime); 100 public final Parser dates = 101 orig_date.and(resent_date.option(null), new Map2(){ 102 public Object map(Object o1, Object o2){ 103 return new Dates((DateTime)getObj((NamedObject)o1), 104 (DateTime)getObj((NamedObject)o2)); 105 } 106 }); 107 private Parser get_authentic(final String type, 108 final String from, final String sender){ 109 return Parsers.plus( 110 field(from, aparser.mailbox).map(new Map(){ 111 public Object map(final Object o){ 112 final NamedObject no = (NamedObject)o; 113 return new SingleAuthentic(type, (Mailbox)no.getObj()); 114 } 115 }).printTrace("authentic.mailbox"), 116 field(sender, aparser.mailbox) 117 .and(field( 118 from, 119 LexicalRules.list1(aparser.mailbox, Mailbox.class) 120 ), 121 new Map2(){ 122 public Object map(Object o1, Object o2){ 123 final NamedObject no1 = (NamedObject)o1; 124 final NamedObject no2 = (NamedObject)o2; 125 return new MultipleAuthentic( 126 type, (Mailbox)no1.getObj(), (Mailbox[])no2.getObj() 127 ); 128 } 129 } 130 ) 131 ); 132 } 133 private Parser get_authenticated_addr(final String type, 134 final String from, final String sender, final String replyto){ 135 return get_authentic(type, from, sender).and( 136 field(replyto, 137 LexicalRules.list1(aparser.address, Address.class)) 138 .option(null), 139 new Map2(){ 140 public Object map(final Object o1, final Object o2){ 141 return new AuthenticatedAddress((Authentic)o1, 142 (Address[])getObj((NamedObject)o2)); 143 } 144 }); 145 } 146 private static Object getObj(final NamedObject no){ 147 return no==null?null:no.getObj(); 148 } 149 public final Parser resent_authentic = 150 get_authentic("resent", "Resent-From", "Resent-Sender"); 151 public final Parser authentic = 152 get_authentic("original", "From", "Sender"); 153 public final Parser resent = 154 get_authenticated_addr("resent", "Resent-From", 155 "Resent-Sender", "Resent-Reply-To"); 156 public final Parser originator = 157 get_authenticated_addr("original", "From", 158 "Sender", "Reply-To"); 159 public final Parser received = 160 keyword("Received").seq(colon).seq( 161 Parsers.mapn(Object .class, new Parser[]{ 162 namedField("from", aparser.domain).option(null), 163 namedField("by", aparser.domain).option(null), 164 namedField("via", aparser.atom).option(null), 165 namedField("with", aparser.atom).many(NamedObject.class), 166 namedField("id", msg_id).option(null), 167 namedField("for", addr_spec).option(null), 168 LexicalRules.isChar(';') 169 .seq(dparser.pdatetime) 170 .followedBy(LexicalRules.crlf) 171 }, new Mapn(){ 172 public Object map(final Object [] args){ 173 final NamedObject from = (NamedObject)args[0]; 174 final NamedObject by = (NamedObject)args[1]; 175 final NamedObject via = (NamedObject)args[2]; 176 final NamedObject[] withs = (NamedObject[])args[3]; 177 final NamedObject id = (NamedObject)args[4]; 178 final NamedObject _for = (NamedObject)args[5]; 179 final DateTime datetime = (DateTime)args[6]; 180 final String [] swith = new String [withs.length]; 181 for(int i =0; i<swith.length; i++){ 182 swith[i] = (String )getObj(withs[i]); 183 } 184 return new Received((String [])getObj(from), 185 (String [])getObj(by), 186 (String )getObj(via), 187 swith, 188 (AddrSpec)getObj(id), 189 (AddrSpec)getObj(_for), 190 datetime 191 ); 192 } 193 }) 194 ); 195 public final Parser retn = 196 field("Return-path", aparser.route_addr); 197 public final Parser trace = 198 retn.and(received.many1(Received.class), new Map2(){ 199 public Object map(final Object o1, final Object o2){ 200 return new Trace( 201 (RouteAddr)getObj((NamedObject)o1), (Received[])o2 202 ); 203 } 204 }); 205 public final Parser source = 206 Parsers.map3( 207 trace.option(null), 208 originator, 209 resent.option(null), 210 new Map3(){ 211 public Object map(final Object o1, Object o2, Object o3){ 212 return new Source( 213 (Trace)o1, 214 (AuthenticatedAddress)o2, 215 (AuthenticatedAddress)o3 216 ); 217 } 218 }); 219 public final Parser fields = Parsers.map4( 220 dates, source, 221 destination.many1(NamedObject.class), 222 optional_field.many(NamedObject.class), 223 new Map4(){ 224 public Object map(Object o1, Object o2, Object o3, Object o4){ 225 return new Fields( 226 (Dates)o1, 227 (Source)o2, 228 (NamedObject[])o3, 229 (NamedObject[])o4); 230 } 231 }); 232 public final Parser body = 233 LexicalRules.toStringLexer(LexicalRules.chr.many()); 234 public final Parser message = 235 fields.and(LexicalRules.crlf.seq(body), 236 new Map2(){ 237 public Object map(Object o1, Object o2){ 238 return new Message((Fields)o1, (String )o2); 239 } 240 }); 241 public Object runParser(CharSequence src, final Parser p){ 242 return LexicalRules.runParser(src, p); 243 } 244 } 245 | Popular Tags |