package org.shedlang.compiler.tokeniser; import org.junit.jupiter.api.Test; import org.zwobble.sourcetext.SourceText; import java.util.List; import static org.zwobble.precisely.AssertThat.assertThat; import static org.zwobble.precisely.Matchers.equalTo; import static org.zwobble.precisely.Matchers.isSequence; public class RegexTokeniserTests { enum TokenType { UNKNOWN, KEYWORD, IDENTIFIER, WHITESPACE } @Test public void emptyStringIsTokenisedToNoTokens() { var tokeniser = new RegexTokeniser<>(TokenType.UNKNOWN, List.of()); var sourceText = sourceText(""); var result = tokeniser.tokenise(sourceText); assertThat(result, isSequence()); } @Test public void regexIsAppliedToGenerateToken() { var tokeniser = new RegexTokeniser<>(TokenType.UNKNOWN, List.of( RegexTokeniser.rule(TokenType.IDENTIFIER, "[A-Za-z0-9]+") )); var sourceText = sourceText("count"); var result = tokeniser.tokenise(sourceText); assertThat(result, isSequence( equalTo(new Token<>( sourceText.characterPosition(0).to(sourceText.characterPosition(5)), TokenType.IDENTIFIER )) )); } @Test public void firstMatchingRegexIsUsed() { var tokeniser = new RegexTokeniser<>(TokenType.UNKNOWN, List.of( RegexTokeniser.rule(TokenType.KEYWORD, "if"), RegexTokeniser.rule(TokenType.IDENTIFIER, "[A-Za-z0-9]+") )); var sourceText = sourceText("if"); var result = tokeniser.tokenise(sourceText); assertThat(result, isSequence( equalTo(new Token<>( sourceText.characterPosition(0).to(sourceText.characterPosition(2)), TokenType.KEYWORD )) )); } @Test public void sequenceOfTokensCanBeGenerated() { var tokeniser = new RegexTokeniser<>(TokenType.UNKNOWN, List.of( RegexTokeniser.rule(TokenType.IDENTIFIER, "[A-Za-z0-9]+"), RegexTokeniser.rule(TokenType.WHITESPACE, "\\s") )); var sourceText = sourceText("one two"); var result = tokeniser.tokenise(sourceText); assertThat(result, isSequence( equalTo(new Token<>( sourceText.characterPosition(0).to(sourceText.characterPosition(3)), TokenType.IDENTIFIER )), equalTo(new Token<>( sourceText.characterPosition(3).to(sourceText.characterPosition(4)), TokenType.WHITESPACE )), equalTo(new Token<>( sourceText.characterPosition(4).to(sourceText.characterPosition(7)), TokenType.IDENTIFIER )) )); } @Test public void whenNoRulesMatchThenUnknownTokensAreGenerated() { var tokeniser = new RegexTokeniser<>(TokenType.UNKNOWN, List.of( RegexTokeniser.rule(TokenType.IDENTIFIER, "[A-Za-z0-9]+") )); var sourceText = sourceText("!!a!"); var result = tokeniser.tokenise(sourceText); assertThat(result, isSequence( equalTo(new Token<>( sourceText.characterPosition(0).to(sourceText.characterPosition(1)), TokenType.UNKNOWN )), equalTo(new Token<>( sourceText.characterPosition(1).to(sourceText.characterPosition(2)), TokenType.UNKNOWN )), equalTo(new Token<>( sourceText.characterPosition(2).to(sourceText.characterPosition(3)), TokenType.IDENTIFIER )), equalTo(new Token<>( sourceText.characterPosition(3).to(sourceText.characterPosition(4)), TokenType.UNKNOWN )) )); } private SourceText sourceText(String sourceContents) { return SourceText.fromString("", sourceContents); } }