Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/Java/Netbeans/php/php.editor/tools/   (Apache JAVA IDE Version 28©)  Datei vom 3.10.2025 mit Größe 166 kB image not shown  

Impressum ASTPHP5Parser.cup   Interaktion und
Portierbarkeitunbekannt

 
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.netbeans.modules.php.editor.parser;

import java.util.*;
import org.netbeans.modules.csl.api.OffsetRange;
import org.netbeans.modules.php.editor.parser.astnodes.*;
import org.openide.util.Pair;

parser code {:
    private static short[][] getActionTable() {}

    enum Access {
        NON_STATIC, STATIC, NULLSAFE
    }
    protected final static Integer IMPLICIT_PUBLIC = Integer.valueOf(BodyDeclaration.Modifier.IMPLICIT_PUBLIC);
    protected final static Integer PUBLIC = Integer.valueOf(BodyDeclaration.Modifier.PUBLIC);
    protected final static Integer PRIVATE = Integer.valueOf(BodyDeclaration.Modifier.PRIVATE);
    protected final static Integer PROTECTED = Integer.valueOf(BodyDeclaration.Modifier.PROTECTED);
    protected final static Integer PUBLIC_SET = Integer.valueOf(BodyDeclaration.Modifier.PUBLIC_SET);
    protected final static Integer PRIVATE_SET = Integer.valueOf(BodyDeclaration.Modifier.PRIVATE_SET);
    protected final static Integer PROTECTED_SET = Integer.valueOf(BodyDeclaration.Modifier.PROTECTED_SET);
    protected final static Integer ABSTRACT = Integer.valueOf(BodyDeclaration.Modifier.ABSTRACT);
    protected final static Integer FINAL = Integer.valueOf(BodyDeclaration.Modifier.FINAL);
    protected final static Integer STATIC = Integer.valueOf(BodyDeclaration.Modifier.STATIC);
    protected final static Integer READONLY = Integer.valueOf(BodyDeclaration.Modifier.READONLY);

    private ErrorStrategy defaultStrategy = new DefaultErrorStrategy();;
    private ErrorStrategy errorStrategy = defaultStrategy;

    private ParserErrorHandler errorHandler = null;
    private String fileName = null;
    private int anonymousClassCounter = 0;


    public void setErrorHandler (ParserErrorHandler handler) {
        this.errorHandler = handler;
    }

    public ParserErrorHandler getErrorHandler () {
        return this.errorHandler;
    }

    public String getFileName() {
        return fileName;
    }

    public void setFileName(String fileName) {
        assert fileName != null;
        this.fileName = fileName;
    }

    public int incrementAndGetAnonymousClassCounter() {
        anonymousClassCounter++;
        return anonymousClassCounter;
    }

    public VariableBase createDispatch(VariableBase dispatcher, Pair<Expression, Access> pair, List dimensions) {
        VariableBase dispatch = null;
        Expression property = pair.first();
        Access access = pair.second();
        if (property instanceof DereferencedArrayAccess) {
            DereferencedArrayAccess arrayAccess = (DereferencedArrayAccess) property;
            dimensions = new LinkedList();
            dimensions.add(arrayAccess.getDimension());
            while (arrayAccess.getDispatcher() instanceof DereferencedArrayAccess) {
                arrayAccess = (DereferencedArrayAccess) arrayAccess.getDispatcher();
                ((LinkedList) dimensions).addFirst(arrayAccess.getDimension());
            }
            property = arrayAccess.getDispatcher();
        }
        if (property instanceof Variable) {
            if (access == Access.STATIC) {
                Variable variable = (Variable) property;
                if (variable.isDollared() || variable instanceof ArrayAccess) {
                    dispatch = new StaticFieldAccess(dispatcher.getStartOffset(), property.getEndOffset(), dispatcher, (Variable) property);
                } else {
                    Expression varName = variable.getName();
                    // it should always be identifier
                    String name = varName instanceof Identifier ? ((Identifier) varName).getName() : "";
                    dispatch = new StaticConstantAccess(dispatcher.getStartOffset(), property.getEndOffset(), dispatcher,
                            new Identifier(variable.getStartOffset(), variable.getEndOffset(), name));
                }
            } else {
                boolean isNullsafe = access == Access.NULLSAFE;
                dispatch = new FieldAccess(dispatcher.getStartOffset(), property.getEndOffset(), dispatcher, (Variable)property, isNullsafe);
            }
        } else if (property instanceof FunctionInvocation) {
            if (access == Access.STATIC) {
                dispatch = new StaticMethodInvocation(dispatcher.getStartOffset(), property.getEndOffset(), dispatcher, (FunctionInvocation)property);
            } else {
                boolean isNullsafe = access == Access.NULLSAFE;
                dispatch = new MethodInvocation(dispatcher.getStartOffset(), property.getEndOffset(), dispatcher, (FunctionInvocation)property, isNullsafe);
            }
        } else if (property instanceof ExpressionArrayAccess || property instanceof Identifier) {
            dispatch = new StaticConstantAccess(dispatcher.getStartOffset(), property.getEndOffset(), dispatcher, property);
        } else {
            throw new IllegalArgumentException("Unexpected class: " + property.getClass().getName());
        }

        if (dimensions != null) {
            for (Object i : dimensions) {
                ArrayDimension index = (ArrayDimension) i;
                dispatch = new DereferencedArrayAccess(dispatch.getStartOffset(), index.getEndOffset(), dispatch, index);
            }
        }
        return dispatch;
    }

    public VariableBase createDispatch(VariableBase dispatcher, VariableBase property, List dimensions, Access access) {
        return createDispatch(dispatcher, Pair.of(property, access), null);
    }

    public VariableBase createDispatch(VariableBase dispatcher, VariableBase property, Access access) {
        return createDispatch(dispatcher, property, null, access);
    }

    public VariableBase createDispatch(Access access, VariableBase var, Expression memberProperty, int memberPropertyleft, int memberPropertyright,
            List<Expression> paramsList, int paramsListright, List propertyList, List aa) {
        Expression firstVarProperty = null;
        if (paramsList == null) {
            firstVarProperty = memberProperty;
        } else {
            FunctionName functionName = new FunctionName(memberPropertyleft, memberPropertyright, memberProperty);
            firstVarProperty = new FunctionInvocation(memberPropertyleft, paramsListright, functionName, paramsList);
        }

        // then get the aggregated list of properties ([->|?->|::]...[->|?->|::]...[->|?->|::]...)
        LinkedList list = (LinkedList) propertyList;
        list.addFirst(Pair.of(firstVarProperty, access));

        // now create the dispatch(es) nodes
        VariableBase dispatch = null;
        VariableBase dispatcher = var;
        List arrayDimensiones = aa;
        Iterator listIt = list.iterator();
        while (listIt.hasNext()) {
            Pair<Expression, Access> property = (Pair<Expression, Access>) listIt.next();
            dispatch = createDispatch(dispatcher, property, arrayDimensiones);
            dispatcher = dispatch;
            arrayDimensiones = new LinkedList();
        }
        return dispatch;
    }

    public Pair<Expression, Access> createDispatchProperty(Access access, Expression memberProperty, int memberPropertyleft, int memberPropertyright,
            List<Expression> paramsList, int paramsListright, List aa) {
        Expression result = null;
        if (paramsList == null) {
            result = memberProperty;
        } else {
            FunctionName functionName = new FunctionName(memberPropertyleft, memberPropertyright, memberProperty);
            result = new FunctionInvocation(memberPropertyleft, paramsListright, functionName, paramsList);
        }
        if (result instanceof VariableBase) {
            for (Object i : aa) {
                ArrayDimension index = (ArrayDimension) i;
                result = new DereferencedArrayAccess(result.getStartOffset(), index.getEndOffset(), (VariableBase) result, index);
            }
        }
        return Pair.of(result, access);
    }

    ClassName createClassName(VariableBase var, VariableBase firstVarProperty, List<Pair<VariableBase, Access>> propertyList, int varleft, int propertyListright, Access access) {
        // then get the aggregated list of properties ([->|?->]...[->|?->]...[->|?->]...)
        LinkedList<Pair<VariableBase, Access>> list = (LinkedList<Pair<VariableBase, Access>>) propertyList;
        list.addFirst(Pair.of(firstVarProperty, access));

        // now create the dispatch(es) nodes
        VariableBase dispatch = null;
        VariableBase dispatcher = var;
        Iterator<Pair<VariableBase, Access>> listIt = list.iterator();
        while (listIt.hasNext()) {
            Pair<VariableBase, Access> property = listIt.next();
            dispatch = createDispatch(dispatcher, property.first(), property.second());
            dispatcher = dispatch;
        }

        // create class name from the dispatch
        return new ClassName(varleft, propertyListright, dispatch);
    }

    Statement createAttributedStatement(Statement statement, List<Attribute> attributes) {
        Statement attributedStatement = statement;
        if (statement instanceof FunctionDeclaration) {
            attributedStatement = FunctionDeclaration.create((FunctionDeclaration) statement, attributes);
        } else if (statement instanceof ClassDeclaration) {
            attributedStatement = ClassDeclaration.create((ClassDeclaration) statement, attributes);
        } else if (statement instanceof InterfaceDeclaration) {
            attributedStatement = InterfaceDeclaration.create((InterfaceDeclaration) statement, attributes);
        } else if (statement instanceof TraitDeclaration) {
            attributedStatement = TraitDeclaration.create((TraitDeclaration) statement, attributes);
        } else if (statement instanceof FieldsDeclaration) {
            attributedStatement = FieldsDeclaration.create((FieldsDeclaration) statement, attributes);
        } else if (statement instanceof ConstantDeclaration) {
            attributedStatement = ConstantDeclaration.create((ConstantDeclaration) statement, attributes);
        } else if (statement instanceof MethodDeclaration) {
            attributedStatement = MethodDeclaration.create((MethodDeclaration) statement, attributes);
        } else if (statement instanceof EnumDeclaration) {
            attributedStatement = EnumDeclaration.create((EnumDeclaration) statement, attributes);
        } else if (statement instanceof CaseDeclaration) {
            attributedStatement = CaseDeclaration.create((CaseDeclaration) statement, attributes);
        } else {
            assert false;
        }
        return attributedStatement;
    }

    List<Identifier> createNamespaceNameSegments(int start, String name) {
        assert name != null;
        String[] names = name.split("\\\\"); // NOI18N
        int startSegment = start;
        List<Identifier> list = new ArrayList<>();
        for (String n : names) {
            if (n.equals("namespace") || n.isEmpty()) { // NOI18N
                startSegment += n.length() + 1; // length + \
                continue;
            }
            list.add(new Identifier(startSegment, startSegment + n.length(), n));
            startSegment += n.length() + 1; // length + \
        }
        return list;
    }

    interface ErrorStrategy {
        public boolean errorRecovery(boolean debug) throws Exception;
    }

    class DefaultErrorStrategy implements ErrorStrategy {

        public boolean errorRecovery(boolean debug) throws Exception {
            return ASTPHP5Parser.super.error_recovery(debug);
        }
    }

    /**
     * Attempt to recover from a syntax error.  This returns false if recovery fails,
     * true if it succeeds.
     * @param debug should we produce debugging messages as we parse.
     */
    protected boolean error_recovery(boolean debug) throws java.lang.Exception {
        return errorStrategy.errorRecovery(debug);
    }

    /**
     * Report a non fatal error (or warning).  This method takes a message
     * string and an additional object (to be used by specializations implemented in subclasses).
     * The super class prints the message to System.err.
     * @param message an error message.
     * @param info    an extra object reserved for use by specialized subclasses.
     */
    public void report_error(String message, Object info) {
        System.out.print("report_eror"  + message);
    }

    /**
     * This method is called when a syntax error has been detected and recovery is about to be invoked.
     * The super class just emit a "Syntax error" error message.
     * @param cur_token the current lookahead Symbol.
     */
    public void syntax_error(java_cup.runtime.Symbol cur_token) {
        java_cup.runtime.Symbol symbol = (java_cup.runtime.Symbol)stack.peek();
        int state = symbol.parse_state;
        short[] rowOfProbe = action_tab[state];
        if (errorHandler != null) {
            errorHandler.handleError(ParserErrorHandler.Type.SYNTAX_ERROR, rowOfProbe, cur_token, symbol);
        }
     }

    void syntax_error() {
        syntax_error(cur_token);
    }

    /**
     * Report a fatal error.  This method takes a message string and an additional object
     * (to be used by specializations implemented in subclasses).
     * The super class reports the error then throws an exception.
     * @param message an error message.
     * @param info    an extra object reserved for use by specialized subclasses.
     */
    public void report_fatal_error(String message, Object info) throws Exception {
        if (errorHandler != null) {
            errorHandler.handleError(ParserErrorHandler.Type.FATAL_PARSER_ERROR, null, cur_token, null);
        }
    }

    protected int error_sync_size() {
        return 1;
    }

:}

