%{ // // Mono.MonoBASIC.Parser.cs (from .jay): The Parser for the MonoBASIC compiler // // Authors: A Rafael D Teixeira (rafaelteixeirabr@hotmail.com) // Anirban Bhattacharjee (banirban@novell.com) // Jambunathan K (kjambunathan@novell.com) // // Licensed under the terms of the GNU GPL // // Copyright (C) 2001, 2002, 2003, 2004 A Rafael D Teixeira // Copyright (C) 2003, 2004 Novell // // namespace Mono.CSharp { using System.Text; using System; using System.Reflection; using System.Collections; using Mono.CSharp; /// /// The MonoBASIC Parser /// // [DefaultParser] // public class Parser : GenericParser // { // /// // /// Current block is used to add statements as we find // /// them. // /// // Block current_block; // /// // /// Tmp block is used to store block endings in if/select's // /// // Block tmp_block; // /// // /// Tmp block is used to store tmp copies of expressions // /// // Expression tmp_expr; // /// // /// Tmp catch is used to store catch clauses in try..catch..finally // /// // ArrayList tmp_catch_clauses; // /// // /// Current interface is used by the various declaration // /// productions in the interface declaration to "add" // /// the interfaces as we find them. // /// // Interface current_interface; // /// // /// This is used by the unary_expression code to resolve // /// a name against a parameter. // /// // Parameters current_local_parameters; // /// // /// This are used when parsing parameters in property // /// declarations. // /// // Parameters set_parameters; // Parameters get_parameters; // /// // /// This is used by the sub_header parser to store modifiers // /// to be passed to sub/constructor // /// // int current_modifiers; // /// // /// This is used by the sub_header parser to store attributes // /// to be passed to sub/constructor // /// // Attributes current_attributes; // /// // /// Using during property parsing to describe the implicit // /// value parameter that is passed to the "set" accessor // /// method // /// // string get_implicit_value_parameter_name; // // // // Using during property parsing to describe the implicit // // value parameter that is passed to the "set" and "get"accesor // // methods (properties and indexers). // // // Expression get_implicit_value_parameter_type; // /// // /// Using during property parsing to describe the implicit // /// value parameter that is passed to the "set" accessor // /// method // /// // string set_implicit_value_parameter_name; // // // // Using during property parsing to describe the implicit // // value parameter that is passed to the "set" and "get"accesor // // methods (properties and indexers). // // // Expression set_implicit_value_parameter_type; // Location member_location; // // An out-of-band stack. // // // Stack oob_stack; // ArrayList current_rank_specifiers; // DoOptions do_type; // // // // Switch stack. // // // Stack switch_stack; // // Expression stack for nested ifs // Stack expr_stack; // Stack tmp_blocks; // Stack statement_stack; // // A stack for With expressions. // // // Stack with_stack; // static public bool InitialOptionExplicit = false; // static public bool InitialOptionStrict = false; // static public bool InitialOptionCompareBinary = true; // static public ArrayList ImportsList = null; // bool OptionExplicit; // bool OptionStrict; // bool OptionCompareBinary; // static public bool UseExtendedSyntax; // for ".mbs" files // bool implicit_modifiers; // public override string[] extensions() // { // string [] list = { ".vb", ".mbs" }; // return list; // } /// /// The C# Parser /// public class CSharpParser { NamespaceEntry current_namespace; TypeContainer current_container; TypeContainer current_class; IIteratorContainer iterator_container; /// /// Current block is used to add statements as we find /// them. /// Block current_block, top_current_block; /// /// This is used by the unary_expression code to resolve /// a name against a parameter. /// Parameters current_local_parameters; /// /// Using during property parsing to describe the implicit /// value parameter that is passed to the "set" and "get"accesor /// methods (properties and indexers). /// Expression implicit_value_parameter_type; Parameters indexer_parameters; /// /// Used to determine if we are parsing the get/set pair /// of an indexer or a property /// bool parsing_indexer; /// /// An out-of-band stack. /// Stack oob_stack; /// /// Switch stack. /// Stack switch_stack; static public int yacc_verbose_flag; // Name of the file we are parsing public string name; /// /// The current file. /// SourceFile file; /// This is used by the sub_header parser to store modifiers /// to be passed to sub/constructor int current_modifiers; /// This is used by the sub_header parser to store attributes /// to be passed to sub/constructor Attributes current_attributes; /// This is used by the attributes parser to syntactically /// validate the attribute rules bool allow_global_attribs = true; bool expecting_global_attribs = false; bool expecting_local_attribs = false; bool local_attrib_section_added = false; ///FIXME ArrayList current_rank_specifiers; /// /// Using during property parsing to describe the implicit /// value parameter that is passed to the "set" accessor /// method /// string get_implicit_value_parameter_name; // // Using during property parsing to describe the implicit // value parameter that is passed to the "set" and "get"accesor // methods (properties and indexers). // Expression get_implicit_value_parameter_type; /// /// Using during property parsing to describe the implicit /// value parameter that is passed to the "set" accessor /// method /// string set_implicit_value_parameter_name; // // Using during property parsing to describe the implicit // value parameter that is passed to the "set" and "get"accesor // methods (properties and indexers). // Expression set_implicit_value_parameter_type; /// /// This are used when parsing parameters in property /// declarations. /// Parameters set_parameters; Parameters get_parameters; // static public ArrayList ImportsList = null; bool implicit_modifiers; /// /// This is used as a helper class for handling of /// pre-processor statements. /// // FIXME: This class MBASException is actually a kludge // It can be done away with a more elegant replacement. public class MBASException : ApplicationException { public int code; public Location loc; public MBASException(int code, Location loc, string text) : base(text) { this.code = code; this.loc = loc; } } public class IfElseStateMachine { public enum State { START, IF_SEEN, ELSEIF_SEEN, ELSE_SEEN, ENDIF_SEEN, MAX } public enum Token { START, IF, ELSEIF, ELSE, ENDIF, EOF, MAX } State state; Stack stateStack; public static Hashtable errStrings = new Hashtable(); int err=0; static int[,] errTable = new int[(int)State.MAX, (int)Token.MAX]; static IfElseStateMachine() { // FIXME: Fix both the error nos and the error strings. // Currently the error numbers and the error strings are // just placeholders for getting the state-machine going. errStrings.Add(0, ""); errStrings.Add(30012, "#If must end with a matching #End If"); errStrings.Add(30013, "#ElseIf, #Else or #End If must be preceded by a matching #If"); errStrings.Add(30014, "#ElseIf must be preceded by a matching #If or #ElseIf"); errStrings.Add(30028, "#Else must be preceded by a matching #If or #ElseIf"); errStrings.Add(32030, "#ElseIf cannot follow #Else as part of #If block"); errTable[(int)State.START, (int)Token.IF] = 0; errTable[(int)State.START, (int)Token.ELSEIF] = 30014; errTable[(int)State.START, (int)Token.ELSE] = 30028; errTable[(int)State.START, (int)Token.ENDIF] = 30013; errTable[(int)State.START, (int)Token.EOF] = 0; errTable[(int)State.IF_SEEN, (int)Token.IF] = 0; errTable[(int)State.IF_SEEN, (int)Token.ELSEIF] = 0; errTable[(int)State.IF_SEEN, (int)Token.ELSE] = 0; errTable[(int)State.IF_SEEN, (int)Token.ENDIF] = 0; errTable[(int)State.IF_SEEN, (int)Token.EOF] = 30012; errTable[(int)State.ELSEIF_SEEN, (int)Token.IF] = 0; errTable[(int)State.ELSEIF_SEEN, (int)Token.ELSEIF] = 0; errTable[(int)State.ELSEIF_SEEN, (int)Token.ELSE] = 0; errTable[(int)State.ELSEIF_SEEN, (int)Token.ENDIF] = 0; errTable[(int)State.ELSEIF_SEEN, (int)Token.EOF] = 30012; errTable[(int)State.ELSE_SEEN, (int)Token.IF] = 0; errTable[(int)State.ELSE_SEEN, (int)Token.ELSEIF] = 32030; errTable[(int)State.ELSE_SEEN, (int)Token.ELSE] = 32030; errTable[(int)State.ELSE_SEEN, (int)Token.ENDIF] = 0; errTable[(int)State.ELSE_SEEN, (int)Token.EOF] = 30012; errTable[(int)State.ENDIF_SEEN, (int)Token.IF] = 0; errTable[(int)State.ENDIF_SEEN, (int)Token.ELSEIF] = 30014; errTable[(int)State.ENDIF_SEEN, (int)Token.ELSE] = 30028; errTable[(int)State.ENDIF_SEEN, (int)Token.ENDIF] = 30013; errTable[(int)State.ENDIF_SEEN, (int)Token.EOF] = 0; } public IfElseStateMachine() { state = State.START; stateStack = new Stack(); stateStack.Push(state); } // The parameter here need not be qualified with IfElseStateMachine // But it hits a bug in mcs. So temporarily scoping it so that builds // are not broken. public void HandleToken(IfElseStateMachine.Token tok) { err = (int) errTable[(int)state, (int)tok]; if(err != 0) throw new ApplicationException("Unexpected pre-processor directive #"+tok); if(tok == Token.IF) { stateStack.Push(state); state = (State) tok; } else if(tok == Token.ENDIF) { state = (State)stateStack.Pop(); } else state = (State)tok; } public int Error { get { return err; } } public string ErrString { get { return (string) errStrings[err]; } } } public class TokenizerController { struct State { public bool CanAcceptTokens; public bool CanSelectBlock; } State currentState; Stack stateStack; Tokenizer lexer; public TokenizerController(Tokenizer lexer) { this.lexer = lexer; stateStack = new Stack(); currentState.CanAcceptTokens = true; currentState.CanSelectBlock = true; stateStack.Push(currentState); } State parentState { get { return (State)stateStack.Peek(); } } public bool IsAcceptingTokens { get { return currentState.CanAcceptTokens; } } public void PositionCursorAtNextPreProcessorDirective() { lexer.PositionCursorAtNextPreProcessorDirective(); } public void PositionTokenizerCursor(IfElseStateMachine.Token tok, BoolLiteral expr) { if(tok == IfElseStateMachine.Token.ENDIF) { currentState = (State)stateStack.Pop(); if(currentState.CanAcceptTokens) return; else { PositionCursorAtNextPreProcessorDirective(); return; } } if(tok == IfElseStateMachine.Token.IF) { stateStack.Push(currentState); currentState.CanAcceptTokens = parentState.CanAcceptTokens; currentState.CanSelectBlock = true; } if(parentState.CanAcceptTokens && currentState.CanSelectBlock && (bool)(expr.GetValue()) ) { currentState.CanAcceptTokens = true; currentState.CanSelectBlock = false; return; } else { currentState.CanAcceptTokens = false; PositionCursorAtNextPreProcessorDirective(); return; } } } bool in_external_source = false; int in_marked_region = 0; TokenizerController tokenizerController; IfElseStateMachine ifElseStateMachine; %} %token EOF %token NONE /* This token is never returned by our lexer */ %token ERROR // This is used not by the parser, but by the tokenizer. // do not remove. /* *These are the MonoBASIC keywords */ %token ADDHANDLER %token ADDRESSOF %token ALIAS %token AND %token ANDALSO %token ANSI %token AS %token ASSEMBLY %token AUTO %token BINARY %token BOOLEAN %token BYREF %token BYTE %token BYVAL %token CALL %token CASE %token CATCH %token CBOOL %token CBYTE %token CCHAR %token CDATE %token CDEC %token CDBL %token CHAR %token CINT %token CLASS %token CLNG %token COBJ %token COMPARE %token CONST %token CSHORT %token CSNG %token CSTR %token CTYPE %token DATE %token DECIMAL %token DECLARE %token DEFAULT %token DELEGATE %token DIM %token DIRECTCAST %token DO %token DOUBLE %token EACH %token ELSE %token ELSEIF %token END %token ENDIF %token ENUM %token EOL %token ERASE %token ERROR %token EVENT %token EXIT %token EXPLICIT %token FALSE %token FINALLY %token FOR %token FRIEND %token FUNCTION %token GET %token GETTYPE %token GOSUB %token GOTO %token HANDLES %token IF %token IMPLEMENTS %token IMPORTS %token IN %token INHERITS %token INTEGER %token INTERFACE %token IS %token LET %token LIB %token LIKE %token LONG %token LOOP %token ME %token MOD %token MODULE %token MUSTINHERIT %token MUSTOVERRIDE %token MYBASE %token MYCLASS %token NAMESPACE %token NEW %token NEXT %token NOT %token NOTHING %token NOTINHERITABLE %token NOTOVERRIDABLE %token OBJECT %token OFF %token ON %token OPTION %token OPTIONAL %token OR %token ORELSE %token OVERLOADS %token OVERRIDABLE %token OVERRIDES %token PARAM_ARRAY %token PRESERVE %token PRIVATE %token PROPERTY %token PROTECTED %token PUBLIC %token RAISEEVENT %token READONLY %token REDIM %token REM %token REMOVEHANDLER %token RESUME %token RETURN %token SELECT %token SET %token SHADOWS %token SHARED %token SHORT %token SINGLE %token SIZEOF %token STATIC %token STEP %token STOP %token STRICT %token STRING %token STRUCTURE %token SUB %token SYNCLOCK %token TEXT %token THEN %token THROW %token TO %token TRUE %token TRY %token TYPEOF %token UNICODE %token UNTIL %token VARIANT %token WEND %token WHEN %token WHILE %token WITH %token WITHEVENTS %token WRITEONLY %token XOR %token YIELD // MonoBASIC extension %token HASH /* MonoBASIC single character operators/punctuation. */ %token OPEN_BRACKET "[" %token CLOSE_BRACKET "]" %token OPEN_PARENS "(" %token OPEN_BRACE "{" %token CLOSE_BRACE "}" %token CLOSE_PARENS ")" %token DOT "." %token COMMA "," %token COLON ":" %token PLUS "+" %token MINUS "-" %token ASSIGN "=" %token OP_LT "<" %token OP_GT ">" %token STAR "*" %token DIV "/" %token OP_EXP "^" %token INTERR "?" %token OP_IDIV "\\" //FIXME: This should be "\" %token OP_CONCAT "&" %token EXCLAMATION "!" %token PERCENT "%" %token LONGTYPECHAR "&" %token AT_SIGN "@" %token SINGLETYPECHAR "!" %token NUMBER_SIGN "#" %token DOLAR_SIGN "$" %token ATTR_ASSIGN ":=" /* MonoBASIC multi-character operators. */ %token OP_LE "<=" %token OP_GE ">=" %token OP_NE "<>" %token OP_XOR "xor" //%token OP_MODULUS //"mod" /* VB.NET 2003 new bit-shift operators */ %token OP_SHIFT_LEFT "<<" %token OP_SHIFT_RIGHT ">>" /* Numbers */ %token LITERAL_INTEGER "int literal" %token LITERAL_SINGLE "float literal" %token LITERAL_DOUBLE "double literal" %token LITERAL_DECIMAL "decimal literal" %token LITERAL_CHARACTER "character literal" %token LITERAL_STRING "string literal" %token LITERAL_DATE "datetime literal" %token IDENTIFIER /* Add precedence rules to solve dangling else s/r conflict */ %nonassoc LOWPREC %nonassoc IF %nonassoc ELSE %right ASSIGN %left OP_OR %left OP_AND %left BITWISE_OR %left BITWISE_AND %left OP_SHIFT_LEFT OP_SHIFT_RIGHT %left PLUS MINUS %left STAR DIV PERCENT %right BITWISE_NOT CARRET UMINUS %nonassoc OP_INC OP_DEC %left OPEN_PARENS %left OPEN_BRACKET OPEN_BRACE %left DOT %right NOT %nonassoc HIGHPREC %start compilation_unit %% end_of_stmt : logical_end_of_line | COLON ; logical_end_of_line : EOL | logical_end_of_line pp_directive ; compilation_unit : logical_end_of_line opt_option_directives opt_imports_directives declarations EOF { $$=$4; } |logical_end_of_line opt_option_directives opt_imports_directives opt_attributes EOF { /* ????? */ ; } ; opt_option_directives : /* empty */ | option_directives ; option_directives : option_directive | option_directives option_directive ; option_directive : option_explicit_directive | option_strict_directive | option_compare_directive ; on_off : /* empty */ { $$ = (object)true; } | ON { $$ = (object)true; } | OFF { $$ = (object)false; } ; text_or_binary : BINARY { $$ = (object)true; } | TEXT { $$ = (object)false; } ; option_explicit_directive : OPTION EXPLICIT on_off logical_end_of_line { // if (!UseExtendedSyntax) // OptionExplicit = (bool)$3; // else // Report.Warning ( // 9999, lexer.Location, // "In MonoBASIC extended syntax explicit declaration is always required. So OPTION EXPLICIT is deprecated"); } ; option_strict_directive : OPTION STRICT on_off logical_end_of_line { // if (!UseExtendedSyntax) // OptionStrict = (bool)$3; // else // Report.Warning ( // 9999, lexer.Location, // "In MonoBASIC extended syntax strict assignability is always required. So OPTION STRICT is deprecated"); } ; option_compare_directive : OPTION COMPARE text_or_binary logical_end_of_line { // OptionCompareBinary = (bool)$3; } ; opt_declarations : /* empty */ | declarations ; declarations : declaration | declarations declaration ; declaration : declaration_qualifiers { // FIXME: Need to check declaration qualifiers for multi-file compilation // FIXME: Qualifiers cannot be applied to namespaces allow_global_attribs = false; } namespace_declaration { current_namespace.DeclarationFound = true; } | declaration_qualifiers { // FIXME: Need to check declaration qualifiers for multi-file compilation allow_global_attribs = false; } type_spec_declaration { string name = ""; int mod_flags; if ($3 is Class){ Class c = (Class) $3; mod_flags = c.ModFlags; name = c.Name; } else if ($3 is Struct){ Struct s = (Struct) $3; mod_flags = s.ModFlags; name = s.Name; } else break; if ((mod_flags & (Modifiers.PRIVATE|Modifiers.PROTECTED)) != 0){ Report.Error ( 1527, lexer.Location, "Namespace elements cant be explicitly " + "declared private or protected in `" + name + "'"); } current_namespace.DeclarationFound = true; } ; identifier : IDENTIFIER | BINARY | TEXT | COMPARE | EXPLICIT | OFF ; type_character : PERCENT { $$ = TypeManager.system_int32_expr; } | LONGTYPECHAR { $$ = TypeManager.system_int64_expr; } | AT_SIGN { $$ = TypeManager.system_decimal_expr; } | SINGLETYPECHAR { $$ = TypeManager.system_single_expr; } | NUMBER_SIGN { $$ = TypeManager.system_double_expr; } | DOLAR_SIGN { $$ = TypeManager.system_string_expr; } ; opt_type_character : /* empty */ { $$ = null; } | type_character { $$ = $1; } ; qualified_identifier : identifier { $$ = new MemberName ((string) $1); } | qualified_identifier DOT identifier // FIXME: It should be qualified_identifier DOT identifier-or-keyword { $$ = new MemberName ((MemberName) $1, (string) $3, null); } ; opt_imports_directives : /* empty */ | imports_directives ; imports_directives : imports_directive | imports_directives imports_directive ; imports_directive : IMPORTS imports_terms logical_end_of_line ; imports_terms : imports_term | imports_terms COMMA imports_term ; imports_term : namespace_or_type_name { string name = ((MemberName) $1).GetName (); current_namespace.Using (name, lexer.Location); } | identifier ASSIGN namespace_or_type_name { current_namespace.UsingAlias ((string) $1, (MemberName) $3, lexer.Location); } ; opt_params : /* empty */ { $$ = Parameters.EmptyReadOnlyParameters; } | OPEN_PARENS CLOSE_PARENS { $$ = Parameters.EmptyReadOnlyParameters; } | OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS { $$ = $2; } ; opt_attributes : /* empty */ { current_attributes = null; } | attribute_sections { $$ = $1; local_attrib_section_added = false; current_attributes = (Attributes) $1; } ; attribute_sections : attribute_section { $$ = $1; if ($1 == null) { expecting_local_attribs = false; expecting_global_attribs = false; break; } if (expecting_local_attribs) { local_attrib_section_added = true; allow_global_attribs = false; $$ = new Attributes ((ArrayList) $1); } if (expecting_global_attribs) { $$ = null; CodeGen.AddGlobalAttributes ((ArrayList) $1); } expecting_local_attribs = false; expecting_global_attribs = false; } | attribute_sections { $$ = lexer.Location; } attribute_section { $$ = $1; if ($3 != null) { ArrayList attrs = (ArrayList) $3; if (expecting_local_attribs) { if (local_attrib_section_added) { expecting_local_attribs = false; expecting_global_attribs = false; Report.Error (30205, (Location) $2, "Multiple attribute sections may not be used; Coalesce multiple attribute sections in to a single attribute section"); break; } if ($1 == null) $$ = new Attributes (attrs); else ((Attributes) $1).AddAttributes (attrs); local_attrib_section_added = true; allow_global_attribs = false; } if (expecting_global_attribs) { $$ = null; CodeGen.AddGlobalAttributes ((ArrayList) $3); } } expecting_local_attribs = false; expecting_global_attribs = false; } ; attribute_section : OP_LT attribute_list OP_GT opt_end_of_stmt { $$ = null; if ($2 != null) { if (expecting_global_attribs && !(bool) $4) { Report.Error (30205, lexer.Location, "End of statement expected"); break; } if (expecting_local_attribs) { if ((bool) $4) { Report.Error (32035, lexer.Location, "Use a line continuation after the attribute specifier to apply it to the following statement."); break; } } $$ = $2; } } ; opt_end_of_stmt : /* empty */ { $$ = false; } | end_of_stmt { $$ = true; } ; attribute_list : attribute { ArrayList attrs = null; if ($1 != null) { attrs = new ArrayList (); attrs.Add ($1); } $$ = attrs; } | attribute_list COMMA attribute { ArrayList attrs = null; if ($3 != null) { attrs = ($1 == null) ? new ArrayList () : (ArrayList) $1; attrs.Add ($3); } $$ = attrs; } ; attribute : namespace_or_type_name { $$ = lexer.Location; } opt_attribute_arguments { $$ = null; if (expecting_global_attribs) Report.Error (32015, (Location) $2, "Expecting Assembly or Module attribute specifiers"); else { expecting_local_attribs = true; MemberName mname = (MemberName) $1; string name = mname.GetName (); $$ = new Attribute (null, name, (ArrayList) $3, (Location) $2); } } | attribute_target_specifier { $$ = lexer.Location; } COLON namespace_or_type_name { $$ = lexer.Location; } opt_attribute_arguments { $$ = null; string attribute_target = (string) $1; if (attribute_target != "assembly" && attribute_target != "module") { Report.Error (29999, lexer.Location, "`" + (string)$1 + "' is an invalid attribute modifier"); break; } if (!allow_global_attribs) { Report.Error (30637, (Location) $2, "Global attribute statements must precede any declarations in a file"); break; } if (expecting_local_attribs) { Report.Error (30183, (Location) $2, "Global attributes cannot be combined with local attributes"); break; } expecting_global_attribs = true; MemberName mname = (MemberName) $4; string aname = mname.GetName (); $$ = new Attribute (attribute_target, aname, (ArrayList) $6, (Location) $5); } ; attribute_target_specifier : ASSEMBLY { $$ = "assembly"; } | MODULE { $$ = "module"; } | namespace_or_type_name ; opt_attribute_arguments : /* empty */ { $$ = null; } | OPEN_PARENS opt_attribute_arguments_list CLOSE_PARENS { $$ = $2; } ; opt_attribute_arguments_list : /* empty */ | attribute_arguments_list ; attribute_arguments_list : positional_argument_list { ArrayList args = new ArrayList (4); args.Add ($1); $$ = args; } | positional_argument_list COMMA named_argument_list { ArrayList args = new ArrayList (4); args.Add ($1); args.Add ($3); $$ = args; } | named_argument_list { ArrayList args = new ArrayList (4); args.Add (null); args.Add ($1); $$ = args; } ; positional_argument_list : constant_expression { ArrayList args = new ArrayList (); args.Add (new Argument ((Expression) $1, Argument.AType.Expression)); $$ = args; } | positional_argument_list COMMA constant_expression { ArrayList args = (ArrayList) $1; args.Add (new Argument ((Expression) $3, Argument.AType.Expression)); $$ = args; } ; named_argument_list : named_argument { ArrayList args = new ArrayList (); args.Add ($1); $$ = args; } | named_argument_list COMMA named_argument { ArrayList args = (ArrayList) $1; args.Add ($3); $$ = args; } ; named_argument : identifier ATTR_ASSIGN constant_expression //FIXME: It should be identifier_or_keyword ATTR_ASSIGN constant_expression { $$ = new DictionaryEntry ( (string) $1, new Argument ((Expression) $3, Argument.AType.Expression)); } ; namespace_declaration : NAMESPACE qualified_identifier logical_end_of_line { if (current_attributes != null) { Report.Error(1518, Lexer.Location, "Attributes cannot be applied to namespaces." + " Expected class, delegate, enum, interface, or struct"); } MemberName name = (MemberName) $2; if ((current_namespace.Parent != null) && (name.Left != null)) { Report.Error (134, lexer.Location, "Cannot use qualified namespace names in nested " + "namespace declarations"); } current_namespace = new NamespaceEntry ( current_namespace, file, name.GetName (), lexer.Location); } opt_declarations END NAMESPACE logical_end_of_line { current_namespace = current_namespace.Parent; } ; declaration_qualifiers : opt_attributes opt_modifiers ; type_spec_declaration : class_declaration | module_declaration | interface_declaration | delegate_declaration | struct_declaration | enum_declaration ; class_declaration : CLASS identifier logical_end_of_line { if (implicit_modifiers && ((current_modifiers & Modifiers.STATIC) != 0)) current_modifiers = (current_modifiers & ~Modifiers.STATIC); MemberName name = MakeName (new MemberName ((string) $2)); int mod_flags = current_modifiers; current_class = new Class (current_namespace, current_container, name, mod_flags, (Attributes) current_attributes, lexer.Location); current_container = current_class; RootContext.Tree.RecordDecl (name.GetName (true), current_class); } opt_inherits opt_implements { ArrayList bases = (ArrayList) $5; ArrayList ifaces = (ArrayList) $6; if (ifaces != null){ if (bases != null) bases.AddRange(ifaces); else bases = ifaces; } if (bases != null) { if (current_class.Name == "System.Object") { Report.Error (537, current_class.Location, "The class System.Object cannot have a base " + "class or implement an interface."); } current_class.Bases = (ArrayList) bases; } current_class.Register (); } opt_class_member_declarations END CLASS logical_end_of_line { $$ = current_class; current_container = current_container.Parent; current_class = current_container; } ; opt_inherits : /* empty */ { $$ = null; } | INHERITS type_list logical_end_of_line { $$ = $2; } ; opt_implements : /* empty */ { $$ = null; } | IMPLEMENTS type_list logical_end_of_line { $$ = $2; } ; opt_modifiers : /* empty */ { $$ = (int) 0; current_modifiers = 0; } | modifiers { $$ = $1; current_modifiers = (int) $1; } ; modifiers : modifier | modifiers modifier { int m1 = (int) $1; int m2 = (int) $2; if ((m1 & m2) != 0) { Location l = lexer.Location; Report.Error (1004, l, "Duplicate modifier: `" + Modifiers.Name (m2) + "'"); } $$ = (int) (m1 | m2); } ; modifier : PUBLIC { $$ = Modifiers.PUBLIC; } | PROTECTED { $$ = Modifiers.PROTECTED; } | PRIVATE { $$ = Modifiers.PRIVATE; } | SHARED { $$ = Modifiers.STATIC; } | FRIEND { $$ = Modifiers.INTERNAL; } | NOTINHERITABLE { $$ = Modifiers.SEALED; } | OVERRIDABLE { $$ = Modifiers.VIRTUAL; } | NOTOVERRIDABLE { $$ = Modifiers.NONVIRTUAL; } | OVERRIDES { $$ = Modifiers.OVERRIDE; } | OVERLOADS { $$ = Modifiers.NEW; } | SHADOWS { $$ = Modifiers.SHADOWS; } | MUSTINHERIT { $$ = Modifiers.ABSTRACT; } | READONLY { $$ = Modifiers.READONLY; } | DEFAULT { $$ = Modifiers.DEFAULT; } | WRITEONLY { $$ = Modifiers.WRITEONLY; } ; module_declaration : MODULE identifier logical_end_of_line { MemberName name = MakeName(new MemberName ((string) $2)); current_class = new VBModule (current_namespace, current_container, name, current_modifiers, current_attributes, lexer.Location); current_container = current_class; RootContext.Tree.RecordDecl(name.GetName (true), current_class); current_class.Register (); } opt_module_member_declarations END MODULE logical_end_of_line { $$ = current_class; // FIXME: ????? // TypeManager.AddStandardModule (current_class); current_container = current_container.Parent; current_class = current_container; } ; opt_module_member_declarations : /* empty */ | module_member_declarations ; module_member_declarations : module_member_declaration | module_member_declarations module_member_declaration ; module_member_declaration : opt_attributes opt_modifiers { current_modifiers = ((int)$2) | Modifiers.STATIC; bool explicit_static = (((int) $2 & Modifiers.STATIC) > 0); implicit_modifiers = (!explicit_static); } module_member_declarator { implicit_modifiers = false; $$ = $3; } ; module_member_declarator : constructor_declaration | method_declaration | field_declaration // | withevents_declaration /* This is a field but must be treated specially, see below */ | constant_declaration | property_declaration | event_declaration | type_spec_declaration ; constant_declaration : CONST constant_declarators logical_end_of_line { if (implicit_modifiers && ((current_modifiers & Modifiers.STATIC) != 0)) current_modifiers = (current_modifiers & ~Modifiers.STATIC); int modflags = (int) current_modifiers; // Structure members are Public by default if ((current_container is Struct) && (modflags == 0)) modflags = Modifiers.PUBLIC; ArrayList consts = (ArrayList) $2; if(consts.Count > 0) { VariableDeclaration.FixupTypes ((ArrayList) $2); VariableDeclaration.FixupArrayTypes ((ArrayList) $2); foreach (VariableDeclaration constant in (ArrayList) $2){ Location l = constant.Location; Const c = new Const (current_class, (Expression) constant.type, (String) constant.identifier, (Expression) constant.expression_or_array_initializer, modflags, current_attributes, l); current_container.AddConstant (c); } } } ; opt_class_member_declarations : /* empty */ | class_member_declarations ; class_member_declarations : class_member_declaration | class_member_declarations class_member_declaration ; class_member_declaration : opt_attributes opt_modifiers class_member_declarator { $$ = $3; } ; class_member_declarator : field_declaration | constant_declaration | method_declaration | constructor_declaration | property_declaration | event_declaration // | withevents_declaration /* This is a field but must be treated specially, see below */ | type_spec_declaration ; method_declaration : sub_declaration | func_declaration // | must_override_declaration ; // must_override_declaration // : must_override_sub_declaration // | must_override_func_declaration // ; // must_override_sub_declaration // : MUSTOVERRIDE SUB identifier opt_params opt_implement_clause logical_end_of_line // { // // if (current_container is Module) // // Report.Error (433, "Methods in a Module cannot be declared 'MustOverride'."); // if (current_container is Struct) // Report.Error (435, "Methods in a Structure cannot be declared 'MustOverride'."); // current_modifiers |= Modifiers.ABSTRACT; // Method method = new Method (TypeManager.system_void_expr, (int) current_modifiers, (string) $3, // (Parameters) $4, null, (ArrayList) $5, lexer.Location); // if (!(current_container is Class)) // Report.Error (9999, "THIS SHOULD NEVER HAPPEN!"); // $$ = method; // } // ; // must_override_func_declaration // : MUSTOVERRIDE FUNCTION identifier opt_type_character opt_params opt_type_with_ranks opt_implement_clause logical_end_of_line // { // Expression ftype = ($6 == null) ? (($4 == null) ? TypeManager. // system_object_expr : (Expression) $4 ) : (Expression) $6; // if (current_container is Module) // Report.Error (433, "Methods in a Module cannot be declared 'MustOverride'."); // if (current_container is Struct) // Report.Error (435, "Methods in a Structure cannot be declared 'MustOverride'."); // current_modifiers |= Modifiers.ABSTRACT; // Method method = new Method ((Expression) ftype, (int) current_modifiers, // (string) $3,(Parameters) $5, null, (ArrayList) $7, // lexer.Location); // if (!(current_container is Class)) // Report.Error (9999, "THIS SHOULD NEVER HAPPEN!"); // $$ = method; // } // ; sub_declaration : SUB identifier opt_params { MemberName name = new MemberName ((string) $2); if ((current_container is Struct) && (current_modifiers == 0)) current_modifiers = Modifiers.PUBLIC; GenericMethod generic = null; Method method = new Method (current_class, generic, TypeManager.system_void_expr, (int) current_modifiers, false, name, (Parameters) $3, (Attributes) current_attributes, lexer.Location); current_local_parameters = (Parameters) $3; $$ = method; iterator_container = (IIteratorContainer) method; } opt_evt_handler opt_implement_clause logical_end_of_line // FIXME: opt_event_handler and opt_implements_clause are yet to be handled begin_block opt_statement_list end_block END SUB logical_end_of_line { Method method = (Method) $4; Block b = (Block) $10; const int extern_abstract = (Modifiers.EXTERN | Modifiers.ABSTRACT); if (b == null){ if ((method.ModFlags & extern_abstract) == 0){ Report.Error ( 501, lexer.Location, current_container.MakeName (method.Name) + "must declare a body because it is not marked abstract or extern"); } } else { if ((method.ModFlags & Modifiers.EXTERN) != 0){ Report.Error ( 179, lexer.Location, current_container.MakeName (method.Name) + " is declared extern, but has a body"); } } method.Block = (ToplevelBlock) $10; current_container.AddMethod (method); current_local_parameters = null; iterator_container = null; } ; func_declaration : FUNCTION identifier opt_type_character opt_params opt_type_with_ranks { MemberName name = new MemberName ((string) $2); Expression rettype = ($5 == null) ? (($3 == null) ? TypeManager.system_object_expr : (Expression) $3 ) : (Expression) $5; GenericMethod generic = null; Method method = new Method (current_class, generic, rettype, current_modifiers, false, name, (Parameters) $4, current_attributes, lexer.Location); current_local_parameters = (Parameters) $4; $$ = method; iterator_container = method; } // FIXME: opt_implement_clauses needs to be taken care of opt_implement_clause logical_end_of_line begin_block { Method method = (Method) $6; ArrayList retval = new ArrayList (); retval.Add (new VariableDeclaration ((string) $2, method.Type, lexer.Location)); declare_local_variables (method.Type, retval, lexer.Location); } opt_statement_list end_block END FUNCTION logical_end_of_line { Method method = (Method) $6; Block b = (Block) $12; const int extern_abstract = (Modifiers.EXTERN | Modifiers.ABSTRACT); if (b == null){ if ((method.ModFlags & extern_abstract) == 0){ Report.Error ( 501, lexer.Location, current_container.MakeName (method.Name) + "must declare a body because it is not marked abstract or extern"); } } else { if ((method.ModFlags & Modifiers.EXTERN) != 0){ Report.Error ( 179, lexer.Location, current_container.MakeName (method.Name) + " is declared extern, but has a body"); } } method.Block = (ToplevelBlock) b; current_container.AddMethod (method); current_local_parameters = null; iterator_container = null; } ; struct_declaration : STRUCTURE identifier logical_end_of_line opt_implement_clause { MemberName name = MakeName (new MemberName ((string) $2)); if (implicit_modifiers && ((current_modifiers & Modifiers.STATIC) != 0)) current_modifiers = (current_modifiers & ~Modifiers.STATIC); current_class = new Struct (current_namespace, current_container, name, current_modifiers, current_attributes, lexer.Location); current_container = current_class; RootContext.Tree.RecordDecl (name.GetName (true), current_class); if ($4 != null) current_class.Bases = (ArrayList) $4; current_class.Register (); } opt_struct_member_declarations { $$ = current_class; current_container = current_container.Parent; current_class = current_container; } END STRUCTURE logical_end_of_line ; // FIXME: logical_end_of_line is actually part of the opt_implements_clause // This rule is temporary opt_logical_end_of_line : /* empty */ | logical_end_of_line ; opt_struct_member_declarations : /* empty */ | struct_member_declarations ; struct_member_declarations : struct_member_declaration | struct_member_declarations struct_member_declaration ; struct_member_declaration : opt_modifiers struct_member_declarator ; struct_member_declarator : field_declaration | constant_declaration | constructor_declaration | method_declaration // | property_declaration | event_declaration | type_spec_declaration // * This is only included so we can flag error 575: // * destructors only allowed on class types // | destructor_declaration ; // event_declaration // : EVENT identifier AS type opt_implement_clause logical_end_of_line // { // VariableDeclaration var = new VariableDeclaration ((string) $2, (Expression) $4, lexer.Location); // Event e = new Event ((Expression) $4, var.identifier, // null, current_modifiers, // current_attributes, (ArrayList) $5, // lexer.Location); // CheckDef (current_container.AddEvent (e), e.Name, e.Location); // } // | EVENT identifier opt_params opt_implement_clause logical_end_of_line // { // string delName = null; // if ($4 == null) { // delName = (string) $2; // delName = delName + "EventHandler"; // Mono.MonoBASIC.Delegate del = new Mono.MonoBASIC.Delegate // (current_container, TypeManager.system_void_expr, // (int) current_modifiers, MakeName(delName), (Parameters) $3, // (Attributes) current_attributes, lexer.Location); // del.Namespace = current_namespace; // CheckDef (current_container.AddDelegate (del), del.Name, lexer.Location); // } else { // ArrayList impls = (ArrayList) $4; // if (impls.Count > 1) { // string expstr = "Event '" + ((Expression) impls[1]).ToString () + // "' can not be implemented with Event '" + // (string) $2 + "', since it's delegate type does not match " + // "with the delegate type of '" + ((Expression) impls[0]).ToString () + "'"; // Report.Error (31407, lexer.Location, expstr); // } // Expression impl = (Expression) impls[0]; // delName = impl.ToString(); // delName = delName.Substring (delName.LastIndexOf(".") + 1); // delName = delName + "EventHandler"; // } // Event e = new Event (DecomposeQI (delName, lexer.Location), // (string) $2, // null, current_modifiers, // current_attributes, (ArrayList) $4, // lexer.Location); // CheckDef (current_container.AddEvent (e), e.Name, e.Location); // } // ; event_declaration : EVENT identifier AS type opt_implement_clause logical_end_of_line { VariableDeclaration var = new VariableDeclaration ((string) $2, (Expression) $4, lexer.Location); MemberName name = new MemberName ((string) $2); Event e = new EventField (current_class, (Expression) $4, current_modifiers, false, name, var.expression_or_array_initializer, current_attributes, lexer.Location); current_container.AddEvent (e); } // | EVENT identifier opt_params opt_implement_clause logical_end_of_line // { // string delName = null; // if ($4 == null) { // delName = (string) $2; // delName = delName + "EventHandler"; // Mono.MonoBASIC.Delegate del = new Mono.MonoBASIC.Delegate // (current_container, TypeManager.system_void_expr, // (int) current_modifiers, MakeName(delName), (Parameters) $3, // (Attributes) current_attributes, lexer.Location); // del.Namespace = current_namespace; // CheckDef (current_container.AddDelegate (del), del.Name, lexer.Location); // } else { // ArrayList impls = (ArrayList) $4; // if (impls.Count > 1) { // string expstr = "Event '" + ((Expression) impls[1]).ToString () + // "' can not be implemented with Event '" + // (string) $2 + "', since it's delegate type does not match " + // "with the delegate type of '" + ((Expression) impls[0]).ToString () + "'"; // Report.Error (31407, lexer.Location, expstr); // } // Expression impl = (Expression) impls[0]; // delName = impl.ToString(); // delName = delName.Substring (delName.LastIndexOf(".") + 1); // delName = delName + "EventHandler"; // } // Event e = new Event (DecomposeQI (delName, lexer.Location), // (string) $2, // null, current_modifiers, // current_attributes, (ArrayList) $4, // lexer.Location); // CheckDef (current_container.AddEvent (e), e.Name, e.Location); // } ; enum_declaration : ENUM identifier opt_type_spec logical_end_of_line opt_enum_member_declarations { Location enum_location = lexer.Location; Expression base_type = TypeManager.system_int32_expr; if ((Expression) $3 != null) base_type = (Expression) $3; ArrayList enum_members = (ArrayList) $5; if (enum_members.Count == 0) Report.Error (30280, enum_location, "Enum can not have empty member list"); if (implicit_modifiers && ((current_modifiers & Modifiers.STATIC) != 0)) current_modifiers = (current_modifiers & ~Modifiers.STATIC); MemberName full_name = MakeName (new MemberName ((string) $2)); Enum e = new Enum (current_namespace, current_container, base_type, (int) current_modifiers, full_name, (Attributes) current_attributes, enum_location); foreach (VariableDeclaration ev in (ArrayList) $5) { e.AddEnumMember (ev.identifier, (Expression) ev.expression_or_array_initializer, ev.Location, ev.OptAttributes, ev.DocComment); } string name = full_name.GetName (); current_container.AddEnum (e); RootContext.Tree.RecordDecl (name, e); } END ENUM logical_end_of_line ; opt_enum_member_declarations : /* empty */ { $$ = new ArrayList (4); } | enum_member_declarations { $$ = $1; } ; enum_member_declarations : enum_member_declaration { ArrayList l = new ArrayList (); l.Add ($1); $$ = l; } | enum_member_declarations enum_member_declaration { ArrayList l = (ArrayList) $1; l.Add ($2); $$ = l; } ; enum_member_declaration : opt_attributes identifier logical_end_of_line { $$ = new VariableDeclaration ((string) $2, null, lexer.Location, (Attributes) $1); } | opt_attributes identifier { $$ = lexer.Location; } ASSIGN expression logical_end_of_line { $$ = new VariableDeclaration ((string) $2, $5, lexer.Location, (Attributes) $1); } ; // interface_property_declaration // : PROPERTY identifier opt_type_character opt_property_parameters opt_type_with_ranks logical_end_of_line // { // Expression ftype = ($5 == null) ? (($3 == null) ? // TypeManager.system_object_expr : (Expression) $3 ) : (Expression) $5; // current_local_parameters = (Parameters) $4; // if (current_local_parameters != Parameters.EmptyReadOnlyParameters) { // get_parameters = current_local_parameters.Copy (lexer.Location); // set_parameters = current_local_parameters.Copy (lexer.Location); // Parameter implicit_value_parameter = new Parameter ( // ftype, "Value", Parameter.Modifier.NONE, null); // set_parameters.AppendParameter (implicit_value_parameter); // } // else // { // get_parameters = Parameters.EmptyReadOnlyParameters; // set_parameters = new Parameters (null, null ,lexer.Location); // Parameter implicit_value_parameter = new Parameter ( // ftype, "Value", Parameter.Modifier.NONE, null); // set_parameters.AppendParameter (implicit_value_parameter); // } // lexer.PropertyParsing = true; // Accessor get_block = new Accessor (null, null); // Accessor set_block = new Accessor (null, null); // Property prop = new Property ((Expression) ftype, (string) $2, current_modifiers, // get_block, set_block, current_attributes, lexer.Location, // null, get_parameters, set_parameters, null); // CheckDef (current_interface.AddProperty (prop), prop.Name, lexer.Location); // get_implicit_value_parameter_type = null; // set_implicit_value_parameter_type = null; // get_parameters = null; // set_parameters = null; // current_local_parameters = null; // } // ; // interface_event_declaration // : EVENT identifier AS type logical_end_of_line // { // VariableDeclaration var = new VariableDeclaration ((string) $2, (Expression) $4, lexer.Location); // Event e = new Event ((Expression) $4, var.identifier, // null, current_modifiers, // current_attributes, lexer.Location); // CheckDef (current_interface.AddEvent (e), e.Name, e.Location); // } // | EVENT identifier opt_params logical_end_of_line // { // string delName = (string) $2; // delName = delName + "EventHandler"; // int delModifiers = (current_modifiers & ~Modifiers.ABSTRACT); // Mono.MonoBASIC.Delegate del = new Mono.MonoBASIC.Delegate // (current_container, TypeManager.system_void_expr, // (int) delModifiers, MakeName(delName), (Parameters) $3, // (Attributes) current_attributes, lexer.Location); // del.Namespace = current_namespace; // CheckDef (current_interface.AddDelegate (del), del.Name, lexer.Location); // Event e = new Event (DecomposeQI (delName, lexer.Location), // (string) $2, // null, current_modifiers, // current_attributes, lexer.Location); // CheckDef (current_interface.AddEvent (e), e.Name, e.Location); // } // ; //FIXME: This apparently doesn't seem to emit the right code with property //having opt_property_parameters defined interface_property_declaration : PROPERTY identifier opt_type_character opt_property_parameters opt_type_with_ranks logical_end_of_line { get_implicit_value_parameter_type = ($5 == null) ? (($3 == null) ? TypeManager.system_object_expr : (Expression) $3 ) : (Expression) $5; current_local_parameters = (Parameters) $4; if (current_local_parameters != Parameters.EmptyReadOnlyParameters) { get_parameters = current_local_parameters.Copy (lexer.Location); set_parameters = current_local_parameters.Copy (lexer.Location); Parameter implicit_value_parameter = new Parameter ( get_implicit_value_parameter_type, "Value", Parameter.Modifier.NONE, null); set_parameters.AppendParameter (implicit_value_parameter); } else { get_parameters = Parameters.EmptyReadOnlyParameters; set_parameters = new Parameters (null, null ,lexer.Location); Parameter implicit_value_parameter = new Parameter ( get_implicit_value_parameter_type, "Value", Parameter.Modifier.NONE, null); set_parameters.AppendParameter (implicit_value_parameter); } lexer.PropertyParsing = true; Location loc = lexer.Location; MemberName name = new MemberName ((string) $2); Accessor get_block = new Accessor (null, 0, null, loc); Accessor set_block = new Accessor (null, 0, null, loc); Property prop = new Property (current_class, get_implicit_value_parameter_type, (int) current_modifiers, true, name, current_attributes, get_parameters, get_block, set_parameters, set_block, lexer.Location); current_container.AddProperty (prop); get_implicit_value_parameter_type = null; set_implicit_value_parameter_type = null; get_parameters = null; set_parameters = null; current_local_parameters = null; } ; // interface_event_declaration // : EVENT identifier AS type logical_end_of_line // { // VariableDeclaration var = new VariableDeclaration ((string) $2, (Expression) $4, lexer.Location); // Event e = new Event ((Expression) $4, var.identifier, // null, current_modifiers, // current_attributes, lexer.Location); // CheckDef (current_interface.AddEvent (e), e.Name, e.Location); // } // | EVENT identifier opt_params logical_end_of_line // { // string delName = (string) $2; // delName = delName + "EventHandler"; // int delModifiers = (current_modifiers & ~Modifiers.ABSTRACT); // Mono.MonoBASIC.Delegate del = new Mono.MonoBASIC.Delegate // (current_container, TypeManager.system_void_expr, // (int) delModifiers, MakeName(delName), (Parameters) $3, // (Attributes) current_attributes, lexer.Location); // del.Namespace = current_namespace; // CheckDef (current_interface.AddDelegate (del), del.Name, lexer.Location); // Event e = new Event (DecomposeQI (delName, lexer.Location), // (string) $2, // null, current_modifiers, // current_attributes, lexer.Location); // CheckDef (current_interface.AddEvent (e), e.Name, e.Location); // } // ; interface_declaration : INTERFACE identifier logical_end_of_line { MemberName name = new MemberName ((string) $2); current_class = new Interface (current_namespace, current_container, name, (int) current_modifiers, (Attributes) current_attributes, lexer.Location); current_container = current_class; RootContext.Tree.RecordDecl (name.GetName (true), current_class); } opt_interface_base { current_class.Bases = (ArrayList) $5; current_class.Register (); } interface_body { $$ = current_class; current_container = current_container.Parent; current_class = current_container; } END INTERFACE logical_end_of_line ; opt_interface_base : /* empty */ { $$ = null; } | interface_bases { $$ = $1; } ; interface_bases : interface_base | interface_bases interface_base { ArrayList bases = (ArrayList) $1; bases.AddRange ((ArrayList) $2); $$ = bases; } ; interface_base : INHERITS type_list logical_end_of_line { $$ = $2; } ; interface_body : opt_interface_member_declarations ; opt_interface_member_declarations : /* empty */ | interface_member_declarations ; interface_member_declarations : interface_member_declaration | interface_member_declarations interface_member_declaration ; interface_member_declaration : opt_attributes opt_modifiers interface_member_declarator ; interface_member_declarator : interface_method_declaration { Method m = (Method) $1; current_container.AddMethod (m); } | interface_property_declaration // | interface_event_declaration ; interface_method_declaration : SUB identifier opt_params logical_end_of_line { MemberName name = (MemberName) new MemberName ((string) $2); GenericMethod generic = null; $$ = new Method (current_class, generic, TypeManager.system_void_expr, (int) current_modifiers, true, name, (Parameters) $3, (Attributes) current_attributes, lexer.Location); } | FUNCTION identifier opt_type_character opt_params opt_type_with_ranks logical_end_of_line { MemberName name = new MemberName ((string) $2); Expression return_type = ($5 == null) ? (($3 == null) ? TypeManager.system_object_expr : (Expression) $3 ) : (Expression) $5; GenericMethod generic = null; $$ = new Method (current_class, generic, return_type, (int) current_modifiers, true, name, (Parameters) $4, (Attributes) current_attributes, lexer.Location); } ; property_declaration : non_abstract_propery_declaration // | abstract_propery_declaration ; // abstract_propery_declaration // : MUSTOVERRIDE PROPERTY identifier opt_type_character opt_property_parameters opt_type_with_ranks logical_end_of_line // { // Expression ftype = ($6 == null) ? (($4 == null) ? // TypeManager.system_object_expr : (Expression) $4 ) : (Expression) $6; // if (current_container is Module) // Report.Error (30503, "Properties in a Module cannot be declared 'MustOverride'."); // if (current_container is Struct) // Report.Error (435, "Methods in a Structure cannot be declared 'MustOverride'."); // current_modifiers |= Modifiers.ABSTRACT; // current_local_parameters = (Parameters) $5; // if (current_local_parameters != Parameters.EmptyReadOnlyParameters) { // get_parameters = current_local_parameters.Copy (lexer.Location); // set_parameters = current_local_parameters.Copy (lexer.Location); // Parameter implicit_value_parameter = new Parameter ( // ftype, "Value", Parameter.Modifier.NONE, null); // set_parameters.AppendParameter (implicit_value_parameter); // } // else // { // get_parameters = Parameters.EmptyReadOnlyParameters; // set_parameters = new Parameters (null, null ,lexer.Location); // Parameter implicit_value_parameter = new Parameter ( // ftype, "Value", Parameter.Modifier.NONE, null); // set_parameters.AppendParameter (implicit_value_parameter); // } // lexer.PropertyParsing = true; // Accessor get_block = new Accessor (null, null); // Accessor set_block = new Accessor (null, null); // Property prop = new Property ((Expression) ftype, (string) $3, current_modifiers, // get_block, set_block, current_attributes, lexer.Location, // null, get_parameters, set_parameters, null); // if (!(current_container is Class)) // Report.Error (9999, "THIS SHOULD NEVER HAPPEN!"); // CheckDef (current_container.AddProperty (prop), prop.Name, lexer.Location); // get_implicit_value_parameter_type = null; // set_implicit_value_parameter_type = null; // get_parameters = null; // set_parameters = null; // current_local_parameters = null; // } // ; non_abstract_propery_declaration : PROPERTY identifier opt_type_character opt_property_parameters opt_type_with_ranks opt_implement_clause logical_end_of_line { get_implicit_value_parameter_type = ($5 == null) ? (($3 == null) ? TypeManager.system_object_expr : (Expression) $3 ) : (Expression) $5; get_implicit_value_parameter_name = (string) $2; current_local_parameters = (Parameters) $4; if (current_local_parameters != Parameters.EmptyReadOnlyParameters) { get_parameters = current_local_parameters.Copy (lexer.Location); set_parameters = current_local_parameters.Copy (lexer.Location); } else { get_parameters = Parameters.EmptyReadOnlyParameters; set_parameters = new Parameters (null, null ,lexer.Location); } lexer.PropertyParsing = true; $$ = lexer.Location; } accessor_declarations END PROPERTY logical_end_of_line { lexer.PropertyParsing = false; Property prop; Pair pair = (Pair) $9; Accessor get_block = (Accessor) pair.First; Accessor set_block = (Accessor) pair.Second; Location loc = lexer.Location; MemberName name = new MemberName ((string) $2); // FIXME: Implements Clause needs to be taken care of. if ((current_container is Struct) && (current_modifiers == 0)) current_modifiers = Modifiers.PUBLIC; prop = new Property (current_class, get_implicit_value_parameter_type, (int) current_modifiers, false, name, (Attributes) current_attributes, get_parameters, get_block, set_parameters, set_block, lexer.Location); current_container.AddProperty (prop); get_implicit_value_parameter_type = null; set_implicit_value_parameter_type = null; get_parameters = null; set_parameters = null; current_local_parameters = null; } ; opt_property_parameters : /* empty */ { $$ = Parameters.EmptyReadOnlyParameters; } | OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS { $$ = $2; } ; opt_implement_clause : /* empty */ { $$ = null; } | IMPLEMENTS implement_clause_list { $$ = $2; } ; implement_clause_list : qualified_identifier { MemberName mname = (MemberName) $1; ArrayList impl_list = new ArrayList (); impl_list.Add (mname.GetTypeExpression (lexer.Location)); $$ = impl_list; } | implement_clause_list COMMA qualified_identifier { MemberName mname = (MemberName) $3; ArrayList impl_list = (ArrayList) $1; impl_list.Add (mname.GetTypeExpression (lexer.Location)); $$ = impl_list; } ; accessor_declarations : get_accessor_declaration opt_set_accessor_declaration { $$ = new Pair ($1, $2); } | set_accessor_declaration opt_get_accessor_declaration { $$ = new Pair ($2, $1); } ; opt_get_accessor_declaration : /* empty */ { $$ = null; } | get_accessor_declaration ; opt_set_accessor_declaration : /* empty */ { $$ = null; } | set_accessor_declaration ; get_accessor_declaration : opt_attributes GET logical_end_of_line { if ((current_modifiers & Modifiers.WRITEONLY) != 0) Report.Error (30023, "'WriteOnly' properties cannot have a 'Get' accessor"); current_local_parameters = get_parameters; lexer.PropertyParsing = false; } begin_block { ArrayList retval = new ArrayList (); retval.Add (new VariableDeclaration (get_implicit_value_parameter_name, get_implicit_value_parameter_type, lexer.Location)); declare_local_variables (get_implicit_value_parameter_type, retval, lexer.Location); } opt_statement_list end_block END GET logical_end_of_line { $$ = new Accessor ((ToplevelBlock) $8, (int) current_modifiers, (Attributes) $1, lexer.Location); current_local_parameters = null; lexer.PropertyParsing = true; } ; set_accessor_declaration : opt_attributes SET opt_set_parameter logical_end_of_line { if ((current_modifiers & Modifiers.READONLY) != 0) Report.Error (30022, "'ReadOnly' properties cannot have a 'Set' accessor"); Parameter implicit_value_parameter = new Parameter ( set_implicit_value_parameter_type, set_implicit_value_parameter_name, Parameter.Modifier.NONE, null); set_parameters.AppendParameter (implicit_value_parameter); current_local_parameters = set_parameters; lexer.PropertyParsing = false; } begin_block opt_statement_list end_block END SET logical_end_of_line { $$ = new Accessor ((ToplevelBlock) $8, (int) current_modifiers, (Attributes) $1, lexer.Location); current_local_parameters = null; lexer.PropertyParsing = true; } ; opt_set_parameter : /* empty */ { set_implicit_value_parameter_type = (Expression) get_implicit_value_parameter_type; // TypeManager.system_object_expr; set_implicit_value_parameter_name = "Value"; } |OPEN_PARENS CLOSE_PARENS { set_implicit_value_parameter_type = (Expression) get_implicit_value_parameter_type; set_implicit_value_parameter_name = "Value"; } | OPEN_PARENS opt_parameter_modifier opt_identifier opt_type_with_ranks CLOSE_PARENS { Parameter.Modifier pm = (Parameter.Modifier)$2; if ((pm | Parameter.Modifier.VAL) != 0) Report.Error (31065, lexer.Location, "Set cannot have a paremeter modifier other than 'ByVal'"); set_implicit_value_parameter_type = (Expression) $4; if (set_implicit_value_parameter_type.ToString () != get_implicit_value_parameter_type.ToString ()) Report.Error (31064, lexer.Location, "Set value parameter type can not be different from property type"); if ($2 != null) set_implicit_value_parameter_name = (string) $3; else set_implicit_value_parameter_name = "Value"; } ; field_declaration : opt_dim_stmt variable_declarators logical_end_of_line { int mod = (int) current_modifiers; VariableDeclaration.FixupTypes ((ArrayList) $2); VariableDeclaration.FixupArrayTypes ((ArrayList) $2); // if (current_container is Module) // mod = mod | Modifiers.STATIC; // Structure members are Public by default if ((current_container is Struct) && (mod == 0)) mod = Modifiers.PUBLIC; if ((mod & Modifiers.Accessibility) == 0) mod |= Modifiers.PRIVATE; foreach (VariableDeclaration var in (ArrayList) $2){ Location l = var.Location; Field field = new Field (current_class, var.type, mod, var.identifier, var.expression_or_array_initializer, (Attributes) null, l); current_container.AddField (field); } } ; // withevents_declaration // : opt_dim_stmt WITHEVENTS variable_declarators logical_end_of_line // { // // Module members are static by default, but delegates *can't* be declared static // // so we must fix it, if mbas was the one actually responsible for this // // instead of triggering an error. // if (implicit_modifiers && ((current_modifiers & Modifiers.STATIC) != 0)) // current_modifiers = (current_modifiers & ~Modifiers.STATIC); // /* WithEvents Fields must be resolved into properties // with a bit of magic behind the scenes */ // VariableDeclaration.FixupTypes ((ArrayList) $3); // foreach (VariableDeclaration var in (ArrayList) $3) { // // 1 - We create a private field // Location l = var.Location; // Property prop; // if ((current_modifiers & Modifiers.STATIC) > 0) // Report.Error (30234, l, "'Static' is not valid on a WithEvents declaration."); // Field field = new Field (var.type, Modifiers.PRIVATE, "_" + var.identifier, // var.expression_or_array_initializer, // (Attributes) null, l); // CheckDef (current_container.AddField (field), field.Name, l); // // 2 - Public property // prop = BuildSimpleProperty (var.type, (string) var.identifier, // field, (int) current_modifiers, // (Attributes) current_attributes, l); // CheckDef (current_container.AddProperty (prop), prop.Name, l); // } // } // ; opt_dim_stmt : /* empty */ | DIM ; delegate_declaration : DELEGATE SUB identifier OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS logical_end_of_line { Location l = lexer.Location; MemberName name = MakeName (new MemberName ((string) $3)); if (implicit_modifiers && ((current_modifiers & Modifiers.STATIC) != 0)) current_modifiers = (current_modifiers & ~Modifiers.STATIC); Delegate del = new Delegate (current_namespace, current_container, TypeManager.system_void_expr, current_modifiers, name, (Parameters) $5, current_attributes, l); current_container.AddDelegate (del); RootContext.Tree.RecordDecl (name.GetName (true), del); } | DELEGATE FUNCTION identifier OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS opt_type_with_ranks logical_end_of_line { Location l = lexer.Location; MemberName name = MakeName (new MemberName ((string) $3)); if (implicit_modifiers && ((current_modifiers & Modifiers.STATIC) != 0)) current_modifiers = (current_modifiers & ~Modifiers.STATIC); Expression rettype = ($7 == null) ? TypeManager.system_object_expr : (Expression) $7; Delegate del = new Delegate (current_namespace, current_container, rettype, current_modifiers, name, (Parameters) $5, current_attributes, l); current_container.AddDelegate (del); RootContext.Tree.RecordDecl (name.GetName (true), del); } ; opt_evt_handler : /* empty */ { $$ = null; } // | HANDLES evt_handler { $$ = $2; } ; // evt_handler // : qualified_identifier // { // $$ = (Expression) DecomposeQI ((string)$1, lexer.Location); // } // | base_access // { // $$ = $1; // } // | ME DOT qualified_identifier // { // $$ = (Expression) DecomposeQI ((string)$3, lexer.Location); // } // /*| MYBASE DOT qualified_identifier // { // // FIXME: this is blatantly wrong and crash-prone // $$ = (Expression) DecomposeQI ("MyBase." + (string)$4, lexer.Location); // }*/ // ; constructor_declaration : SUB NEW opt_params logical_end_of_line { current_local_parameters = (Parameters) $3; $$ = new Constructor (current_class, current_container.Basename, 0, (Parameters) $3, (ConstructorInitializer) null, lexer.Location); } begin_block opt_statement_list end_block { Constructor c = (Constructor) $5; c.Block = (ToplevelBlock) $8; c.ModFlags = (int) current_modifiers; c.OptAttributes = current_attributes; // FIXME: Some more error checking from mcs needs to be merged here ??? c.Initializer = CheckConstructorInitializer (ref c.Block.statements); current_container.AddConstructor(c); current_local_parameters = null; } END SUB logical_end_of_line ; opt_formal_parameter_list : /* empty */ { $$ = Parameters.EmptyReadOnlyParameters; } | formal_parameter_list { $$ = $1; } ; formal_parameter_list : parameters { ArrayList pars_list = (ArrayList) $1; Parameter [] pars = null; Parameter array_parameter = null; int non_array_count = pars_list.Count; if (pars_list.Count > 0 && (((Parameter) pars_list [pars_list.Count - 1]).ModFlags & Parameter.Modifier.PARAMS) != 0) { array_parameter = (Parameter) pars_list [pars_list.Count - 1]; non_array_count = pars_list.Count - 1; } foreach (Parameter par in pars_list) if (par != array_parameter && (par.ModFlags & Parameter.Modifier.PARAMS) != 0) { Report.Error (30192, lexer.Location, "ParamArray parameters must be last"); non_array_count = 0; array_parameter = null; break; } if (non_array_count > 0) { pars = new Parameter [non_array_count]; pars_list.CopyTo (0, pars, 0, non_array_count); } $$ = new Parameters (pars, array_parameter, lexer.Location); } ; parameters : parameter { ArrayList pars = new ArrayList (); pars.Add ($1); $$ = pars; } | parameters COMMA parameter { ArrayList pars = (ArrayList) $1; pars.Add ($3); $$ = $1; } ; parameter : opt_attributes opt_parameter_modifier identifier opt_type_character opt_rank_specifiers opt_type_with_ranks opt_variable_initializer { Parameter.Modifier pm = (Parameter.Modifier)$2; bool opt_parm = ((pm & Parameter.Modifier.OPTIONAL) != 0); Expression ptype; if (opt_parm && ($7 == null)) Report.Error (30812, lexer.Location, "Optional parameters must have a default value"); if (!opt_parm && ($7 != null)) Report.Error (32024, lexer.Location, "Non-Optional parameters should not have a default value"); if ((pm & Parameter.Modifier.PARAMS) != 0) { if ((pm & ~Parameter.Modifier.PARAMS) != 0) Report.Error (30667, lexer.Location, "ParamArray parameters must be ByVal"); } if ((pm & Parameter.Modifier.REF) !=0) pm |= Parameter.Modifier.ISBYREF; if ($4 != null && $6 != null && $4 != $6) Report.Error (30302, lexer.Location, "Type character conflicts with declared type."); // TODO: Correct error number and message text ptype = (Expression)(($6 == null) ? (($4 == null) ? TypeManager.system_object_expr : $4) : $6); if ($5 != null) { string t = ptype.ToString (); if (t.IndexOf('[') >= 0) Report.Error (31087, lexer.Location, "Array types specified in too many places"); else ptype = DecomposeQI (t + VariableDeclaration.BuildRanks ((ArrayList) $5, true, lexer.Location), lexer.Location); } if ((pm & Parameter.Modifier.PARAMS) != 0 && ptype.ToString ().IndexOf('[') < 0) Report.Error (30050, lexer.Location, "ParamArray parameters must be an array type"); $$ = new Parameter (ptype, (string) $3, pm, (Attributes) $1, (Expression) $7, opt_parm); } ; opt_parameter_modifier : /* empty */ { $$ = Parameter.Modifier.VAL; } | parameter_modifiers { $$ = $1; } ; parameter_modifiers : parameter_modifiers parameter_modifier { $$ = (Parameter.Modifier)$1 | (Parameter.Modifier)$2; } | parameter_modifier { $$ = $1; } ; parameter_modifier : BYREF { $$ = Parameter.Modifier.REF | Parameter.Modifier.ISBYREF; } | BYVAL { $$ = Parameter.Modifier.VAL; } | OPTIONAL { $$ = Parameter.Modifier.OPTIONAL; } | PARAM_ARRAY { $$ = Parameter.Modifier.PARAMS; } ; opt_statement_list : /* empty */ | statement_list end_of_stmt ; statement_list : statement | statement_list end_of_stmt statement ; block : begin_block opt_statement_list end_block { $$ = $3; } ; begin_block : /* empty */ { if (current_block == null){ current_block = new ToplevelBlock ((ToplevelBlock) top_current_block, current_local_parameters, lexer.Location); top_current_block = current_block; } else { current_block = new Block (current_block, current_local_parameters, lexer.Location, Location.Null); } } ; end_block : /* empty */ { while (current_block.Implicit) current_block = current_block.Parent; $$ = current_block; current_block.SetEndLocation (lexer.Location); current_block = current_block.Parent; if (current_block == null) top_current_block = null; } ; statement : declaration_statement { if ($1 != null && (Block) $1 != current_block){ current_block.AddStatement ((Statement) $1); current_block = (Block) $1; } } | embedded_statement { Statement s = (Statement) $1; current_block.AddStatement ((Statement) $1); } // | labeled_statement | ADDHANDLER prefixed_unary_expression COMMA ADDRESSOF expression { Location loc = lexer.Location; ExpressionStatement expr = new CompoundAssign (Binary.Operator.Addition, (Expression) $2, (Expression) $5, loc); Statement stmt = new StatementExpression (expr, loc); current_block.AddStatement (stmt); } | REMOVEHANDLER prefixed_unary_expression COMMA ADDRESSOF expression { Location loc = lexer.Location; ExpressionStatement expr = new CompoundAssign (Binary.Operator.Subtraction, (Expression) $2, (Expression) $5, loc); Statement stmt = new StatementExpression (expr, loc); current_block.AddStatement (stmt); } | RAISEEVENT identifier opt_raise_event_args //OPEN_PARENS opt_argument_list CLOSE_PARENS { Location loc = lexer.Location; MemberName mname = new MemberName ((string) $2); Expression expr = mname.GetTypeExpression (loc); Invocation inv_expr = new Invocation (expr, (ArrayList) $3, loc); Statement stmt = new StatementExpression (inv_expr, loc); current_block.AddStatement (stmt); } // /* | array_handling_statement */ // /* | empty_statement */ // | with_statement // { // Statement s = (Statement) $1; // current_block.AddStatement ((Statement) $1); // } ; opt_raise_event_args : /* empty */ { $$ = null; } | OPEN_PARENS opt_argument_list CLOSE_PARENS { $$ = $2; } ; // label_name // : identifier // | LITERAL_INTEGER // { // $$ = $1.ToString(); // } // ; // labeled_statement // : label_name COLON // { // LabeledStatement labeled = new LabeledStatement ((string) $1, lexer.Location); // if (!current_block.AddLabel ((string) $1, labeled)){ // Location l = lexer.Location; // Report.Error (140, l, "The label '" + ((string) $1) + "' is a duplicate"); // } // current_block.AddStatement (labeled); // } // | label_name COLON // { // LabeledStatement labeled = new LabeledStatement ((string) $1, lexer.Location); // if (!current_block.AddLabel ((string) $1, labeled)){ // Location l = lexer.Location; // Report.Error (140, l, "The label '" + ((string) $1) + "' is a duplicate"); // } // current_block.AddStatement (labeled); // } // statement // ; embedded_statement : expression_statement | selection_statement // | iteration_statement | try_statement | synclock_statement | jump_statement // | array_handling_statement ; // /* // empty_statement // : end_of_stmt // { // $$ = new EmptyStatement (); // } // ; // */ // with_statement // : WITH expression end_of_stmt /* was : WITH qualified_identifier end_of_stmt */ // { // // was : Expression e = DecomposeQI ((string) $2, lexer.Location); // Expression e = (Expression) $2; // with_stack.Push(e); // start_block(); // } // opt_statement_list // END WITH // { // Block b = end_block(); // with_stack.Pop(); // $$ = b; // } // ; // array_handling_statement // : redim_statement // | erase_statement // ; // redim_statement // : REDIM opt_preserve redim_clauses // { // ArrayList list = (ArrayList) $3; // ReDim r = new ReDim (list, (bool) $2, lexer.Location); // $$ = r; // } // ; // opt_preserve // : /* empty */ { $$ = false; } // | PRESERVE { $$ = true; } // ; // redim_clauses // : redim_clause // { // ArrayList clauses = new ArrayList (); // clauses.Add ($1); // $$ = clauses; // } // | redim_clauses COMMA redim_clause // { // ArrayList clauses = (ArrayList) ($1); // clauses.Add ($2); // $$ = clauses; // } // ; // redim_clause // : invocation_expression // { // Invocation i = (Invocation) $1; // RedimClause rc = new RedimClause (i.expr, i.Arguments); // $$ = rc; // } // ; // erase_statement // : ERASE erase_clauses // { // ArrayList list = (ArrayList) $2; // foreach(Expression e in list) // { // Erase r = new Erase (e, lexer.Location); // $$ = r; // } // } // ; // erase_clauses // : erase_clause // { // ArrayList clauses = new ArrayList (); // clauses.Add ($1); // $$ = clauses; // } // | erase_clauses COMMA erase_clause // { // ArrayList clauses = (ArrayList) ($1); // clauses.Add ($2); // $$ = clauses; // } // ; // erase_clause // : primary_expression // ; jump_statement : /*break_statement | continue_statement | */return_statement | goto_statement | throw_statement // | exit_statement // | yield_statement ; goto_statement : GOTO label_name { $$ = new Goto (current_block, (string) $2, lexer.Location); } ; throw_statement : THROW opt_expression { $$ = new Throw ((Expression) $2, lexer.Location); } ; // exit_statement // : EXIT exit_type // { // $$ = new Exit ((ExitType)$2, lexer.Location); // } // ; // exit_type // : DO { $$ = ExitType.DO; } // | FOR { $$ = ExitType.FOR; } // | WHILE { $$ = ExitType.WHILE; } // | SELECT { $$ = ExitType.SELECT; } // | SUB { $$ = ExitType.SUB; } // | FUNCTION { $$ = ExitType.FUNCTION; } // | PROPERTY { $$ = ExitType.PROPERTY; } // | TRY { $$ = ExitType.TRY; } // ; return_statement : RETURN opt_expression { $$ = new Return ((Expression) $2, lexer.Location); } ; // iteration_statement // : while_statement // | do_statement // | for_statement // | foreach_statement // ; // foreach_statement // : FOR EACH identifier opt_type_spec IN // { // oob_stack.Push (lexer.Location); // } // expression end_of_stmt // { // Location l = lexer.Location; // LocalVariableReference v = null; // VariableInfo vi; // if ($4 != null) // { // start_block(); // VariableDeclaration decl = new VariableDeclaration ((string) $3, // (Expression) $4, null, lexer.Location, null); // vi = current_block.AddVariable ( // (Expression) $4, decl.identifier, current_local_parameters, decl.Location); // Expression expr; // if (decl.expression_or_array_initializer is Expression) // expr = (Expression) decl.expression_or_array_initializer; // else if (decl.expression_or_array_initializer == null) // expr = null; // else // { // ArrayList init = (ArrayList) decl.expression_or_array_initializer; // expr = new ArrayCreation ((Expression) $4, "", init, decl.Location); // } // v = new LocalVariableReference (current_block, decl.identifier, l); // if (expr != null) // { // Assign a = new Assign (v, expr, decl.Location); // current_block.AddStatement (new StatementExpression (a, lexer.Location)); // } // } // else // { // vi = current_block.GetVariableInfo ((string) $3); // if (vi != null) { // // Get a reference to this variable. // v = new LocalVariableReference (current_block, (string) $3, l, vi, false); // } // else // Report.Error (451, "Name '" + (string) $3 + "' is not declared."); // } // oob_stack.Push (v); // start_block(); // } // opt_statement_list // NEXT opt_identifier // { // LocalVariableReference v = (LocalVariableReference) oob_stack.Pop (); // Block foreach_block = end_block(); // Location l = (Location) oob_stack.Pop (); // Foreach f = null; // if (v != null) // f = new Foreach (null, v, (Expression) $7, foreach_block, l); // if ($4 != null) // { // current_block.AddStatement (f); // $$ = end_block (); // } // else // $$ = f; // } // ; // yield_statement // : YIELD expression // { // if (!UseExtendedSyntax) // { // ReportError9998(); // $$ = null; // } // /* else // if (iterator_container == null){ // Report.Error (204, lexer.Location, "yield statement can only be used within a method, operator or property"); // $$ = null; // } else { // iterator_container.SetYields (); // $$ = new Yield ((Expression) $2, lexer.Location); // } */ // } // | YIELD STOP // { // if (!UseExtendedSyntax) // { // ReportError9998(); // $$ = null; // } // /* else // if (iterator_container == null){ // Report.Error (204, lexer.Location, "yield statement can only be used within a method, operator or property"); // $$ = null; // } else { // iterator_container.SetYields (); // $$ = new YieldBreak (lexer.Location); // } */ // } // ; synclock_statement : SYNCLOCK expression end_of_stmt block END SYNCLOCK { $$ = new Lock ((Expression) $2, (Statement) $4, lexer.Location); } ; try_statement : try_catch | try_catch_finally ; try_catch : TRY end_of_stmt block opt_catch_clauses END TRY { Catch g = null; ArrayList c = (ArrayList)$4; for (int i = 0; i < c.Count; ++i) { Catch cc = (Catch) c [i]; if (cc.IsGeneral) { if (i != c.Count - 1) Report.Error (1017, cc.loc, "Empty catch block must be the last in a series of catch blocks"); g = cc; c.RemoveAt (i); i--; } } // Now s contains the list of specific catch clauses // and g contains the general one. $$ = new Try ((Block) $3, c, g, null, ((Block) $3).loc); } ; try_catch_finally : TRY end_of_stmt block opt_catch_clauses FINALLY end_of_stmt block END TRY { Catch g = null; ArrayList s = new ArrayList (4); ArrayList catch_list = (ArrayList) $4; if (catch_list != null){ foreach (Catch cc in catch_list) { if (cc.IsGeneral) g = cc; else s.Add (cc); } } $$ = new Try ((Block) $3, s, g, (Block) $7, ((Block) $3).loc); } ; opt_catch_clauses : /* empty */ { $$ = null; } | catch_clauses ; catch_clauses : catch_clause { ArrayList l = new ArrayList (4); l.Add ($1); $$ = l; } | catch_clauses catch_clause { ArrayList l = (ArrayList) $1; l.Add ($2); $$ = l; } ; opt_identifier : /* empty */ { $$ = null; } | identifier ; // opt_when // : /* empty */ { $$ = null; } // | WHEN boolean_expression { $$ = $2; } // ; catch_clause // : CATCH opt_catch_args opt_when end_of_stmt : CATCH opt_catch_args end_of_stmt { // FIXME: opt_when needs to be hnadled Expression type = null; string id = null; if ($2 != null) { DictionaryEntry cc = (DictionaryEntry) $2; type = (Expression) cc.Key; id = (string) cc.Value; if (id != null){ ArrayList one = new ArrayList (4); Location loc = lexer.Location; one.Add (new VariableDeclaration (id, type, loc)); $1 = current_block; current_block = new Block (current_block); Block b = declare_local_variables (type, one, loc); current_block = b; } } } block { Expression type = null; string id = null; if ($2 != null){ DictionaryEntry cc = (DictionaryEntry) $2; type = (Expression) cc.Key; id = (string) cc.Value; if ($1 != null){ // // FIXME: I can change this for an assignment. // while (current_block != (Block) $1) current_block = current_block.Parent; } } $$ = new Catch (type, id , (Block) $5, ((Block) $5).loc); } ; opt_catch_args : /* empty */ { $$ = null; } | catch_args ; catch_args : identifier AS type { $$ = new DictionaryEntry ($3, $1); } ; // do_statement // : DO opt_do_construct end_of_stmt // { // start_block(); // oob_stack.Push (lexer.Location); // } // opt_statement_list // LOOP opt_do_construct // { // Expression t_before = (Expression) $2; // Expression t_after = (Expression) $7; // Expression t; // if ((t_before != null) && (t_after != null)) // Report.Error (30238, "'Loop' cannot have a condition if matching 'Do' has one."); // if ((t_before == null) && (t_after == null)) // t = new BoolLiteral (true); // else // t = (t_before != null) ? t_before : t_after; // DoOptions test_type = (t_before != null) ? DoOptions.TEST_BEFORE : DoOptions.TEST_AFTER; // if (((do_type == DoOptions.WHILE) && (test_type == DoOptions.TEST_BEFORE)) || // ((do_type == DoOptions.UNTIL) && (test_type == DoOptions.TEST_AFTER))) // t = new Unary (Unary.Operator.LogicalNot, (Expression) t, lexer.Location); // $$ = new Do ((Statement) end_block(), (Expression) t, test_type, lexer.Location); // } // ; // opt_do_construct // : /* empty */ { $$ = null; } // | while_or_until boolean_expression // { // do_type = (DoOptions)$1; // $$ = (Expression) $2; // } // ; // while_or_until // : WHILE { $$ = DoOptions.WHILE; } // | UNTIL { $$ = DoOptions.UNTIL; } // ; while_statement : WHILE { oob_stack.Push (lexer.Location); } boolean_expression end_of_stmt begin_block opt_statement_list end_block END WHILE { Location l = (Location) oob_stack.Pop (); $$ = new While ((Expression) $3, (Statement) $7, l); } ; // for_statement // : FOR identifier opt_type_spec ASSIGN expression TO expression opt_step end_of_stmt // { // if ($3 != null) // { // start_block(); // ArrayList VarDeclaration = new ArrayList (); // VarDeclaration.Add (new VariableDeclaration ((string) $2, // (Expression) $3, null, lexer.Location, null)); // DictionaryEntry de = new DictionaryEntry (DecomposeQI("_local_vars_", lexer.Location), VarDeclaration); // Block b = declare_local_variables ((Expression) de.Key, (ArrayList) de.Value, lexer.Location); // current_block = b; // } // oob_stack.Push (lexer.Location); // start_block(); // } // opt_statement_list // NEXT opt_identifier // { // Block inner_statement = end_block(); // Location l = (Location) oob_stack.Pop (); // Expression for_var = (Expression) DecomposeQI ((string)$2, l); // Expression assign_expr = new Assign (for_var, (Expression) $5, l); // Expression test_expr = new Binary (Binary.Operator.LessThanOrEqual, // for_var, (Expression) $7, l); // Expression step_expr = new Assign (for_var, (Expression) new Binary (Binary.Operator.Addition, // for_var, (Expression) $8, l), l); // Statement assign_stmt = new StatementExpression ((ExpressionStatement) assign_expr, l); // Statement step_stmt = new StatementExpression ((ExpressionStatement) step_expr, l); // For f = new For (assign_stmt, test_expr, step_stmt, inner_statement, l); // if ($3 != null) // { // current_block.AddStatement (f); // $$ = end_block(); // } // else // $$ = f; // } // ; // opt_step // : /* empty */ { $$ = new IntLiteral ((Int32) 1); } // | STEP expression { $$ = $2; } // ; selection_statement : if_statement // | select_statement ; // if_statement // : IF boolean_expression opt_then end_of_stmt // if_statement_rest // // | IF boolean_expression THEN block opt_else_pre_embedded_statement // // | IF boolean_expression else_pre_embedded_statement // ; // FXIME: The rule for LineIfThenStatement needs to be still enabled // FIXME: The lexer.Location that is calculated may have to replaced with the most correct one if_statement : IF boolean_expression opt_then end_of_stmt block END IF { oob_stack.Push (lexer.Location); Location l = (Location) oob_stack.Pop (); $$ = new If ((Expression) $2, (Statement) $5, l); if (RootContext.WarningLevel >= 3){ if ($5 == EmptyStatement.Value) Report.Warning (642, lexer.Location, "Possible mistaken empty statement"); } } | IF boolean_expression opt_then end_of_stmt block ELSE end_of_stmt block END IF { oob_stack.Push (lexer.Location); Location l = (Location) oob_stack.Pop (); $$ = new If ((Expression) $2, (Statement) $5, (Statement) $8, l); } | IF boolean_expression opt_then end_of_stmt block else_if_statement_rest { oob_stack.Push (lexer.Location); Location l = (Location) oob_stack.Pop (); $$ = new If ((Expression) $2, (Statement) $5, (Statement) $6, l); } ; else_if_statement_rest : ELSEIF boolean_expression opt_then end_of_stmt block END IF { oob_stack.Push (lexer.Location); Location l = (Location) oob_stack.Pop (); $$ = new If ((Expression) $2, (Statement) $5, l); if (RootContext.WarningLevel >= 3){ if ($5 == EmptyStatement.Value) Report.Warning (642, lexer.Location, "Possible mistaken empty statement"); } } | ELSEIF boolean_expression opt_then end_of_stmt block ELSE end_of_stmt block END IF { oob_stack.Push (lexer.Location); Location l = (Location) oob_stack.Pop (); $$ = new If ((Expression) $2, (Statement) $5, (Statement) $8, l); } | ELSEIF boolean_expression opt_then end_of_stmt block else_if_statement_rest { oob_stack.Push (lexer.Location); Location l = (Location) oob_stack.Pop (); $$ = new If ((Expression) $2, (Statement) $5, (Statement) $6, l); } ; // opt_else_pre_embedded_statement // : /* empty */ // | else_pre_embedded_statement // ; // else_pre_embedded_statement // : ELSE // { // Block bl = end_block(); // tmp_blocks.Push(bl); // start_block(); // } // | ELSE embedded_statement // { // Block bl = end_block(); // tmp_blocks.Push(bl); // start_block(); // Statement s = (Statement) $2; // current_block.AddStatement ((Statement) $2); // } // ; opt_then : /* empty */ | THEN ; // select_statement // : SELECT opt_case expression end_of_stmt // { // oob_stack.Push (lexer.Location); // switch_stack.Push (current_block); // } // opt_case_sections // END SELECT // { // $$ = new Switch ((Expression) $3, (ArrayList) $6, (Location) oob_stack.Pop ()); // current_block = (Block) switch_stack.Pop (); // } // ; // opt_case_sections // : /* empty */ { $$ = null; } // | case_sections { $$ = $1; } // ; // case_sections // : case_sections case_section // { // ArrayList sections = (ArrayList) $1; // sections.Add ($2); // $$ = sections; // } // | case_section // { // ArrayList sections = new ArrayList (4); // sections.Add ($1); // $$ = sections; // } // ; // ends // : end_of_stmt // | ends end_of_stmt // ; // case_section // : CASE case_clauses ends // { // start_block(); // } // opt_statement_list // { // //Block topmost = current_block; // Block topmost = end_block(); // while (topmost.Implicit) // topmost = topmost.Parent; // // FIXME: This is a horrible hack which MUST go // topmost.statements.Add (new Break (lexer.Location)); // $$ = new SwitchSection ((ArrayList) $2, topmost); // } // | CASE ELSE ends // /* FIXME: we should somehow flag an error // (BC30321 'Case' cannot follow a 'Case Else' // in the same 'Select' statement.) // if Case Else is not the last of the Case clauses // */ // { // start_block(); // } // opt_statement_list // { // //Block topmost = current_block; // Block topmost = end_block(); // while (topmost.Implicit) // topmost = topmost.Parent; // // FIXME: This is a horrible hack which MUST go // topmost.statements.Add (new Break (lexer.Location)); // ArrayList a = new ArrayList(); // a.Add (new SwitchLabel (null, lexer.Location)); // $$ = new SwitchSection ((ArrayList) a, topmost); // } // ; case_clauses : case_clause { ArrayList labels = new ArrayList (); labels.Add ($1); $$ = labels; } | case_clauses COMMA case_clause { ArrayList labels = (ArrayList) ($1); labels.Add ($2); $$ = labels; } ; case_clause : opt_is comparison_operator expression | expression { $$ = new SwitchLabel ((Expression) $1, lexer.Location); } ; opt_is : /* empty */ | IS ; comparison_operator : OP_LT | OP_GT | OP_LE | OP_NE /*| OP_EQ */ ; opt_case : /* empty */ | CASE ; expression_statement : statement_expression { $$ = $1; } ; statement_expression : invocation_expression { $$ = new StatementExpression ((ExpressionStatement) $1, lexer.Location); } | object_creation_expression { $$ = new StatementExpression ((ExpressionStatement) $1, lexer.Location); } | assignment_expression { $$ = new StatementExpression ((ExpressionStatement) $1, lexer.Location); } ; object_creation_expression : NEW type OPEN_PARENS opt_argument_list CLOSE_PARENS { $$ = new New ((Expression) $2, (ArrayList) $4, lexer.Location); } | NEW type { $$ = new New ((Expression) $2, new ArrayList(), lexer.Location); } ; // array_creation_expression // : object_creation_expression opt_rank_specifiers array_initializer // { // New n = (New) $1; // ArrayList dims = new ArrayList(); // if (n.Arguments != null) { // foreach (Argument a in n.Arguments) { // dims.Add (a.Expr); // } // } // Expression atype = n.RequestedType; // if ($2 != null) // atype = DecomposeQI (atype.ToString () + VariableDeclaration.BuildRanks ((ArrayList)$2, true, lexer.Location), lexer.Location); // ArrayList init = (ArrayList) $3; // if (init.Count == 0) // init = null; // if (VariableDeclaration.IndexesSpecifiedInRank(dims)) { // VariableDeclaration.VBFixIndexList (ref dims); // $$ = new ArrayCreation (atype, dims, "", init, lexer.Location); // } // else // { // string rank = VariableDeclaration.BuildRank (dims); // $$ = new ArrayCreation (atype, rank, (ArrayList) $3, lexer.Location); // } // //Console.WriteLine ("Creating a new array of type " + (atype.ToString()) + " with rank '" + dims + "'"); // } // ; new_expression : object_creation_expression // | array_creation_expression ; declaration_statement : local_variable_declaration { if ($1 != null){ DictionaryEntry de = (DictionaryEntry) $1; $$ = declare_local_variables ((Expression) de.Key, (ArrayList) de.Value, lexer.Location); } } | local_constant_declaration { if ($1 != null){ DictionaryEntry de = (DictionaryEntry) $1; $$ = declare_local_constant ((Expression) de.Key, (ArrayList) de.Value); } } ; local_variable_declaration : DIM variable_declarators { $$ = new DictionaryEntry (DecomposeQI("_local_vars_", lexer.Location), $2); } ; local_constant_declaration : CONST constant_declarators { if ($2 != null) $$ = new DictionaryEntry (DecomposeQI("_local_consts_", lexer.Location), $2); else $$ = null; } ; constant_declarators : constant_declarator { ArrayList decl = new ArrayList (); if ($1 != null) decl.Add ($1); $$ = decl; } | constant_declarators COMMA constant_declarator { ArrayList decls = (ArrayList) $1; if ($3 != null) decls.Add ($3); $$ = $1; } ; constant_declarator : variable_name opt_type_decl opt_variable_initializer { VarName vname = (VarName) $1; string varname = (string) vname.Name; current_rank_specifiers = (ArrayList) vname.Rank; object varinit = $3; ArrayList a_dims = null; if (varinit == null) Report.Error ( 30438, lexer.Location, "Constant should have a value" ); if (vname.Type != null && $2 != null) Report.Error ( 30302, lexer.Location, "Type character cannot be used with explicit type declaration" ); Expression vartype = ($2 == null) ? ((vname.Type == null) ? TypeManager.system_object_expr : (Expression) vname.Type ) : (Expression) $2; if (current_rank_specifiers != null) { Report.Error (30424, lexer.Location, "Constant doesn't support array"); $$ = null; } else $$ = new VariableDeclaration (varname, vartype, varinit, lexer.Location, null); } ; variable_declarators : variable_declarator { ArrayList decl = new ArrayList (); decl.AddRange ((ArrayList) $1); $$ = decl; } | variable_declarators COMMA variable_declarator { ArrayList decls = (ArrayList) $1; decls.AddRange ((ArrayList) $3); $$ = $1; } ; variable_declarator : variable_names opt_type_decl opt_variable_initializer { ArrayList names = (ArrayList) $1; object varinit = $3; ArrayList VarDeclarations = new ArrayList(); Expression vartype; ArrayList a_dims = null; if ((names.Count > 1) && (varinit != null)) Report.Error ( 30671, lexer.Location, "Multiple variables with single type can not have " + "a explicit initialization" ); foreach (VarName vname in names) { string varname = (string) vname.Name; current_rank_specifiers = (ArrayList) vname.Rank; a_dims = null; varinit = $3; if(vname.Type != null && $2 != null) Report.Error ( 30302, lexer.Location, "Type character cannot be used with explicit type declaration" ); // Some checking is required for particularly weird declarations // like Dim a As Integer(,) if ($2 is Pair) { vartype = (Expression) ((Pair) $2).First; /*if ($3 != null && $3 is ArrayList) Report.Error (205, "End of statement expected.");*/ ArrayList args = (ArrayList) ((Pair) $2).Second; if (current_rank_specifiers != null) Report.Error (31087, lexer.Location, "Array types specified in too many places"); if (VariableDeclaration.IndexesSpecifiedInRank (args)) Report.Error (30638, "Array bounds cannot appear in type specifiers."); current_rank_specifiers = new ArrayList (); current_rank_specifiers.Add (args); } else vartype = ($2 == null) ? ((vname.Type == null) ? TypeManager.system_object_expr : (Expression) vname.Type ) : (Expression) $2; // if the variable is an array with explicit bound // and having explicit initialization throw exception if (current_rank_specifiers != null && varinit != null) { bool broken = false; foreach (ArrayList exprs in current_rank_specifiers) { foreach (Expression expr in exprs) { if (!((Expression)expr is EmptyExpression )) { Report.Error ( 30672, lexer.Location, "Array declared with explicit bound " + " can not have explicit initialization"); broken = true; break; } } if (broken) break; } } /* Check for a declaration like Dim a(2) or Dim a(2,3) If this is the case, we must generate an ArrayCreationExpression and, in case, add the initializer after the array has been created. */ // if (VariableDeclaration.IsArrayDecl (this)) { // if (VariableDeclaration.IndexesSpecified(current_rank_specifiers)) { // a_dims = (ArrayList) current_rank_specifiers; // VariableDeclaration.VBFixIndexLists (ref a_dims); // varinit = VariableDeclaration.BuildArrayCreator(vartype, a_dims, (ArrayList) varinit, lexer.Location); // } // vartype = DecomposeQI (vartype.ToString() + VariableDeclaration.BuildRanks (current_rank_specifiers, false, lexer.Location), lexer.Location); // } if (vartype is New) { if (varinit != null) { Report.Error (30205, lexer.Location, "End of statement expected"); $$ = null; } else { varinit = vartype; vartype = ((New)vartype).RequestedType; } } VarDeclarations.Add (new VariableDeclaration (varname, vartype, varinit, lexer.Location, null)); }// end of for $$ = VarDeclarations; } ; variable_names : variable_name { ArrayList list = new ArrayList (); list.Add ($1); $$ = list; } | variable_names COMMA variable_name { ArrayList list = (ArrayList) $1; list.Add ($3); $$ = list; } ; variable_name : identifier opt_type_character opt_array_name_modifier { $$ = new VarName ($1, $2, $3); } ; opt_type_spec : /* empty */ { $$ = null; } | AS type { $$ = (Expression) $2; } ; opt_type_with_ranks : opt_type_spec // | AS type rank_specifiers // { // // $$ = DecomposeQI ($2.ToString() + VariableDeclaration.BuildRanks ((ArrayList)$3, true, lexer.Location), lexer.Location); // } ; opt_type_decl : opt_type_with_ranks { $$ = $1; } | AS NEW type { New n = new New ((Expression)$3, null, lexer.Location); $$ = (Expression) n; } | AS NEW type OPEN_PARENS opt_argument_list CLOSE_PARENS { New n = new New ((Expression)$3, (ArrayList) $5, lexer.Location); $$ = (Expression) n; } /*| AS NEW type OPEN_PARENS ADDRESSOF expression CLOSE_PARENS { ArrayList args = new ArrayList(); Argument arg = new Argument ((Expression) $6, Argument.AType.Expression); args.Add (arg); New n = new New ((Expression)$3, (ArrayList) args, lexer.Location); $$ = (Expression) n; }*/ ; opt_array_name_modifier : /* empty */ { $$ = null; } // | array_type_modifier { $$ = $1; } ; // array_type_modifier // : rank_specifiers { $$ = $1; } // ; opt_variable_initializer : /* empty */ { $$ = null; } | ASSIGN variable_initializer { $$ = $2; } ; variable_initializer : expression { $$ = $1; } | array_initializer { $$ = $1; } ; array_initializer : OPEN_BRACE CLOSE_BRACE { ArrayList list = new ArrayList (); $$ = list; } | OPEN_BRACE variable_initializer_list CLOSE_BRACE { $$ = (ArrayList) $2; } ; variable_initializer_list : variable_initializer { ArrayList list = new ArrayList (); list.Add ($1); $$ = list; } | variable_initializer_list COMMA variable_initializer { ArrayList list = (ArrayList) $1; list.Add ($3); $$ = list; } ; opt_rank_specifiers : /* empty */ { // $$ = ""; $$ = null; } | rank_specifiers { $$ = $1; } ; rank_specifiers : rank_specifier { ArrayList rs = new ArrayList(); rs.Add ($1); $$ = rs; } | rank_specifiers rank_specifier { ArrayList rs = (ArrayList) $1; rs.Add ($2); $$ = rs; } ; rank_specifier : OPEN_PARENS opt_dim_specifiers CLOSE_PARENS { $$ = $2; } ; opt_dim_specifiers : /* empty */ { ArrayList ds = new ArrayList(); ds.Add (new EmptyExpression()); $$ = ds; } | expression { ArrayList ds = new ArrayList(); ds.Add ((Expression) $1); $$ = ds; } | opt_dim_specifiers COMMA expression { ArrayList ds = (ArrayList) $1; ds.Add ((Expression) $3); $$ = ds; } | opt_dim_specifiers COMMA { ArrayList ds = (ArrayList) $1; ds.Add (new EmptyExpression()); $$ = ds; } ; // primary_expression // : literal // { // //TODO // } // | parenthesized_expression // | this_access // | base_access // | qualified_identifier // { // string name = (string) $1; // $$ = DecomposeQI (name, lexer.Location); // } // | get_type_expression // | member_access // | invocation_expression // //| element_access // | new_expression // | cast_expression // ; primary_expression : literal { //TODO } | parenthesized_expression | this_access | base_access | qualified_identifier { $$ = ((MemberName) $1).GetTypeExpression (lexer.Location); } | get_type_expression | member_access | invocation_expression //| element_access | new_expression | cast_expression ; literal : boolean_literal | integer_literal | real_literal // | LITERAL_DATE { $$ = new DateLiteral ((DateTime)lexer.Value); } | LITERAL_CHARACTER { $$ = new CharLiteral ((char) lexer.Value); } | LITERAL_STRING { $$ = new StringLiteral ((string) lexer.Value); } | NOTHING { $$ = NullLiteral.Null; } ; real_literal : LITERAL_SINGLE { $$ = new FloatLiteral ((float) lexer.Value); } | LITERAL_DOUBLE { $$ = new DoubleLiteral ((double) lexer.Value); } | LITERAL_DECIMAL { $$ = new DecimalLiteral ((decimal) lexer.Value); } ; integer_literal : LITERAL_INTEGER { object v = lexer.Value; if (v is int) $$ = new IntLiteral ((Int32)v); // else if (v is short) // $$ = new ShortLiteral ((Int16)v); else if (v is long) $$ = new LongLiteral ((Int64)v); else Console.WriteLine ("OOPS. Unexpected result from scanner"); } ; boolean_literal : TRUE { $$ = new BoolLiteral (true); } | FALSE { $$ = new BoolLiteral (false); } ; parenthesized_expression : OPEN_PARENS expression CLOSE_PARENS { $$ = $2; } ; member_access : primary_expression DOT identifier { if ($1 != null) { string id_name = (string)$3; if (id_name.ToUpper() == "NEW") id_name = ".ctor"; $$ = new MemberAccess ((Expression) $1, id_name, lexer.Location); } else { // if (with_stack.Count > 0) { // Expression e = (Expression) with_stack.Peek(); // $$ = new MemberAccess (e, (string) $3, lexer.Location); // } // else // { // // OOps // } } } /* | primary_expression DOT NEW { $$ = new MemberAccess ((Expression) $1, (string) ".ctor", lexer.Location); } */ | predefined_type DOT identifier { if ($1 != null) $$ = new MemberAccess ((Expression) $1, (string) $3, lexer.Location); else { // if (with_stack.Count > 0) { // Expression e = (Expression) with_stack.Peek(); // $$ = new MemberAccess (e, (string) $3, lexer.Location); // } // else // { // // OOps // } } } ; predefined_type : builtin_types ; invocation_expression : primary_expression OPEN_PARENS opt_argument_list CLOSE_PARENS { if ($1 == null) { Location l = lexer.Location; Report.Error (1, l, "Parse error"); } $$ = new Invocation ((Expression) $1, (ArrayList) $3, lexer.Location); } | CALL primary_expression OPEN_PARENS opt_argument_list CLOSE_PARENS { if ($2 == null) { Location l = lexer.Location; Report.Error (1, l, "THIS IS CRAZY"); } $$ = new Invocation ((Expression) $2, (ArrayList) $3, lexer.Location); // Console.WriteLine ("Invocation: {0} with {1} arguments", $2, ($3 != null) ? ((ArrayList) $3).Count : 0); } ; base_access : MYBASE DOT IDENTIFIER { string id_name = (string) $3; if (id_name.ToUpper() == "NEW") id_name = "New"; $$ = new BaseAccess (id_name, lexer.Location); } /* | MYBASE DOT NEW { $$ = new BaseAccess ("New", lexer.Location); }*/ ; opt_argument_list : argument_list { /* The 'argument' rule returns an 'empty' argument of type NoArg (used for default arguments in invocations) if no arguments are actually passed. If there is only one argument and it is o type NoArg, we return a null (empty) list */ ArrayList args = (ArrayList) $1; if (args.Count == 1 && ((Argument)args[0]).ArgType == Argument.AType.NoArg) $$ = null; else $$ = $1; } ; argument_list : argument { ArrayList list = new ArrayList (); list.Add ($1); $$ = list; } | argument_list COMMA argument { ArrayList list = (ArrayList) $1; list.Add ($3); $$ = list; } ; argument : expression { $$ = new Argument ((Expression) $1, Argument.AType.Expression); } | BYREF variable_reference { $$ = new Argument ((Expression) $2, Argument.AType.Ref); } | /* empty */ { $$ = new Argument (new EmptyExpression (), Argument.AType.NoArg); } | ADDRESSOF expression { $$ = new Argument ((Expression) $2, Argument.AType.AddressOf); } ; variable_reference : expression {/* note ("section 5.4"); */ $$ = $1; } ; expression : conditional_xor_expression { $$ = $1; } /*| assignment_expression*/ ; opt_expression : /* empty */ | expression ; this_access : ME { $$ = new This (current_block, lexer.Location); } | MYCLASS { // FIXME: This is actually somewhat different from Me // because it is for accessing static (classifier) methods/properties/fields $$ = new This (current_block, lexer.Location); } ; cast_expression : DIRECTCAST OPEN_PARENS expression COMMA type CLOSE_PARENS { // TODO } | CTYPE OPEN_PARENS expression COMMA type CLOSE_PARENS { $$ = new Cast ((Expression) $5, (Expression) $3, lexer.Location); } | cast_operator OPEN_PARENS expression CLOSE_PARENS { $$ = new Cast ((Expression) $1, (Expression) $3, lexer.Location); } ; cast_operator : CBOOL { $$ = TypeManager.system_boolean_expr; } | CBYTE { $$ = TypeManager.system_byte_expr; } | CCHAR { $$ = TypeManager.system_char_expr; } // | CDATE { $$ = TypeManager.system_date_expr; } | CDBL { $$ = TypeManager.system_double_expr; } | CDEC { $$ = TypeManager.system_decimal_expr; } | CINT { $$ = TypeManager.system_int32_expr; } | CLNG { $$ = TypeManager.system_int64_expr; } | COBJ { $$ = TypeManager.system_object_expr; } | CSHORT { $$ = TypeManager.system_int16_expr; } | CSNG { $$ = TypeManager.system_single_expr; } | CSTR { $$ = TypeManager.system_string_expr; } ; get_type_expression : GETTYPE OPEN_PARENS type CLOSE_PARENS { $$ = new TypeOf ((Expression) $3, lexer.Location); } ; exponentiation_expression : primary_expression | exponentiation_expression OP_EXP primary_expression { //TODO } ; prefixed_unary_expression : exponentiation_expression | PLUS prefixed_unary_expression { //FIXME: Is this rule correctly defined ? $$ = new Unary (Unary.Operator.UnaryPlus, (Expression) $2, lexer.Location); } | MINUS prefixed_unary_expression { //FIXME: Is this rule correctly defined ? $$ = new Unary (Unary.Operator.UnaryNegation, (Expression) $2, lexer.Location); } ; multiplicative_expression : prefixed_unary_expression | multiplicative_expression STAR prefixed_unary_expression { $$ = new Binary (Binary.Operator.Multiply, (Expression) $1, (Expression) $3, lexer.Location); } | multiplicative_expression DIV prefixed_unary_expression { $$ = new Binary (Binary.Operator.Division, (Expression) $1, (Expression) $3, lexer.Location); } ; integer_division_expression : multiplicative_expression | integer_division_expression OP_IDIV multiplicative_expression { //FIXME: Is this right ? $$ = new Binary (Binary.Operator.Division, (Expression) $1, (Expression) $3, lexer.Location); } ; mod_expression : integer_division_expression | mod_expression MOD integer_division_expression { $$ = new Binary (Binary.Operator.Modulus, (Expression) $1, (Expression) $3, lexer.Location); } ; additive_expression : mod_expression | additive_expression PLUS mod_expression { $$ = new Binary (Binary.Operator.Addition, (Expression) $1, (Expression) $3, lexer.Location); } | additive_expression MINUS mod_expression { $$ = new Binary (Binary.Operator.Subtraction, (Expression) $1, (Expression) $3, lexer.Location); } ; concat_expression : additive_expression | concat_expression OP_CONCAT additive_expression { // FIXME: This should only work for String expressions // We probably need to use something from the runtime $$ = new Binary (Binary.Operator.Addition, (Expression) $1, (Expression) $3, lexer.Location); } ; shift_expression : concat_expression | shift_expression OP_SHIFT_LEFT concat_expression { // TODO } | shift_expression OP_SHIFT_RIGHT concat_expression { //TODO } ; relational_expression : shift_expression | relational_expression ASSIGN shift_expression { $$ = new Binary (Binary.Operator.Equality, (Expression) $1, (Expression) $3, lexer.Location); } | relational_expression OP_NE shift_expression { $$ = new Binary (Binary.Operator.Inequality, (Expression) $1, (Expression) $3, lexer.Location); } | relational_expression OP_LT shift_expression { $$ = new Binary (Binary.Operator.LessThan, (Expression) $1, (Expression) $3, lexer.Location); } | relational_expression OP_GT shift_expression { $$ = new Binary (Binary.Operator.GreaterThan, (Expression) $1, (Expression) $3, lexer.Location); } | relational_expression OP_LE shift_expression { $$ = new Binary (Binary.Operator.LessThanOrEqual, (Expression) $1, (Expression) $3, lexer.Location); } | relational_expression OP_GE shift_expression { $$ = new Binary (Binary.Operator.GreaterThanOrEqual, (Expression) $1, (Expression) $3, lexer.Location); } | relational_expression IS shift_expression { //FIXME: Should be a different op for reference equality but allows tests to use Is $$ = new Binary (Binary.Operator.Equality, (Expression) $1, (Expression) $3, lexer.Location); } | TYPEOF shift_expression IS type { //FIXME: Is this rule correctly defined ? $$ = new Is ((Expression) $2, (Expression) $4, lexer.Location); } ; negation_expression : relational_expression | NOT negation_expression { //FIXME: Is this rule correctly defined ? $$ = new Unary (Unary.Operator.LogicalNot, (Expression) $2, lexer.Location); } ; conditional_and_expression : negation_expression | conditional_and_expression AND negation_expression { $$ = new Binary (Binary.Operator.LogicalAnd, (Expression) $1, (Expression) $3, lexer.Location); } | conditional_and_expression ANDALSO negation_expression { // FIXME: this is likely to be broken $$ = new Binary (Binary.Operator.LogicalAnd, (Expression) $1, (Expression) $3, lexer.Location); } ; conditional_or_expression : conditional_and_expression | conditional_or_expression OR conditional_and_expression { $$ = new Binary (Binary.Operator.LogicalOr, (Expression) $1, (Expression) $3, lexer.Location); } | conditional_or_expression ORELSE conditional_and_expression { // FIXME: this is likely to be broken $$ = new Binary (Binary.Operator.LogicalOr, (Expression) $1, (Expression) $3, lexer.Location); } ; conditional_xor_expression : conditional_or_expression | conditional_xor_expression XOR conditional_or_expression { $$ = new Binary (Binary.Operator.ExclusiveOr, (Expression) $1, (Expression) $3, lexer.Location); } ; assignment_expression : prefixed_unary_expression ASSIGN expression { $$ = new Assign ((Expression) $1, (Expression) $3, lexer.Location); } | prefixed_unary_expression STAR ASSIGN expression { Location l = lexer.Location; $$ = new CompoundAssign ( Binary.Operator.Multiply, (Expression) $1, (Expression) $4, l); } | prefixed_unary_expression DIV ASSIGN expression { Location l = lexer.Location; $$ = new CompoundAssign ( Binary.Operator.Division, (Expression) $1, (Expression) $4, l); } | prefixed_unary_expression PLUS ASSIGN expression { Location l = lexer.Location; $$ = new CompoundAssign ( Binary.Operator.Addition, (Expression) $1, (Expression) $4, l); } | prefixed_unary_expression MINUS ASSIGN expression { Location l = lexer.Location; $$ = new CompoundAssign ( Binary.Operator.Subtraction, (Expression) $1, (Expression) $4, l); } | prefixed_unary_expression OP_SHIFT_LEFT ASSIGN expression { Location l = lexer.Location; $$ = new CompoundAssign ( Binary.Operator.LeftShift, (Expression) $1, (Expression) $4, l); } | prefixed_unary_expression OP_SHIFT_RIGHT ASSIGN expression { Location l = lexer.Location; $$ = new CompoundAssign ( Binary.Operator.RightShift, (Expression) $1, (Expression) $4, l); } | prefixed_unary_expression OP_CONCAT ASSIGN expression { Location l = lexer.Location; // FIXME should be strings only $$ = new CompoundAssign ( Binary.Operator.Addition, (Expression) $1, (Expression) $4, l); } | prefixed_unary_expression OP_EXP ASSIGN expression { Location l = lexer.Location; /* TODO: $$ = new CompoundAssign ( Binary.Operator.ExclusiveOr, (Expression) $1, (Expression) $4, l); */ } | prefixed_unary_expression ASSIGN ADDRESSOF expression { // ArrayList args = new ArrayList(); // Argument arg = new Argument ((Expression) $4, Argument.AType.Expression); // args.Add (arg); // New n = new New ((Expression) $1, (ArrayList) args, lexer.Location); // n.isDelegate = true; $$ = new Assign ((Expression) $1, (Expression) $4, lexer.Location); } ; constant_expression : expression ; boolean_expression : expression ; type : namespace_or_type_name { $$ = ((MemberName) $1).GetTypeExpression (lexer.Location); } | builtin_types //| array_type ; type_list : type { ArrayList types = new ArrayList (); types.Add ($1); $$ = types; } | type_list COMMA type { ArrayList types = (ArrayList) $1; types.Add ($3); $$ = types; } ; namespace_or_type_name : qualified_identifier ; builtin_types : OBJECT { $$ = TypeManager.system_object_expr; } | primitive_type ; primitive_type : numeric_type | BOOLEAN { $$ = TypeManager.system_boolean_expr; } // | DATE { $$ = TypeManager.system_date_expr; } | CHAR { $$ = TypeManager.system_char_expr; } | STRING { $$ = TypeManager.system_string_expr; } ; numeric_type : integral_type | floating_point_type | DECIMAL { $$ = TypeManager.system_decimal_expr; } ; integral_type : | BYTE { $$ = TypeManager.system_byte_expr; } | SHORT { $$ = TypeManager.system_int16_expr; } | INTEGER { $$ = TypeManager.system_int32_expr; } | LONG { $$ = TypeManager.system_int64_expr; } ; floating_point_type : SINGLE { $$ = TypeManager.system_single_expr; } | DOUBLE { $$ = TypeManager.system_double_expr; } ; pp_directive : HASH IDENTIFIER OPEN_PARENS LITERAL_STRING COMMA LITERAL_INTEGER CLOSE_PARENS EOL { // if(tokenizerController.IsAcceptingTokens) // { // if(in_external_source) // Report.Error (30580, lexer.Location, "#ExternalSource directives may not be nested"); // else { // in_external_source = true; // lexer.EffectiveSource = (string) $4; // lexer.EffectiveLine = (int) $6; // } // } } | HASH IDENTIFIER LITERAL_STRING EOL { if(tokenizerController.IsAcceptingTokens) { string id = ($2 as string); if(!($2 as string).ToLower().Equals("region")) Report.Error (30205, lexer.Location, "Invalid Pre-processor directive"); else { ++in_marked_region; } } } | HASH END IDENTIFIER EOL { if(tokenizerController.IsAcceptingTokens) { // if( ($3 as string).ToLower().Equals("externalsource")) { // if(!in_external_source) // Report.Error (30578, lexer.Location, "'#End ExternalSource' must be preceded by a matching '#ExternalSource'"); // else { // in_external_source = false; // lexer.EffectiveSource = lexer.Source; // lexer.EffectiveLine = lexer.Line; // } // } /* else */if(($3 as string).ToLower().Equals("region")) { if(in_marked_region > 0) --in_marked_region; else Report.Error (30205, lexer.Location, "'#End Region' must be preceded by a matching '#Region'"); } else { Report.Error (29999, lexer.Location, "Unrecognized Pre-Processor statement"); } } } | HASH CONST IDENTIFIER ASSIGN boolean_literal EOL { if(tokenizerController.IsAcceptingTokens) { //TODO; } } | HASH IF { IfElseStateMachine.Token tok = IfElseStateMachine.Token.IF; try { ifElseStateMachine.HandleToken(tok); } catch(ApplicationException) { throw new MBASException(ifElseStateMachine.Error, lexer.Location, ifElseStateMachine.ErrString); } } boolean_literal opt_then EOL { HandleConditionalDirective(IfElseStateMachine.Token.IF, (BoolLiteral)$4); } | HASH ELSEIF { IfElseStateMachine.Token tok = IfElseStateMachine.Token.ELSEIF; try { ifElseStateMachine.HandleToken(tok); } catch(ApplicationException) { throw new MBASException(ifElseStateMachine.Error, lexer.Location, ifElseStateMachine.ErrString); } } boolean_literal opt_then EOL { HandleConditionalDirective(IfElseStateMachine.Token.ELSEIF, (BoolLiteral)$4); } | HASH ELSE { IfElseStateMachine.Token tok = IfElseStateMachine.Token.ELSE; try { ifElseStateMachine.HandleToken(tok); } catch(ApplicationException) { throw new MBASException(ifElseStateMachine.Error, lexer.Location, ifElseStateMachine.ErrString); } } EOL { HandleConditionalDirective(IfElseStateMachine.Token.ELSE, new BoolLiteral(true)); } | HASH END IF { IfElseStateMachine.Token tok = IfElseStateMachine.Token.ENDIF; try { ifElseStateMachine.HandleToken(tok); } catch(ApplicationException) { throw new MBASException(ifElseStateMachine.Error, lexer.Location, ifElseStateMachine.ErrString); } } EOL { HandleConditionalDirective(IfElseStateMachine.Token.ENDIF, new BoolLiteral(false)); } | HASH error EOL { if(tokenizerController.IsAcceptingTokens) Report.Error(2999, lexer.Location, "Unrecognized Pre-Processor statement"); else Report.Warning (9999, lexer.Location, "Unrecognized Pre-Processor statement"); } ; %% Tokenizer lexer; public Tokenizer Lexer { get { return lexer; } } public static Expression DecomposeQI (string name, Location loc) { Expression o; if (name.IndexOf ('.') == -1){ return new SimpleName (name, loc); } else { int pos = name.LastIndexOf ("."); string left = name.Substring (0, pos); string right = name.Substring (pos + 1); o = DecomposeQI (left, loc); return new MemberAccess (o, right, loc); } } Block declare_local_variables (Expression dummy_type, ArrayList variable_declarators, Location loc) { Block implicit_block; ArrayList inits = null; // // We use the `Used' property to check whether statements // have been added to the current block. If so, we need // to create another block to contain the new declaration // otherwise, as an optimization, we use the same block to // add the declaration. // // FIXME: A further optimization is to check if the statements // that were added were added as part of the initialization // below. In which case, no other statements have been executed // and we might be able to reduce the number of blocks for // situations like this: // // int j = 1; int k = j + 1; // VariableDeclaration.FixupTypes (variable_declarators); // FIXME: Should VariableDeclaration.FixupArrayTypes be called here if (current_block.Used) implicit_block = new Block (current_block, Block.Flags.Implicit, loc, Location.Null); else implicit_block = current_block; foreach (VariableDeclaration decl in variable_declarators){ Expression type = decl.type; if (implicit_block.AddVariable (type, decl.identifier, current_local_parameters, decl.Location) != null) { if (decl.expression_or_array_initializer != null){ if (inits == null) inits = new ArrayList (); inits.Add (decl); } } } if (inits == null) return implicit_block; foreach (VariableDeclaration decl in inits){ Assign assign; Expression expr; Expression type = decl.type; if ((decl.expression_or_array_initializer is Expression) || (decl.expression_or_array_initializer is New)) { expr = (Expression) decl.expression_or_array_initializer; } else { ArrayList init = (ArrayList) decl.expression_or_array_initializer; expr = new ArrayCreation (type, "", init, decl.Location); } LocalVariableReference var; var = new LocalVariableReference (implicit_block, decl.identifier, loc); assign = new Assign (var, expr, decl.Location); implicit_block.AddStatement (new StatementExpression (assign, lexer.Location)); } return implicit_block; } Block declare_local_constant (Expression dummy_type, ArrayList variable_declarators) { Block implicit_block; VariableDeclaration.FixupTypes (variable_declarators); if (current_block.Used) implicit_block = new Block (current_block, Block.Flags.Implicit); else implicit_block = current_block; foreach (VariableDeclaration decl in variable_declarators){ Expression type = decl.type; implicit_block.AddConstant (type, decl.identifier, (Expression) decl.expression_or_array_initializer, current_local_parameters, decl.Location); } return implicit_block; } struct VarName { public object Name; public object Type; public object Rank; public VarName (object n, object t, object r) { Name = n; Type = t; Rank = r; } } // // A class used to pass around variable declarations and constants // public class VariableDeclaration { public string identifier; public object expression_or_array_initializer; public Location Location; public Attributes OptAttributes; public string DocComment; public Expression type; public ArrayList dims; public VariableDeclaration (string id, Expression t, object eoai, Location l, Attributes opt_attrs) { this.identifier = id; this.expression_or_array_initializer = eoai; this.Location = l; this.OptAttributes = opt_attrs; this.type = t; this.dims = null; } public VariableDeclaration (string id, object eoai, Location l) : this (id, eoai, l, null) { } public VariableDeclaration (string id, Expression t, Location l) : this (id, t, null, l, null) { } public VariableDeclaration (string id, object eoai, Location l, Attributes opt_attrs) : this (id, TypeManager.system_object_expr, eoai, l, opt_attrs) { } public static ArrayCreation BuildArrayCreator (Expression vartype, ArrayList a_dims, ArrayList varinit, Location l) { // FIXME : This is broken: only the first rank is parsed return new ArrayCreation (vartype, (ArrayList) a_dims[0], "", varinit, l); } public static void FixupTypes (ArrayList vars) { int varcount = vars.Count; VariableDeclaration last_var = (VariableDeclaration) vars[varcount - 1]; if (last_var.type == null) last_var.type = TypeManager.system_object_expr; Expression cur_type = last_var.type; int n = varcount - 1; while (n >= 0) { VariableDeclaration var = (VariableDeclaration) vars[n--]; if (var.type == null) var.type = cur_type; else cur_type = var.type; } } public static bool IndexesSpecifiedInRank (ArrayList IndexList) { bool res = false; if (IndexList != null) { foreach (Expression e in IndexList) if (!(e is EmptyExpression)) { res = true; break; } } return (res); } public static bool IndexesSpecified (ArrayList ranks) { bool res = false; if (ranks != null) { foreach (ArrayList IndexList in ranks) { if (IndexesSpecifiedInRank (IndexList)) { res = true; break; } } } return (res); } public static string StripDims (string varname, ref string d) { string res = varname; string dres = ""; if (varname.IndexOf("[") >= 0) { dres = varname.Substring(varname.IndexOf("["), (varname.LastIndexOf("]") - varname.IndexOf("["))+1); res = varname.Substring(0, varname.IndexOf("[")); } d = dres; return (res); } public static string StripDims (string varname) { string dres = ""; return (StripDims(varname, ref dres)); } public static string StripIndexesFromDims (string dims) { StringBuilder sb = new StringBuilder(); foreach (char c in dims) if (c == ',' || c == ']' || c == '[') sb.Append (c); return sb.ToString(); } public static string BuildRank (ArrayList rank) { bool allEmpty; return BuildRank(rank, out allEmpty); } public static string BuildRank (ArrayList rank, out bool allEmpty) { string res = ""; res += "["; allEmpty = true; bool first = true; foreach (object e in rank) { if (!(e is EmptyExpression)) allEmpty = false; if (!first) res += ","; first = false; } res += "]"; return res; } public static string BuildRanks (ArrayList rank_specifiers, bool mustBeEmpty, Location loc) { string res = ""; bool allEmpty = true; foreach (ArrayList rank in rank_specifiers) { bool tmp; res = BuildRank (rank, out tmp) + res; if (!tmp) allEmpty = false; } if (!allEmpty && mustBeEmpty) Report.Error (30638, loc, "Array bounds cannot appear in type specifiers."); return res; } public static void VBFixIndexList (ref ArrayList IndexList) { if (IndexList != null) { for (int x = 0; x < IndexList.Count; x++) { Expression e = (Expression) IndexList[x]; if (!(e is EmptyExpression)) { IndexList[x] = new Binary (Binary.Operator.Addition, e, new IntLiteral(1), Location.Null); } } } } // public static bool IsArrayDecl (Parser t) // { // // return (varname.IndexOf("[") >= 0); // return (t.current_rank_specifiers != null); // } public static void VBFixIndexLists (ref ArrayList ranks) { if (ranks != null) { for (int x = 0; x < ranks.Count; x++) { ArrayList IndexList = (ArrayList) ranks[x]; VBFixIndexList (ref IndexList); } } } public static void FixupArrayTypes (ArrayList vars) { int varcount = vars.Count; string dims; foreach (VariableDeclaration var in vars) { if (var.identifier.EndsWith(",")) { dims = "[" + var.identifier.Substring(var.identifier.IndexOf (","), var.identifier.LastIndexOf(",")) + "]"; var.identifier = var.identifier.Substring (0, var.identifier.IndexOf (",")); var.type = new ComposedCast (var.type, (string) dims, var.Location); } } } } // public Property BuildSimpleProperty (Expression p_type, string name, // Field p_fld, int mod_flags, // Attributes attrs, Location loc) // { // Property p; // Block get_block, set_block; // Accessor acc_set, acc_get; // StatementExpression a_set; // Statement a_get; // Parameter [] args; // // Build SET Block // Parameter implicit_value_parameter = new Parameter (p_type, "value", Parameter.Modifier.NONE, null); // args = new Parameter [1]; // args [0] = implicit_value_parameter; // Parameters set_params = new Parameters (args, null, loc); // a_set = new StatementExpression ((ExpressionStatement) new Assign ((Expression) DecomposeQI(p_fld.Name, loc), // (Expression) new SimpleName("value", loc), loc), loc); // set_block = new Block (current_block, set_params, loc, Location.Null); // set_block.AddStatement ((Statement) a_set); // acc_set = new Accessor (set_block, attrs); // // Build GET Block // a_get = (Statement) new Return ((Expression) DecomposeQI(p_fld.Name, loc), loc); // get_block = new Block (current_block, null, loc, Location.Null); // get_block.AddStatement ((Statement) a_get); // acc_get = new Accessor (get_block, attrs); // p = new Property (p_type, name, mod_flags, (Accessor) acc_get, (Accessor) acc_set, attrs, loc); // return (p); // } void start_block () { if (current_block == null){ current_block = new ToplevelBlock ((ToplevelBlock) top_current_block, current_local_parameters, lexer.Location); top_current_block = current_block; } else { current_block = new Block (current_block, current_local_parameters, lexer.Location, Location.Null); } } Block end_block () { Block res; while (current_block.Implicit) current_block = current_block.Parent; res = current_block; current_block.SetEndLocation (lexer.Location); current_block = current_block.Parent; if (current_block == null) top_current_block = null; return res; } // private void AddHandler (Expression evt_definition, Expression handler_exp) // { // AddHandler (current_block, evt_definition, handler_exp); // } void CheckAttributeTarget (string a) { switch (a) { case "assembly" : case "field" : case "method" : case "param" : case "property" : case "type" : return; default : Location l = lexer.Location; Report.Error (658, l, "`" + a + "' is an invalid attribute target"); break; } } // private void AddHandler (Block b, Expression evt_id, Expression handles_exp) // { // Expression evt_target; // Location loc = lexer.Location; // Statement addhnd = (Statement) new AddHandler (evt_id, // handles_exp, // loc); // b.AddStatement (addhnd); // } // private void RaiseEvent (string evt_name, ArrayList args) // { // Location loc = lexer.Location; // Invocation evt_call = new Invocation (DecomposeQI(evt_name, loc), args, lexer.Location); // Statement s = (Statement)(new StatementExpression ((ExpressionStatement) evt_call, loc)); // current_block.AddStatement (s); // } // private void RemoveHandler (Block b, Expression evt_definition, Expression handler_exp) // { // Expression evt_target; // Location loc = lexer.Location; // Statement rmhnd = (Statement) new RemoveHandler (evt_definition, // handler_exp, // loc); // b.AddStatement (rmhnd); // } // // This method is used to get at the complete string representation of // a fully-qualified type name, hiding inside a MemberAccess ;-) // This is necessary because local_variable_type admits primary_expression // as the type of the variable. So we do some extra checking // string GetQualifiedIdentifier (Expression expr) { if (expr is SimpleName) return ((SimpleName)expr).Name; else if (expr is MemberAccess) return GetQualifiedIdentifier (((MemberAccess)expr).Expr) + "." + ((MemberAccess) expr).Identifier; else throw new Exception ("Expr has to be either SimpleName or MemberAccess! (" + expr + ")"); } // private void RemoveHandler (Expression evt_definition, Expression handler_exp) // { // RemoveHandler (current_block, evt_definition, handler_exp); // } // FIXME: This needs to be fixed for This and Base access because the way the name of the // mbas' constructor is changed from "New" to current_container.Basename private ConstructorInitializer CheckConstructorInitializer (ref ArrayList s) { ConstructorInitializer ci = null; if (s.Count > 0) { if (s[0] is StatementExpression && ((StatementExpression) s[0]).expr is Invocation) { Invocation i = (Invocation) ((StatementExpression) s[0]).expr; if (i.expr is BaseAccess) { BaseAccess ba = (BaseAccess) i.expr; if (ba.member == "New" || ba.member == ".ctor") { ci = new ConstructorBaseInitializer (i.Arguments, current_local_parameters, lexer.Location); s.RemoveAt(0); } } if (i.expr.ToString() == "Mono.MonoBASIC.This..ctor") { ci = new ConstructorThisInitializer (i.Arguments, current_local_parameters, lexer.Location); s.RemoveAt(0); } } } return ci; } void Error_ExpectingTypeName (Location l, Expression expr) { if (expr is Invocation){ Report.Error (1002, l, "; expected"); } else { Report.Error (-1, l, "Invalid Type definition"); } } static bool AlwaysAccept (MemberInfo m, object filterCriteria) { return true; } private void ReportError9998() { Report.Error (29998, lexer.Location, "This construct is only available in MonoBASIC extended syntax."); } public CSharpParser (SeekableStreamReader reader, SourceFile file, ArrayList defines) { current_namespace = new NamespaceEntry (null, file, null, Location.Null); this.name = file.Name; this.file = file; current_container = RootContext.Tree.Types; current_container.NamespaceEntry = current_namespace; oob_stack = new Stack (); switch_stack = new Stack (); lexer = new Tokenizer (reader, file, defines); ifElseStateMachine = new IfElseStateMachine(); tokenizerController = new TokenizerController(lexer); } public void parse () { try { if (yacc_verbose_flag > 1) yyparse (lexer, new yydebug.yyDebugSimple ()); else yyparse (lexer); Tokenizer tokenizer = lexer as Tokenizer; tokenizer.cleanup (); } catch (Exception e){ // // Removed for production use, use parser verbose to get the output. // // Console.WriteLine (e); Report.Error (-25, lexer.Location, "Parsing error"); if (yacc_verbose_flag > 0) Console.WriteLine (e); } } // protected override int parse () // { // RootContext.InitializeImports(ImportsList); // current_namespace = new Namespace (null, RootContext.RootNamespace); // current_container = RootContext.Tree.Types; // current_container.Namespace = current_namespace; // oob_stack = new Stack (); // switch_stack = new Stack (); // expr_stack = new Stack (); // tmp_blocks = new Stack(); // with_stack = new Stack(); // statement_stack = new Stack(); // allow_global_attribs = true; // expecting_global_attribs = false; // expecting_local_attribs = false; // local_attrib_section_added = false; // UseExtendedSyntax = name.EndsWith(".mbs"); // OptionExplicit = InitialOptionExplicit || UseExtendedSyntax; // OptionStrict = InitialOptionStrict || UseExtendedSyntax; // OptionCompareBinary = InitialOptionCompareBinary; // lexer = new Tokenizer (input, name, defines); // ifElseStateMachine = new IfElseStateMachine(); // tokenizerController = new TokenizerController(lexer); // StringBuilder value = new StringBuilder (); // try { // if (yacc_verbose_flag > 0) // yyparse (lexer, new yydebug.yyDebugSimple ()); // else { // yyparse (lexer); // cleanup(); // } // } // catch(MBASException e) { // Report.Error(e.code, e.loc, e.Message); // } // catch (Exception e) { // if (Report.Stacktrace) // Console.WriteLine(e); // Report.Error (29999, lexer.Location, "Parsing error"); // } // RootContext.VerifyImports(); // return Report.Errors; // } // void cleanup() // { // try { // ifElseStateMachine.HandleToken(IfElseStateMachine.Token.EOF); // } // catch(ApplicationException) { // throw new MBASException(ifElseStateMachine.Error, lexer.Location, ifElseStateMachine.ErrString); // } // if(in_external_source) // Report.Error (30579, lexer.Location, "'#ExternalSource' directives must end with matching '#End ExternalSource'"); // if(in_marked_region > 0) // Report.Error (30205, lexer.Location, "'#Region' directive must be followed by a matching '#End Region'"); // } void HandleConditionalDirective(IfElseStateMachine.Token tok, BoolLiteral expr) { try { tokenizerController.PositionTokenizerCursor(tok, expr); } catch(ApplicationException) { tok = IfElseStateMachine.Token.EOF; try { ifElseStateMachine.HandleToken(tok); } catch(ApplicationException) { throw new MBASException(ifElseStateMachine.Error, lexer.Location, ifElseStateMachine.ErrString); } } } /* end end end */ // // Given the @class_name name, it creates a fully qualified name // based on the containing declaration space // MemberName MakeName (MemberName class_name) { string ns = current_namespace.FullName; if (current_container.Name == ""){ if (ns != "") return new MemberName (new MemberName (ns), class_name); else return class_name; } else { return new MemberName (current_container.MemberName, class_name); } } }