From afaab00f62a95dd614cc058e51c6ecda0a537046 Mon Sep 17 00:00:00 2001
From: Jerry Yan <792602257@qq.com>
Date: Fri, 22 Jan 2021 10:20:05 +0800
Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=8D=A2=E6=88=90=E9=93=BE=E8=A1=A8?=
 =?UTF-8?q?=E7=BB=93=E6=9E=84?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .gitlab-ci.yml                       | 16 +++++----
 src/Reader/StringReader.php          |  2 +-
 src/Token/Token.php                  |  1 +
 src/Token/TokenDefine.php            | 15 +++++++++
 src/Token/TokenFactory.php           | 14 ++++----
 src/Token/TokenInterface.php         | 50 ++++++++++++++++++++++++++++
 src/Token/TokenVar.php               | 15 +++++++++
 src/Tokenizer/Tokenizer.php          | 17 ++++++----
 src/Tokenizer/TokenizerInterface.php |  5 ++-
 9 files changed, 111 insertions(+), 24 deletions(-)
 create mode 100644 src/Token/TokenDefine.php
 create mode 100644 src/Token/TokenVar.php

diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index a69d4cf..5407ad6 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -19,10 +19,12 @@ unitTest:
         - phpunit-report.xml
   coverage: '/^\s*Lines:\s*\d+.\d+\%/'
 
-composerPublish:
-  image: curlimages/curl:latest
-  only:
-    - tags
-  stage: deploy
-  script:
-    - curl --data "tag=${CI_COMMIT_TAG}" "http://__token__:${CI_JOB_TOKEN}@gitlab/api/v4/projects/${CI_PROJECT_ID}/packages/composer"
\ No newline at end of file
+#composerPublish:
+#  image: curlimages/curl:latest
+#  only:
+#    - tags
+#  stage: deploy
+#  script:
+#    - curl --data "tag=${CI_COMMIT_TAG}" "http://__token__:${CI_JOB_TOKEN}@gitlab/api/v4/projects/${CI_PROJECT_ID}/packages/composer"
+#  dependencies:
+#    - unitTest
\ No newline at end of file
diff --git a/src/Reader/StringReader.php b/src/Reader/StringReader.php
index a4bb497..dcdec40 100644
--- a/src/Reader/StringReader.php
+++ b/src/Reader/StringReader.php
@@ -106,7 +106,7 @@ class StringReader extends ReaderInterface
             }
         }
         $this->currentToken = $curToken;