/*
 * terminals
 *
 * To keep existing values(see: ASTPHP5Symbols), add new one to end.
 * If the values are changed, it's incompatible.
 */

terminal String T_EXIT;
terminal String T_IF;
terminal String T_LNUMBER;
terminal String T_DNUMBER;
terminal String T_STRING;
terminal String T_STRING_VARNAME;
terminal String T_VARIABLE;
terminal String T_NUM_STRING;
terminal T_INLINE_HTML;
terminal String T_ENCAPSED_AND_WHITESPACE;
terminal String T_CONSTANT_ENCAPSED_STRING;
terminal String T_ECHO;
terminal String T_DO;
terminal String T_WHILE;
terminal String T_ENDWHILE;
terminal String T_FOR;
terminal String T_ENDFOR;
terminal String T_FOREACH;
terminal String T_ENDFOREACH;
terminal String T_DECLARE;
terminal String T_ENDDECLARE;
terminal String T_INSTANCEOF;
terminal String T_CLONE;
terminal String T_AS;
terminal String T_SWITCH;
terminal String T_ENDSWITCH;
terminal String T_MATCH;
terminal String T_CASE;
terminal String T_DEFAULT;
terminal String T_BREAK;
terminal String T_CONTINUE;
terminal String T_GOTO;
terminal String T_FN;
terminal String T_FUNCTION;
terminal String T_CONST;
terminal String T_RETURN;
terminal String T_YIELD;
terminal T_YIELD_FROM;
terminal String T_TRY;
terminal String T_CATCH;
terminal String T_THROW;
terminal String T_FINALLY;
terminal String T_USE;
terminal String T_GLOBAL;
terminal String T_VAR;
terminal String T_UNSET;
terminal String T_ISSET;
terminal String T_EMPTY;
terminal T_HALT_COMPILER;
terminal String T_CLASS;
terminal String T_INTERFACE;
terminal String T_EXTENDS;
terminal String T_IMPLEMENTS;
terminal T_OBJECT_OPERATOR;
terminal T_NULLSAFE_OBJECT_OPERATOR;
terminal T_DOUBLE_ARROW;
terminal String T_LIST;
terminal String T_ARRAY;
terminal String T_CALLABLE;
terminal String T_CLASS_C;
terminal String T_TRAIT_C;
terminal String T_METHOD_C;
terminal String T_FUNC_C;
terminal String T_LINE;
terminal String T_FILE;
terminal T_START_HEREDOC;
terminal T_END_HEREDOC;
terminal T_DOLLAR_OPEN_CURLY_BRACES;
terminal T_CURLY_OPEN_WITH_DOLAR;
terminal T_CURLY_OPEN;
terminal T_CURLY_CLOSE;
terminal T_PAAMAYIM_NEKUDOTAYIM;
terminal String T_NAMESPACE;
terminal String T_NS_C;
terminal String T_DIR;
terminal T_NS_SEPARATOR;
terminal String T_VAR_COMMENT;
terminal String T_DEFINE;

terminal String T_INCLUDE,T_INCLUDE_ONCE,T_EVAL,T_REQUIRE,T_REQUIRE_ONCE;
terminal T_COMMA;
terminal String T_LOGICAL_OR,T_LOGICAL_XOR,T_LOGICAL_AND,T_PRINT;
terminal T_EQUAL;
terminal T_PLUS_EQUAL,T_MINUS_EQUAL,T_MUL_EQUAL,T_DIV_EQUAL,T_CONCAT_EQUAL,T_MOD_EQUAL,T_AND_EQUAL,T_OR_EQUAL,T_XOR_EQUAL,T_SL_EQUAL,T_SR_EQUAL;
terminal T_QUESTION_MARK;
terminal T_SEMICOLON;
terminal T_BOOLEAN_OR, T_BOOLEAN_AND;
terminal T_OR;
terminal T_KOVA;
terminal T_REFERENCE;
terminal T_IS_EQUAL,T_IS_NOT_EQUAL,T_IS_IDENTICAL,T_IS_NOT_IDENTICAL;
terminal T_IS_SMALLER_OR_EQUAL,T_IS_GREATER_OR_EQUAL;
terminal T_SPACESHIP;
terminal T_RGREATER;
terminal T_LGREATER;
terminal T_SL,T_SR;
terminal T_PLUS;
terminal T_MINUS;
terminal T_TIMES;
terminal T_DIV;
terminal T_PRECENT;
terminal T_NOT;
terminal T_TILDA;
terminal T_NEKUDA;
terminal T_INC,T_DEC,T_INT_CAST,T_DOUBLE_CAST,T_STRING_CAST,T_ARRAY_CAST,T_OBJECT_CAST,T_BOOL_CAST,T_UNSET_CAST;
terminal T_AT;
terminal T_OPEN_RECT,T_CLOSE_RECT;
terminal String T_NEW;
terminal String T_ENDIF;
terminal String T_ELSEIF;
terminal String T_ELSE;
terminal String T_STATIC, T_ABSTRACT, T_FINAL, T_PRIVATE, T_PROTECTED, T_PUBLIC;
terminal T_OPEN_PARENTHESE,T_CLOSE_PARENTHESE;
terminal T_NEKUDOTAIM;
terminal T_DOLLAR;
terminal T_QUATE,T_BACKQUATE;
terminal T_START_NOWDOC, T_END_NOWDOC;
terminal String T_TRAIT;
terminal String T_INSTEADOF;
terminal T_POW;
terminal T_POW_EQUAL;
terminal T_ELLIPSIS;
terminal T_COALESCE;
terminal T_COALESCE_EQUAL;
terminal T_ATTRIBUTE;
terminal String T_READONLY;
terminal T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG; /* & */
terminal String T_ENUM; /* PHP 8.1 */
terminal String T_NAME_RELATIVE; /* PHP 8.0 namespace\Foo */
terminal String T_NAME_QUALIFIED; /* PHP 8.0 Foo\Bar */
terminal String T_NAME_FULLY_QUALIFIED; /* PHP 8.0 \Foo\Bar */
terminal String T_PUBLIC_SET, T_PROTECTED_SET, T_PRIVATE_SET; /* PHP 8.4 */

