github.com/nuvolaris/goja@v0.0.0-20230825100449-967811910c6d/parser/lexer_test.go (about)

     1  package parser
     2  
     3  import (
     4  	"testing"
     5  
     6  	"github.com/nuvolaris/goja/file"
     7  	"github.com/nuvolaris/goja/token"
     8  	"github.com/nuvolaris/goja/unistring"
     9  )
    10  
    11  func TestLexer(t *testing.T) {
    12  	tt(t, func() {
    13  		setup := func(src string) *_parser {
    14  			parser := newParser("", src)
    15  			return parser
    16  		}
    17  
    18  		test := func(src string, test ...interface{}) {
    19  			parser := setup(src)
    20  			for len(test) > 0 {
    21  				tkn, literal, _, idx := parser.scan()
    22  				if len(test) > 0 {
    23  					is(tkn, test[0].(token.Token))
    24  					test = test[1:]
    25  				}
    26  				if len(test) > 0 {
    27  					is(literal, unistring.String(test[0].(string)))
    28  					test = test[1:]
    29  				}
    30  				if len(test) > 0 {
    31  					// FIXME terst, Fix this so that cast to file.Idx is not necessary?
    32  					is(idx, file.Idx(test[0].(int)))
    33  					test = test[1:]
    34  				}
    35  			}
    36  		}
    37  
    38  		test("",
    39  			token.EOF, "", 1,
    40  		)
    41  
    42  		test("#!",
    43  			token.EOF, "", 3,
    44  		)
    45  
    46  		test("#!\n1",
    47  			token.NUMBER, "1", 4,
    48  			token.EOF, "", 5,
    49  		)
    50  
    51  		test("1",
    52  			token.NUMBER, "1", 1,
    53  			token.EOF, "", 2,
    54  		)
    55  
    56  		test(".0",
    57  			token.NUMBER, ".0", 1,
    58  			token.EOF, "", 3,
    59  		)
    60  
    61  		test("abc",
    62  			token.IDENTIFIER, "abc", 1,
    63  			token.EOF, "", 4,
    64  		)
    65  
    66  		test("abc(1)",
    67  			token.IDENTIFIER, "abc", 1,
    68  			token.LEFT_PARENTHESIS, "", 4,
    69  			token.NUMBER, "1", 5,
    70  			token.RIGHT_PARENTHESIS, "", 6,
    71  			token.EOF, "", 7,
    72  		)
    73  
    74  		test(".",
    75  			token.PERIOD, "", 1,
    76  			token.EOF, "", 2,
    77  		)
    78  
    79  		test("===.",
    80  			token.STRICT_EQUAL, "", 1,
    81  			token.PERIOD, "", 4,
    82  			token.EOF, "", 5,
    83  		)
    84  
    85  		test(">>>=.0",
    86  			token.UNSIGNED_SHIFT_RIGHT_ASSIGN, "", 1,
    87  			token.NUMBER, ".0", 5,
    88  			token.EOF, "", 7,
    89  		)
    90  
    91  		test(">>>=0.0.",
    92  			token.UNSIGNED_SHIFT_RIGHT_ASSIGN, "", 1,
    93  			token.NUMBER, "0.0", 5,
    94  			token.PERIOD, "", 8,
    95  			token.EOF, "", 9,
    96  		)
    97  
    98  		test("\"abc\"",
    99  			token.STRING, "\"abc\"", 1,
   100  			token.EOF, "", 6,
   101  		)
   102  
   103  		test("abc = //",
   104  			token.IDENTIFIER, "abc", 1,
   105  			token.ASSIGN, "", 5,
   106  			token.EOF, "", 9,
   107  		)
   108  
   109  		test("abc = 1 / 2",
   110  			token.IDENTIFIER, "abc", 1,
   111  			token.ASSIGN, "", 5,
   112  			token.NUMBER, "1", 7,
   113  			token.SLASH, "", 9,
   114  			token.NUMBER, "2", 11,
   115  			token.EOF, "", 12,
   116  		)
   117  
   118  		test("xyzzy = 'Nothing happens.'",
   119  			token.IDENTIFIER, "xyzzy", 1,
   120  			token.ASSIGN, "", 7,
   121  			token.STRING, "'Nothing happens.'", 9,
   122  			token.EOF, "", 27,
   123  		)
   124  
   125  		test("abc = !false",
   126  			token.IDENTIFIER, "abc", 1,
   127  			token.ASSIGN, "", 5,
   128  			token.NOT, "", 7,
   129  			token.BOOLEAN, "false", 8,
   130  			token.EOF, "", 13,
   131  		)
   132  
   133  		test("abc = !!true",
   134  			token.IDENTIFIER, "abc", 1,
   135  			token.ASSIGN, "", 5,
   136  			token.NOT, "", 7,
   137  			token.NOT, "", 8,
   138  			token.BOOLEAN, "true", 9,
   139  			token.EOF, "", 13,
   140  		)
   141  
   142  		test("abc *= 1",
   143  			token.IDENTIFIER, "abc", 1,
   144  			token.MULTIPLY_ASSIGN, "", 5,
   145  			token.NUMBER, "1", 8,
   146  			token.EOF, "", 9,
   147  		)
   148  
   149  		test("if 1 else",
   150  			token.IF, "if", 1,
   151  			token.NUMBER, "1", 4,
   152  			token.ELSE, "else", 6,
   153  			token.EOF, "", 10,
   154  		)
   155  
   156  		test("null",
   157  			token.NULL, "null", 1,
   158  			token.EOF, "", 5,
   159  		)
   160  
   161  		test(`"\u007a\x79\u000a\x78"`,
   162  			token.STRING, "\"\\u007a\\x79\\u000a\\x78\"", 1,
   163  			token.EOF, "", 23,
   164  		)
   165  
   166  		test(`"[First line \
   167  Second line \
   168   Third line\
   169  .     ]"
   170  	`,
   171  			token.STRING, "\"[First line \\\nSecond line \\\n Third line\\\n.     ]\"", 1,
   172  			token.EOF, "", 53,
   173  		)
   174  
   175  		test("/",
   176  			token.SLASH, "", 1,
   177  			token.EOF, "", 2,
   178  		)
   179  
   180  		test("var abc = \"abc\uFFFFabc\"",
   181  			token.VAR, "var", 1,
   182  			token.IDENTIFIER, "abc", 5,
   183  			token.ASSIGN, "", 9,
   184  			token.STRING, "\"abc\uFFFFabc\"", 11,
   185  			token.EOF, "", 22,
   186  		)
   187  
   188  		test(`'\t' === '\r'`,
   189  			token.STRING, "'\\t'", 1,
   190  			token.STRICT_EQUAL, "", 6,
   191  			token.STRING, "'\\r'", 10,
   192  			token.EOF, "", 14,
   193  		)
   194  
   195  		test(`var \u0024 = 1`,
   196  			token.VAR, "var", 1,
   197  			token.IDENTIFIER, "\\u0024", 5,
   198  			token.ASSIGN, "", 12,
   199  			token.NUMBER, "1", 14,
   200  			token.EOF, "", 15,
   201  		)
   202  
   203  		test("10e10000",
   204  			token.NUMBER, "10e10000", 1,
   205  			token.EOF, "", 9,
   206  		)
   207  
   208  		test(`var if var class`,
   209  			token.VAR, "var", 1,
   210  			token.IF, "if", 5,
   211  			token.VAR, "var", 8,
   212  			token.CLASS, "class", 12,
   213  			token.EOF, "", 17,
   214  		)
   215  
   216  		test(`-0`,
   217  			token.MINUS, "", 1,
   218  			token.NUMBER, "0", 2,
   219  			token.EOF, "", 3,
   220  		)
   221  
   222  		test(`.01`,
   223  			token.NUMBER, ".01", 1,
   224  			token.EOF, "", 4,
   225  		)
   226  
   227  		test(`.01e+2`,
   228  			token.NUMBER, ".01e+2", 1,
   229  			token.EOF, "", 7,
   230  		)
   231  
   232  		test(";",
   233  			token.SEMICOLON, "", 1,
   234  			token.EOF, "", 2,
   235  		)
   236  
   237  		test(";;",
   238  			token.SEMICOLON, "", 1,
   239  			token.SEMICOLON, "", 2,
   240  			token.EOF, "", 3,
   241  		)
   242  
   243  		test("//",
   244  			token.EOF, "", 3,
   245  		)
   246  
   247  		test(";;//",
   248  			token.SEMICOLON, "", 1,
   249  			token.SEMICOLON, "", 2,
   250  			token.EOF, "", 5,
   251  		)
   252  
   253  		test("1",
   254  			token.NUMBER, "1", 1,
   255  		)
   256  
   257  		test("12 123",
   258  			token.NUMBER, "12", 1,
   259  			token.NUMBER, "123", 4,
   260  		)
   261  
   262  		test("1.2 12.3",
   263  			token.NUMBER, "1.2", 1,
   264  			token.NUMBER, "12.3", 5,
   265  		)
   266  
   267  		test("/ /=",
   268  			token.SLASH, "", 1,
   269  			token.QUOTIENT_ASSIGN, "", 3,
   270  		)
   271  
   272  		test(`"abc"`,
   273  			token.STRING, `"abc"`, 1,
   274  		)
   275  
   276  		test(`'abc'`,
   277  			token.STRING, `'abc'`, 1,
   278  		)
   279  
   280  		test("++",
   281  			token.INCREMENT, "", 1,
   282  		)
   283  
   284  		test(">",
   285  			token.GREATER, "", 1,
   286  		)
   287  
   288  		test(">=",
   289  			token.GREATER_OR_EQUAL, "", 1,
   290  		)
   291  
   292  		test(">>",
   293  			token.SHIFT_RIGHT, "", 1,
   294  		)
   295  
   296  		test(">>=",
   297  			token.SHIFT_RIGHT_ASSIGN, "", 1,
   298  		)
   299  
   300  		test(">>>",
   301  			token.UNSIGNED_SHIFT_RIGHT, "", 1,
   302  		)
   303  
   304  		test(">>>=",
   305  			token.UNSIGNED_SHIFT_RIGHT_ASSIGN, "", 1,
   306  		)
   307  
   308  		test("1 \"abc\"",
   309  			token.NUMBER, "1", 1,
   310  			token.STRING, "\"abc\"", 3,
   311  		)
   312  
   313  		test(",",
   314  			token.COMMA, "", 1,
   315  		)
   316  
   317  		test("1, \"abc\"",
   318  			token.NUMBER, "1", 1,
   319  			token.COMMA, "", 2,
   320  			token.STRING, "\"abc\"", 4,
   321  		)
   322  
   323  		test("new abc(1, 3.14159);",
   324  			token.NEW, "new", 1,
   325  			token.IDENTIFIER, "abc", 5,
   326  			token.LEFT_PARENTHESIS, "", 8,
   327  			token.NUMBER, "1", 9,
   328  			token.COMMA, "", 10,
   329  			token.NUMBER, "3.14159", 12,
   330  			token.RIGHT_PARENTHESIS, "", 19,
   331  			token.SEMICOLON, "", 20,
   332  		)
   333  
   334  		test("1 == \"1\"",
   335  			token.NUMBER, "1", 1,
   336  			token.EQUAL, "", 3,
   337  			token.STRING, "\"1\"", 6,
   338  		)
   339  
   340  		test("1\n[]\n",
   341  			token.NUMBER, "1", 1,
   342  			token.LEFT_BRACKET, "", 3,
   343  			token.RIGHT_BRACKET, "", 4,
   344  		)
   345  
   346  		test("1\ufeff[]\ufeff",
   347  			token.NUMBER, "1", 1,
   348  			token.LEFT_BRACKET, "", 5,
   349  			token.RIGHT_BRACKET, "", 6,
   350  		)
   351  
   352  		test("x ?.30 : false",
   353  			token.IDENTIFIER, "x", 1,
   354  			token.QUESTION_MARK, "", 3,
   355  			token.NUMBER, ".30", 4,
   356  			token.COLON, "", 8,
   357  			token.BOOLEAN, "false", 10,
   358  		)
   359  
   360  		test("a\n?.b",
   361  			token.IDENTIFIER, "a", 1,
   362  			token.QUESTION_DOT, "", 3,
   363  			token.IDENTIFIER, "b", 5,
   364  		)
   365  
   366  		// ILLEGAL
   367  
   368  		test(`3ea`,
   369  			token.ILLEGAL, "3e", 1,
   370  			token.IDENTIFIER, "a", 3,
   371  			token.EOF, "", 4,
   372  		)
   373  
   374  		test(`3in`,
   375  			token.ILLEGAL, "3", 1,
   376  			token.IN, "in", 2,
   377  			token.EOF, "", 4,
   378  		)
   379  
   380  		test("\"Hello\nWorld\"",
   381  			token.ILLEGAL, "", 1,
   382  			token.IDENTIFIER, "World", 8,
   383  			token.ILLEGAL, "", 13,
   384  			token.EOF, "", 14,
   385  		)
   386  
   387  		test("\u203f = 10",
   388  			token.ILLEGAL, "", 1,
   389  			token.ASSIGN, "", 5,
   390  			token.NUMBER, "10", 7,
   391  			token.EOF, "", 9,
   392  		)
   393  
   394  		test(`"\x0G"`,
   395  			token.ILLEGAL, "\"\\x0G\"", 1,
   396  			//token.STRING, "\"\\x0G\"", 1,
   397  			token.EOF, "", 7,
   398  		)
   399  
   400  	})
   401  }