package mireka.address.parser; import java.text.ParseException; import mireka.address.parser.Ipv4Parser.Ipv4; import mireka.address.parser.Ipv6Parser.Ipv6; import mireka.address.parser.ast.AddressLiteralRemotePartAST; import mireka.address.parser.ast.Ipv4RemotePartAST; import mireka.address.parser.ast.Ipv6RemotePartAST; import mireka.address.parser.base.CharParser; import mireka.address.parser.base.CharScanner; /** * AddressLiteralParser parses the remote part of an SMTP mailbox (after the * '@'). */ public class AddressLiteralParser extends CharParser { public AddressLiteralParser(CharScanner charScanner) { super(charScanner); } public AddressLiteralRemotePartAST parse() throws ParseException { AddressLiteralRemotePartAST remotePartAST = parseAddressLiteralRemotePart(); scanner.pushBack(currentToken); decorateWithInetAddress(remotePartAST); return remotePartAST; } private AddressLiteralRemotePartAST parseAddressLiteralRemotePart() throws ParseException { pushPosition(); pushSpelling(); accept('['); scanner.pushBack(currentToken); AddressLiteralTagScanner addressLiteralTagScanner = new AddressLiteralTagScanner(scanner); AddressLiteralTagToken tagToken = addressLiteralTagScanner.scan(); addressLiteralTagScanner.finish(); currentToken = scanner.scan(); spelling.append(tagToken.spelling); switch (tagToken.kind) { case DIGIT: Ipv4 ipv4AST = parseIpv4AddressLiteral(); accept(']'); return new Ipv4RemotePartAST(popPosition(), popSpelling(), ipv4AST); case IPv6: accept(':'); Ipv6 ipv6AST = parseIpv6AddressLiteral(); accept(']'); return new Ipv6RemotePartAST(popPosition(), popSpelling(), ipv6AST); case STANDARDIZED_TAG: throw tagToken .syntaxException("IPv4 address literal or 'IPv6' tag"); default: throw new RuntimeException("Assertion failed"); } } private Ipv4 parseIpv4AddressLiteral() throws ParseException { scanner.pushBack(currentToken); Ipv4 ipv4 = new Ipv4Parser(scanner).parseLeft(); currentToken = scanner.scan(); spelling.append(ipv4.spelling); return ipv4; } private Ipv6 parseIpv6AddressLiteral() throws ParseException { scanner.pushBack(currentToken); Ipv6 ipv6 = new Ipv6Parser(scanner).parseLeft(); currentToken = scanner.scan(); spelling.append(ipv6.spelling); return ipv6; } private void decorateWithInetAddress( AddressLiteralRemotePartAST remotePartAST) { if (remotePartAST instanceof Ipv4RemotePartAST) { Ipv4RemotePartAST ipv4RemotePartAST = (Ipv4RemotePartAST) remotePartAST; remotePartAST.addressBytes = ipv4RemotePartAST.ipv4.addressBytes; remotePartAST.address = ipv4RemotePartAST.ipv4.address; } else if (remotePartAST instanceof Ipv6RemotePartAST) { Ipv6RemotePartAST ipv6RemotePartAST = (Ipv6RemotePartAST) remotePartAST; remotePartAST.addressBytes = ipv6RemotePartAST.ipv6.addressBytes; remotePartAST.address = ipv6RemotePartAST.ipv6.address; } else { throw new RuntimeException("Assertion failed"); } } }