OSDN Git Service

add import function (#25)
authoroysheng <33340252+oysheng@users.noreply.github.com>
Tue, 20 Nov 2018 08:07:12 +0000 (16:07 +0800)
committerPaladz <yzhu101@uottawa.ca>
Tue, 20 Nov 2018 08:07:12 +0000 (16:07 +0800)
* add import function

* modify scan string with '' and ""

* add check for empty path

* modify name

* add test

* add import unit test
modify compile test

* modify loan collateral and repay collateral

* optimise

compiler/compile_test.go
compiler/equitytest/LoanCollateral [new file with mode: 0644]
compiler/equitytest/RepayCollateral [new file with mode: 0644]
compiler/equitytest/equity_test.go [new file with mode: 0644]
compiler/equitytest/equitytest.go [deleted file]
compiler/import.go [new file with mode: 0644]
compiler/parse.go

index 71e994a..e11e641 100644 (file)
@@ -4,11 +4,228 @@ import (
        "encoding/hex"
        "strings"
        "testing"
+)
 
-       chainjson "github.com/bytom/encoding/json"
+const TrivialLock = `
+contract TrivialLock() locks amount of asset {
+  clause trivialUnlock() {
+    unlock amount of asset
+  }
+}
+`
 
-       "github.com/equity/compiler/equitytest"
-)
+const LockWithPublicKey = `
+contract LockWithPublicKey(publicKey: PublicKey) locks amount of asset {
+  clause unlockWithSig(sig: Signature) {
+    verify checkTxSig(publicKey, sig)
+    unlock amount of asset
+  }
+}
+`
+
+const LockWithPKHash = `
+contract LockWithPublicKeyHash(pubKeyHash: Hash) locks amount of asset {
+  clause spend(pubKey: PublicKey, sig: Signature) {
+    verify sha3(pubKey) == pubKeyHash
+    verify checkTxSig(pubKey, sig)
+    unlock amount of asset
+  }
+}
+`
+
+const LockWith2of3Keys = `
+contract LockWith3Keys(pubkey1, pubkey2, pubkey3: PublicKey) locks amount of asset {
+  clause unlockWith2Sigs(sig1, sig2: Signature) {
+    verify checkTxMultiSig([pubkey1, pubkey2, pubkey3], [sig1, sig2])
+    unlock amount of asset
+  }
+}
+`
+
+const LockToOutput = `
+contract LockToOutput(address: Program) locks amount of asset {
+  clause relock() {
+    lock amount of asset with address
+  }
+}
+`
+
+const TradeOffer = `
+contract TradeOffer(requestedAsset: Asset, requestedAmount: Amount, sellerProgram: Program, sellerKey: PublicKey) locks amount of asset {
+  clause trade() {
+    lock requestedAmount of requestedAsset with sellerProgram
+    unlock amount of asset
+  }
+  clause cancel(sellerSig: Signature) {
+    verify checkTxSig(sellerKey, sellerSig)
+    unlock amount of asset
+  }
+}
+`
+
+const EscrowedTransfer = `
+contract EscrowedTransfer(agent: PublicKey, sender: Program, recipient: Program) locks amount of asset {
+  clause approve(sig: Signature) {
+    verify checkTxSig(agent, sig)
+    lock amount of asset with recipient
+  }
+  clause reject(sig: Signature) {
+    verify checkTxSig(agent, sig)
+    lock amount of asset with sender
+  }
+}
+`
+
+const CollateralizedLoan = `
+contract CollateralizedLoan(balanceAsset: Asset, balanceAmount: Amount, finalHeight: Integer, lender: Program, borrower: Program) locks valueAmount of valueAsset {
+  clause repay() {
+    lock balanceAmount of balanceAsset with lender
+    lock valueAmount of valueAsset with borrower
+  }
+  clause default() {
+    verify above(finalHeight)
+    lock valueAmount of valueAsset with lender
+  }
+}
+`
+
+const RevealPreimage = `
+contract RevealPreimage(hash: Hash) locks amount of asset {
+  clause reveal(string: String) {
+    verify sha3(string) == hash
+    unlock amount of asset
+  }
+}
+`
+
+const PriceChanger = `
+contract PriceChanger(askAmount: Amount, askAsset: Asset, sellerKey: PublicKey, sellerProg: Program) locks valueAmount of valueAsset {
+  clause changePrice(newAmount: Amount, newAsset: Asset, sig: Signature) {
+    verify checkTxSig(sellerKey, sig)
+    lock valueAmount of valueAsset with PriceChanger(newAmount, newAsset, sellerKey, sellerProg)
+  }
+  clause redeem() {
+    lock askAmount of askAsset with sellerProg
+    unlock valueAmount of valueAsset
+  }
+}
+`
+
+const CallOptionWithSettlement = `
+contract CallOptionWithSettlement(strikePrice: Amount,
+                    strikeCurrency: Asset,
+                    sellerProgram: Program,
+                    sellerKey: PublicKey,
+                    buyerKey: PublicKey,
+                    finalHeight: Integer) locks valueAmount of valueAsset {
+  clause exercise(buyerSig: Signature) {
+    verify below(finalHeight)
+    verify checkTxSig(buyerKey, buyerSig)
+    lock strikePrice of strikeCurrency with sellerProgram
+    unlock valueAmount of valueAsset
+  }
+  clause expire() {
+    verify above(finalHeight)
+    lock valueAmount of valueAsset with sellerProgram
+  }
+  clause settle(sellerSig: Signature, buyerSig: Signature) {
+    verify checkTxSig(sellerKey, sellerSig)
+    verify checkTxSig(buyerKey, buyerSig)
+    unlock valueAmount of valueAsset
+  }
+}
+`
+
+const TestDefineVar = `
+contract TestDefineVar(result: Integer) locks valueAmount of valueAsset {
+  clause LockWithMath(left: Integer, right: Integer) {
+    define calculate: Integer = left + right
+    verify left != calculate
+    verify result == calculate
+    unlock valueAmount of valueAsset
+  }
+}
+`
+
+const TestAssignVar = `
+contract TestAssignVar(result: Integer) locks valueAmount of valueAsset {
+  clause LockWithMath(first: Integer, second: Integer) {
+    define calculate: Integer = first
+    assign calculate = calculate + second
+    verify result == calculate
+    unlock valueAmount of valueAsset
+  }
+}
+`
+
+const TestSigIf = `
+contract TestSigIf(a: Integer, count:Integer) locks valueAmount of valueAsset {
+  clause check(b: Integer, c: Integer) {
+    verify b != count
+    if a > b {
+        verify b > c
+    } else {
+        verify a > c
+    }
+    unlock valueAmount of valueAsset
+  }
+}
+`
+
+const TestIfAndMultiClause = `
+contract TestIfAndMultiClause(a: Integer, cancelKey: PublicKey) locks valueAmount of valueAsset {
+  clause check(b: Integer, c: Integer) {
+    verify b != c
+    if a > b {
+        verify a > c
+    }
+    unlock valueAmount of valueAsset
+  }
+  clause cancel(sellerSig: Signature) {
+    verify checkTxSig(cancelKey, sellerSig)
+    unlock valueAmount of valueAsset
+  }
+}
+`
+
+const TestIfNesting = `
+contract TestIfNesting(a: Integer, count:Integer) locks valueAmount of valueAsset {
+  clause check(b: Integer, c: Integer, d: Integer) {
+    verify b != count
+    if a > b {
+        if d > c {
+           verify a > d
+        }
+        verify d != b
+    } else {
+        verify a > c
+    }
+    verify c != count
+    unlock valueAmount of valueAsset
+  }
+  clause cancel(e: Integer, f: Integer) {
+    verify a != e
+    if a > f {
+      verify e > count
+    }
+    verify f != count
+    unlock valueAmount of valueAsset
+  }
+}
+`
+
+const TestConstantMath = `
+contract TestConstantMath(result: Integer, hashByte: Hash, hashStr: Hash, outcome: Boolean) locks valueAmount of valueAsset {
+  clause calculation(left: Integer, right: Integer, boolResult: Boolean) {
+    verify result == left + right + 10
+    verify hashByte == sha3(0x31323330)
+    verify hashStr == sha3('string')
+    verify !outcome
+    verify boolResult && (result == left + 20)
+    unlock valueAmount of valueAsset
+  }
+}
+`
 
 func TestCompile(t *testing.T) {
        cases := []struct {
@@ -18,80 +235,91 @@ func TestCompile(t *testing.T) {
        }{
                {
                        "TrivialLock",
-                       equitytest.TrivialLock,
+                       TrivialLock,
                        "51",
                },
                {
                        "LockWithPublicKey",
-                       equitytest.LockWithPublicKey,
+                       LockWithPublicKey,
                        "ae7cac",
                },
                {
                        "LockWithPublicKeyHash",
-                       equitytest.LockWithPKHash,
+                       LockWithPKHash,
                        "5279aa887cae7cac",
                },
                {
                        "LockWith2of3Keys",
-                       equitytest.LockWith2of3Keys,
+                       LockWith2of3Keys,
                        "537a547a526bae71557a536c7cad",
                },
                {
                        "LockToOutput",
-                       equitytest.LockToOutput,
+                       LockToOutput,
                        "00c3c251547ac1",
                },
                {
                        "TradeOffer",
-                       equitytest.TradeOffer,
+                       TradeOffer,
                        "547a6413000000007b7b51547ac1631a000000547a547aae7cac",
                },
                {
                        "EscrowedTransfer",
-                       equitytest.EscrowedTransfer,
+                       EscrowedTransfer,
                        "537a641a000000537a7cae7cac6900c3c251557ac16328000000537a7cae7cac6900c3c251547ac1",
                },
                {
+                       "CollateralizedLoan",
+                       CollateralizedLoan,
+                       "557a641b000000007b7b51557ac16951c3c251557ac163260000007bcd9f6900c3c251567ac1",
+               },
+               {
                        "RevealPreimage",
-                       equitytest.RevealPreimage,
+                       RevealPreimage,
                        "7caa87",
                },
                {
                        "PriceChanger",
-                       equitytest.PriceChanger,
+                       PriceChanger,
                        "557a6432000000557a5479ae7cac6900c3c25100597a89587a89587a89587a89557a890274787e008901c07ec1633a000000007b537a51567ac1",
                },
                {
+                       "CallOptionWithSettlement",
+                       CallOptionWithSettlement,
+                       "567a76529c64360000006425000000557acda06971ae7cac69007c7b51547ac16346000000557acd9f6900c3c251567ac1634600000075577a547aae7cac69557a547aae7cac",
+               },
+               {
                        "TestDefineVar",
-                       equitytest.TestDefineVar,
+                       TestDefineVar,
                        "52797b937b7887916987",
                },
                {
                        "TestAssignVar",
-                       equitytest.TestAssignVar,
+                       TestAssignVar,
                        "7b7b9387",
                },
                {
                        "TestSigIf",
-                       equitytest.TestSigIf,
+                       TestSigIf,
                        "53797b879169765379a09161641c00000052795279a0696321000000765279a069",
                },
                {
                        "TestIfAndMultiClause",
-                       equitytest.TestIfAndMultiClause,
+                       TestIfAndMultiClause,
                        "7b641f0000007087916976547aa09161641a000000765379a06963240000007b7bae7cac",
                },
                {
                        "TestIfNesting",
-                       equitytest.TestIfNesting,
+                       TestIfNesting,
                        "7b644400000054795279879169765579a09161643500000052795479a091616429000000765379a06952795579879169633a000000765479a06953797b8791635c0000007654798791695279a091616459000000527978a0697d8791",
                },
                {
                        "TestConstantMath",
-                       equitytest.TestConstantMath,
+                       TestConstantMath,
                        "765779577a935a93887c0431323330aa887c06737472696e67aa887c91697b011493879a",
                },
        }
+
        for _, c := range cases {
                t.Run(c.name, func(t *testing.T) {
                        r := strings.NewReader(c.contract)
@@ -114,12 +342,3 @@ func TestCompile(t *testing.T) {
                })
        }
 }
-
-func mustDecodeHex(h string) *chainjson.HexBytes {
-       bits, err := hex.DecodeString(h)
-       if err != nil {
-               panic(err)
-       }
-       result := chainjson.HexBytes(bits)
-       return &result
-}
diff --git a/compiler/equitytest/LoanCollateral b/compiler/equitytest/LoanCollateral
new file mode 100644 (file)
index 0000000..8197d87
--- /dev/null
@@ -0,0 +1,18 @@
+import "./RepayCollateral"
+
+contract LoanCollateral(assetLoaned: Asset,
+                        amountLoaned: Amount,
+                        loanBlockHeight: Integer,
+                        RepayBlockHeight: Integer,
+                        lender: Program,
+                        borrower: Program) locks valueAmount of valueAsset {
+  clause loan() {
+    verify below(loanBlockHeight)
+    lock amountLoaned of assetLoaned with RepayCollateral(valueAsset, valueAmount, RepayBlockHeight, lender, borrower)
+    lock valueAmount of valueAsset with borrower
+  }
+  clause cancel() {
+    verify above(loanBlockHeight)
+    lock valueAmount of valueAsset with lender
+  }
+}
diff --git a/compiler/equitytest/RepayCollateral b/compiler/equitytest/RepayCollateral
new file mode 100644 (file)
index 0000000..2047119
--- /dev/null
@@ -0,0 +1,15 @@
+contract RepayCollateral(assetRepayed: Asset,
+                        amountRepayed: Amount,
+                        RepayBlockHeight: Integer,
+                        lender: Program,
+                        borrower: Program) locks valueAmount of valueAsset {
+  clause repay() {
+    verify below(RepayBlockHeight)
+    lock amountRepayed of assetRepayed with lender
+    lock valueAmount of valueAsset with borrower
+  }
+  clause default() {
+    verify above(RepayBlockHeight)
+    lock valueAmount of valueAsset with lender
+  }
+}
diff --git a/compiler/equitytest/equity_test.go b/compiler/equitytest/equity_test.go
new file mode 100644 (file)
index 0000000..e1e2caa
--- /dev/null
@@ -0,0 +1,59 @@
+package equitytest
+
+import (
+       "bufio"
+       "encoding/hex"
+       "os"
+       "path/filepath"
+       "testing"
+
+       "github.com/equity/compiler"
+)
+
+func TestCompileContract(t *testing.T) {
+       cases := []struct {
+               pathFile string
+               want     string
+       }{
+               {
+                       "./RepayCollateral",
+                       "557a641f0000007bcda069007b7b51547ac16951c3c251547ac1632a0000007bcd9f6900c3c251567ac1",
+               },
+               {
+                       "./LoanCollateral",
+                       "567a64650000007bcda06900c3537ac2547a5100597989587a89577a89557a89537a8901747e2a557a641f0000007bcda069007b7b51547ac16951c3c251547ac1632a0000007bcd9f6900c3c251567ac189008901c07ec16951c3c251547ac163700000007bcd9f6900c3c251577ac1",
+               },
+       }
+
+       for _, c := range cases {
+               contractName := filepath.Base(c.pathFile)
+               t.Run(contractName, func(t *testing.T) {
+                       absPathFile, err := filepath.Abs(c.pathFile)
+                       if err != nil {
+                               t.Fatal(err)
+                       }
+
+                       if _, err := os.Stat(absPathFile); err != nil {
+                               t.Fatal(err)
+                       }
+
+                       inputFile, err := os.Open(absPathFile)
+                       if err != nil {
+                               t.Fatal(err)
+                       }
+                       defer inputFile.Close()
+
+                       inputReader := bufio.NewReader(inputFile)
+                       contracts, err := compiler.Compile(inputReader)
+                       if err != nil {
+                               t.Fatal(err)
+                       }
+
+                       contract := contracts[len(contracts)-1]
+                       got := hex.EncodeToString(contract.Body)
+                       if got != c.want {
+                               t.Errorf("%s got %s\nwant %s", contractName, got, c.want)
+                       }
+               })
+       }
+}
diff --git a/compiler/equitytest/equitytest.go b/compiler/equitytest/equitytest.go
deleted file mode 100644 (file)
index f5906b9..0000000
+++ /dev/null
@@ -1,181 +0,0 @@
-package equitytest
-
-const TrivialLock = `
-contract TrivialLock() locks amount of asset {
-  clause trivialUnlock() {
-    unlock amount of asset
-  }
-}
-`
-
-const LockWithPublicKey = `
-contract LockWithPublicKey(publicKey: PublicKey) locks amount of asset {
-  clause unlockWithSig(sig: Signature) {
-    verify checkTxSig(publicKey, sig)
-    unlock amount of asset
-  }
-}
-`
-
-const LockWithPKHash = `
-contract LockWithPublicKeyHash(pubKeyHash: Hash) locks amount of asset {
-  clause spend(pubKey: PublicKey, sig: Signature) {
-    verify sha3(pubKey) == pubKeyHash
-    verify checkTxSig(pubKey, sig)
-    unlock amount of asset
-  }
-}
-`
-
-const LockWith2of3Keys = `
-contract LockWith3Keys(pubkey1, pubkey2, pubkey3: PublicKey) locks amount of asset {
-  clause unlockWith2Sigs(sig1, sig2: Signature) {
-    verify checkTxMultiSig([pubkey1, pubkey2, pubkey3], [sig1, sig2])
-    unlock amount of asset
-  }
-}
-`
-
-const LockToOutput = `
-contract LockToOutput(address: Program) locks amount of asset {
-  clause relock() {
-    lock amount of asset with address
-  }
-}
-`
-
-const TradeOffer = `
-contract TradeOffer(requestedAsset: Asset, requestedAmount: Amount, sellerProgram: Program, sellerKey: PublicKey) locks amount of asset {
-  clause trade() {
-    lock requestedAmount of requestedAsset with sellerProgram
-    unlock amount of asset
-  }
-  clause cancel(sellerSig: Signature) {
-    verify checkTxSig(sellerKey, sellerSig)
-    unlock amount of asset
-  }
-}
-`
-
-const EscrowedTransfer = `
-contract EscrowedTransfer(agent: PublicKey, sender: Program, recipient: Program) locks amount of asset {
-  clause approve(sig: Signature) {
-    verify checkTxSig(agent, sig)
-    lock amount of asset with recipient
-  }
-  clause reject(sig: Signature) {
-    verify checkTxSig(agent, sig)
-    lock amount of asset with sender
-  }
-}
-`
-
-const RevealPreimage = `
-contract RevealPreimage(hash: Hash) locks amount of asset {
-  clause reveal(string: String) {
-    verify sha3(string) == hash
-    unlock amount of asset
-  }
-}
-`
-const PriceChanger = `
-contract PriceChanger(askAmount: Amount, askAsset: Asset, sellerKey: PublicKey, sellerProg: Program) locks valueAmount of valueAsset {
-  clause changePrice(newAmount: Amount, newAsset: Asset, sig: Signature) {
-    verify checkTxSig(sellerKey, sig)
-    lock valueAmount of valueAsset with PriceChanger(newAmount, newAsset, sellerKey, sellerProg)
-  }
-  clause redeem() {
-    lock askAmount of askAsset with sellerProg
-    unlock valueAmount of valueAsset
-  }
-}
-`
-
-const TestDefineVar = `
-contract TestDefineVar(result: Integer) locks valueAmount of valueAsset {
-  clause LockWithMath(left: Integer, right: Integer) {
-    define calculate: Integer = left + right
-    verify left != calculate
-    verify result == calculate
-    unlock valueAmount of valueAsset
-  }
-}
-`
-
-const TestAssignVar = `
-contract TestAssignVar(result: Integer) locks valueAmount of valueAsset {
-  clause LockWithMath(first: Integer, second: Integer) {
-    define calculate: Integer = first
-    assign calculate = calculate + second
-    verify result == calculate
-    unlock valueAmount of valueAsset
-  }
-}
-`
-
-const TestSigIf = `
-contract TestSigIf(a: Integer, count:Integer) locks valueAmount of valueAsset {
-  clause check(b: Integer, c: Integer) {
-    verify b != count
-    if a > b {
-        verify b > c
-    } else {
-        verify a > c
-    }
-    unlock valueAmount of valueAsset
-  }
-}
-`
-const TestIfAndMultiClause = `
-contract TestIfAndMultiClause(a: Integer, cancelKey: PublicKey) locks valueAmount of valueAsset {
-  clause check(b: Integer, c: Integer) {
-    verify b != c
-    if a > b {
-        verify a > c
-    }
-    unlock valueAmount of valueAsset
-  }
-  clause cancel(sellerSig: Signature) {
-    verify checkTxSig(cancelKey, sellerSig)
-    unlock valueAmount of valueAsset
-  }
-}
-`
-
-const TestIfNesting = `
-contract TestIfNesting(a: Integer, count:Integer) locks valueAmount of valueAsset {
-  clause check(b: Integer, c: Integer, d: Integer) {
-    verify b != count
-    if a > b {
-        if d > c {
-           verify a > d
-        }
-        verify d != b
-    } else {
-        verify a > c
-    }
-    verify c != count
-    unlock valueAmount of valueAsset
-  }
-  clause cancel(e: Integer, f: Integer) {
-    verify a != e
-    if a > f {
-      verify e > count
-    }
-    verify f != count
-    unlock valueAmount of valueAsset
-  }
-}
-`
-const TestConstantMath = `
-contract TestConstantMath(result: Integer, hashByte: Hash, hashStr: Hash, outcome: Boolean) locks valueAmount of valueAsset {
-  clause calculation(left: Integer, right: Integer, boolResult: Boolean) {
-    verify result == left + right + 10
-    verify hashByte == sha3(0x31323330)
-    verify hashStr == sha3('string')
-    verify !outcome
-    verify boolResult && (result == left + 20)
-    unlock valueAmount of valueAsset
-  }
-}
-`
diff --git a/compiler/import.go b/compiler/import.go
new file mode 100644 (file)
index 0000000..8989e87
--- /dev/null
@@ -0,0 +1,75 @@
+package compiler
+
+import (
+       "bufio"
+       "io/ioutil"
+       "os"
+       "path/filepath"
+)
+
+func parseImportDirectives(p *parser) []*Contract {
+       var result []*Contract
+       for peekKeyword(p) == "import" {
+               contracts := parseImportDirective(p)
+               for _, contract := range contracts {
+                       result = append(result, contract)
+               }
+       }
+       return result
+}
+
+func parseImportDirective(p *parser) []*Contract {
+       pathFile := parseImport(p)
+       if len(pathFile) == 0 {
+               p.errorf("Import path is empty")
+       }
+
+       // acquire absolute path and check the file status
+       importFile, err := absolutePath(string(pathFile))
+       if err != nil {
+               p.errorf("Check absolute path error: %v", err)
+       }
+
+       inputFile, err := os.Open(importFile)
+       if err != nil {
+               p.errorf("Open the import contract file \"%s\" error: %v", importFile, err)
+       }
+       defer inputFile.Close()
+
+       inputReader := bufio.NewReader(inputFile)
+       importContract, err := ioutil.ReadAll(inputReader)
+       if err != nil {
+               p.errorf("Read the import contract file \"%s\" error: %v", inputFile.Name(), err)
+       }
+
+       // parse the import contract
+       contracts, err := parse(importContract)
+       if err != nil {
+               p.errorf("Parse the import contract file \"%s\" error: %v", inputFile.Name(), err)
+       }
+       return contracts
+}
+
+func parseImport(p *parser) []byte {
+       consumeKeyword(p, "import")
+       importPathFile, newOffset := scanStrLiteral(p.buf, p.pos)
+       if newOffset < 0 {
+               p.errorf("Invalid import character format")
+       }
+       p.pos = newOffset
+
+       return importPathFile
+}
+
+func absolutePath(pathFile string) (string, error) {
+       absPathFile, err := filepath.Abs(pathFile)
+       if err != nil {
+               return "", err
+       }
+
+       // check the status of absolute path file
+       if _, err := os.Stat(absPathFile); err != nil {
+               return "", err
+       }
+       return absPathFile, nil
+}
index 956825e..0399eea 100644 (file)
@@ -44,14 +44,17 @@ func parse(buf []byte) (contracts []*Contract, err error) {
        return
 }
 
-// parse functions
-
+// parse contracts
 func parseContracts(p *parser) []*Contract {
        var result []*Contract
+       contracts := parseImportDirectives(p)
+       for _, c := range contracts {
+               result = append(result, c)
+       }
+
        if pos := scanKeyword(p.buf, p.pos, "contract"); pos < 0 {
                p.errorf("expected contract")
        }
-
        for peekKeyword(p) == "contract" {
                contract := parseContract(p)
                result = append(result, contract)
@@ -494,12 +497,12 @@ func scanIntLiteral(buf []byte, offset int) (integerLiteral, int) {
 
 func scanStrLiteral(buf []byte, offset int) (bytesLiteral, int) {
        offset = skipWsAndComments(buf, offset)
-       if offset >= len(buf) || buf[offset] != '\'' {
+       if offset >= len(buf) || !(buf[offset] == '\'' || buf[offset] == '"') {
                return bytesLiteral{}, -1
        }
        var byteBuf bytesLiteral
        for i := offset + 1; i < len(buf); i++ {
-               if buf[i] == '\'' {
+               if (buf[offset] == '\'' && buf[i] == '\'') || (buf[offset] == '"' && buf[i] == '"') {
                        return byteBuf, i + 1
                }
                if buf[i] == '\\' && i < len(buf)-1 {