/* Non terminals */

non terminal Program thestart;
non terminal List namespace_name;
non terminal NamespaceName namespace_name_access;
non terminal NamespaceName legacy_namespace_name;
non terminal List namespace_declaration_name;
non terminal List group_namespace_parts;
non terminal List non_empty_group_namespace_parts;
non terminal SingleUseStatementPart group_namespace_part;
non terminal UseStatementPart use_declaration;
non terminal List use_declarations;
non terminal List top_statement_list;
non terminal Statement top_statement;
non terminal Statement statement;
non terminal List inner_statement_list;
non terminal Statement inner_statement;
non terminal Statement unticked_statement;
non terminal List unset_variables;
non terminal VariableBase unset_variable;
non terminal Expression use_filename;
non terminal Expression foreach_optional_arg;
non terminal Expression foreach_variable;
non terminal Statement for_statement;
non terminal Statement foreach_statement;
non terminal Statement declare_statement;
non terminal List[] declare_list;
non terminal Block switch_case_list;
non terminal List case_list;
non terminal case_separator;
non terminal Statement while_statement;
non terminal List[] elseif_list;
non terminal List[] new_elseif_list;
non terminal Statement else_single;
non terminal Statement new_else_single;
non terminal List parameter_list;
non terminal List lexical_vars;
non terminal List lexical_var_list;
non terminal List non_empty_parameter_list;
non terminal FormalParameter parameter;
non terminal List function_call_parameter_list;
non terminal List non_empty_function_call_parameter_list;
non terminal Expression argument;
non terminal Expression argument_expr;
non terminal List global_var_list;
non terminal VariableBase global_var;
non terminal List static_var_list;
non terminal List class_statement_list;
non terminal Statement class_statement;
non terminal Boolean is_reference;
non terminal Boolean is_variadic;
non terminal List echo_expr_list;
non terminal List for_expr;
non terminal List non_empty_for_expr;
non terminal Expression expr_without_variable;
non terminal Expression expr_without_variable_and_class_instance;
non terminal Expression callable_expr;
non terminal VariableBase function_call;
non terminal Expression exit_expr;
non terminal List ctor_arguments;
non terminal Expression common_scalar;
non terminal Expression static_scalar;
non terminal Expression static_scalar_with_class_instance;
non terminal Expression static_scalar_value;
non terminal Expression static_scalar_value_with_class_instance;
non terminal Expression static_operation;
non terminal Expression scalar;
non terminal List static_array_pair_list;
non terminal possible_comma;
non terminal List non_empty_static_array_pair_list;
non terminal Expression expr;
non terminal Expression expr_with_error;
non terminal Expression expr_with_yields;
non terminal Expression expr_with_yields_and_error;
non terminal Expression expr_without_class_instance;
non terminal Expression yield_expr;
non terminal Expression yield_from_expr;
non terminal Expression inline_function;
non terminal MatchExpression match;
non terminal List match_arm_list;
non terminal List non_empty_match_arm_list;
non terminal MatchArm match_arm;
non terminal List match_arm_condition_list;
non terminal ParenthesisExpression parenthesis_expr;
non terminal Variable reference_variable;
non terminal Variable variable_class_name;
non terminal Variable compound_variable;
non terminal Expression dim_offset;
non terminal ArrayDimension array_dimension;
non terminal ArrayDimension array_dimension_with_static_scalar_value;
non terminal List array_access_or_not;
non terminal Expression static_property;
non terminal VariableBase object_property;
non terminal VariableBase object_dim_list;
non terminal VariableBase variable_name;
non terminal Integer simple_indirect_reference;
non terminal List array_pair_list;
non terminal ArrayElement possible_array_pair;
non terminal ArrayElement array_pair;
non terminal List non_empty_array_pair_list;
non terminal List encaps_list;
non terminal VariableBase encaps_var;
non terminal Expression encaps_var_offset;
non terminal Expression internal_functions_in_yacc;
non terminal String string_st;
non terminal Integer interface_entry;
non terminal List interface_extends_list;
non terminal List use_traits;
non terminal Block use_traits_body;
non terminal List use_traits_body_statement_list;
non terminal Statement use_traits_body_statement;
non terminal Statement trait_conflict_resolution_declaration;
non terminal Statement trait_method_alias_declaration;
non terminal TraitMethodAliasDeclaration.Modifier traits_alias_modifier;
non terminal List trait_statement_list;
non terminal Statement trait_statement;
non terminal List interface_statement_list;
non terminal Statement interface_statement;
non terminal UseTraitStatementPart use_trait;
non terminal Quote heredoc;
non terminal VariableBase field_or_method_access;
non terminal Expression expression_array_access;
non terminal Expression constant_array_access;
non terminal Expression array_creation;
non terminal VariableBase array_creation_with_access;
non terminal ClassInstanceCreation anonymous_class;

non terminal VariableBase w_variable;
non terminal Expression class_name;
non terminal NamespaceName fully_qualified_class_name;
non terminal List class_variable_declaration;
non terminal Identifier reserved_non_modifiers_without_class;
non terminal Identifier semi_reserved_without_class;
non terminal Identifier identifier_without_class;
non terminal Identifier identifier;
non terminal Pair<Expression, List<ASTNode[]>> class_constant_declaration;
non terminal List constant_declaration;
non terminal Integer optional_property_modifiers;
non terminal Integer constant_modifiers;
non terminal Integer method_modifiers;
non terminal Block method_body;
non terminal List method_or_not;
non terminal List variable_properties;
non terminal FunctionDeclaration function_declaration_statement;
non terminal Statement class_declaration_statement;
non terminal VariableBase variable;
non terminal List additional_catches;
non terminal List non_empty_additional_catches;
non terminal CatchClause additional_catch;
non terminal List catch_class_names;
non terminal List additional_catch_class_names;
non terminal List non_empty_additional_catch_class_names;
non terminal Expression additional_catch_class_name;
non terminal FinallyClause additional_finally;
non terminal FunctionDeclaration unticked_function_declaration_statement;
non terminal Statement unticked_class_declaration_statement;
non terminal Map<ClassDeclaration.Modifier, Set<OffsetRange>> class_entry_type;
non terminal Map<ClassDeclaration.Modifier, Set<OffsetRange>> class_modifiers;
non terminal ClassDeclaration.Modifier class_modifier;
non terminal Expression extends_from;
non terminal List implements_list;
non terminal List interface_list;
non terminal Expression optional_class_type_without_static;
non terminal Expression type_expr;
non terminal Expression type_expr_without_static;
non terminal Expression class_type;
non terminal Expression class_type_without_static;
non terminal List<Expression> union_type;
non terminal Expression union_type_element;
non terminal List<Expression> union_type_without_static;
non terminal Expression union_type_without_static_element;
non terminal List<Expression> intersection_type;
non terminal List<Expression> intersection_type_without_static;
non terminal ampersand;
non terminal Expression optional_return_type;
non terminal VariableBase r_variable;
non terminal Integer variable_modifiers;
non terminal VariableBase rw_variable;
non terminal Variable variable_without_objects;
non terminal Pair<Expression, Boolean> variable_property;
non terminal VariableBase static_member;
non terminal List isset_variables;
non terminal Expression isset_variable;
non terminal Variable tracked_variable;
non terminal Variable optional_tracked_variable;
non terminal Integer abstract_modifier;
non terminal Integer final_modifier;
non terminal Integer readonly_modifier;
non terminal Integer static_modifier;
non terminal Integer ppp_modifiers;
non terminal Integer ppp_set_modifiers;
non terminal Integer af_modifiers;
non terminal Integer member_modifiers;
non terminal Integer non_empty_member_modifiers;

