mirror of
https://github.com/robertkrimen/otto
synced 2025-09-28 18:45:22 +08:00
273 lines
4.0 KiB
Go
273 lines
4.0 KiB
Go
package otto
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
"testing"
|
|
. "github.com/robertkrimen/terst"
|
|
)
|
|
|
|
func lexerCollect(source string) (result []_token) {
|
|
parser := newParser()
|
|
parser.lexer.Source = source
|
|
for {
|
|
token := parser.Next()
|
|
result = append(result, token)
|
|
if token.Error || token.Kind == "EOF" {
|
|
break
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
func lexerCollectAndTest(input string, arguments... string){
|
|
result := lexerCollect(input)
|
|
for index, expect := range arguments {
|
|
result := result[index]
|
|
got := result.Kind
|
|
if strings.Contains(expect, " ") {
|
|
got = fmt.Sprintf("%s %s", result.Kind, result.Text)
|
|
}
|
|
Is(got, expect)
|
|
}
|
|
}
|
|
|
|
func testLexerRead(lexer *_lexer, count int, wantRead []rune, wantWord string, wantFound, wantWidth int) {
|
|
haveRead, haveWord, haveFound, haveWidth := lexer.read(count)
|
|
Is(haveRead, wantRead)
|
|
Is(haveWord, wantWord)
|
|
Is(haveFound, wantFound)
|
|
Is(haveWidth, wantWidth)
|
|
}
|
|
|
|
func TestLexer(t *testing.T) {
|
|
Terst(t)
|
|
|
|
{
|
|
lexer := newLexer("")
|
|
token := lexer.Scan()
|
|
Is(token.Kind, "EOF")
|
|
|
|
lexer = newLexer("1")
|
|
token = lexer.Scan()
|
|
Is(token.Kind, "number")
|
|
}
|
|
|
|
{
|
|
test := testLexerRead
|
|
|
|
lexer := newLexer("")
|
|
test(&lexer, 1, []rune{-1}, "", 0, 0)
|
|
lexer.next()
|
|
test(&lexer, 1, []rune{-1}, "", 0, 0)
|
|
|
|
lexer = newLexer("1")
|
|
test(&lexer, 1, []rune{49}, "1", 1, 1)
|
|
lexer.next()
|
|
test(&lexer, 1, []rune{-1}, "", 0, 0)
|
|
lexer.next()
|
|
test(&lexer, 1, []rune{-1}, "", 0, 0)
|
|
|
|
lexer = newLexer("abc")
|
|
test(&lexer, 2, []rune{97, 98}, "ab", 2, 2)
|
|
lexer.next()
|
|
test(&lexer, 2, []rune{98, 99}, "bc", 2, 2)
|
|
lexer.next()
|
|
test(&lexer, 2, []rune{99, -1}, "c", 1, 1)
|
|
lexer.next()
|
|
test(&lexer, 2, []rune{-1, -1}, "", 0, 0)
|
|
|
|
lexer = newLexer("abcdef")
|
|
lexer.next()
|
|
lexer.next()
|
|
test(&lexer, 8, []rune{99, 100, 101, 102, -1, -1, -1, -1}, "cdef", 4, 4)
|
|
lexer.back()
|
|
test(&lexer, 8, []rune{98, 99, 100, 101, 102, -1, -1, -1}, "bcdef", 5, 5)
|
|
for limit := 8; limit > 0; limit-- {
|
|
lexer.back()
|
|
}
|
|
test(&lexer, 2, []rune{97, 98}, "ab", 2, 2)
|
|
// Should get the same thing twice.
|
|
test(&lexer, 2, []rune{97, 98}, "ab", 2, 2)
|
|
lexer.next()
|
|
test(&lexer, 2, []rune{98, 99}, "bc", 2, 2)
|
|
lexer.skip(1)
|
|
test(&lexer, 2, []rune{99, 100}, "cd", 2, 2)
|
|
lexer.skip(3)
|
|
test(&lexer, 2, []rune{102, -1}, "f", 1, 1)
|
|
}
|
|
}
|
|
|
|
|
|
func TestParserLexer(t *testing.T) {
|
|
Terst(t)
|
|
|
|
test := lexerCollectAndTest
|
|
|
|
test("",
|
|
"EOF",
|
|
)
|
|
|
|
test("1",
|
|
"number 1",
|
|
"EOF",
|
|
)
|
|
|
|
test(".0",
|
|
"number .0",
|
|
"EOF",
|
|
)
|
|
|
|
test("xyzzy",
|
|
"identifier xyzzy",
|
|
"EOF",
|
|
)
|
|
|
|
test("xyzzy(1)",
|
|
"identifier xyzzy",
|
|
"(",
|
|
"number 1",
|
|
")",
|
|
"EOF")
|
|
|
|
test(".",
|
|
".",
|
|
"EOF")
|
|
|
|
test(".0",
|
|
"number .0",
|
|
"EOF")
|
|
|
|
test("===.",
|
|
"===",
|
|
".",
|
|
"EOF")
|
|
|
|
test(">>>=",
|
|
">>>=",
|
|
"EOF")
|
|
|
|
test(">>>=.0",
|
|
">>>=",
|
|
"number .0",
|
|
"EOF")
|
|
|
|
test(">>>=0.0.",
|
|
">>>=",
|
|
"number 0.0",
|
|
".",
|
|
"EOF")
|
|
|
|
test("\"Xyzzy\"",
|
|
"string Xyzzy",
|
|
"EOF")
|
|
|
|
test("xyzzy = //",
|
|
"identifier xyzzy",
|
|
"=",
|
|
"EOF")
|
|
|
|
test("xyzzy = 1 / 2",
|
|
"identifier xyzzy",
|
|
"=",
|
|
"number 1",
|
|
"/",
|
|
"number 2",
|
|
"EOF")
|
|
|
|
test("xyzzy = 'Nothing happens.'",
|
|
"identifier xyzzy",
|
|
"=",
|
|
"string Nothing happens.",
|
|
"EOF")
|
|
|
|
test("xyzzy = !false",
|
|
"identifier xyzzy",
|
|
"=",
|
|
"!",
|
|
"boolean false",
|
|
"EOF")
|
|
|
|
test("xyzzy = !!true",
|
|
"identifier xyzzy",
|
|
"=",
|
|
"!",
|
|
"!",
|
|
"boolean true",
|
|
"EOF")
|
|
|
|
test("xyzzy *= 1",
|
|
"identifier xyzzy",
|
|
"*=",
|
|
"number 1",
|
|
"EOF")
|
|
|
|
test("if 1 else",
|
|
"if",
|
|
"number 1",
|
|
"else",
|
|
"EOF")
|
|
|
|
test("null",
|
|
"null",
|
|
"EOF")
|
|
|
|
test("3ea",
|
|
"illegal 3e",
|
|
)
|
|
|
|
test("3in",
|
|
"illegal 3i",
|
|
)
|
|
|
|
test(`"\u007a\x79\u000a\x78"`,
|
|
"string zy\nx",
|
|
)
|
|
|
|
test(`
|
|
"[First line \
|
|
Second line \
|
|
Third line\
|
|
. ]"
|
|
`,
|
|
"string [First line Second line Third line. ]",
|
|
)
|
|
|
|
test("/",
|
|
"/",
|
|
"EOF",
|
|
)
|
|
|
|
test("var abc = \"abc\uFFFFabc\"",
|
|
"var",
|
|
"identifier abc",
|
|
"=",
|
|
"string abc\uFFFFabc",
|
|
"EOF",
|
|
)
|
|
|
|
test(`'\t' === '\r'`,
|
|
"string \t",
|
|
"===",
|
|
"string \r",
|
|
"EOF",
|
|
)
|
|
|
|
test("\"Hello\nWorld\"",
|
|
"illegal \"Hello",
|
|
)
|
|
|
|
test("\u203f = 10",
|
|
"illegal",
|
|
)
|
|
|
|
test(`var \u0024 = 1`,
|
|
"var",
|
|
"identifier $",
|
|
"=",
|
|
"number 1",
|
|
"EOF",
|
|
)
|
|
|
|
}
|