func (p *Parser) parseClass() *ast.Class { if p.current.Typ == token.Abstract { p.expect(token.Class) } if p.current.Typ == token.Final { p.expect(token.Class) } switch p.next(); { case p.current.Typ == token.Identifier: case lexer.IsKeyword(p.current.Typ, p.current.Val): default: p.errorf("unexpected variable operand %s", p.current) } name := p.current.Val if p.peek().Typ == token.Extends { p.expect(token.Extends) p.expect(token.Identifier) } if p.peek().Typ == token.Implements { p.expect(token.Implements) p.expect(token.Identifier) for p.peek().Typ == token.Comma { p.expect(token.Comma) p.expect(token.Identifier) } } p.expect(token.BlockBegin) c := p.parseClassFields(&ast.Class{Name: name}) p.namespace.ClassesAndInterfaces[c.Name] = c return c }
func (p *Parser) parseFunctionDefinition() *ast.FunctionDefinition { def := &ast.FunctionDefinition{} if p.peek().Typ == token.AmpersandOperator { // This is a function returning a reference ... ignore this for now p.next() } if !p.accept(token.Identifier) { p.next() if !lexer.IsKeyword(p.current.Typ, p.current.Val) { p.errorf("bad function name: %s", p.current.Val) } } def.Name = p.current.Val def.Arguments = make([]*ast.FunctionArgument, 0) p.expect(token.OpenParen) if p.peek().Typ == token.CloseParen { p.expect(token.CloseParen) return def } def.Arguments = append(def.Arguments, p.parseFunctionArgument()) for { switch p.peek().Typ { case token.Comma: p.expect(token.Comma) def.Arguments = append(def.Arguments, p.parseFunctionArgument()) case token.CloseParen: p.expect(token.CloseParen) return def default: p.errorf("unexpected argument separator: %s", p.current) return def } } }
func (p *Parser) parseVariable() ast.Expr { var expr *ast.Variable p.expectCurrent(token.VariableOperator) switch p.next(); { case lexer.IsKeyword(p.current.Typ, p.current.Val): // keywords are all valid variable names fallthrough case p.current.Typ == token.Identifier: expr = ast.NewVariable(p.current.Val) case p.current.Typ == token.BlockBegin: expr = &ast.Variable{Name: p.parseNextExpression()} p.expect(token.BlockEnd) case p.current.Typ == token.VariableOperator: expr = &ast.Variable{Name: p.parseVariable()} default: p.errorf("unexpected variable operand %s", p.current) return nil } p.scope.Variable(expr) return expr }