non terminal ClassName class_name_reference;
non terminal StaticConstantAccess class_constant;
non terminal StaticConstantAccess enum_constant;
non terminal ClassName dynamic_class_name_reference;
non terminal VariableBase dereferencable_variable;
non terminal VariableBase base_variable;
non terminal VariableBase base_variable_without_reference_variable;
non terminal List dynamic_class_name_variable_properties;
non terminal Pair<VariableBase, ASTPHP5Parser.Access> dynamic_class_name_variable_property;
non terminal VariableBase static_class_constant;
non terminal Expression static_reference_constant;
non terminal Expression static_array_creation_with_access;
non terminal Expression static_constant_array_access;
non terminal Expression static_class_constant_array_access;
non terminal Expression class_constant_array_access;
non terminal Expression static_array_creation;
non terminal VariableBase base_variable_with_function_calls;
non terminal Expression new_expr;
non terminal ASTPHP5Parser.Access access_operator;

non terminal Expression enum_backing_type;
non terminal Statement enum_case;
non terminal Expression enum_case_expr;

non terminal List class_name_list;
/*
 * NETBEANS-4443 PHP 8.0 Attribute Syntax
 * - https://wiki.php.net/rfc/attributes_v2
 * - https://wiki.php.net/rfc/shorter_attribute_syntax
 * - https://wiki.php.net/rfc/shorter_attribute_syntax_change
 */
non terminal Attribute attribute;
non terminal List<Attribute> attributes;
non terminal AttributeDeclaration attribute_decl;
non terminal List<AttributeDeclaration> attribute_group;
non terminal Statement attributed_statement;
non terminal Statement attributed_interface_statement;
non terminal Statement attributed_class_statement;
non terminal Statement attributed_trait_statement;
non terminal FormalParameter attributed_parameter;

precedence nonassoc T_THROW;
precedence left T_INCLUDE, T_INCLUDE_ONCE, T_EVAL, T_REQUIRE, T_REQUIRE_ONCE;
precedence left T_COMMA;
precedence left T_LOGICAL_OR;
precedence left T_LOGICAL_XOR;
precedence left T_LOGICAL_AND;
precedence right T_PRINT;
precedence right T_YIELD;
precedence right T_DOUBLE_ARROW;
precedence right T_YIELD_FROM;
precedence left T_EQUAL, T_PLUS_EQUAL,T_MINUS_EQUAL,T_MUL_EQUAL,T_DIV_EQUAL,T_CONCAT_EQUAL,T_MOD_EQUAL,T_AND_EQUAL,T_OR_EQUAL,T_XOR_EQUAL,T_SL_EQUAL,T_SR_EQUAL,T_POW_EQUAL,T_COALESCE_EQUAL;
precedence right T_POW;
precedence left T_QUESTION_MARK,T_SEMICOLON;
precedence left T_BOOLEAN_OR;
precedence left T_BOOLEAN_AND;
precedence left T_OR;
precedence left T_KOVA;
precedence left T_REFERENCE;
precedence left T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG;
precedence left T_ELLIPSIS;
precedence left T_COALESCE;

precedence nonassoc T_IS_EQUAL,T_IS_NOT_EQUAL,T_IS_IDENTICAL,T_IS_NOT_IDENTICAL;
precedence nonassoc T_RGREATER,T_IS_SMALLER_OR_EQUAL,T_LGREATER,T_IS_GREATER_OR_EQUAL,T_SPACESHIP;
precedence left T_SL,T_SR;
precedence left T_PLUS,T_MINUS,T_NEKUDA;
precedence left T_TIMES,T_DIV,T_PRECENT;
precedence right T_NOT;
precedence nonassoc T_INSTANCEOF;
precedence right T_TILDA,T_INC,T_DEC,T_INT_CAST,T_DOUBLE_CAST,T_STRING_CAST,T_ARRAY_CAST,T_OBJECT_CAST,T_BOOL_CAST,T_UNSET_CAST,T_AT;
precedence right T_CLOSE_PARENTHESE;
precedence right T_OPEN_RECT, T_CURLY_OPEN, T_OPEN_PARENTHESE;
precedence nonassoc T_NEW, T_CLONE;
precedence left T_ELSEIF;
precedence left T_ELSE;
precedence left T_ENDIF;
precedence right T_STATIC, T_ABSTRACT, T_FINAL, T_PRIVATE, T_PROTECTED, T_PUBLIC, T_READONLY, T_PUBLIC_SET, T_PROTECTED_SET, T_PRIVATE_SET;

thestart ::=
top_statement_list:statementList
{:
    ASTPHP5Scanner phpAstLexer5 = (ASTPHP5Scanner) parser.getScanner();
    List commentList = phpAstLexer5.getCommentList();
    int endOfProgram = statementListright > phpAstLexer5.getWhitespaceEndPosition() || phpAstLexer5.isEndedPhp() ? statementListright : phpAstLexer5.getWhitespaceEndPosition();
    Program program = new Program(statementListleft, endOfProgram, statementList, commentList);
    RESULT = program;
:}
;

namespace_name ::=
T_STRING:n
{:
    List list = new LinkedList();
    list.add(new Identifier(nleft, nright, n));
    RESULT = list;
:}

|
T_DEFINE:n
{:
    List list = new LinkedList();
    list.add(new Identifier(nleft, nright, "define"));
    RESULT = list;
:}

| T_NAME_QUALIFIED:name
{:
    // e.g. Foo\Bar
    RESULT = parser.createNamespaceNameSegments(nameleft, name);
:}
;

namespace_declaration_name ::=
identifier: identifier
{:
    // e.g. Foo
    List list = new LinkedList();
    list.add(identifier);
    RESULT = list;

:}

| T_NAME_QUALIFIED:name
{:
    // e.g. Foo\Bar
    RESULT = parser.createNamespaceNameSegments(nameleft, name);
:}
;

legacy_namespace_name ::=
namespace_name:list
{:
    RESULT = new NamespaceName(listleft, listright, list, false, false);
:}

| T_NAME_FULLY_QUALIFIED:name
{:
    // e.g. \Foo\Bar
    RESULT = NamespaceName.create(nameleft, nameright, name);
:}
;

namespace_name_access ::=
T_STRING:name
{:
    RESULT = NamespaceName.create(nameleft, nameright, name);
:}

| T_DEFINE:name
{:
    RESULT = NamespaceName.create(nameleft, nameright, name);
:}

| T_NAME_QUALIFIED:name
{:
    // e.g. Foo\Bar
    RESULT = NamespaceName.create(nameleft, nameright, name);
:}

| T_NAME_FULLY_QUALIFIED:name
{:
    // e.g. \Foo\Bar
    RESULT = NamespaceName.create(nameleft, nameright, name);
:}

| T_NAME_RELATIVE:name
{:
    // e.g. namespace\Foo\Bar
    RESULT = NamespaceName.create(nameleft, nameright, name);
:}
;

reserved_non_modifiers_without_class ::=
T_INCLUDE:reserved
{:
    RESULT = new Identifier(reservedleft, reservedright, reserved, true);
:}

| T_INCLUDE_ONCE:reserved
{:
    RESULT = new Identifier(reservedleft, reservedright, reserved, true);
:}

| T_EVAL:reserved
{:
    RESULT = new Identifier(reservedleft, reservedright, reserved, true);
:}

| T_REQUIRE:reserved
{:
    RESULT = new Identifier(reservedleft, reservedright, reserved, true);
:}

| T_REQUIRE_ONCE:reserved
{:
    RESULT = new Identifier(reservedleft, reservedright, reserved, true);
:}

| T_LOGICAL_OR:reserved
{:
    RESULT = new Identifier(reservedleft, reservedright, reserved, true);
:}

| T_LOGICAL_XOR:reserved
{:
    RESULT = new Identifier(reservedleft, reservedright, reserved, true);
:}

| T_LOGICAL_AND:reserved
{:
    RESULT = new Identifier(reservedleft, reservedright, reserved, true);
:}

| T_INSTANCEOF:reserved
{:
    RESULT = new Identifier(reservedleft, reservedright, reserved, true);
:}

| T_NEW:reserved
{:
    RESULT = new Identifier(reservedleft, reservedright, reserved, true);
:}

| T_CLONE:reserved
{:
    RESULT = new Identifier(reservedleft, reservedright, reserved, true);
:}

| T_EXIT:reserved
{:
    RESULT = new Identifier(reservedleft, reservedright, reserved, true);
:}

| T_IF:reserved
{:
    RESULT = new Identifier(reservedleft, reservedright, reserved, true);
:}

| T_ELSEIF:reserved
{:
    RESULT = new Identifier(reservedleft, reservedright, reserved, true);
:}

| T_ELSE:reserved
{:
    RESULT = new Identifier(reservedleft, reservedright, reserved, true);
:}

| T_ENDIF:reserved
{:
    RESULT = new Identifier(reservedleft, reservedright, reserved, true);
:}

| T_ECHO:reserved
{:
    RESULT = new Identifier(reservedleft, reservedright, reserved, true);
:}

| T_DO:reserved
{:
    RESULT = new Identifier(reservedleft, reservedright, reserved, true);
:}

| T_WHILE:reserved
{:
    RESULT = new Identifier(reservedleft, reservedright, reserved, true);
:}

