package com.googlecode.totallylazy.parser;
import org.junit.Test;
import java.util.List;
import static com.googlecode.totallylazy.Assert.assertThat;
import static com.googlecode.totallylazy.Characters.among;
import static com.googlecode.totallylazy.Lists.list;
import static com.googlecode.totallylazy.Segment.constructors.characters;
import static com.googlecode.totallylazy.Strings.startsWith;
import static com.googlecode.totallylazy.parser.CharacterParser.character;
import static com.googlecode.totallylazy.parser.Parsers.characters;
import static com.googlecode.totallylazy.parser.Parsers.isChar;
import static com.googlecode.totallylazy.parser.Parsers.pattern;
import static com.googlecode.totallylazy.parser.Parsers.string;
import static com.googlecode.totallylazy.predicates.Predicates.is;
import static com.googlecode.totallylazy.predicates.Predicates.not;
import static java.lang.String.format;
public class ParsersTest {
@Test
public void supportsFlatMap() throws Exception {
final Parser<CharSequence> parser = characters(not('}')).flatMap(c -> characters(among("abc")).parse(c));
final Result<CharSequence> result = parser.parse("ab}");
assertThat(result.value().toString(), is("ab"));
assertThat(result.remainder().toString(), is("}"));
}
@Test
public void whitespaceCharIsOptionalAround() throws Exception {
assertThat(Parsers.wsChar('}').parse(" }").value(), is('}'));
assertThat(Parsers.wsChar('}').parse("} ").value(), is('}'));
assertThat(Parsers.wsChar('}').parse("}").value(), is('}'));
assertThat(Parsers.wsChar('}').parse(" } ").value(), is('}'));
assertThat(Parsers.wsChar('}').parse(" } ").value(), is('}'));
}
@Test
public void supportsPrefix() throws Exception {
Parser<String> parser = pattern("[0-9]").prefix(isChar('+').map(ignore -> a -> format("positive(%s)", a)));
assertThat(parser.parse(characters("+1")).value(), is("positive(1)"));
assertThat(parser.parse(characters("++1")).value(), is("positive(positive(1))"));
assertThat(parser.parse(characters("1")).value(), is("1"));
assertThat(parser.parse(characters("1")).value(), is("1"));
}
@Test
public void supportsLeftAssociativeInfix() throws Exception {
Parser<String> parser = pattern("[A-C]").infixLeft(string(" AND ").map(ignore -> (a, b) -> format("( %s + %s )", a, b)));
String result = parser.parse(characters("A AND B AND C")).value();
assertThat(result, is("( ( A + B ) + C )"));
}
@Test
public void supportsRightAssociativeInfix() throws Exception {
Parser<String> parser = pattern("[A-C]").infixRight(string(" AND ").map(ignore -> (a, b) -> format("( %s + %s )", a, b)));
String result = parser.parse(characters("A AND B AND C")).value();
assertThat(result, is("( A + ( B + C ) )"));
}
@Test
public void supportsPeek() throws Exception {
Parser<Character> parser = character('A').peek(character('B'));
Result<Character> success = parser.parse("ABC");
assertThat(success.value(), is('A'));
assertThat(success.remainder(), is(characters("BC")));
Result<Character> failure = parser.parse("AC");
assertThat(failure.message(), is("B expected, C encountered."));
}
@Test
public void supportsReturns() throws Exception {
Result<Integer> result = character('A').returns(1).parse("ABC");
assertThat(result.value(), is(1));
assertThat(result.remainder().head(), is('B'));
}
@Test
public void supportsFollowedBy() throws Exception {
Result<Character> result = character('A').followedBy(character('B')).parse("ABC");
assertThat(result.value(), is('A'));
assertThat(result.remainder().head(), is('C'));
}
@Test
public void supportsBetween() throws Exception {
Result<Character> result = character('B').between(character('A'), character('C')).parse("ABCD");
assertThat(result.value(), is('B'));
assertThat(result.remainder().head(), is('D'));
}
@Test
public void supportsSurroundedBy() throws Exception {
Result<Character> result = character('B').surroundedBy(character('$')).parse("$B$D");
assertThat(result.value(), is('B'));
assertThat(result.remainder().head(), is('D'));
}
@Test
public void supportsSeparatedBy() throws Exception {
Result<List<Character>> result = character('A').separatedBy(character(',')).parse("A,A,ABC");
assertThat(result.value(), is(list('A', 'A', 'A')));
assertThat(result.remainder().head(), is('B'));
}
@Test
public void supportsPretty() throws Exception {
Parser<Character> pretty = character('A').pretty("some pretty thing");
Result<Character> success = pretty.parse("A");
assertThat(success.value(), is('A'));
Result<Character> failure = pretty.parse("BBB");
assertThat(failure.message(), startsWith("some pretty thing"));
}
}