diff --git a/src/Reader.php b/src/Reader.php index 1471d3c..3ef2bd1 100644 --- a/src/Reader.php +++ b/src/Reader.php @@ -27,6 +27,8 @@ class Reader return $this->readSpecialForm($tokens, $index, 'quasiquote'); } elseif ($tokens[$index] == "~") { return $this->readSpecialForm($tokens, $index, 'unquote'); + } elseif ($tokens[$index] == "~@") { + return $this->readSpecialForm($tokens, $index, 'unquote-splice'); } elseif ($tokens[$index] == '(') { return $this->readList($tokens, $index); } elseif ($tokens[$index] == '[') { diff --git a/src/Tokenizer.php b/src/Tokenizer.php index 98d0d36..020ba59 100644 --- a/src/Tokenizer.php +++ b/src/Tokenizer.php @@ -101,6 +101,14 @@ class Tokenizer // Other special characters $addCurrent(); $tokens[] = $c; + } elseif ($c == '@') { + // If the last token was ~ then add @ to it + if (count($tokens) > 0 && $tokens[count($tokens) - 1] == '~') { + $tokens[count($tokens) - 1] .= $c; + } else { + // Otherwise treat it like normal character + $current .= $c; + } } else { // All other characters $current .= $c; diff --git a/test/ReaderTest.php b/test/ReaderTest.php index c62ddfc..160770d 100644 --- a/test/ReaderTest.php +++ b/test/ReaderTest.php @@ -28,6 +28,7 @@ class ReaderTest extends TestCase ["'", 'quote'], ['`', 'quasiquote'], ['~', 'unquote'], + ['~@', 'unquote-splice'], ]; } diff --git a/test/TokenizerTest.php b/test/TokenizerTest.php index 583a675..b71e2aa 100644 --- a/test/TokenizerTest.php +++ b/test/TokenizerTest.php @@ -76,6 +76,9 @@ class TokenizerTest extends TestCase // Other non-alphabet characters are symbols ["(aa!@#$%^&*-_=+bb<>,./?\\|cc)", ['(', "aa!@#$%^&*-_=+bb<>,./?\\|cc", ')']], + // @ after ~ is single token, @ anywhere else is normal character + ['aa@~@@bb', ['aa@', '~@', '@bb']], + // Strings ['"abc"', ['"abc"']], ['aa"bb"cc', ['aa', '"bb"', 'cc']],