| T_ENDWHILE:reserved
{:
    RESULT = new Identifier(reservedleft, reservedright, reserved, true);
:}

| T_FOR:reserved
{:
    RESULT = new Identifier(reservedleft, reservedright, reserved, true);
:}

| T_ENDFOR:reserved
{:
    RESULT = new Identifier(reservedleft, reservedright, reserved, true);
:}

| T_FOREACH:reserved
{:
    RESULT = new Identifier(reservedleft, reservedright, reserved, true);
:}

| T_ENDFOREACH:reserved
{:
    RESULT = new Identifier(reservedleft, reservedright, reserved, true);
:}

| T_DECLARE:reserved
{:
    RESULT = new Identifier(reservedleft, reservedright, reserved, true);
:}

| T_ENDDECLARE:reserved
{:
    RESULT = new Identifier(reservedleft, reservedright, reserved, true);
:}

| T_AS:reserved
{:
    RESULT = new Identifier(reservedleft, reservedright, reserved, true);
:}

| T_TRY:reserved
{:
    RESULT = new Identifier(reservedleft, reservedright, reserved, true);
:}

| T_CATCH:reserved
{:
    RESULT = new Identifier(reservedleft, reservedright, reserved, true);
:}

| T_FINALLY:reserved
{:
    RESULT = new Identifier(reservedleft, reservedright, reserved, true);
:}

| T_THROW:reserved
{:
    RESULT = new Identifier(reservedleft, reservedright, reserved, true);
:}

| T_USE:reserved
{:
    RESULT = new Identifier(reservedleft, reservedright, reserved, true);
:}

| T_INSTEADOF:reserved
{:
    RESULT = new Identifier(reservedleft, reservedright, reserved, true);
:}

| T_GLOBAL:reserved
{:
    RESULT = new Identifier(reservedleft, reservedright, reserved, true);
:}

| T_VAR:reserved
{:
    RESULT = new Identifier(reservedleft, reservedright, reserved, true);
:}

| T_UNSET:reserved
{:
    RESULT = new Identifier(reservedleft, reservedright, reserved, true);
:}

| T_ISSET:reserved
{:
    RESULT = new Identifier(reservedleft, reservedright, reserved, true);
:}

| T_EMPTY:reserved
{:
    RESULT = new Identifier(reservedleft, reservedright, reserved, true);
:}

| T_CONTINUE:reserved
{:
    RESULT = new Identifier(reservedleft, reservedright, reserved, true);
:}

| T_GOTO:reserved
{:
    RESULT = new Identifier(reservedleft, reservedright, reserved, true);
:}

| T_FN:reserved
{:
    // PHP 7.4
    RESULT = new Identifier(reservedleft, reservedright, reserved, true);
:}

| T_FUNCTION:reserved
{:
    RESULT = new Identifier(reservedleft, reservedright, reserved, true);
:}

| T_CONST:reserved
{:
    RESULT = new Identifier(reservedleft, reservedright, reserved, true);
:}

| T_RETURN:reserved
{:
    RESULT = new Identifier(reservedleft, reservedright, reserved, true);
:}

| T_PRINT:reserved
{:
    RESULT = new Identifier(reservedleft, reservedright, reserved, true);
:}

| T_YIELD:reserved
{:
    RESULT = new Identifier(reservedleft, reservedright, reserved, true);
:}

| T_LIST:reserved
{:
    RESULT = new Identifier(reservedleft, reservedright, reserved, true);
:}

| T_MATCH:reserved
{:
    RESULT = new Identifier(reservedleft, reservedright, reserved, true);
:}

| T_SWITCH:reserved
{:
    RESULT = new Identifier(reservedleft, reservedright, reserved, true);
:}

| T_ENDSWITCH:reserved
{:
    RESULT = new Identifier(reservedleft, reservedright, reserved, true);
:}

| T_CASE:reserved
{:
    RESULT = new Identifier(reservedleft, reservedright, reserved, true);
:}

| T_DEFAULT:reserved
{:
    RESULT = new Identifier(reservedleft, reservedright, reserved, true);
:}

| T_BREAK:reserved
{:
    RESULT = new Identifier(reservedleft, reservedright, reserved, true);
:}

| T_ARRAY:reserved
{:
    RESULT = new Identifier(reservedleft, reservedright, reserved, true);
:}

| T_CALLABLE:reserved
{:
    RESULT = new Identifier(reservedleft, reservedright, reserved, true);
:}

| T_EXTENDS:reserved
{:
    RESULT = new Identifier(reservedleft, reservedright, reserved, true);
:}

| T_IMPLEMENTS:reserved
{:
    RESULT = new Identifier(reservedleft, reservedright, reserved, true);
:}

| T_NAMESPACE:reserved
{:
    RESULT = new Identifier(reservedleft, reservedright, reserved, true);
:}

| T_TRAIT:reserved
{:
    RESULT = new Identifier(reservedleft, reservedright, reserved, true);
:}

| T_INTERFACE:reserved
{:
    RESULT = new Identifier(reservedleft, reservedright, reserved, true);
:}

/*
| T_CLASS:reserved
{:
    RESULT = new Identifier(reservedleft, reservedright, reserved, true);
:}
*/

| T_CLASS_C:reserved
{:
    RESULT = new Identifier(reservedleft, reservedright, reserved, true);
:}

| T_TRAIT_C:reserved
{:
    RESULT = new Identifier(reservedleft, reservedright, reserved, true);
:}

| T_FUNC_C:reserved
{:
    RESULT = new Identifier(reservedleft, reservedright, reserved, true);
:}

| T_METHOD_C:reserved
{:
    RESULT = new Identifier(reservedleft, reservedright, reserved, true);
:}

| T_LINE:reserved
{:
    RESULT = new Identifier(reservedleft, reservedright, reserved, true);
:}

| T_FILE:reserved
{:
    RESULT = new Identifier(reservedleft, reservedright, reserved, true);
:}

| T_DIR:reserved
{:
    RESULT = new Identifier(reservedleft, reservedright, reserved, true);
:}

| T_NS_C:reserved
{:
    RESULT = new Identifier(reservedleft, reservedright, reserved, true);
:}
;

semi_reserved_without_class ::=
reserved_non_modifiers_without_class:reserved
{:
    RESULT = reserved;
:}

| T_STATIC:modifier
{:
    RESULT = new Identifier(modifierleft, modifierright, modifier, true);
:}

| T_ABSTRACT:modifier
{:
    RESULT = new Identifier(modifierleft, modifierright, modifier, true);
:}

| T_FINAL:modifier
{:
    RESULT = new Identifier(modifierleft, modifierright, modifier, true);
:}

| T_PRIVATE:modifier
{:
    RESULT = new Identifier(modifierleft, modifierright, modifier, true);
:}

| T_PROTECTED:modifier
{:
    RESULT = new Identifier(modifierleft, modifierright, modifier, true);
:}

| T_PUBLIC:modifier
{:
    RESULT = new Identifier(modifierleft, modifierright, modifier, true);
:}

| T_READONLY:modifier
{:
    RESULT = new Identifier(modifierleft, modifierright, modifier, true);
:}
;

identifier ::=
identifier_without_class:ident
{:
    RESULT = ident;
:}

| T_CLASS:reserved
{:
    RESULT = new Identifier(reservedleft, reservedright, reserved, true);
:}
;

identifier_without_class ::=
T_STRING:string
{:
    RESULT = new Identifier(stringleft, stringright, string);
:}

| T_DEFINE:define
{:
    RESULT = new Identifier(defineleft, defineright, define);
:}

| semi_reserved_without_class:reserved
{:
    RESULT = reserved;
:}
;

top_statement_list ::=
top_statement_list:sList top_statement:statement
{:
    if(statement != null) {
        if (!(statement instanceof NamespaceDeclaration) && sList.size() > 0) {
            Statement lastStatement = (Statement) ((LinkedList) sList).getLast();
            if (lastStatement instanceof NamespaceDeclaration) {
                NamespaceDeclaration namespaceDeclaration = (NamespaceDeclaration) lastStatement;
                // there should be NO statement outside bracketed namespaces - it's PHP FATAL ERROR
                // (that statement doesn't belong to last bracketed namespace)
                if (!namespaceDeclaration.isBracketed()) {
                    namespaceDeclaration.addStatement(statement);
                }
            } else {
                sList.add(statement);
            }
        } else {
            sList.add(statement);
        }
    }
    RESULT = sList;
:}

| /* empty */
{:
    RESULT = new LinkedList();
:}
;

attributed_statement ::=
function_declaration_statement:statement
{:
    RESULT = statement;
:}

| class_declaration_statement:statement
{:
    RESULT = statement;
:}
;

top_statement ::=
statement:statement
{:
    RESULT = statement;
:}

| attributed_statement:statement
{:
    RESULT = statement;
:}

| attributes:attributes attributed_statement:statement
{:
    RESULT = parser.createAttributedStatement(statement, attributes);
:}

| T_HALT_COMPILER:halt
{:
    RESULT = new HaltCompiler(haltleft, haltright);
:}

