package mireka.address.parser;
import static mireka.address.parser.CharClasses.*;
import java.text.ParseException;
import mireka.address.parser.ast.DomainAST;
import mireka.address.parser.base.CharParser;
import mireka.address.parser.base.CharScanner;
public class DomainParser extends CharParser {
protected DomainParser(CharScanner charScanner) {
super(charScanner);
}
public DomainAST parseLeft() throws ParseException {
DomainAST domainAST = parseDomain();
scanner.pushBack(currentToken);
return domainAST;
}
private DomainAST parseDomain() throws ParseException {
pushPosition();
pushSpelling();
parseSubDomain();
while (currentToken.ch == '.') {
acceptIt();
parseSubDomain();
}
return new DomainAST(popPosition(), popSpelling());
}
private void parseSubDomain() throws ParseException {
parseLetDig();
if (LDH.isSatisfiedBy(currentToken.ch))
parseLdhStr();
}
private void parseLetDig() throws ParseException {
if (LET_DIG.isSatisfiedBy(currentToken.ch))
acceptIt();
else
throw currentToken.syntaxException("letter or digit");
}
/**
* Original ABNF:
* <ul>
* <li>Let-dig = ALPHA / DIGIT
* <li>Ldh-str = *( ALPHA / DIGIT / "-" ) Let-dig
* </ul>
* This corresponds to A*(A|B)A. This is not an LL(1) language, but it can
* be transformed: A *(A|*BA)
*
* Transformed:
* <ul>
* <li>Let-dig = ALPHA / DIGIT
* <li>Ldh-str = *( Let-dig / (1*"-" Let-dig) )
* </ul>
*
* @throws ParseException
*
*/
private void parseLdhStr() throws ParseException {
while (LDH.isSatisfiedBy(currentToken.ch)) {
if (LET_DIG.isSatisfiedBy(currentToken.ch)) {
parseLetDig();
} else if (currentToken.ch == '-') {
acceptIt();
while (currentToken.ch == '-')
acceptIt();
parseLetDig();
} else {
throw currentToken.syntaxException("letter, digit or hyphen");
}
}
}
}