-        return $curChar !== "";
+        return $curToken !== "";
     }
 
     /**
diff --git a/src/Token/Token.php b/src/Token/Token.php
index 023add4..8063c9a 100644
--- a/src/Token/Token.php
+++ b/src/Token/Token.php
@@ -19,4 +19,5 @@ final class Token
 {
     const AND = "And";
     const OR = "Or";
+    const VAR = "Var";
 }
\ No newline at end of file
diff --git a/src/Token/TokenDefine.php b/src/Token/TokenDefine.php
new file mode 100644
index 0000000..f863b71
--- /dev/null
+++ b/src/Token/TokenDefine.php
@@ -0,0 +1,15 @@
+<?php
+/**
+ * @filename TokenDefine.php
+ * @author Jerry Yan <792602257@qq.com>
+ * @date 2021/1/22 9:41
+ */
+
+
+namespace JerryYan\DSL\Token;
+
+
+class TokenDefine extends TokenInterface
+{
+
+}
\ No newline at end of file
diff --git a/src/Token/TokenFactory.php b/src/Token/TokenFactory.php
index 5dfd04d..c08be84 100644
--- a/src/Token/TokenFactory.php
+++ b/src/Token/TokenFactory.php
@@ -15,6 +15,7 @@ class TokenFactory
     private $tokenMap = [
         Token::AND => TokenAnd::class,
         Token::OR => TokenOr::class,
+        Token::VAR => TokenVar::class,
     ];
 
     protected $tokenNameMap = [
@@ -23,13 +24,14 @@ class TokenFactory
 
     public function getTokenByName(string $name): TokenInterface
     {
-        if (!isset($this->tokenNameMap[$name])) {
-            return new TokenUndefined();
+        $originalName = $name;
+        if (isset($this->tokenNameMap[$name])) {
+            $name = $this->tokenNameMap[$name];
         }
-        $tokenType = $this->tokenNameMap[$name];
-        if (!isset($this->tokenMap[$tokenType])) {
-            return new TokenUndefined();
+        if (!isset($this->tokenMap[$name])) {
+            return new TokenUndefined($originalName);
+        } else {
+            return new $this->tokenMap[$name]($originalName);
         }
-        return new $this->tokenMap[$tokenType];
     }
 }
\ No newline at end of file
diff --git a/src/Token/TokenInterface.php b/src/Token/TokenInterface.php
index 87799c5..690955f 100644
--- a/src/Token/TokenInterface.php
+++ b/src/Token/TokenInterface.php
@@ -11,5 +11,55 @@ namespace JerryYan\DSL\Token;
 
 abstract class TokenInterface
 {
+    /** @var ?TokenInterface 上一个Token */
+    protected $prevToken;
+    /** @var ?TokenInterface 下一个Token */
+    protected $nextToken=NULL;
+    /** @var string 原始数据 */
+    protected $_raw = "";
 
+    public function __construct(string $original)
+    {
+        $this->_raw = $original;
+    }
+
+    public function setPrevToken(?TokenInterface $token): void
+    {
+        $this->prevToken = $token;
+    }
+    public function setNextToken(TokenInterface $token): void
+    {
+        $this->nextToken = $token;
+    }
+
+    /**
+     * 获取链表第一个元素
+     * @return ?$this
+     * @author Jerry Yan <792602257@qq.com>
+     * @date 2021/1/22 10:01
+     */
+    public function getFirstToken(): ?TokenInterface
+    {
+        if ($this->hasPrevToken()) return $this->prevToken->getFirstToken();
+        else return $this;
+    }
+    public function getLastToken(): ?TokenInterface
+    {
+        if ($this->hasNextToken()) return $this->nextToken->getLastToken();
+        else return $this;
+    }
+    public function hasPrevToken(): bool
+    {
+        return $this->prevToken !== NULL;
+    }
+    public function hasNextToken(): bool
+    {
+        return $this->nextToken !== NULL;
+    }
+    public function getPrevToken(): ?TokenInterface{
+        return $this->prevToken;
+    }
+    public function getNextToken(): ?TokenInterface{
+        return $this->nextToken;
+    }
 }
\ No newline at end of file
diff --git a/src/Token/TokenVar.php b/src/Token/TokenVar.php
new file mode 100644
index 0000000..84dd6bb
--- /dev/null
+++ b/src/Token/TokenVar.php
@@ -0,0 +1,15 @@
+<?php
+/**
+ * @filename TokenVar.php
+ * @author Jerry Yan <792602257@qq.com>
+ * @date 2021/1/22 9:41
+ */
+
+
+namespace JerryYan\DSL\Token;
+
+
+class TokenVar extends TokenInterface
+{
+
+}
\ No newline at end of file
diff --git a/src/Tokenizer/Tokenizer.php b/src/Tokenizer/Tokenizer.php
index a165ba2..2831c71 100644
--- a/src/Tokenizer/Tokenizer.php
+++ b/src/Tokenizer/Tokenizer.php
@@ -9,9 +9,9 @@
 namespace JerryYan\DSL\Tokenizer;
 
 
-use ArrayIterator;
 use JerryYan\DSL\Reader\ReaderInterface;
 use JerryYan\DSL\Token\TokenFactory;
+use JerryYan\DSL\Token\TokenInterface;
 
 class Tokenizer extends TokenizerInterface
 {
@@ -24,16 +24,19 @@ class Tokenizer extends TokenizerInterface
     /**
      * @inheritDoc
      */
-    function tokenize(ReaderInterface $reader): ArrayIterator
+    function tokenize(ReaderInterface $reader): ?TokenInterface
     {
         $reader->resetCursor();
-        $tokens = [];
-        while($reader->moveToNextToken())
+        /** @var TokenInterface $lastToken */
+        $lastToken = NULL;
+        do
         {
             $currentTokenName = $reader->getCurrentToken();
             $currentToken = $this->tokenFactory->getTokenByName($currentTokenName);
-            $tokens[] = $currentToken;
-        }
-        return new ArrayIterator($tokens);
+            $currentToken->setPrevToken($lastToken);
+            if ($lastToken !== NULL) $lastToken->setNextToken($currentToken);
+            $lastToken = $currentToken;
+        }while($reader->moveToNextToken());
+        return $lastToken->getFirstToken();
     }
 }
\ No newline at end of file
diff --git a/src/Tokenizer/TokenizerInterface.php b/src/Tokenizer/TokenizerInterface.php
index 45aeb39..896cca7 100644
--- a/src/Tokenizer/TokenizerInterface.php
+++ b/src/Tokenizer/TokenizerInterface.php
@@ -9,7 +9,6 @@
 namespace JerryYan\DSL\Tokenizer;
 
 
-use ArrayIterator;
 use JerryYan\DSL\Reader\ReaderInterface;
 use JerryYan\DSL\Token\TokenInterface;
 
@@ -20,9 +19,9 @@ abstract class TokenizerInterface
     /**
      *
      * @param ReaderInterface $reader
-     * @return ArrayIterator<TokenInterface>
+     * @return ?TokenInterface
      * @author Jerry Yan <792602257@qq.com>
      * @date 2020/12/18 11:43
      */
-    abstract function tokenize(ReaderInterface $reader): ArrayIterator;
+    abstract function tokenize(ReaderInterface $reader): ?TokenInterface;
 }
\ No newline at end of file