| T_NAMESPACE:s namespace_declaration_name:list T_SEMICOLON:e
{:
    RESULT = new NamespaceDeclaration(sleft, eright,
        new NamespaceName(listleft, listright, list, false, false), null, false);
:}

| T_NAMESPACE:s namespace_declaration_name:list T_CURLY_OPEN:token top_statement_list:sList T_CURLY_CLOSE:e
{:
    RESULT = new NamespaceDeclaration(sleft, eright,
        new NamespaceName(listleft, listright, list, false, false),
        new Block(tokenleft, eright, sList), true);
:}

| T_NAMESPACE:s T_CURLY_OPEN:token top_statement_list:sList T_CURLY_CLOSE:e
{:
    RESULT = new NamespaceDeclaration(sleft, eright, null,
        new Block(tokenleft, eright, sList), true);
:}

| T_USE:s use_declarations:list T_SEMICOLON:e
{:
    RESULT = new UseStatement(sleft, eright, list);
:}

| T_USE:use T_FUNCTION use_declarations:list T_SEMICOLON:e
{:
    RESULT = new UseStatement(useleft, eright, list, UseStatement.Type.FUNCTION);
:}

| T_USE:use T_CONST use_declarations:list T_SEMICOLON:e
{:
    RESULT = new UseStatement(useleft, eright, list, UseStatement.Type.CONST);
:}

| constant_declaration:list T_SEMICOLON:e
{:
    RESULT = new ConstantDeclaration(listleft, eright, ASTPHP5Parser.IMPLICIT_PUBLIC, list, true);
:}
;

attribute_decl ::=
class_name:name
{:
    RESULT = new AttributeDeclaration(nameleft, nameright, name, null);
:}

| class_name:name T_OPEN_PARENTHESE function_call_parameter_list:paramList T_CLOSE_PARENTHESE:e
{:
    RESULT = new AttributeDeclaration(nameleft, eright, name, paramList);
:}
;

attribute_group ::=
attribute_decl:decl
{:
    List list = new LinkedList();
    list.add(decl);
    RESULT = list;
:}

| attribute_group:list T_COMMA attribute_decl:decl
{:
    list.add(decl);
    RESULT = list;
:}
;

attribute ::=
T_ATTRIBUTE:start attribute_group:group possible_comma T_CLOSE_RECT:end
{:
    RESULT = new Attribute(startleft, endright, group);
:}
;

attributes ::=
attribute:attribute
{:
    List list = new LinkedList();
    list.add(attribute);
    RESULT = list;
:}

| attributes:list attribute:attribute
{:
    list.add(attribute);
    RESULT = list;
:}
;

use_declarations ::=
use_declarations:list T_COMMA use_declaration:useDecl
{:
    list.add(useDecl);
    RESULT = list;
:}

| use_declaration:useDecl
{:
    List list = new LinkedList();
    list.add(useDecl);
    RESULT = list;
:}
;

use_declaration ::=
legacy_namespace_name:name
{:
    RESULT = new SingleUseStatementPart(nameleft, nameright, name, null);
:}

| legacy_namespace_name:name T_AS T_STRING:aliasName
{:
    RESULT = new SingleUseStatementPart(nameleft, aliasNameright, name,
        new Identifier(aliasNameleft, aliasNameright, aliasName));
:}

| legacy_namespace_name:basens T_NS_SEPARATOR:s T_CURLY_OPEN:open group_namespace_parts:parts T_CURLY_CLOSE:close
{:
    RESULT = new GroupUseStatementPart(basensleft, closeright, basens, parts);
:}
;

// used only in group uses
group_namespace_parts ::=
non_empty_group_namespace_parts:list possible_comma
{:
    RESULT = list;
:}

| /* empty */
{:
    List list = new LinkedList();
    RESULT = list;
:}
;

non_empty_group_namespace_parts ::=
non_empty_group_namespace_parts:list T_COMMA group_namespace_part:part
{:
    list.add(part);
    RESULT = list;
:}

| group_namespace_part:part
{:
    List list = new LinkedList();
    list.add(part);
    RESULT = list;
:}
;

group_namespace_part ::=
namespace_name:part
{:
    RESULT = new SingleUseStatementPart(partleft, partright, new NamespaceName(partleft, partright, part, false, false), null);
:}

| namespace_name:part T_AS T_STRING:alias
{:
    RESULT = new SingleUseStatementPart(partleft, aliasright, new NamespaceName(partleft, partright, part, false, false), new Identifier(aliasleft, aliasright, alias));
:}

| T_FUNCTION:f namespace_name:part
{:
    RESULT = new SingleUseStatementPart(fleft, partright, UseStatement.Type.FUNCTION, new NamespaceName(partleft, partright, part, false, false), null);
:}

| T_FUNCTION:f namespace_name:part T_AS T_STRING:alias
{:
    RESULT = new SingleUseStatementPart(fleft, aliasright, UseStatement.Type.FUNCTION, new NamespaceName(partleft, partright, part, false, false), new Identifier(aliasleft, aliasright, alias));
:}

| T_CONST:c namespace_name:part
{:
    RESULT = new SingleUseStatementPart(cleft, partright, UseStatement.Type.CONST, new NamespaceName(partleft, partright, part, false, false), null);
:}

| T_CONST:c namespace_name:part T_AS T_STRING:alias
{:
    RESULT = new SingleUseStatementPart(cleft, aliasright, UseStatement.Type.CONST, new NamespaceName(partleft, partright, part, false, false), new Identifier(aliasleft, aliasright, alias));
:}
;

inner_statement_list ::=
inner_statement_list:statementList inner_statement:statement
{:
    // Ignore null statements
    if(statement != null) {
        statementList.add(statement);
    }
    RESULT = statementList;
:}

| /* empty */
{:
    RESULT = new LinkedList();
:}
;

inner_statement ::=
statement:statement
{:
    RESULT = statement;
:}

| attributed_statement:statement
{:
    RESULT = statement;
:}

| attributes:attributes attributed_statement:statement
{:
    RESULT = parser.createAttributedStatement(statement, attributes);
:}
;

statement ::=
unticked_statement:statement
{:
    RESULT = statement;
:}
| T_STRING:label T_NEKUDOTAIM:e
{:
    RESULT = new GotoLabel(labelleft, eright, new Identifier(labelleft, labelright, label));
:}
;

unticked_statement ::=
T_CURLY_OPEN:token inner_statement_list:statementList T_CURLY_CLOSE:end
{:
    Block block = new Block(tokenleft, endright, statementList);
    RESULT = block;
:}

| T_IF:token T_OPEN_PARENTHESE expr:condition T_CLOSE_PARENTHESE statement:iftrue elseif_list:elseif else_single:iffalse
{:
    Expression innerCondition = null;
    Statement trueStatement = null;
    Statement falseStatement = iffalse;

    for (int i=0 ; i < elseif[0].size() ; i++) {
        innerCondition = (Expression)elseif[0].get(i);
        trueStatement = (Statement)elseif[1].get(i);
        int start = ((Integer)elseif[2].get(i)).intValue();
        falseStatement = new IfStatement(start, iffalseright, innerCondition, trueStatement, falseStatement);
    }
    IfStatement ifStatement = new IfStatement(tokenleft, iffalseright, condition, iftrue, falseStatement);

    RESULT = ifStatement;
:}

| T_IF:token T_OPEN_PARENTHESE expr:condition T_CLOSE_PARENTHESE T_NEKUDOTAIM:colon inner_statement_list:ifTrueStatementList new_elseif_list:elseif new_else_single:iffalse T_ENDIF T_SEMICOLON:end
{:
    Expression innerCondition = null;
    Statement trueStatement = null;
    Statement falseStatement = iffalse;

    for (int i=0 ; i < elseif[0].size() ; i++) {
        innerCondition = (Expression)elseif[0].get(i);
        trueStatement = (Statement)elseif[1].get(i);
        int start = ((Integer)elseif[2].get(i)).intValue();
        falseStatement = new IfStatement(start, iffalseright, innerCondition, trueStatement, falseStatement);
    }
    Block block = new Block(colonleft, ifTrueStatementListright, ifTrueStatementList, false);
    IfStatement ifStatement = new IfStatement(tokenleft, iffalseright, condition, block, falseStatement);

    RESULT = ifStatement;
:}

| T_WHILE:token T_OPEN_PARENTHESE expr:expr T_CLOSE_PARENTHESE while_statement:statement
{:
    WhileStatement whileStatement = new WhileStatement(tokenleft, statementright, expr, statement);
    RESULT = whileStatement;
:}

| T_DO:token statement:statement T_WHILE T_OPEN_PARENTHESE expr:expr T_CLOSE_PARENTHESE T_SEMICOLON:end
{:
    DoStatement doStatement = new DoStatement(tokenleft, endright, expr, statement);
    RESULT = doStatement;
:}

