func TestInstantiation(t *testing.T) { testStr := `<? $obj = new Obj::$classes['obj']($arg);` p := NewParser(testStr) a, errs := p.Parse() if len(errs) != 0 { t.Fatalf("Did not parse instantiation correctly: %s", errs) } tree := ast.ExpressionStmt{ast.AssignmentExpression{ Operator: "=", Assignee: ast.NewVariable("obj"), Value: &ast.NewExpression{ Class: ast.NewClassExpression("Obj", &ast.ArrayLookupExpression{ Array: ast.NewVariable("classes"), Index: &ast.Literal{Type: ast.String, Value: `'obj'`}, }), Arguments: []ast.Expression{ ast.NewVariable("arg"), }, }, }} if !assertEquals(a[0], tree) { t.Fatalf("Instantiation did not parse correctly") } }
func (p *Parser) parseIdentifier() (expr ast.Expr) { switch typ := p.peek().Typ; { case typ == token.OpenParen && !p.instantiation: // Function calls are okay here because we know they came with // a non-dynamic identifier. expr = p.parseFunctionCall(&ast.Identifier{Value: p.current.Val}) p.next() case typ == token.ScopeResolutionOperator: classIdent := p.current.Val p.next() // get onto ::, then we get to the next expr p.next() expr = ast.NewClassExpression(classIdent, p.parseOperand()) p.next() case p.instantiation: defer p.next() return &ast.Identifier{Value: p.current.Val} default: name := p.current.Val v := ast.NewVariable(p.current.Val) expr = ast.ConstantExpr{ Variable: v, } p.namespace.Constants[name] = append(p.namespace.Constants[name], v) p.next() } return expr }
// parseScopeResolutionFromKeyword specifically parses self::, static::, and parent:: func (p *Parser) parseScopeResolutionFromKeyword() ast.Expr { if p.peek().Typ == token.ScopeResolutionOperator { r := p.current.Val p.expect(token.ScopeResolutionOperator) p.next() expr := ast.NewClassExpression(r, p.parseOperand()) p.next() return expr } // TODO Error p.next() return nil }
func (p *Parser) parseIdentifier() (expr ast.Expression) { switch p.peek().typ { case token.OpenParen: // Function calls are okay here because we know they came with // a non-dynamic identifier. expr = p.parseFunctionCall(ast.Identifier{Value: p.current.val}) p.next() case token.ScopeResolutionOperator: classIdent := p.current.val p.next() // get onto ::, then we get to the next expr p.next() expr = ast.NewClassExpression(classIdent, p.parseOperand()) p.next() default: expr = ast.ConstantExpression{ Variable: ast.NewVariable(p.current.val), } p.next() } return expr }