package scanner import ( "testing" "github.com/z7zmey/php-parser/freefloating" "github.com/z7zmey/php-parser/position" "gotest.tools/assert" ) type lval struct { Tkn *Token } func (lv *lval) Token(t *Token) { lv.Tkn = t } func TestTokens(t *testing.T) { src := `inline html - <=> != <> !== == === <<= >>= >= <= ** << >> ?? # inline comment // inline comment /* multiline comment */ /** * PHP Doc comment */ ; : , . [ ] ( ) | / ^ & + - * = % ! ~ $ < > ? @ { } $var str -> ` + "\t\r\n" + ` ->prop ( array ) ( bool ) ( boolean ) ( real ) ( double ) ( float ) ( int ) ( integer ) ( object ) ( string ) ( binary ) ( unset ) ` expected := []string{ T_INLINE_HTML.String(), TokenID(int(';')).String(), T_INLINE_HTML.String(), T_ECHO.String(), TokenID(int(';')).String(), T_INLINE_HTML.String(), T_ABSTRACT.String(), T_ARRAY.String(), T_AS.String(), T_BREAK.String(), T_CALLABLE.String(), T_CASE.String(), T_CATCH.String(), T_CLASS.String(), T_CLONE.String(), T_CONST.String(), T_CONTINUE.String(), T_DECLARE.String(), T_DEFAULT.String(), T_DO.String(), T_ECHO.String(), T_ELSE.String(), T_ELSEIF.String(), T_EMPTY.String(), T_ENDDECLARE.String(), T_ENDFOR.String(), T_ENDFOREACH.String(), T_ENDIF.String(), T_ENDSWITCH.String(), T_ENDWHILE.String(), T_EVAL.String(), T_EXIT.String(), T_EXTENDS.String(), T_FINAL.String(), T_FINALLY.String(), T_FOR.String(), T_FOREACH.String(), T_FUNCTION.String(), T_FUNCTION.String(), T_GLOBAL.String(), T_GOTO.String(), T_IF.String(), T_ISSET.String(), T_IMPLEMENTS.String(), T_INSTANCEOF.String(), T_INSTEADOF.String(), T_INTERFACE.String(), T_LIST.String(), T_NAMESPACE.String(), T_PRIVATE.String(), T_PUBLIC.String(), T_PRINT.String(), T_PROTECTED.String(), T_RETURN.String(), T_STATIC.String(), T_SWITCH.String(), T_THROW.String(), T_TRAIT.String(), T_TRY.String(), T_UNSET.String(), T_USE.String(), T_VAR.String(), T_WHILE.String(), T_YIELD_FROM.String(), T_YIELD.String(), T_INCLUDE.String(), T_INCLUDE_ONCE.String(), T_REQUIRE.String(), T_REQUIRE_ONCE.String(), T_CLASS_C.String(), T_DIR.String(), T_FILE.String(), T_FUNC_C.String(), T_LINE.String(), T_NS_C.String(), T_METHOD_C.String(), T_TRAIT_C.String(), T_HALT_COMPILER.String(), T_NEW.String(), T_LOGICAL_AND.String(), T_LOGICAL_OR.String(), T_LOGICAL_XOR.String(), T_NS_SEPARATOR.String(), T_ELLIPSIS.String(), T_PAAMAYIM_NEKUDOTAYIM.String(), T_BOOLEAN_AND.String(), T_BOOLEAN_OR.String(), T_AND_EQUAL.String(), T_OR_EQUAL.String(), T_CONCAT_EQUAL.String(), T_MUL_EQUAL.String(), T_POW_EQUAL.String(), T_DIV_EQUAL.String(), T_PLUS_EQUAL.String(), T_MINUS_EQUAL.String(), T_XOR_EQUAL.String(), T_MOD_EQUAL.String(), T_DEC.String(), T_INC.String(), T_DOUBLE_ARROW.String(), T_SPACESHIP.String(), T_IS_NOT_EQUAL.String(), T_IS_NOT_EQUAL.String(), T_IS_NOT_IDENTICAL.String(), T_IS_EQUAL.String(), T_IS_IDENTICAL.String(), T_SL_EQUAL.String(), T_SR_EQUAL.String(), T_IS_GREATER_OR_EQUAL.String(), T_IS_SMALLER_OR_EQUAL.String(), T_POW.String(), T_SL.String(), T_SR.String(), T_COALESCE.String(), TokenID(int(';')).String(), TokenID(int(':')).String(), TokenID(int(',')).String(), TokenID(int('.')).String(), TokenID(int('[')).String(), TokenID(int(']')).String(), TokenID(int('(')).String(), TokenID(int(')')).String(), TokenID(int('|')).String(), TokenID(int('/')).String(), TokenID(int('^')).String(), TokenID(int('&')).String(), TokenID(int('+')).String(), TokenID(int('-')).String(), TokenID(int('*')).String(), TokenID(int('=')).String(), TokenID(int('%')).String(), TokenID(int('!')).String(), TokenID(int('~')).String(), TokenID(int('$')).String(), TokenID(int('<')).String(), TokenID(int('>')).String(), TokenID(int('?')).String(), TokenID(int('@')).String(), TokenID(int('{')).String(), TokenID(int('}')).String(), T_VARIABLE.String(), T_STRING.String(), T_OBJECT_OPERATOR.String(), T_OBJECT_OPERATOR.String(), T_STRING.String(), T_ARRAY_CAST.String(), T_BOOL_CAST.String(), T_BOOL_CAST.String(), T_DOUBLE_CAST.String(), T_DOUBLE_CAST.String(), T_DOUBLE_CAST.String(), T_INT_CAST.String(), T_INT_CAST.String(), T_OBJECT_CAST.String(), T_STRING_CAST.String(), T_STRING_CAST.String(), T_UNSET_CAST.String(), } lexer := NewLexer([]byte(src)) lexer.WithFreeFloating = true lv := &lval{} actual := []string{} for { token := lexer.Lex(lv) if token == 0 { break } actual = append(actual, TokenID(token).String()) } assert.DeepEqual(t, expected, actual) } func TestNumberTokens(t *testing.T) { src := `prop $var[1] $var[0x1] $var[0b1] $var[var_name] $var[$var] {$var} ${var_name} {s $ \$a CAT; ` expected := []string{ T_START_HEREDOC.String(), T_ENCAPSED_AND_WHITESPACE.String(), T_END_HEREDOC.String(), TokenID(int(';')).String(), T_START_HEREDOC.String(), T_ENCAPSED_AND_WHITESPACE.String(), T_END_HEREDOC.String(), TokenID(int(';')).String(), T_START_HEREDOC.String(), T_ENCAPSED_AND_WHITESPACE.String(), T_VARIABLE.String(), T_OBJECT_OPERATOR.String(), T_STRING.String(), T_ENCAPSED_AND_WHITESPACE.String(), T_VARIABLE.String(), TokenID(int('[')).String(), T_NUM_STRING.String(), TokenID(int(']')).String(), T_ENCAPSED_AND_WHITESPACE.String(), T_VARIABLE.String(), TokenID(int('[')).String(), T_NUM_STRING.String(), TokenID(int(']')).String(), T_ENCAPSED_AND_WHITESPACE.String(), T_VARIABLE.String(), TokenID(int('[')).String(), T_NUM_STRING.String(), TokenID(int(']')).String(), T_ENCAPSED_AND_WHITESPACE.String(), T_VARIABLE.String(), TokenID(int('[')).String(), T_STRING.String(), TokenID(int(']')).String(), T_ENCAPSED_AND_WHITESPACE.String(), T_VARIABLE.String(), TokenID(int('[')).String(), T_VARIABLE.String(), TokenID(int(']')).String(), T_ENCAPSED_AND_WHITESPACE.String(), T_CURLY_OPEN.String(), T_VARIABLE.String(), TokenID(int('}')).String(), T_ENCAPSED_AND_WHITESPACE.String(), T_DOLLAR_OPEN_CURLY_BRACES.String(), T_STRING_VARNAME.String(), TokenID(int('}')).String(), T_ENCAPSED_AND_WHITESPACE.String(), T_END_HEREDOC.String(), TokenID(int(';')).String(), } lexer := NewLexer([]byte(src)) lexer.WithFreeFloating = true lv := &lval{} actual := []string{} for { token := lexer.Lex(lv) if token == 0 { break } actual = append(actual, TokenID(token).String()) } assert.DeepEqual(t, expected, actual) } func TestHereDocTokens2(t *testing.T) { src := ` test test ` expected := []string{ T_VARIABLE.String(), TokenID(int(';')).String(), T_INLINE_HTML.String(), T_VARIABLE.String(), TokenID(int(';')).String(), T_INLINE_HTML.String(), } lexer := NewLexer([]byte(src)) lexer.WithFreeFloating = true lv := &lval{} actual := []string{} for { token := lexer.Lex(lv) if token == 0 { break } actual = append(actual, TokenID(token).String()) } assert.DeepEqual(t, expected, actual) } func TestStringTokensAfterVariable(t *testing.T) { src := ` test` expected := []freefloating.String{ { Value: " bar ( '' ) ;` lexer := NewLexer([]byte(src)) lexer.WithFreeFloating = true lv := &lval{} expected := []freefloating.String{ { Value: "