| T_FOR:token T_OPEN_PARENTHESE for_expr:initializations T_SEMICOLON for_expr:conditions T_SEMICOLON for_expr:increasements T_CLOSE_PARENTHESE for_statement:statement
{:
    ForStatement forStatement = new ForStatement(tokenleft, statementright, initializations, conditions, increasements, statement);
    RESULT = forStatement;
:}

| T_SWITCH:token T_OPEN_PARENTHESE expr:expr T_CLOSE_PARENTHESE switch_case_list:caseBlock
{:
    SwitchStatement switchStatement = new SwitchStatement(tokenleft, caseBlockright, expr, caseBlock);
    RESULT = switchStatement;
:}

| T_BREAK:token T_SEMICOLON:end
{:
    RESULT = new BreakStatement(tokenleft, endright);
:}

| T_BREAK:token expr:expr T_SEMICOLON:end
{:
    RESULT = new BreakStatement(tokenleft, endright, expr);
:}

| T_CONTINUE:token T_SEMICOLON:end
{:
    RESULT = new ContinueStatement(tokenleft, endright);
:}

| T_CONTINUE:token expr:expr T_SEMICOLON:end
{:
    RESULT = new ContinueStatement(tokenleft, endright, expr);
:}

| T_RETURN:token T_SEMICOLON:end
{:
    RESULT = new ReturnStatement(tokenleft, endright);
:}

| T_RETURN:token expr_without_variable:expr T_SEMICOLON:end
{:
    RESULT = new ReturnStatement(tokenleft, endright, expr);
:}

| T_RETURN:token variable:expr T_SEMICOLON:end
{:
    RESULT = new ReturnStatement(tokenleft, endright, expr);
:}

| T_RETURN:token yield_from_expr:expr T_SEMICOLON:end
{:
    RESULT = new ReturnStatement(tokenleft, endright, expr);
:}

| T_GLOBAL:start global_var_list:list T_SEMICOLON:end
{:
    GlobalStatement global = new GlobalStatement(startleft, endright, list);
    RESULT = global;
:}

| T_STATIC:start static_var_list:list T_SEMICOLON:end
{:
    StaticStatement s = new StaticStatement(startleft, endright, list);
    RESULT = s;
:}

| T_ECHO:start echo_expr_list:exprList T_SEMICOLON:end
{:
    RESULT = new EchoStatement(startleft, endright, exprList);
:}

| T_INLINE_HTML:html
{:
    InLineHtml inLineHtml = new InLineHtml(htmlleft, htmlright);
    RESULT = inLineHtml;
:}

| expr_with_yields:expr T_SEMICOLON:end
{:
    ExpressionStatement expressionStatement = new ExpressionStatement(exprleft, endright, expr);
    RESULT = expressionStatement;
:}

| T_USE:start use_filename:expr T_SEMICOLON:end
{:
    List list = new LinkedList();
    list.add(expr);
    Identifier id = new Identifier(startleft, startright, "use");
    FunctionName functionName = new FunctionName(startleft, startright, id);
    FunctionInvocation functionInvocation = new FunctionInvocation(startleft, exprright, functionName, list);
    ExpressionStatement expressionStatement = new ExpressionStatement(startleft, endright, functionInvocation);
    RESULT = expressionStatement;
:}

| T_UNSET:start T_OPEN_PARENTHESE unset_variables:list possible_comma T_CLOSE_PARENTHESE:closePar T_SEMICOLON:end
{:
    Identifier id = new Identifier(startleft, startright, "unset");
    FunctionName functionName = new FunctionName(startleft, startright, id);
    FunctionInvocation functionInvocation = new FunctionInvocation(startleft, closeParright, functionName, list);
    ExpressionStatement expressionStatement = new ExpressionStatement(startleft, endright, functionInvocation);
    RESULT = expressionStatement;
:}

| T_FOREACH:token T_OPEN_PARENTHESE variable:expr T_AS foreach_variable:var foreach_optional_arg:arg T_CLOSE_PARENTHESE foreach_statement:statement
{:
    ForEachStatement forEachStatement = null;
    if (arg == null) {
        forEachStatement = new ForEachStatement(tokenleft, statementright, expr, var, statement);
    } else {
        forEachStatement = new ForEachStatement(tokenleft, statementright, expr, var, arg, statement);
    }
    RESULT = forEachStatement;
:}

| T_FOREACH:token T_OPEN_PARENTHESE expr_without_variable:expr T_AS foreach_variable:var foreach_optional_arg:arg T_CLOSE_PARENTHESE foreach_statement:statement
{:
    ForEachStatement forEachStatement = null;
    if (arg == null) {
        forEachStatement = new ForEachStatement(tokenleft, statementright, expr, var, statement);
    } else {
        forEachStatement = new ForEachStatement(tokenleft, statementright, expr, var, arg, statement);
    }
    RESULT = forEachStatement;
:}

| T_DECLARE:start T_OPEN_PARENTHESE declare_list:lists T_CLOSE_PARENTHESE declare_statement:statement
{:
    DeclareStatement declare = new DeclareStatement(startleft, statementright, lists[0], lists[1], statement);
    RESULT = declare;
:}

| T_SEMICOLON:token /* empty statement */
{:
    RESULT = new EmptyStatement(tokenleft, tokenright);
:}

| T_TRY:start T_CURLY_OPEN:tryBlockStart inner_statement_list:tryList T_CURLY_CLOSE:tryBlockEnd T_FINALLY:finally_word T_CURLY_OPEN:finallyBlockStart inner_statement_list:finallyList T_CURLY_CLOSE:finallyBlockEnd
{:
    Block tryBlock = new Block(tryBlockStartleft, tryBlockEndright, tryList);
    Block finallyBlock = new Block(finallyBlockStartleft, finallyBlockEndright, finallyList);
    FinallyClause finallyClause = new FinallyClause(finally_wordleft, finallyBlockEndright, finallyBlock);
    TryStatement tryStatement = new TryStatement(startleft, finallyBlockEndright, tryBlock, null, finallyClause);
    RESULT = tryStatement;
:}

| T_TRY:start T_CURLY_OPEN:tryBlockStart inner_statement_list:tryList T_CURLY_CLOSE:tryBlockEnd T_CATCH:catch_word T_OPEN_PARENTHESE catch_class_names:classNames optional_tracked_variable:var T_CLOSE_PARENTHESE
T_CURLY_OPEN:catchBlockStart inner_statement_list:catchList T_CURLY_CLOSE:catchBlockEnd additional_catches:catchesList additional_finally:finallyBlock
{:
    Block tryBlock = new Block(tryBlockStartleft, tryBlockEndright, tryList);
    Block catchBlock = new Block(catchBlockStartleft, catchBlockEndright, catchList);
    CatchClause catchClause = new CatchClause(catch_wordleft, catchBlockEndright, classNames, var, catchBlock);
    ((LinkedList) catchesList).addFirst(catchClause);
    int end = finallyBlock == null ? catchesListright : finallyBlockright;
    TryStatement tryStatement = new TryStatement(startleft, end, tryBlock, catchesList, finallyBlock);
    RESULT = tryStatement;
:}

| T_GOTO:s T_STRING:label T_SEMICOLON:e
{:
    RESULT = new GotoStatement(sleft, eright, new Identifier(labelleft, labelright, label));
:}

| error:theError /* error statement */
{:
    ASTError error = new ASTError(theErrorleft, theErrorright);
    RESULT = error;
:}

| T_VAR_COMMENT:varComment
{:
    // TODO: var comment should be added as parser.ast node
:}
;

additional_catches ::=
non_empty_additional_catches:list
{:
    RESULT = list;
:}

| /* empty */
{:
    List list = new LinkedList();
    RESULT = list;
:}
;

non_empty_additional_catches ::=
additional_catch:catch_statement
{:
    List list = new LinkedList();
    list.add(catch_statement);
    RESULT = list;
:}
| non_empty_additional_catches:list additional_catch:catch_statement
{:
    list.add(catch_statement);
    RESULT = list;
:}
;

additional_catch ::=
T_CATCH:catch_word T_OPEN_PARENTHESE catch_class_names:classNames optional_tracked_variable:variable T_CLOSE_PARENTHESE
 T_CURLY_OPEN:catchBlockStart inner_statement_list:catchList T_CURLY_CLOSE:catchBlockEnd
{:
    Block catchBlock = new Block(catchBlockStartleft, catchBlockEndright, catchList);
    CatchClause catchClause = new CatchClause(catch_wordleft, catchBlockEndright, classNames, variable, catchBlock);
    RESULT = catchClause;
:}
;

additional_finally ::=
 /* empty */
{:
    RESULT = null;
:}

| T_FINALLY:finally_word T_CURLY_OPEN:finallyBlockStart inner_statement_list:finallyList T_CURLY_CLOSE:finallyBlockEnd
{:
    Block finallyBlock = new Block(finallyBlockStartleft, finallyBlockEndright, finallyList);
    FinallyClause finallyClause = new FinallyClause(finally_wordleft, finallyBlockEndright, finallyBlock);
    RESULT = finallyClause;
:}
;

catch_class_names ::=
fully_qualified_class_name:className additional_catch_class_names:list
{:
    ((LinkedList) list).addFirst(className);
    RESULT = list;
:}
;

additional_catch_class_names ::=
non_empty_additional_catch_class_names:list
{:
    RESULT = list;
:}

| /* empty */
{:
    List list = new LinkedList();
    RESULT = list;
:}
;

non_empty_additional_catch_class_names ::=
additional_catch_class_name:className
{:
    List list = new LinkedList();
    list.add(className);
    RESULT = list;
:}

| non_empty_additional_catch_class_names:list additional_catch_class_name:className
{:
    list.add(className);
    RESULT = list;
:}
;

additional_catch_class_name ::=
T_OR fully_qualified_class_name:className
{:
    RESULT = className;
:}
;

unset_variables ::=
unset_variable:var
{:
    List list = new LinkedList();
    list.add(var);
    RESULT = list;
:}

| unset_variables:list T_COMMA unset_variable:var
{:
    list.add(var);
    RESULT = list;
:}
;

unset_variable ::=
variable:var
{:
    RESULT = var;
:}
;

use_filename ::=
T_CONSTANT_ENCAPSED_STRING:scalar
{:
    Scalar s = new Scalar(scalarleft, scalarright, scalar, Scalar.Type.STRING);
    RESULT = s;
:}

| T_OPEN_PARENTHESE:start T_CONSTANT_ENCAPSED_STRING:scalar T_CLOSE_PARENTHESE:end
{:
    Scalar s = new Scalar(startleft, endright, scalar, Scalar.Type.STRING);
    RESULT = s;
:}
;

function_declaration_statement ::=
unticked_function_declaration_statement:functionDeclaration
{:
    RESULT = functionDeclaration;
:}
;

class_declaration_statement ::=
unticked_class_declaration_statement:classDeclaration
{:
    RESULT = classDeclaration;
:}
;

is_reference ::=
/* empty */
{:
    RESULT = Boolean.FALSE;
:}

| ampersand
{:
    RESULT = Boolean.TRUE;
:}
;

is_variadic ::=
/* empty */
{:
    RESULT = Boolean.FALSE;
:}

| T_ELLIPSIS
{:
    RESULT = Boolean.TRUE;
:}
;

unticked_function_declaration_statement ::=
T_FUNCTION:start is_reference:isReference string_st:functionName
T_OPEN_PARENTHESE parameter_list:paramList T_CLOSE_PARENTHESE
optional_return_type:returnType
T_CURLY_OPEN:blockStart inner_statement_list:statementList T_CURLY_CLOSE:blockEnd
{:
    Identifier functionId = new Identifier(functionNameleft, functionNameright, functionName);
    Block block = new Block(blockStartleft, blockEndright, statementList);
    FunctionDeclaration functionDeclaration = new FunctionDeclaration(startleft, blockEndright, functionId, paramList, returnType, block, isReference.booleanValue());
    RESULT = functionDeclaration;
:}
;

unticked_class_declaration_statement ::=
class_entry_type:modifiers T_STRING:className
extends_from:superClass implements_list:interfaces
T_CURLY_OPEN:blockStart class_statement_list:statementList T_CURLY_CLOSE:blockEnd
{:
    Identifier classId = new Identifier(classNameleft, classNameright, className);
    Block block = new Block(blockStartleft, blockEndright, statementList);
    ClassDeclaration classDeclaration = new ClassDeclaration(modifiersleft ,blockEndright, modifiers, classId, superClass, interfaces, block);
    RESULT = classDeclaration;
:}

|
interface_entry:start T_STRING:className
interface_extends_list:interfaces
T_CURLY_OPEN:blockStart interface_statement_list:statementList T_CURLY_CLOSE:blockEnd
{:
    Identifier classId = new Identifier(classNameleft, classNameright, className);
    Block block = new Block(blockStartleft, blockEndright, statementList);
    InterfaceDeclaration interfaceDeclaration = new InterfaceDeclaration(startleft ,blockEndright, classId, interfaces, block);
    RESULT = interfaceDeclaration;
:}

|
T_TRAIT:start T_STRING:traitName
T_CURLY_OPEN:blockStart trait_statement_list:statementList T_CURLY_CLOSE:blockEnd
{:
    Identifier traitId = new Identifier(traitNameleft, traitNameright, traitName);
    Block block = new Block(blockStartleft, blockEndright, statementList);
    TraitDeclaration traitDeclaration = new TraitDeclaration(startleft, blockEndright, traitId, block);
    RESULT = traitDeclaration;
:}

|
T_ENUM:start T_STRING:enumName enum_backing_type:type implements_list:interfaces
T_CURLY_OPEN:blockStart class_statement_list:statementList T_CURLY_CLOSE:blockEnd
{:
    Identifier name = new Identifier(enumNameleft, enumNameright, enumName);
    Block block = new Block(blockStartleft, blockEndright, statementList);
    EnumDeclaration enumDeclaration = new EnumDeclaration(startleft, blockEndright, name, type, interfaces, block);
    RESULT = enumDeclaration;
:}
;

interface_statement_list ::=
interface_statement_list:list interface_statement:interfaceStatement
{:
    list.add(interfaceStatement);
    RESULT = list;
:}

| /* empty */
{:
    List list = new LinkedList();
    RESULT = list;
:}
;

attributed_interface_statement ::=
constant_modifiers:modifier class_constant_declaration:list T_SEMICOLON:end
{:
    int constantStart = modifier == null ? listleft : modifierleft;
    modifier = modifier == null ? ASTPHP5Parser.IMPLICIT_PUBLIC : modifier;
    ConstantDeclaration classConstantDeclaration = ConstantDeclaration.create(constantStart, endright, modifier, list.first(), list.second(), false);
    RESULT = classConstantDeclaration;
:}

| method_modifiers:modifier T_FUNCTION:start is_reference:isReference identifier:functionId
T_OPEN_PARENTHESE parameter_list:paramList T_CLOSE_PARENTHESE
optional_return_type:returnType
T_SEMICOLON:end
{:
    int methodStart = modifier == null ? startleft : modifierleft;
    modifier = modifier == null ? ASTPHP5Parser.PUBLIC : modifier;
    Block block = new Block(endleft, endright, Collections.EMPTY_LIST, false);
    FunctionDeclaration functionDeclaration = new FunctionDeclaration(startleft, endright, functionId, paramList, returnType, block, isReference.booleanValue());
    MethodDeclaration methodDeclaration = new MethodDeclaration(methodStart, endright, modifier.intValue(), functionDeclaration, true);
    RESULT = methodDeclaration;
:}
;

interface_statement ::=
attributed_interface_statement:statement
{:
    RESULT = statement;
:}

| attributes:attributes attributed_interface_statement:statement
{:
    RESULT = parser.createAttributedStatement(statement, attributes);
:}

| T_VAR_COMMENT:varComment
{:

:}
;

trait_statement_list ::=
trait_statement_list:list trait_statement:traitStatement
{:
    list.add(traitStatement);
    RESULT = list;
:}

| /* empty */
{:
    List list = new LinkedList();
    RESULT = list;
:}
;

attributed_trait_statement ::=
attributed_class_statement:statement
{:
    RESULT = statement;
:}
;

trait_statement ::=
attributed_trait_statement:statement
{:
    RESULT = statement;
:}

| attributes:attributes attributed_trait_statement:statement
{:
    RESULT = parser.createAttributedStatement(statement, attributes);
:}

| T_VAR_COMMENT:varComment
{:

:}

| T_USE:s use_traits:list use_traits_body:body
{:
    RESULT = new UseTraitStatement(sleft, bodyright, list, body);
:}
;

class_modifiers ::=
class_modifier:modifier
{:
    Map<ClassDeclaration.Modifier, Set<OffsetRange>> modifiers = new EnumMap<>(ClassDeclaration.Modifier.class);
    Set<OffsetRange> offsetRanges = new HashSet<>();
    offsetRanges.add(new OffsetRange(modifierleft, modifierright));
    modifiers.put(modifier, offsetRanges);
    RESULT = modifiers;
:}

| class_modifiers:modifiers class_modifier:modifier
{:
    Set<OffsetRange> offsetRanges = modifiers.get(modifier);
    if (offsetRanges == null) {
        offsetRanges = new HashSet<>();
    }
    offsetRanges.add(new OffsetRange(modifierleft, modifierright));
    modifiers.put(modifier, offsetRanges);
    RESULT = modifiers;
:}
;

class_modifier ::=
T_ABSTRACT
{:
    RESULT = ClassDeclaration.Modifier.ABSTRACT;
:}

| T_FINAL
{:
    RESULT = ClassDeclaration.Modifier.FINAL;
:}

| T_READONLY
{:
    // PHP 8.2 gh-4725
    RESULT = ClassDeclaration.Modifier.READONLY;
:}
;

class_entry_type ::=
T_CLASS
{:
--> --------------------

--> maximum size reached

--> --------------------

[ Seitenstruktur0.55Drucken  etwas mehr zur Ethik  ]