%{ //---------------------------------------------------------------------------- // // Copyright (c) 2002-2011 Microsoft Corporation. // // This source code is subject to terms and conditions of the Apache License, Version 2.0. A // copy of the license can be found in the License.html file at the root of this distribution. // By using this source code in any fashion, you are agreeing to be bound // by the terms of the Apache License, Version 2.0. // // You must not remove this notice, or any other, from this software. //---------------------------------------------------------------------------- #nowarn "1182" // generated code has lots of unused "parseState" open Internal.Utilities open Microsoft.FSharp.Compiler.AbstractIL open Microsoft.FSharp.Compiler.AbstractIL.Internal open Microsoft.FSharp.Compiler.AbstractIL.Internal.Library open Microsoft.FSharp.Compiler open Internal.Utilities.Text.Parsing open System open Microsoft.FSharp.Compiler.Range open Microsoft.FSharp.Compiler.Ast open Microsoft.FSharp.Compiler.Lib open Microsoft.FSharp.Compiler.PrettyNaming open Microsoft.FSharp.Compiler.ErrorLogger let mkSynOptionalExpr m xopt = match xopt with | None -> mkSynLidGet m Ast.FSharpLib.CorePath "None" | Some x -> SynExpr.App(ExprAtomicFlag.NonAtomic, mkSynLidGet m Ast.FSharpLib.CorePath "Some",x,m) let mkSynDoBinding (vis,strict,expr,m) = if isSome vis then errorR(Error(FSComp.SR.parsDoCannotHaveVisibilityDeclarations(),m)); Binding (None, (if strict then DoBinding else StandaloneExpression), false,false,[],PreXmlDoc.Empty,SynInfo.emptyValSynData, (if strict then SynPat.Const(SynConst.Unit,m) else SynPat.Wild m), None,expr,m,NoSequencePointAtDoBinding) let mkSynDoDecl (e: SynExpr, m) = let spExpr = if IsControlFlowExpression e then NoSequencePointAtDoBinding else SequencePointAtBinding e.Range in SynModuleDecl.DoExpr(spExpr, e, m) let addAttribs attrs p = SynPat.Attrib(p,attrs,p.Range) // error recovery let arbExpr(parseState) = SynExpr.ArbitraryAfterError(lhs(parseState)) // This function is called by the generated parser code. Returning initiates error recovery // It must be called precisely "parse_error_rich" let parse_error_rich = Some (fun (ctxt: ParseErrorContext<_>) -> errorR(SyntaxError(box(ctxt), getLexerRange ctxt.ParseState.LexBuffer))) let reportParseErrorAt m s = errorR(Error(s,m)) let raiseParseErrorAt m s = reportParseErrorAt m s; // This initiates error recovery raise RecoverableParseError let checkEndOfFileError t = match t with | LexCont.IfDefSkip(_,_,m) -> reportParseErrorAt m (FSComp.SR.parsEofInHashIf()) | LexCont.String (_,m) -> reportParseErrorAt m (FSComp.SR.parsEofInString()) | LexCont.VerbatimString (_,m) -> reportParseErrorAt m (FSComp.SR.parsEofInVerbatimString()) | LexCont.Comment (_,_,m) -> reportParseErrorAt m (FSComp.SR.parsEofInComment()) | LexCont.TokenizedComment (_,_,m) -> reportParseErrorAt m (FSComp.SR.parsEofInComment()) | LexCont.CommentString (_,_,m) -> reportParseErrorAt m (FSComp.SR.parsEofInStringInComment()) | LexCont.CommentVerbatimString (_,_,m) -> reportParseErrorAt m (FSComp.SR.parsEofInVerbatimStringInComment()) | LexCont.MLOnly (_,m) -> reportParseErrorAt m (FSComp.SR.parsEofInIfOcaml()) | LexCont.EndLine(LexerEndlineContinuation.Skip(_,_,m)) -> reportParseErrorAt m (FSComp.SR.parsEofInDirective()) | LexCont.EndLine(LexerEndlineContinuation.Token(stack)) | LexCont.Token(stack) -> match stack with | [] -> () | (_,m) :: _ -> reportParseErrorAt m (FSComp.SR.parsNoHashEndIfFound()) type BindingSet = BindingSetPreAttrs of range * bool * bool * (SynAttributes -> SynAccess option -> SynAttributes * SynBinding list) let mkClassMemberLocalBindings(isStatic,wholem,attrs,vis,BindingSetPreAttrs(_,isRec,isUse,declsPreAttrs)) = let ignoredFreeAttrs,decls = declsPreAttrs attrs vis if nonNil ignoredFreeAttrs then warning(Error(FSComp.SR.parsAttributesIgnored(),wholem)); if isUse then errorR(Error(FSComp.SR.parsUseBindingsIllegalInImplicitClassConstructors(),wholem)); SynMemberDefn.LetBindings (decls,isStatic,isRec,wholem) let mkLocalBindings (wholem,BindingSetPreAttrs(_,isRec,isUse,declsPreAttrs),body) = let ignoredFreeAttrs,decls = declsPreAttrs [] None if nonNil ignoredFreeAttrs then warning(Error(FSComp.SR.parsAttributesIgnored(),wholem)); SynExpr.LetOrUse (isRec,isUse,decls,body,wholem) let mkDefnBindings (wholem,BindingSetPreAttrs(_,isRec,isUse,declsPreAttrs),attrs,vis,attrsm) = if isUse then warning(Error(FSComp.SR.parsUseBindingsIllegalInModules(),wholem)); let freeAttrs,decls = declsPreAttrs attrs vis let letDecls = [ SynModuleDecl.Let (isRec,decls,wholem) ] let attrDecls = if nonNil freeAttrs then [ SynModuleDecl.Attributes (freeAttrs,attrsm) ] else [] attrDecls @ letDecls let idOfPat m p = match p with | SynPat.Named (SynPat.Wild _,id,false,_,_) -> id | _ -> raiseParseErrorAt m (FSComp.SR.parsIntegerForLoopRequiresSimpleIdentifier()) let checkForMultipleAugmentations m a1 a2 = if nonNil a1 && nonNil a2 then raiseParseErrorAt m (FSComp.SR.parsOnlyOneWithAugmentationAllowed()); a1 @ a2 let grabXmlDoc(parseState:IParseState,elemIdx) = LexbufLocalXmlDocStore.GrabXML(parseState.LexBuffer,rhs parseState elemIdx) %} %token BYTEARRAY %token STRING %token KEYWORD_STRING // Like __SOURCE_DIRECTORY__ %token IDENT %token INFIX_STAR_STAR_OP %token INFIX_COMPARE_OP %token INFIX_AT_HAT_OP %token INFIX_BAR_OP %token PREFIX_OP %token INFIX_STAR_DIV_MOD_OP %token INFIX_AMP_OP %token PLUS_MINUS_OP %token ADJACENT_PREFIX_OP %token FUNKY_OPERATOR_NAME /* bool indicates if INT8 was 'bad' max_int+1, e.g. '128' */ %token INT8 %token INT16 %token INT32 INT32_DOT_DOT %token INT64 %token UINT8 %token UINT16 %token UINT32 %token UINT64 %token UNATIVEINT %token NATIVEINT %token IEEE32 %token IEEE64 %token CHAR %token DECIMAL %token <(string * string)> BIGNUM %token LET YIELD YIELD_BANG %token LESS GREATER /* here the bool indicates if the tokens are part of a type application or type parameter declaration, e.g. C, detected by the lex filter */ %token PERCENT_OP BINDER %token LQUOTE RQUOTE RQUOTE_DOT %token BAR_BAR UPCAST DOWNCAST NULL RESERVED MODULE NAMESPACE DELEGATE CONSTRAINT BASE %token AND AS ASSERT OASSERT ASR BEGIN DO DONE DOWNTO ELSE ELIF END DOT_DOT %token EXCEPTION FALSE FOR FUN FUNCTION IF IN FINALLY DO_BANG %token LAZY OLAZY MATCH MUTABLE NEW OF %token OPEN OR REC THEN TO TRUE TRY TYPE VAL INLINE INTERFACE INSTANCE %token WHEN WHILE WITH HASH AMP AMP_AMP QUOTE LPAREN RPAREN STAR COMMA RARROW GREATER_BAR_RBRACK LPAREN_STAR_RPAREN %token QMARK QMARK_QMARK DOT COLON COLON_COLON COLON_GREATER COLON_QMARK_GREATER COLON_QMARK COLON_EQUALS SEMICOLON %token SEMICOLON_SEMICOLON LARROW EQUALS LBRACK LBRACK_BAR LBRACK_LESS LBRACE %token LBRACE_LESS BAR_RBRACK GREATER_RBRACE UNDERSCORE %token BAR RBRACK RBRACE MINUS DOLLAR %token GREATER_RBRACK STRUCT SIG %token STATIC MEMBER CLASS ABSTRACT OVERRIDE DEFAULT CONSTRUCTOR INHERIT %token EXTERN VOID PUBLIC PRIVATE INTERNAL GLOBAL /* for high-precedence tyapps and apps */ %token HIGH_PRECEDENCE_BRACK_APP /* inserted for f[x], but not f [x] */ %token HIGH_PRECEDENCE_PAREN_APP /* inserted for f(x) and f(x), but not f (x) */ %token HIGH_PRECEDENCE_TYAPP /* inserted for x, but not x OLET /* LexFilter #light converts 'LET' tokens to 'OLET' when starting (CtxtLetDecl(blockLet=true)) */ %token OBINDER /* LexFilter #light converts 'BINDER' tokens to 'OBINDER' when starting (CtxtLetDecl(blockLet=true)) */ %token ODO /* LexFilter #light converts 'DO' tokens to 'ODO' */ %token ODO_BANG /* LexFilter #light converts 'DO_BANG' tokens to 'ODO_BANG' */ %token OTHEN /* LexFilter #light converts 'THEN' tokens to 'OTHEN' */ %token OELSE /* LexFilter #light converts 'ELSE' tokens to 'OELSE' except if immeditely followed by 'if', when they become 'ELIF' */ %token OWITH /* LexFilter #light converts SOME (but not all) 'WITH' tokens to 'OWITH' */ %token OFUNCTION /* LexFilter #light converts 'FUNCTION' tokens to 'OFUNCTION' */ %token OFUN /* LexFilter #light converts 'FUN' tokens to 'OFUN' */ %token ORESET /* LexFilter uses internally to force a complete reset on a ';;' */ %token OBLOCKBEGIN /* LexFilter #light inserts for: - just after first '=' or ':' when in 'CtxtModuleHead', i.e. after 'module' and sequence of dot/identifier/access tokens - just after first '=' when in 'CtxtMemberHead' - just after first '=' when in 'CtxtType' - just after 'do' in any context (when opening CtxtDo) - just after 'finally' in any context - just after 'with' (when opening CtxtWithAsAugment) - just after 'else' (when opening CtxtElse) - just after 'then' (when opening CtxtThen) - just after 'interface' (when pushing CtxtParen(INTERFACE), i.e. next token is DEFAULT | OVERRIDE | INTERFACE | NEW | TYPE | STATIC | END | MEMBER | ABSTRACT | INHERIT | LBRACK_LESS) - just after 'class' (when pushing CtxtParen(CLASS) - just after 'class' But not when opening these CtxtSeqBlocks: - just after first non-dot/identifier token past 'namespace' - just after first '=' when in 'CtxtLetDecl' or 'CtxtWithAsLet' - just after 'lazy' in any context - just after '->' in any context - when opening CtxtNamespaceHead, CtxtModuleHead */ %token OBLOCKSEP /* LexFilter #light inserts when transforming CtxtSeqBlock(NotFirstInSeqBlock,_,AddBlockEnd) to CtxtSeqBlock(FirstInSeqBlock,_,AddBlockEnd) on exact alignment */ %token OEND /* LexFilter #light inserts when closing CtxtFun, CtxtMatchClauses, CtxtWithAsLet _ */ %token ODECLEND /* LexFilter #light inserts when closing CtxtDo and CtxtLetDecl(block) */ %token ORIGHT_BLOCK_END /* LexFilter #light inserts when closing CtxtSeqBlock(_,_,AddOneSidedBlockEnd) */ %token OBLOCKEND /* LexFilter #light inserts when closing CtxtSeqBlock(_,_,AddBlockEnd) */ %token OINTERFACE_MEMBER /* inserted for non-paranthetical use of 'INTERFACE', i.e. not INTERFACE/END */ %token ODUMMY /* These are artificial */ %token LEX_FAILURE %token COMMENT WHITESPACE HASH_LINE HASH_LIGHT INACTIVECODE LINE_COMMENT STRING_TEXT EOF %token HASH_IF HASH_ELSE HASH_ENDIF %start signatureFile implementationFile interaction %type implementationFile %type signatureFile %type interaction %type ident %type typ %type tyconSpfns %type patternResult %type declExpr %type minusExpr %type appExpr %type argExpr %type declExprBlock %type headBindingPattern %type atomicExprAfterType %type typedSeqExprBlock %type atomicExpr /* About precedence rules: * * Tokens and dummy-terminals are given precedence below (lowest first). * A rule has precedence of the first token or the dummy terminal given after %prec. * The precedence resolve shift/reduce conflicts: * (a) If either rule has no precedence: * S/R: shift over reduce, and * R/R: reduce earlier rule over later rule. * (b) If both rules have precedence: * S/R: choose highest precedence action (precedence of reduce rule vs shift token) * if same precedence: leftassoc gives reduce, rightassoc gives shift, nonassoc error. * R/R: reduce the rule that comes first (textually first in the yacc file) * * Advice from: http://dinosaur.compilertools.net/yacc/ * * 'Conflicts resolved by precedence are not counted in the number of S/R and R/R * conflicts reported by Yacc. This means that mistakes in the moduleSpfn of * precedences may disguise errors in the input grammar; it is a good idea to be * sparing with precedences, and use them in an essentially ``cookbook'' fashion, * until some experience has been gained' * * Observation: * It is possible to eliminate conflicts by giving precedence to rules and tokens. * Dummy tokens can be used for the rule and the tokens also need precedence. * The danger is that giving precedence to the tokens may twist the grammar elsewhere. * Maybe it would be good to assign precedence at given locations, e.g. * * order: precShort precLong * * rule: TokA TokB %@precShort {action1} -- assign prec to rule. * | TokA TokB TokC@precLong TokD {action2} -- assign prec to TokC at this point. * * Observation: reduce/reduce * If there is a common prefix with a reduce/reduce conflict, * e.g "OPEN path" for topopens and moduleDefns then can factor * opendef = "OPEN path" which can be on both paths. * * Debugging and checking precedence rules. * - comment out a rule's %prec and see what conflicts are introduced. * * Dummy terminals (like prec_type_prefix) can assign precedence to a rule. * Doc says rule and (shift) token precedence resolves shift/reduce conflict. * It seems like dummy terminals can not assign precedence to the shift, * but including the tokens in the precedences below will order them. * e.g. prec_type_prefix lower precedence than RARROW, LBRACK, IDENT, STAR (all extend types). */ /* start with lowest */ %nonassoc prec_args_error /* less than RPAREN */ %nonassoc prec_atomexpr_lparen_error /* less than RPAREN */ %right AS /* prec_wheretyp_prefix = "where typ" lower than extensions, i.e. "WHEN" */ %nonassoc prec_wheretyp_prefix /* lower than WHEN and RPAREN */ %nonassoc RPAREN %right WHEN /* prec_pat_pat_action = "pattern when expr -> expr" * Lower than match extensions - i.e. BAR. */ %nonassoc prec_pat_pat_action /* lower than BAR */ /* "a then b" as an object constructor is very low precedence */ /* Lower than "if a then b" */ %left prec_then_before %nonassoc prec_then_if %left BAR %right SEMICOLON prec_semiexpr_sep OBLOCKSEP %right prec_defn_sep /* prec_atompat_pathop = precedence of at atomic pattern, e.g "Constructor". * Lower than possible pattern extensions, so "pathOp . extension" does shift not reduce. * possible extensions are: * - constant terminals. * - null * - LBRACK = [ * - TRUE,FALSE */ %nonassoc prec_atompat_pathop %nonassoc INT8 UINT8 INT16 UINT16 INT32 UINT32 INT64 UINT64 NATIVEINT UNATIVEINT IEEE32 IEEE64 CHAR KEYWORD_STRING STRING BYTEARRAY BIGNUM DECIMAL %nonassoc LPAREN LBRACE LBRACK_BAR %nonassoc TRUE FALSE UNDERSCORE NULL /* prec_typ_prefix lower than "T -> T -> T" extensions. * prec_tuptyp_prefix lower than "T * T * T * T" extensions. * prec_tuptyptail_prefix lower than "T * T * T * T" extensions. * Lower than possible extensions: * - STAR, IDENT, RARROW * - LBRACK = [ - for "base[]" types * Shifts not reduces. */ %nonassoc prec_typ_prefix /* lower than STAR, IDENT, RARROW etc */ %nonassoc prec_tuptyp_prefix /* ditto */ %nonassoc prec_tuptyptail_prefix /* ditto */ %nonassoc prec_toptuptyptail_prefix /* ditto */ %right RARROW %nonassoc IDENT LBRACK /* prec_opt_attributes_none = precedence of no attributes * These can prefix LET-moduleDefns. * Committing to an opt_attribute (reduce) forces the decision that a following LET is a moduleDefn. * At the top-level, it could turn out to be an expr, so prefer to shift and find out... */ %nonassoc prec_opt_attributes_none /* lower than LET,NEW */ /* LET,NEW higher than SEMICOLON so shift * "seqExpr = seqExpr; . let x = y in z" * "seqExpr = seqExpr; . new...." */ %nonassoc LET NEW /* Redundant dummies: expr_let, expr_function, expr_fun, expr_match */ /* Resolves conflict: expr_try, expr_if */ %nonassoc expr_let %nonassoc decl_let %nonassoc expr_function expr_fun expr_match expr_try expr_do %nonassoc decl_match decl_do %nonassoc expr_if /* lower than ELSE to disambiguate "if _ then if _ then _ else _" */ %nonassoc ELSE /* prec_atomtyp_path = precedence of atomType "path" * Lower than possible extension "path" to allow "path . <" shift. * Extensions: LESS */ %nonassoc prec_atomtyp_path /* lower than LESS */ %nonassoc prec_atomtyp_get_path /* lower than LESS */ /* prec_no_more_attr_bindings = precedence of "moreLocalBindings = ." * Lower precedence than AND so further bindings are shifted. */ %nonassoc prec_no_more_attr_bindings /* lower than AND */ %nonassoc OPEN /* prec_interfaces_prefix - lower than extensions, i.e. INTERFACE */ %nonassoc prec_interfaces_prefix /* lower than INTERFACE */ %nonassoc INTERFACE %right LARROW %right COLON_EQUALS %nonassoc pat_tuple expr_tuple %left COMMA %nonassoc slice_comma /* for matrix.[1..2,3..4] the ".." has higher precedence than "2,3" */ %nonassoc DOT_DOT /* for matrix.[1..2,3..4] the ".." has higher precedence than "2,3" */ %nonassoc paren_pat_colon %nonassoc paren_pat_attribs %left OR BAR_BAR %left AND /* check */ %left AMP AMP_AMP %nonassoc pat_conj %nonassoc expr_not %left COLON_GREATER COLON_QMARK_GREATER %left INFIX_COMPARE_OP DOLLAR LESS GREATER EQUALS INFIX_BAR_OP INFIX_AMP_OP %right INFIX_AT_HAT_OP %right COLON_COLON %nonassoc pat_isinst %left COLON_QMARK %left PLUS_MINUS_OP MINUS expr_prefix_plus_minus ADJACENT_PREFIX_OP %left INFIX_STAR_DIV_MOD_OP STAR PERCENT_OP %right INFIX_STAR_STAR_OP %left QMARK_QMARK %left head_expr_adjacent_minus %left expr_app expr_assert expr_lazy LAZY ASSERT %left arg_expr_adjacent_minus %left expr_args %right matching_bar %left pat_app %left pat_args %left PREFIX_OP %left DOT QMARK %left HIGH_PRECEDENCE_BRACK_APP %left HIGH_PRECEDENCE_PAREN_APP %left HIGH_PRECEDENCE_TYAPP %nonassoc prec_interaction_empty %% /* F# TopLevel */ /* NOTE: interactions */ /* A SEMICOLON_SEMICOLON (or EOF) will mark the end of all interaction blocks. */ /* The end of interaction blocks must be determined without needing to lookahead one more token. */ /* A lookahead token would be dropped between parser calls. See bug 1027. */ interaction: | interactiveItemsTerminator { IDefns ($1,lhs(parseState)) } | SEMICOLON { warning(Error(FSComp.SR.parsUnexpectedSemicolon(),rhs parseState 1)); IDefns ([],lhs(parseState)) } | OBLOCKSEP { IDefns ([],lhs(parseState)) } hashDirective: | HASH IDENT hashDirectiveArgs { ParsedHashDirective ($2,$3,lhs(parseState)) } stringOrKeywordString: | STRING { $1 } | KEYWORD_STRING { $1 } hashDirectiveArg: | stringOrKeywordString { $1 } hashDirectiveArgs: | { [] } | hashDirectiveArgs hashDirectiveArg { $1 @ [$2] } interactiveTerminator: | SEMICOLON_SEMICOLON {} | EOF {} /* Represents the sequence of items swallowed in one interaction by F# Interactive */ /* It is important to make this as large as possible given the chunk of input */ /* text. More or less identical to 'moduleDefns' but where SEMICOLON_SEMICOLON is */ /* not part of the grammar of topSeps and HASH interactions are not part of */ /* the swalloed blob, since things like #use must be processed separately. */ interactiveItemsTerminator: /* Always ends on interactiveTerminator */ | interactiveTerminator { [] } | interactiveModuleDefns interactiveTerminator { $1 } | interactiveExpr interactiveTerminator { $1 } | interactiveHash interactiveTerminator { $1 } | interactiveModuleDefns interactiveSeparators interactiveItemsTerminator { $1 @ $3 } | interactiveExpr interactiveSeparators interactiveItemsTerminator { $1 @ $3 } | interactiveHash interactiveSeparators interactiveItemsTerminator { $1 @ $3 } interactiveModuleDefns: /* One or more moduleDefn. */ | moduleDefn { $1 } | moduleDefn interactiveModuleDefns { $1 @ $2 } interactiveExpr: | opt_attributes opt_declVisibility declExpr { if isSome $2 then errorR(Error(FSComp.SR.parsUnexpectedVisibilityDeclaration(),rhs parseState 3)); let attrDecls = if nonNil $1 then [ SynModuleDecl.Attributes ($1,rhs parseState 1) ] else [] in attrDecls @ [ mkSynDoDecl($3,rhs parseState 3)] } interactiveHash: | hashDirective { [SynModuleDecl.HashDirective($1,rhs parseState 1)] } /* F# Language Proper */ signatureFile: | fileNamespaceSpecs EOF { checkEndOfFileError $2; $1 } | fileNamespaceSpecs error EOF { $1 } /* If this rule fires it is kind of catastrophic: error recovery yields no results! */ /* This will result in NO intellisense for the file! Ideally we wouldn't need this rule */ /* Note: the compiler assumes there is at least one "fragment", so an empty one is used (see 4488) */ | error EOF { let emptySigFileFrag = AnonTopModuleSig([],rhs parseState 1) in ParsedSigFile([],[emptySigFileFrag]) } implementationFile: | fileNamespaceImpls EOF { checkEndOfFileError $2; $1 } | fileNamespaceImpls error EOF { $1 } /* If this rule fires it is kind of catastrophic: error recovery yields no results! */ /* This will result in NO intellisense for the file! Ideally we wouldn't need this rule */ /* Note: the compiler assumes there is at least one "fragment", so an empty one is used (see 4488) */ | error EOF { let emptyImplFileFrag = AnonTopModule([],rhs parseState 1) in ParsedImplFile([],[emptyImplFileFrag]) } moduleIntro: | MODULE opt_access path { $3,grabXmlDoc(parseState,1),$2 } namespaceIntro: | NAMESPACE path { $2,grabXmlDoc(parseState,1) } fileNamespaceSpecs: | fileModuleSpec { ParsedSigFile([],[ ($1 ([],PreXmlDoc.Empty)) ]) } | fileModuleSpec fileNamespaceSpecList { // If there are namespaces, the first fileModuleImpl may only contain # directives let decls = match ($1 ([],PreXmlDoc.Empty)) with | AnonTopModuleSig(decls,m) -> decls | NamespaceFragmentSig(_,_, decls, _,_,_) -> decls | NamedTopModuleSig(ModuleOrNamespaceSig(_,_,_,_,_,_,m)) -> raiseParseErrorAt m (FSComp.SR.parsOnlyHashDirectivesAllowed()) let decls = decls |> List.collect (function | (SynModuleSigDecl.HashDirective (hd,_)) -> [hd] | d -> reportParseErrorAt d.Range (FSComp.SR.parsOnlyHashDirectivesAllowed()); []) ParsedSigFile(decls, $2) } fileNamespaceSpecList: | fileNamespaceSpec fileNamespaceSpecList { $1 :: $2 } | fileNamespaceSpec { [$1] } fileNamespaceSpec: | opt_attributes namespaceIntro deprecated_opt_equals fileModuleSpec { let path,xml = $2 in ($4 (path,xml)) } fileNamespaceImpls: | fileModuleImpl { ParsedImplFile([], [ ($1 ([],PreXmlDoc.Empty)) ]) } | fileModuleImpl fileNamespaceImplList { // If there are namespaces, the first fileModuleImpl may only contain # directives let decls = match ($1 ([],PreXmlDoc.Empty)) with | AnonTopModule(decls,m) -> decls | NamespaceFragment(_,_, decls, _,_,_) -> decls | NamedTopModule(ModuleOrNamespace(_,_,_,_,_,_,m)) -> raiseParseErrorAt m (FSComp.SR.parsOnlyHashDirectivesAllowed()) let decls = decls |> List.collect (function | (SynModuleDecl.HashDirective (hd,_)) -> [hd] | d -> reportParseErrorAt d.Range (FSComp.SR.parsOnlyHashDirectivesAllowed()); []) ParsedImplFile(decls, $2) } fileNamespaceImplList: | fileNamespaceImpl fileNamespaceImplList { $1 :: $2 } | fileNamespaceImpl { [$1] } fileNamespaceImpl: | opt_attributes namespaceIntro deprecated_opt_equals fileModuleImpl { let path,xml = $2 in ($4 (path,xml)) } fileModuleSpec: | opt_attributes opt_declVisibility moduleIntro moduleSpfnsPossiblyEmptyBlock { if isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(),rhs parseState 2)); let m2 = rhs parseState 3 let m = (rhs2 parseState 3 4) (fun (path,_) -> if nonNil path then errorR(Error(FSComp.SR.parsNamespaceOrModuleNotBoth(),m2)); let path2,xml,vis = $3 let lid = path@path2 NamedTopModuleSig(ModuleOrNamespaceSig(lid,true, $4, xml,$1,vis,m))) } | moduleSpfnsPossiblyEmptyBlock { let m = (rhs parseState 1) (fun (path,xml) -> match path with | [] -> AnonTopModuleSig($1, m) | _ -> NamespaceFragmentSig(path,false, $1, xml,[],m)) } fileModuleImpl: | opt_attributes opt_declVisibility moduleIntro moduleDefnsOrExprPossiblyEmptyOrBlock { if isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(),rhs parseState 2)); let m2 = rhs parseState 3 let m = (rhs2 parseState 3 4) (fun (path,_) -> if nonNil path then errorR(Error(FSComp.SR.parsNamespaceOrModuleNotBoth(),m2)); let path2,xml,vis = $3 let lid = path@path2 NamedTopModule(ModuleOrNamespace(lid,true, $4, xml,$1,vis,m))) } | moduleDefnsOrExprPossiblyEmptyOrBlock { let m = (rhs parseState 1) (fun (path,xml) -> match path with | [] -> AnonTopModule($1,m) | _ -> NamespaceFragment(path,false, $1, xml,[],m)) } moduleSpfnsPossiblyEmptyBlock: | moduleSpfnsPossiblyEmpty { $1 } | OBLOCKBEGIN moduleSpfnsPossiblyEmpty OBLOCKEND opt_OBLOCKSEP { $2 } | OBLOCKBEGIN moduleSpfnsPossiblyEmpty recover { // The lex filter ensures we can only get a mismatch in OBLOCKBEGIN/OBLOCKEND tokens if there was some other kind of error, hence we don't need to report this error // reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnClosedBlockInHashLight()); $2 } | OBLOCKBEGIN error OBLOCKEND { [] } moduleSpfnsPossiblyEmpty: | moduleSpfns { $1 } | error { [] } | { [] } moduleSpfns: | moduleSpfn opt_topSeparators moduleSpfns { $1 :: $3 } | error topSeparators moduleSpfns { (* silent recovery *) $3 } | moduleSpfn opt_topSeparators { [$1] } moduleDefnsOrExprPossiblyEmptyOrBlock: | OBLOCKBEGIN moduleDefnsOrExprPossiblyEmpty OBLOCKEND opt_OBLOCKSEP { $2 } | OBLOCKBEGIN moduleDefnsOrExprPossiblyEmpty recover { // The lex filter ensures we can only get a mismatch in OBLOCKBEGIN/OBLOCKEND tokens if there was some other kind of error, hence we don't need to report this error // reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnClosedBlockInHashLight()); $2 } | OBLOCKBEGIN error OBLOCKEND { [] } | moduleDefnsOrExprPossiblyEmpty { $1 } moduleDefnsOrExprPossiblyEmpty: | moduleDefnsOrExpr { $1 } | { [] } /* A naked expression is only allowed at the start of a module/file, or straight after a topSeparators */ moduleDefnsOrExpr: | opt_attributes opt_declVisibility declExpr topSeparators moduleDefnsOrExpr { if isSome $2 then errorR(Error(FSComp.SR.parsUnexpectedVisibilityDeclaration(),rhs parseState 3)); let attrDecls = if nonNil $1 then [ SynModuleDecl.Attributes ($1,rhs parseState 1) ] else [] attrDecls @ mkSynDoDecl ($3,rhs parseState 3) :: $5 } | opt_attributes opt_declVisibility declExpr topSeparators { if isSome $2 then errorR(Error(FSComp.SR.parsUnexpectedVisibilityDeclaration(),rhs parseState 3)); let attrDecls = if nonNil $1 then [ SynModuleDecl.Attributes ($1,rhs parseState 1) ] else [] attrDecls @ [ mkSynDoDecl($3,rhs parseState 3) ] } | opt_attributes opt_declVisibility declExpr { if isSome $2 then errorR(Error(FSComp.SR.parsUnexpectedVisibilityDeclaration(),rhs parseState 3)); let attrDecls = if nonNil $1 then [ SynModuleDecl.Attributes ($1,rhs parseState 1) ] else [] attrDecls @ [ mkSynDoDecl($3,rhs parseState 3) ] } | moduleDefns { $1 } | error { [] } moduleDefns: | moduleDefnOrDirective moduleDefns { $1 @ $2 } | moduleDefnOrDirective topSeparators moduleDefnsOrExpr { $1 @ $3 } | moduleDefnOrDirective { $1 } | moduleDefnOrDirective topSeparators { $1 } | error topSeparators moduleDefnsOrExpr { $3 } moduleDefnOrDirective: | moduleDefn { $1 } | hashDirective { [ SynModuleDecl.HashDirective ($1,rhs2 parseState 1 1) ] } /* Recover whenever an error occurs in a moduleDefn */ /* This is used by both "fsi" interactions and "source file" fragments defined by moduleDefns */ moduleDefn: | opt_attributes opt_declVisibility defnBindings %prec decl_let { if isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(),rhs parseState 2)); GlobalSynArgNameGenerator.Reset(); mkDefnBindings (rhs parseState 3,$3,$1,$2,rhs parseState 3) } | opt_attributes opt_declVisibility hardwhiteLetBindings %prec decl_let { if isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(),rhs parseState 2)); GlobalSynArgNameGenerator.Reset(); mkDefnBindings (rhs parseState 3,$3,$1,$2,rhs parseState 3) } | opt_attributes opt_declVisibility doBinding %prec decl_let { if isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(),rhs parseState 2)); let letm = rhs parseState 3 mkDefnBindings (letm,$3,$1,$2,rhs parseState 3) } | opt_attributes opt_declVisibility TYPE tyconDefn tyconDefnList { if isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(),rhs parseState 2)); let (TypeDefn(ComponentInfo(cas ,a,cs,b,c,d,d2,d3),e,f,g)) = $4 let tc = (TypeDefn(ComponentInfo($1@cas,a,cs,b,c,d,d2,d3),e,f,g)) [ SynModuleDecl.Types(tc :: $5,rhs2 parseState 3 5) ] } | opt_attributes opt_declVisibility exconDefn { if isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(),rhs parseState 2)); let (ExceptionDefn(ExceptionDefnRepr(cas,a,b,c,d,d2),e,f)) = $3 let ec = (ExceptionDefn(ExceptionDefnRepr($1@cas,a,b,c,d,d2),e,f)) [ SynModuleDecl.Exception(ec, rhs2 parseState 3 3) ] } | opt_attributes opt_declVisibility moduleIntro EQUALS namedModuleDefnBlock { if isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(),rhs parseState 2)); let attribs,(path,xml,vis) = $1,$3 match $5 with | Choice1Of2 eqn -> if isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(),rhs parseState 2)); if List.length path <> 1 then raiseParseErrorAt (rhs parseState 3) (FSComp.SR.parsModuleAbbreviationMustBeSimpleName()); if List.length $1 <> 0 then raiseParseErrorAt (rhs parseState 1) (FSComp.SR.parsIgnoreAttributesOnModuleAbbreviation()); if isSome vis then raiseParseErrorAt (rhs parseState 1) (FSComp.SR.parsIgnoreAttributesOnModuleAbbreviationAlwaysPrivate()); [ SynModuleDecl.ModuleAbbrev(List.head path,eqn,rhs2 parseState 3 5) ] | Choice2Of2 def -> if List.length path <> 1 then raiseParseErrorAt (rhs parseState 3) (FSComp.SR.parsModuleAbbreviationMustBeSimpleName()); let info = ComponentInfo(attribs,[],[],path,xml,false,vis,rhs parseState 3) [ SynModuleDecl.NestedModule(info,def,false,rhs2 parseState 3 5) ] } | openDecl { [SynModuleDecl.Open($1,rhs parseState 1)] } /* this occurs on the right of a module abbreviation (#light encloses the r.h.s. with OBLOCKBEGIN/OBLOCKEND) */ /* We don't use it in signature files */ namedModuleAbbrevBlock: | OBLOCKBEGIN path OBLOCKEND { $2 } | path { $1 } namedModuleDefnBlock: | OBLOCKBEGIN wrappedNamedModuleDefn OBLOCKEND { Choice2Of2 $2 } | OBLOCKBEGIN moduleDefnsOrExpr OBLOCKEND { // BUG 2644 FSharp 1.0: // There is an ambiguity here // In particular, consider the following two: // module M2 = // System.DateTime.Now // module M2 = // Microsoft.FSharp.Core.List // The second is a module abbreviation , the first a module containing a single expression. // This is a bit unfortunate. For F# v1 the resolution is in favour of // the module abbreviation, i.e. anything of the form // module M2 = ID.ID.ID.ID // will be taken as a module abbreviation, regardles of the identifiers themselves. // In a later version (Dev11) we could actually try resolving the names // to both expressions and module identifiers and base the resolution of that semantic lookup // // This is similar to the ambiguitty between // type X = int // and // type X = OneValue // However in that case we do use type name lookup to make the resolution. match $2 with | [ SynModuleDecl.DoExpr (_,LongOrSingleIdent(false,path,_),_) ] -> Choice1Of2 path | _ -> Choice2Of2 $2 } | OBLOCKBEGIN moduleDefnsOrExpr recover { // The lex filter ensures we can only get a mismatch in OBLOCKBEGIN/OBLOCKEND tokens if there was some other kind of error, hence we don't need to report this error // reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnClosedBlockInHashLight()); Choice2Of2 $2 } | OBLOCKBEGIN error OBLOCKEND { Choice2Of2 [] } | wrappedNamedModuleDefn { Choice2Of2 $1 } | path { Choice1Of2 $1 } wrappedNamedModuleDefn: | structOrBegin moduleDefnsOrExprPossiblyEmpty END { $2 } | structOrBegin moduleDefnsOrExprPossiblyEmpty recover { reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnmatchedBeginOrStruct()); $2 } | structOrBegin error END { [] } opt_signature : | { None } tyconDefnAugmentation: | WITH classDefnBlock declEnd { $2 } /* opt_sig: { None } | COLON sigOrBegin moduleSpfns END { $3 } */ moduleSpfn: | hashDirective { SynModuleSigDecl.HashDirective ($1,rhs2 parseState 1 1) } | valSpfn { $1 } | opt_attributes opt_declVisibility moduleIntro colonOrEquals namedModuleAbbrevBlock { if isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(),rhs parseState 2)); let path,xml,vis = $3 if List.length path <> 1 then raiseParseErrorAt (rhs parseState 3) (FSComp.SR.parsModuleAbbreviationMustBeSimpleName()); if List.length $1 <> 0 then raiseParseErrorAt (rhs parseState 1) (FSComp.SR.parsIgnoreAttributesOnModuleAbbreviation()); if isSome(vis) then raiseParseErrorAt (rhs parseState 1) (FSComp.SR.parsIgnoreVisibilityOnModuleAbbreviationAlwaysPrivate()); SynModuleSigDecl.ModuleAbbrev(List.head path,$5,rhs2 parseState 3 5) } | opt_attributes opt_declVisibility moduleIntro colonOrEquals moduleSpecBlock { let path,xml,vis = $3 if List.length path <> 1 then raiseParseErrorAt (rhs parseState 3) (FSComp.SR.parsModuleDefnMustBeSimpleName()); let info = ComponentInfo($1,[],[],path,xml,false,vis,rhs parseState 3) if isSome($2) then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(),rhs parseState 2)); SynModuleSigDecl.NestedModule(info,$5,rhs2 parseState 3 5) } | opt_attributes opt_declVisibility tyconSpfns { if isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(),rhs parseState 2)); let (TypeDefnSig(ComponentInfo(cas,a,cs,b,c,d,d2,d3),e,f,g)),rest = match $3 with | [] -> raiseParseErrorAt (rhs parseState 3) (FSComp.SR.parsUnexpectedEmptyModuleDefn()) | h::t -> h,t let tc = (TypeDefnSig(ComponentInfo($1@cas,a,cs,b,c,d,d2,d3),e,f,g))in SynModuleSigDecl.Types (tc::rest,rhs parseState 3) } | opt_attributes opt_declVisibility exconSpfn { if isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(),rhs parseState 2)); let (ExceptionSig(ExceptionDefnRepr(cas,a,b,c,d,d2),e,f)) = $3 let ec = (ExceptionSig(ExceptionDefnRepr($1@cas,a,b,c,d,d2),e,f)) SynModuleSigDecl.Exception(ec, rhs parseState 3) } | OPEN path { SynModuleSigDecl.Open ($2, rhs2 parseState 1 2) } valSpfn: | opt_attributes opt_declVisibility VAL opt_attributes opt_inline opt_mutable opt_access nameop opt_explicitValTyparDecls COLON topTypeWithTypeConstraints opt_literalValue { if isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(),rhs parseState 2)); let attr1,attr2,inlineFlag,mutableFlag,vis2,id,doc,explicitValTyparDecls,(ty,arity),konst = ($1),($4),($5),($6),($7),($8),grabXmlDoc(parseState,3),($9),($11),($12) if nonNil attr2 then errorR(Deprecated(FSComp.SR.parsAttributesMustComeBeforeVal(),rhs parseState 4)); let m = rhs2 parseState 3 11 let valSpfn = ValSpfn((attr1@attr2),id,explicitValTyparDecls,ty,arity,inlineFlag,mutableFlag,doc, vis2,konst,m) SynModuleSigDecl.Val(valSpfn,m) } opt_literalValue: | { None } | EQUALS declExpr { Some($2) } moduleSpecBlock: | OBLOCKBEGIN moduleSpfns OBLOCKEND { $2 } | OBLOCKBEGIN sigOrBegin moduleSpfnsPossiblyEmpty END OBLOCKEND { $3 } | sigOrBegin moduleSpfnsPossiblyEmpty END { $2 } opt_attributes: | attributes { $1 } | %prec prec_opt_attributes_none { [] } attributes: | attributeList { $1 } | attributeList attributes { $1 @ $2 } attributeList: | LBRACK_LESS attributeListElements opt_seps GREATER_RBRACK opt_OBLOCKSEP { $2 } attributeListElements: | attribute { [$1] } | attributeListElements seps attribute { $1 @ [$3] } attribute: | path opt_HIGH_PRECEDENCE_APP opt_atomicExprAfterType { let arg = match $3 with None -> mkSynUnit (rangeOfLid $1) | Some e -> e { TypeName=$1; ArgExpr=arg; Target=None; AppliesToGetterAndSetter=false; Range=rangeOfLid $1 } } | attributeTarget COLON path opt_HIGH_PRECEDENCE_APP opt_atomicExprAfterType { let arg = match $5 with None -> mkSynUnit (rangeOfLid $3) | Some e -> e { TypeName=$3; ArgExpr=arg; Target=Some $1; AppliesToGetterAndSetter=false; Range=rangeOfLid $3 } } attributeTarget: | MODULE { ident("module",lhs(parseState)) } | TYPE { ident("type",lhs(parseState)) } | ident { $1 } | YIELD /* return */ { if $1 then reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsSyntaxError()); ident("return",lhs(parseState)) } tyconSpfns: | TYPE tyconSpfnList { $2 } tyconSpfnList: | tyconSpfn AND tyconSpfnList { $1 :: $3 } | tyconSpfn { [$1] } tyconSpfn: | typeNameInfo EQUALS tyconSpfnRhsBlock { let lhsm = rhs parseState 1 $3 lhsm $1 } | typeNameInfo opt_classSpfn { TypeDefnSig($1,SynTypeDefnSigRepr.Simple (SynTypeDefnSimpleRepr.None (lhs(parseState)),lhs(parseState)),$2,lhs(parseState)) } tyconSpfnRhsBlock: /* This rule allows members to be given for record and union types in the #light syntax */ /* without the use of 'with' ... 'end'. For example: */ /* type R = */ /* { a : int } */ /* member r.A = a */ /* It also takes into account that any existing 'with' */ /* block still needs to be considered and may occur indented or undented from the core type */ /* representation. */ | OBLOCKBEGIN tyconSpfnRhs opt_OBLOCKSEP classSpfnMembers opt_classSpfn OBLOCKEND opt_classSpfn { let m = lhs(parseState) (fun lhsm nameInfo -> $2 lhsm nameInfo (checkForMultipleAugmentations m ($4 @ $5) $7)) } | tyconSpfnRhs opt_classSpfn { let m = lhs(parseState) (fun lhsm nameInfo -> $1 lhsm nameInfo $2) } tyconSpfnRhs: | tyconDefnOrSpfnSimpleRepr { let m = lhs(parseState) (fun lhsm nameInfo augmentation -> TypeDefnSig(nameInfo,SynTypeDefnSigRepr.Simple ($1,m),augmentation,m)) } | tyconClassSpfn { let m = lhs(parseState) let needsCheck,(kind,decls) = $1 (fun nameRange nameInfo augmentation -> if needsCheck && isNil decls then reportParseErrorAt nameRange (FSComp.SR.parsEmptyTypeDefinition()); TypeDefnSig(nameInfo,SynTypeDefnSigRepr.ObjectModel (kind,decls,m),augmentation,m)) } | DELEGATE OF topType { let m = lhs(parseState) let ty,arity = $3 let invoke = SynMemberSig.Member(ValSpfn([],mkSynId m "Invoke",inferredTyparDecls,ty,arity,false,false,PreXmlDoc.Empty,None,None,m),AbstractMemberFlags MemberKind.Member,m) (fun nameRange nameInfo augmentation -> if nonNil augmentation then raiseParseErrorAt m (FSComp.SR.parsAugmentationsIllegalOnDelegateType()); TypeDefnSig(nameInfo,SynTypeDefnSigRepr.ObjectModel (TyconDelegate (ty,arity),[invoke],m),[],m)) } tyconClassSpfn: | classSpfnBlockKindUnspecified { let needsCheck,decls = $1 needsCheck,(TyconUnspecified, decls) } | classOrInterfaceOrStruct classSpfnBlock END { false,($1,$2) } | classOrInterfaceOrStruct classSpfnBlock recover { reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnmatchedClassInterfaceOrStruct()); false,($1,$2) } | classOrInterfaceOrStruct error END { // silent recovery false,($1,[]) } classSpfnBlockKindUnspecified: | OBLOCKBEGIN classSpfnMembers OBLOCKEND { true, $2 } | OBLOCKBEGIN classSpfnMembers recover { if not $3 then reportParseErrorAt (rhs parseState 3) (FSComp.SR.parsUnexpectedEndOfFile()); false, $2 } /* NOTE: these rules enable a 'heavy' syntax to omit the kind of a type. */ | BEGIN classSpfnBlock END { false, $2 } | BEGIN classSpfnBlock recover { false, $2 } classSpfnBlock: | OBLOCKBEGIN classSpfnMembers OBLOCKEND { $2 } | OBLOCKBEGIN classSpfnMembers recover { if not $3 then reportParseErrorAt (rhs parseState 3) (FSComp.SR.parsUnexpectedEndOfFile()); $2 } | classSpfnMembers { $1 } classSpfnMembers: | classMemberSpfn opt_seps classSpfnMembers { $1 :: $3 } | { [] } memberFlags: | STATIC MEMBER { StaticMemberFlags } | MEMBER { NonVirtualMemberFlags } | OVERRIDE { OverrideMemberFlags } | DEFAULT { OverrideMemberFlags } memberSpecFlags: | memberFlags { $1 } | ABSTRACT { AbstractMemberFlags } | ABSTRACT MEMBER { AbstractMemberFlags } classMemberSpfnGetSet: | /* EMPTY */ { (fun arity -> (match arity with SynValInfo([],_) -> MemberKind.PropertyGet | _ -> MemberKind.Member)) } | WITH classMemberSpfnGetSetElements { (fun arity -> $2) } | OWITH classMemberSpfnGetSetElements OEND { (fun arity -> $2) } | OWITH classMemberSpfnGetSetElements error { reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnmatchedWith()); (fun arity -> $2) } classMemberSpfnGetSetElements: | nameop { (let (id:Ident) = $1 if id.idText = "get" then MemberKind.PropertyGet else if id.idText = "set" then MemberKind.PropertySet else raiseParseErrorAt (rhs parseState 1) (FSComp.SR.parsGetOrSetRequired())) } | nameop COMMA nameop { let (id:Ident) = $1 if not ((id.idText = "get" && $3.idText = "set") || (id.idText = "set" && $3.idText = "get")) then raiseParseErrorAt (rhs2 parseState 1 3) (FSComp.SR.parsGetOrSetRequired()); MemberKind.PropertyGetSet } classMemberSpfn: | opt_attributes opt_declVisibility memberSpecFlags opt_inline opt_access nameop opt_explicitValTyparDecls COLON topTypeWithTypeConstraints classMemberSpfnGetSet opt_literalValue { if isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(),rhs parseState 2)); let inlineFlag,doc,vis2,id,explicitValTyparDecls,(ty,arity),optLiteralValue = $4,grabXmlDoc(parseState,3),$5,$6,$7,$9,$11 let m = rhs2 parseState 3 10 let valSpfn = ValSpfn($1,id,explicitValTyparDecls,ty,arity, inlineFlag,false,doc, vis2,optLiteralValue,m) SynMemberSig.Member(valSpfn, $3 ($10 arity),m) } | opt_attributes opt_declVisibility interfaceMember appType { if isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(),rhs parseState 2)); SynMemberSig.Interface ($4,unionRanges (rhs parseState 3) ($4).Range) } | opt_attributes opt_declVisibility INHERIT appType { if isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(),rhs parseState 2)); SynMemberSig.Inherit ($4,unionRanges (rhs parseState 3) ($4).Range) } | opt_attributes opt_declVisibility VAL fieldDecl { if isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(),rhs parseState 2)); let fld = $4 $1 false SynMemberSig.ValField(fld,rhs2 parseState 3 4) } | opt_attributes opt_declVisibility STATIC VAL fieldDecl { if isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(),rhs parseState 2)); SynMemberSig.ValField($5 $1 true,rhs2 parseState 3 5) } | opt_attributes opt_declVisibility STATIC TYPE tyconSpfn { if isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(),rhs parseState 2)); SynMemberSig.NestedType($5,rhs2 parseState 3 5) } | opt_attributes opt_declVisibility NEW COLON topTypeWithTypeConstraints { let vis,doc,(ty,valSynInfo) = $2,grabXmlDoc(parseState,3),$5 let m = unionRanges (rhs parseState 3) ty.Range let inlineFlag = false let valSpfn = ValSpfn ($1, mkSynId (rhs parseState 3) "new", noInferredTypars, ty, valSynInfo, inlineFlag, false, doc, vis, None, m) SynMemberSig.Member(valSpfn, CtorMemberFlags,m) } typeNameInfo: | opt_attributes tyconNameAndTyparDecls opt_typeConstraints { let typars,lid,fixity,tpcs1,vis,xmlDoc = $2 let tpcs2 = $3 ComponentInfo($1,typars,(tpcs1 @ tpcs2),lid,xmlDoc,fixity,vis,rangeOfLid lid) } tyconDefnList: | AND tyconDefn tyconDefnList { $2 :: $3 } | { [] } tyconDefn: | typeNameInfo { TypeDefn($1,SynTypeDefnRepr.Simple(SynTypeDefnSimpleRepr.None(lhs(parseState)),lhs(parseState)),[],lhs(parseState)) } | typeNameInfo EQUALS tyconDefnRhsBlock { let nameRange = rhs parseState 1 let tcDefRepr,members = $3 nameRange TypeDefn($1,tcDefRepr,members,lhs(parseState)) } | typeNameInfo tyconDefnAugmentation { let m = lhs(parseState) TypeDefn($1,SynTypeDefnRepr.ObjectModel(TyconAugmentation,[],m),$2,m) } | typeNameInfo opt_attributes opt_declVisibility opt_HIGH_PRECEDENCE_APP simplePatterns optAsSpec EQUALS tyconDefnRhsBlock { let vis,spats, az = $3,$5,$6 let nameRange = rhs parseState 1 let (tcDefRepr,members) = $8 nameRange let (ComponentInfo(_,_,_,lid,_,_,_,_)) = $1 let memberCtorPattern = SynMemberDefn.ImplicitCtor (vis,$2,spats,az,rangeOfLid lid) let tcDefRepr = match tcDefRepr with | SynTypeDefnRepr.ObjectModel (k,cspec,m) -> SynTypeDefnRepr.ObjectModel (k,memberCtorPattern::cspec,m) | _ -> reportParseErrorAt (rhs2 parseState 1 5) (FSComp.SR.parsOnlyClassCanTakeValueArguments()); tcDefRepr TypeDefn($1,tcDefRepr,members,lhs(parseState)) } tyconDefnRhsBlock: /* This rule allows members to be given for record and union types in the #light syntax */ /* without the use of 'with' ... 'end'. For example: */ /* type R = */ /* { a : int } */ /* member r.A = a */ /* It also takes into account that any existing 'with' */ /* block still needs to be considered and may occur indented or undented from the core type */ /* representation. */ | OBLOCKBEGIN tyconDefnRhs opt_OBLOCKSEP classDefnMembers opt_classDefn OBLOCKEND opt_classDefn { let m = lhs(parseState) (fun nameRange -> $2 nameRange (checkForMultipleAugmentations m ($4 @ $5) $7)) } | tyconDefnRhs opt_classDefn { let m = lhs(parseState) (fun nameRange -> $1 nameRange $2) } tyconDefnRhs: | tyconDefnOrSpfnSimpleRepr { let m = lhs(parseState) (fun nameRange augmentation -> SynTypeDefnRepr.Simple ($1,m),augmentation) } | tyconClassDefn { let needsCheck,(kind,decls) = $1 let m = lhs(parseState) (fun nameRange augmentation -> if needsCheck && isNil decls then reportParseErrorAt nameRange (FSComp.SR.parsEmptyTypeDefinition()); SynTypeDefnRepr.ObjectModel (kind,decls,m),augmentation) } | DELEGATE OF topType { let m = lhs(parseState) let ty,arity = $3 (fun nameRange augmentation -> let valSpfn = ValSpfn([],mkSynId m "Invoke",inferredTyparDecls,ty,arity,false,false,PreXmlDoc.Empty,None,None,m) let invoke = SynMemberDefn.AbstractSlot(valSpfn,AbstractMemberFlags MemberKind.Member,m) if nonNil augmentation then raiseParseErrorAt m (FSComp.SR.parsAugmentationsIllegalOnDelegateType()); SynTypeDefnRepr.ObjectModel (TyconDelegate (ty,arity),[invoke],m),[]) } tyconClassDefn: | classDefnBlockKindUnspecified { let needsCheck,decls = $1 needsCheck,(TyconUnspecified, decls) } | classOrInterfaceOrStruct classDefnBlock END { false,($1,$2) } | classOrInterfaceOrStruct classDefnBlock recover { reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnmatchedClassInterfaceOrStruct()); false,($1,$2) } | classOrInterfaceOrStruct error END { // silent recovery false,($1,[]) } classDefnBlockKindUnspecified: | OBLOCKBEGIN classDefnMembers recover { if not $3 then reportParseErrorAt (rhs parseState 3) (FSComp.SR.parsUnexpectedEndOfFile()); false,$2 } | OBLOCKBEGIN classDefnMembers OBLOCKEND { true, $2 } /* NOTE: these rules enable a 'heavy' syntax to omit the kind of a type. However this doesn't seem necessary to support. NOTE: that is 'type kind inference' is only supported for #light | BEGIN classDefnBlock END { false,$2 } | BEGIN classDefnBlock recover { reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnmatchedBegin()); false,$2 } | BEGIN error END { // silent recovery * false,[] } */ classDefnBlock: | OBLOCKBEGIN classDefnMembers recover { if not $3 then reportParseErrorAt (rhs parseState 3) (FSComp.SR.parsUnexpectedEndOfFile()); $2 } | OBLOCKBEGIN classDefnMembers OBLOCKEND { $2 } | classDefnMembers { $1 } classDefnMembers: | classDefnMember opt_seps classDefnMembers { $1 @ $3 } | error classDefnMembers { $2 } | { [] } classDefnMemberGetSet: | WITH classDefnMemberGetSetElements { $2 } | OWITH classDefnMemberGetSetElements OEND { $2 } | OWITH classDefnMemberGetSetElements error { reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnmatchedWith()); $2 } classDefnMemberGetSetElements: | classDefnMemberGetSetElement { [$1] } | classDefnMemberGetSetElement AND classDefnMemberGetSetElement { [$1;$3] } classDefnMemberGetSetElement: | opt_inline opt_attributes bindingPattern opt_topReturnTypeWithTypeConstraints EQUALS typedSeqExprBlock { let rhsm = ($6 : SynExpr).Range ($1,$2,$3,$4,$6,rhsm) } memberCore: /* methods and simple getter properties */ | opt_inline bindingPattern opt_topReturnTypeWithTypeConstraints EQUALS typedSeqExprBlock { let rhsm = $5.Range let wholem = unionRanges (rhs2 parseState 3 4) rhsm let mpat = rhs parseState 2 let optReturnType = $3 let bindingBuilder,bindm = $2 (fun vis memFlagsBuilder attrs -> [ SynMemberDefn.Member (bindingBuilder (vis,$1,false,bindm,NoSequencePointAtInvisibleBinding,wholem,optReturnType,$5,rhsm,[],attrs,Some(memFlagsBuilder MemberKind.Member)),bindm) ]) } /* properties with explicit get/set, also indexer properties */ | opt_inline bindingPattern opt_topReturnTypeWithTypeConstraints classDefnMemberGetSet { let wholem = rhs2 parseState 2 4 let propertyNameBindingBuilder,_ = $2 let optPropertyType = $3 let mutableFlag = false (fun visNoLongerUsed memFlagsBuilder attrs -> let hasGet = ref false let hasSet = ref false // Iterate over 1 or 2 'get'/'set' entries $4 |> List.map (fun (optInline,optAttrs,(bindingBuilder,bindm),optReturnType,expr,exprm) -> let optInline = $1 || optInline // optional attributes are only applied to getters and setters // the "top level" attrs will be applied to both let optAttrs = optAttrs |> List.map (fun (a:SynAttribute) -> { a with AppliesToGetterAndSetter=true }) let attrs = attrs @ optAttrs let binding = bindingBuilder (visNoLongerUsed,optInline,mutableFlag,bindm,NoSequencePointAtInvisibleBinding,wholem,optReturnType,expr,exprm,[],attrs,Some (memFlagsBuilder MemberKind.Member)) let (Binding (vis, _, pseudo, _, attrs, doc, valSynData, pv, _, _, bindm, spBind)) = binding let memberKind = let getset = let rec go p = match p with | SynPat.LongIdent ([id],_,_,_,_,_) -> id.idText | SynPat.Named (_,nm,_,_,_) -> nm.idText | SynPat.Typed (p,_,_) -> go p | SynPat.Attrib (p,_,_) -> go p | _ -> raiseParseErrorAt bindm (FSComp.SR.parsInvalidDeclarationSyntax()) go pv if getset = "get" then ( if !hasGet then raiseParseErrorAt bindm (FSComp.SR.parsGetAndOrSetRequired()); hasGet := true; MemberKind.PropertyGet ) else if getset = "set" then ( if !hasSet then raiseParseErrorAt bindm (FSComp.SR.parsGetAndOrSetRequired()); hasSet := true; MemberKind.PropertySet ) else raiseParseErrorAt bindm (FSComp.SR.parsGetAndOrSetRequired()) begin match optPropertyType with | Some _ -> errorR(Error(FSComp.SR.parsTypeAnnotationsOnGetSet(),bindm)) | None -> () end; let optReturnType = match (memberKind, optReturnType) with | MemberKind.PropertySet,_ -> optReturnType | _, None -> optPropertyType | _ -> optReturnType // REDO with the correct member kind let binding = bindingBuilder(vis,pseudo,mutableFlag,bindm,NoSequencePointAtInvisibleBinding,wholem,optReturnType,expr,exprm,[],attrs,Some(memFlagsBuilder memberKind)) let (Binding (vis, _, pseudo, _, attrs, doc, valSynData, pv, rhsRetInfo, rhsExpr, bindm, spBind)) = binding let (SynValData(_,valSynInfo,_)) = valSynData // Setters have all arguments tupled in their internal TAST form, though they don't appear to be // tupled from the syntax let memFlags = memFlagsBuilder memberKind let valSynInfo = let adjustValueArg valueArg = if List.length valueArg = 1 then valueArg else SynInfo.unnamedTopArg match memberKind, valSynInfo with | MemberKind.PropertyGet,SynValInfo ([],ret) when not memFlags.IsInstance -> raiseParseErrorAt bindm (FSComp.SR.parsGetterMustHaveAtLeastOneArgument()) | MemberKind.PropertyGet,SynValInfo ([thisArg],ret) when memFlags.IsInstance -> raiseParseErrorAt bindm (FSComp.SR.parsGetterMustHaveAtLeastOneArgument()) | MemberKind.PropertyGet,SynValInfo ([thisArg;indexOrUnitArgs],ret) when memFlags.IsInstance -> SynValInfo ([thisArg; indexOrUnitArgs],ret) | MemberKind.PropertyGet,SynValInfo ([indexOrUnitArgs],ret) when not memFlags.IsInstance -> SynValInfo ([indexOrUnitArgs],ret) | MemberKind.PropertyGet,SynValInfo _ -> raiseParseErrorAt bindm (FSComp.SR.parsGetterAtMostOneArgument()) | MemberKind.PropertySet,SynValInfo ([thisArg;valueArg],ret) when memFlags.IsInstance -> SynValInfo ([thisArg; adjustValueArg valueArg],ret) | MemberKind.PropertySet,SynValInfo ([thisArg;indexArgs;valueArg],ret) when memFlags.IsInstance -> SynValInfo ([thisArg;indexArgs @ adjustValueArg valueArg],ret) | MemberKind.PropertySet,SynValInfo ([valueArg],ret) when not memFlags.IsInstance -> SynValInfo ([adjustValueArg valueArg],ret) | MemberKind.PropertySet,SynValInfo ([indexArgs;valueArg],ret) when not memFlags.IsInstance -> SynValInfo ([indexArgs @ adjustValueArg valueArg],ret) | MemberKind.PropertySet,SynValInfo _ -> raiseParseErrorAt bindm (FSComp.SR.parsSetterAtMostTwoArguments()) | _ -> // should be unreachable, cover just in case raiseParseErrorAt bindm (FSComp.SR.parsInvalidProperty()) let valSynData = SynValData(Some(memFlags), valSynInfo,None) // Fold together the information from the first lambda pattern and the get/set binding // This uses the 'this' variable from the first and the patterns for the get/set binding, // replacing the get/set identifier. A little unpleasant. let bindingPatAdjusted, xmlDocAdjusted = let bindingOuter = propertyNameBindingBuilder(vis,optInline,mutableFlag,bindm,spBind,bindm,optReturnType,expr,exprm,[],attrs,Some(memFlagsBuilder MemberKind.Member)) let (Binding (_,_,_,_,_,doc2,_,bindingPatOuter,_,_,_,_)) = bindingOuter let lidOuter,lidVisOuter = match bindingPatOuter with | SynPat.LongIdent (lid,None,None,[],lidVisOuter,m) -> lid,lidVisOuter | SynPat.Named (_,id,_,visOuter,m) -> [id],visOuter | p -> raiseParseErrorAt bindm (FSComp.SR.parsInvalidDeclarationSyntax()) // Merge the visibility from the outer point with the inner point, e.g. // member this.Size with get () = m_size let mergeLidVisOuter lidVisInner = match lidVisInner,lidVisOuter with | None,None -> None | Some lidVisInner,None | None,Some lidVisInner -> Some lidVisInner | Some _, Some _ -> errorR(Error(FSComp.SR.parsMultipleAccessibilitiesForGetSet(),bindm)); lidVisInner // Replace the "get" or the "set" with the right name let rec go p = match p with | SynPat.LongIdent ([id],_,tyargs,args,lidVisInner,m) -> // Setters have all arguments tupled in their internal form, though they don't // appear to be tupled from the syntax. Somewhat unfortunate let args = if id.idText = "set" then match args with | [SynPat.Paren(SynPat.Tuple (indexPats,_),indexPatRange);valuePat] when id.idText = "set" -> [SynPat.Tuple(indexPats@[valuePat],unionRanges indexPatRange valuePat.Range)] | [indexPat;valuePat] -> [SynPat.Tuple(args,unionRanges indexPat.Range valuePat.Range)] | [valuePat] -> [valuePat] | _ -> raiseParseErrorAt m (FSComp.SR.parsSetSyntax()) else args // let idTool : Ident list = lidOuter |> List.map (fun (li:Ident) -> ident(li.idText,id.idRange)) |> List.rev |> List.take 1 SynPat.LongIdent (lidOuter,Some(id),tyargs,args,mergeLidVisOuter lidVisInner,m) | SynPat.Named (_,nm,_,lidVisInner,m) -> SynPat.LongIdent (lidOuter,None,None,[],mergeLidVisOuter lidVisInner,m) | SynPat.Typed (p,ty,m) -> SynPat.Typed(go p,ty,m) | SynPat.Attrib (p,attribs,m) -> SynPat.Attrib(go p,attribs,m) | SynPat.Wild(m) -> SynPat.Wild(m) | _ -> raiseParseErrorAt bindm (FSComp.SR.parsInvalidDeclarationSyntax()) go pv,PreXmlDoc.Merge doc2 doc SynMemberDefn.Member (Binding (vis, NormalBinding, pseudo, mutableFlag, attrs, xmlDocAdjusted, valSynData, bindingPatAdjusted, rhsRetInfo, rhsExpr, bindm, spBind),bindm))) } abstractMemberFlags: | ABSTRACT {} | ABSTRACT MEMBER {} classDefnMember: | opt_attributes opt_declVisibility classDefnBindings { if isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(),rhs parseState 2)); [mkClassMemberLocalBindings(false,rhs2 parseState 3 3,$1,$2,$3)] } | opt_attributes opt_declVisibility STATIC classDefnBindings { if isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(),rhs parseState 2)); [mkClassMemberLocalBindings(true,rhs2 parseState 3 4,$1,$2,$4)] } | opt_attributes opt_declVisibility memberFlags memberCore opt_ODECLEND { if isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(),rhs parseState 2)); $4 $2 $3 $1 } | opt_attributes opt_declVisibility interfaceMember appType opt_interfaceImplDefn { if nonNil $1 then errorR(Error(FSComp.SR.parsAttributesAreNotPermittedOnInterfaceImplementations(),rhs parseState 1)); if isSome $2 then errorR(Error(FSComp.SR.parsInterfacesHaveSameVisibilityAsEnclosingType(),rhs parseState 3)); [ SynMemberDefn.Interface ($4, $5,rhs2 parseState 3 4) ] } | opt_attributes opt_declVisibility abstractMemberFlags opt_inline nameop opt_explicitValTyparDecls COLON topTypeWithTypeConstraints classMemberSpfnGetSet opt_ODECLEND { let ty,arity = $8 let inlineFlag,doc,id,explicitValTyparDecls = $4,grabXmlDoc(parseState,3),$5,$6 let m = rhs2 parseState 3 9 if isSome $2 then errorR(Error(FSComp.SR.parsAccessibilityModsIllegalForAbstract(),m)); let valSpfn = ValSpfn($1,id,explicitValTyparDecls,ty,arity, inlineFlag,false,doc, None,None,m) [ SynMemberDefn.AbstractSlot(valSpfn,AbstractMemberFlags ($9 arity), m) ] } | opt_attributes opt_declVisibility inheritsDefn { if nonNil $1 then errorR(Error(FSComp.SR.parsAttributesIllegalOnInherit(),rhs parseState 1)); if isSome $2 then errorR(Error(FSComp.SR.parsVisibilityIllegalOnInherit(),rhs parseState 1)); [ $3 ] } | opt_attributes opt_declVisibility VAL fieldDecl { if isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(),rhs parseState 2)); [ SynMemberDefn.ValField($4 $1 false,rhs2 parseState 3 4) ] } | opt_attributes opt_declVisibility STATIC VAL fieldDecl { if isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(),rhs parseState 2)); [ SynMemberDefn.ValField($5 $1 true,rhs2 parseState 3 5) ] } | opt_attributes opt_declVisibility NEW atomicPattern optAsSpec EQUALS typedSeqExprBlock opt_ODECLEND { let m = unionRanges (rhs2 parseState 3 6) $7.Range let expr = $7 let valSynData = SynValData (Some CtorMemberFlags, SynValInfo([SynInfo.InferArgSynInfoFromPat $4],SynInfo.unnamedRetVal), $5) let vis = $2 let declPat = SynPat.LongIdent ([mkSynId (rhs parseState 3) "new"],None,Some noInferredTypars,[$4],vis,rhs parseState 3) // Check that 'SynPatForConstructorDecl' matches this correctly assert (match declPat with SynPatForConstructorDecl _ -> true | _ -> false); [ SynMemberDefn.Member(Binding (None,NormalBinding,false,false,$1,grabXmlDoc(parseState,3),valSynData, declPat,None,expr,m,NoSequencePointAtInvisibleBinding),m) ] } | opt_attributes opt_declVisibility STATIC TYPE tyconDefn { if isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(),rhs parseState 2)); [ SynMemberDefn.NestedType($5,None,rhs2 parseState 3 5) ] } atomicPatternLongIdent: | GLOBAL DOT pathOp { (None,[ident(MangledGlobalName,rhs parseState 1)] @ $3) } | pathOp { (None,$1) } | access pathOp { (Some($1), $2) } opt_access: | { None } | access { Some($1) } access: | PRIVATE { SynAccess.Private } | PUBLIC { SynAccess.Public } | INTERNAL { SynAccess.Internal } /* only valid on 'NEW' */ opt_declVisibility: | access { Some($1) } | { None } opt_interfaceImplDefn: | WITH objectImplementationBlock declEnd { Some($2) } | { None } opt_classDefn: | WITH classDefnBlock declEnd { $2 } | { [] } opt_classSpfn: | WITH classSpfnBlock declEnd { $2 } | { [] } inheritsDefn: | INHERIT appTypeNonAtomicDeprecated optBaseSpec { let mDecl = unionRanges (rhs parseState 1) (($2): SynType).Range SynMemberDefn.Inherit($2,$3,mDecl) } | INHERIT appTypeNonAtomicDeprecated opt_HIGH_PRECEDENCE_APP atomicExprAfterType optBaseSpec { let mDecl = unionRanges (rhs parseState 1) $4.Range SynMemberDefn.ImplicitInherit($2,$4,$5,mDecl) } optAsSpec: | asSpec { Some($1) } | { None } asSpec: | AS ident { $2 } optBaseSpec: | baseSpec { Some($1) } | { None } baseSpec: | AS ident { if ($2).idText <> "base" then errorR(Error(FSComp.SR.parsInheritDeclarationsCannotHaveAsBindings(),rhs2 parseState 1 2)); ident("base",rhs parseState 2) } | AS BASE { errorR(Error(FSComp.SR.parsInheritDeclarationsCannotHaveAsBindings(),rhs2 parseState 1 2)); ident("base",rhs parseState 2) } objectImplementationBlock: | OBLOCKBEGIN objectImplementationMembers OBLOCKEND { $2 } | OBLOCKBEGIN objectImplementationMembers recover { if not $3 then reportParseErrorAt (rhs parseState 3) (FSComp.SR.parsUnexpectedEndOfFile()); $2 } | objectImplementationMembers { $1 } objectImplementationMembers: | objectImplementationMember opt_seps objectImplementationMembers { $1 @ $3 } | objectImplementationMember opt_seps { $1 } objectImplementationMember: | opt_attributes memberOrOverride memberCore opt_ODECLEND { $3 None OverrideMemberFlags $1 } | opt_attributes memberOrOverride error { [] } memberOrOverride: | MEMBER {} | OVERRIDE {} tyconDefnOrSpfnSimpleRepr: | opt_attributes opt_declVisibility typ { if nonNil $1 then errorR(Error(FSComp.SR.parsAttributesIllegalHere(),rhs parseState 1)); if isSome $2 then errorR(Error(FSComp.SR.parsTypeAbbreviationsCannotHaveVisibilityDeclarations(),rhs parseState 2)); SynTypeDefnSimpleRepr.TypeAbbrev ($3, lhs(parseState)) } | opt_attributes opt_declVisibility unionRepr { if nonNil $1 then errorR(Error(FSComp.SR.parsAttributesIllegalHere(),rhs parseState 1)); if $3 |> List.exists (function Choice1Of2 _ -> true | _ -> false) then ( if isSome $2 then errorR(Error(FSComp.SR.parsEnumTypesCannotHaveVisibilityDeclarations(),rhs parseState 2)); SynTypeDefnSimpleRepr.Enum ($3 |> List.choose (function | Choice1Of2 data -> Some(data) | Choice2Of2(UnionCase(_,_,_,_,_,m)) -> errorR(Error(FSComp.SR.parsAllEnumFieldsRequireValues(),m)); None), lhs(parseState)) ) else SynTypeDefnSimpleRepr.Union ($2, $3 |> List.choose (function Choice2Of2 data -> Some(data) | Choice1Of2 _ -> failwith "huh?"), lhs(parseState)) } | opt_attributes opt_declVisibility braceFieldDeclList { if nonNil $1 then errorR(Error(FSComp.SR.parsAttributesIllegalHere(),rhs parseState 1)); SynTypeDefnSimpleRepr.Record ($2,$3,lhs(parseState)) } | opt_attributes opt_declVisibility LPAREN inlineAssemblyTyconRepr RPAREN { if nonNil $1 then errorR(Error(FSComp.SR.parsAttributesIllegalHere(),rhs parseState 1)); libraryOnlyError (lhs(parseState)); if isSome $2 then errorR(Error(FSComp.SR.parsInlineAssemblyCannotHaveVisibilityDeclarations(),rhs parseState 2)); $4 } braceFieldDeclList: | LBRACE recdFieldDeclList RBRACE { $2 } | LBRACE recdFieldDeclList recover { reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnmatchedBrace()); $2 } | LBRACE error RBRACE { [] } inlineAssemblyTyconRepr: | HASH stringOrKeywordString opt_HASH { libraryOnlyError (lhs(parseState)); let lhsm = lhs(parseState) SynTypeDefnSimpleRepr.ILAssembly (ParseAssemblyCodeType $2 (rhs parseState 2),lhsm) } classOrInterfaceOrStruct: | CLASS { TyconClass } | INTERFACE { TyconInterface } | STRUCT { TyconStruct } interfaceMember: | INTERFACE { } | OINTERFACE_MEMBER { } tyconNameAndTyparDecls: | opt_access path { [], $2,false,[],$1,grabXmlDoc(parseState,2) } | opt_access prefixTyparDecls path { $2, $3,false,[],$1,grabXmlDoc(parseState,2) } | opt_access path postfixTyparDecls { let tps,tpcs = $3 tps, $2,true,tpcs,$1,grabXmlDoc(parseState,2) } prefixTyparDecls: | typar { [ TyparDecl([],$1) ] } | LPAREN prefixTyparDeclList RPAREN { List.rev $2 } prefixTyparDeclList: | prefixTyparDeclList COMMA typarDecl { $3 :: $1 } | typarDecl { [$1] } typarDecl : | opt_attributes typar { TyparDecl($1,$2) } /* Any tokens in this grammar must be added to the lex filter rule 'peekAdjacentTypars' */ /* See the F# specification "Lexical analysis of type applications and type parameter definitions" */ postfixTyparDecls: | opt_HIGH_PRECEDENCE_TYAPP LESS prefixTyparDeclList opt_typeConstraints GREATER { if not $2 then warning(Error(FSComp.SR.parsNonAdjacentTypars(),rhs2 parseState 2 5)); List.rev $3, $4 } /* Any tokens in this grammar must be added to the lex filter rule 'peekAdjacentTypars' */ /* See the F# specification "Lexical analysis of type applications and type parameter definitions" */ explicitValTyparDeclsCore: | prefixTyparDeclList COMMA DOT_DOT { (List.rev $1,true) } | prefixTyparDeclList { (List.rev $1,false) } | { ([],false) } explicitValTyparDecls: | opt_HIGH_PRECEDENCE_TYAPP LESS explicitValTyparDeclsCore opt_typeConstraints GREATER { if not $2 then warning(Error(FSComp.SR.parsNonAdjacentTypars(),rhs2 parseState 2 5)); let tps,flex = $3 SynValTyparDecls(tps,flex,$4) } opt_explicitValTyparDecls: | explicitValTyparDecls { $1 } | { SynValTyparDecls([],true,[]) } opt_explicitValTyparDecls2: | explicitValTyparDecls { Some $1 } | { None } /* Any tokens in this grammar must be added to the lex filter rule 'peekAdjacentTypars' */ /* See the F# specification "Lexical analysis of type applications and type parameter definitions" */ opt_typeConstraints: | { [] } | WHEN typeConstraints { List.rev $2 } /* Any tokens in this grammar must be added to the lex filter rule 'peekAdjacentTypars' */ /* See the F# specification "Lexical analysis of type applications and type parameter definitions" */ typeConstraints: | typeConstraints AND typeConstraint { $3 :: $1 } | typeConstraint { [$1] } /* Any tokens in this grammar must be added to the lex filter rule 'peekAdjacentTypars' */ /* See the F# specification "Lexical analysis of type applications and type parameter definitions" */ typeConstraint: | DEFAULT typar COLON typ { libraryOnlyError (lhs(parseState)); WhereTyparDefaultsToType($2,$4,lhs(parseState)) } | typar COLON_GREATER typ { WhereTyparSubtypeOfType($1,$3,lhs(parseState)) } | typar COLON STRUCT { WhereTyparIsValueType($1,lhs(parseState)) } | typar COLON IDENT STRUCT { if $3 <> "not" then reportParseErrorAt (rhs parseState 3) (FSComp.SR.parsUnexpectedIdentifier($3)); WhereTyparIsReferenceType($1,lhs(parseState)) } | typar COLON NULL { WhereTyparSupportsNull($1,lhs(parseState)) } | typar COLON LPAREN classMemberSpfn RPAREN { WhereTyparSupportsMember([ $1 ],$4,lhs(parseState)) } | LPAREN typar OR typar RPAREN COLON LPAREN classMemberSpfn RPAREN { WhereTyparSupportsMember([ $2 ; $4 ],$8,lhs(parseState)) } | typar COLON DELEGATE typeArgsNoHpaDeprecated { WhereTyparIsDelegate($1,$4,lhs(parseState)) } | typar COLON IDENT typeArgsNoHpaDeprecated { match $3 with | "enum" -> WhereTyparIsEnum($1,$4,lhs(parseState)) | nm -> raiseParseErrorAt (rhs parseState 3) (FSComp.SR.parsUnexpectedIdentifier(nm)) } | typar COLON IDENT { match $3 with | "comparison" -> WhereTyparIsComparable($1,lhs(parseState)) | "equality" -> WhereTyparIsEquatable($1,lhs(parseState)) | "unmanaged" -> WhereTyparIsUnmanaged($1,lhs(parseState)) | nm -> raiseParseErrorAt (rhs parseState 3) (FSComp.SR.parsUnexpectedIdentifier(nm)) } unionRepr: /* Note the next three rules are required to disambiguate this from type x = y */ /* Attributes can only appear on a single constructor if you've used a | */ | barAndgrabXmlDoc attrUnionCaseDecls { $2 $1 } | firstUnionCaseDeclOfMany barAndgrabXmlDoc attrUnionCaseDecls { $1 :: $3 $2 } | firstUnionCaseDecl { [$1] } barAndgrabXmlDoc : | BAR { grabXmlDoc(parseState,1) } attrUnionCaseDecls: | attrUnionCaseDecl barAndgrabXmlDoc attrUnionCaseDecls { (fun xmlDoc -> $1 xmlDoc :: $3 $2) } | attrUnionCaseDecl { (fun xmlDoc -> [ $1 xmlDoc ]) } attrUnionCaseDecl: | opt_attributes opt_access unionCaseName opt_OBLOCKSEP { if isSome $2 then errorR(Error(FSComp.SR.parsUnionCasesCannotHaveVisibilityDeclarations(),rhs parseState 2)); let mDecl = rhs parseState 3 (fun xmlDoc -> Choice2Of2 (UnionCase ( $1, $3,UnionCaseFields [],xmlDoc,None,mDecl))) } | opt_attributes opt_access unionCaseName OF unionCaseRepr opt_OBLOCKSEP { if isSome $2 then errorR(Error(FSComp.SR.parsUnionCasesCannotHaveVisibilityDeclarations(),rhs parseState 2)); let mDecl = rhs2 parseState 3 5 (fun xmlDoc -> Choice2Of2 (UnionCase ( $1, $3,UnionCaseFields $5,xmlDoc,None,mDecl))) } | opt_attributes opt_access unionCaseName COLON topType opt_OBLOCKSEP { if isSome $2 then errorR(Error(FSComp.SR.parsUnionCasesCannotHaveVisibilityDeclarations(),rhs parseState 2)); libraryOnlyWarning(lhs(parseState)); let mDecl = rhs2 parseState 3 5 (fun xmlDoc -> Choice2Of2 (UnionCase ( $1, $3,UnionCaseFullType $5,xmlDoc,None,mDecl))) } | opt_attributes opt_access unionCaseName EQUALS constant opt_OBLOCKSEP { if isSome $2 then errorR(Error(FSComp.SR.parsEnumFieldsCannotHaveVisibilityDeclarations(),rhs parseState 2)); let mDecl = rhs2 parseState 3 5 (fun xmlDoc -> Choice1Of2 (EnumCase ( $1, $3,$5,xmlDoc,mDecl))) } unionCaseName: | nameop { $1 } | LPAREN COLON_COLON RPAREN { ident(opNameCons,rhs parseState 2) } | LPAREN LBRACK RBRACK RPAREN { ident(opNameNil,rhs2 parseState 2 3) } firstUnionCaseDeclOfMany: | ident opt_OBLOCKSEP { Choice2Of2 (UnionCase ( [], $1,UnionCaseFields [],PreXmlDoc.Empty,None,rhs parseState 1)) } | ident EQUALS constant opt_OBLOCKSEP { Choice1Of2 (EnumCase ([],$1,$3,PreXmlDoc.Empty,rhs2 parseState 1 3)) } | firstUnionCaseDecl opt_OBLOCKSEP { $1 } firstUnionCaseDecl: | ident OF unionCaseRepr { Choice2Of2 (UnionCase ( [],$1,UnionCaseFields $3,PreXmlDoc.Empty,None,rhs2 parseState 1 3)) } | ident EQUALS constant opt_OBLOCKSEP { Choice1Of2 (EnumCase ([],$1,$3,PreXmlDoc.Empty,rhs2 parseState 1 3)) } unionCaseRepr: | braceFieldDeclList { errorR(Deprecated(FSComp.SR.parsConsiderUsingSeparateRecordType(),lhs(parseState))); $1 } | appType STAR tupleTypeElements { List.map mkAnonField ($1 :: $3) } | appType { [mkAnonField $1] } recdFieldDeclList: | recdFieldDecl seps recdFieldDeclList { $1 :: $3 } | recdFieldDecl opt_seps { [$1] } recdFieldDecl: | opt_attributes fieldDecl { let fld = $2 $1 false let (Field(a,b,c,d,e,f,vis,g)) = fld if isSome vis then errorR(Error(FSComp.SR.parsRecordFieldsCannotHaveVisibilityDeclarations(),rhs parseState 2)); Field(a,b,c,d,e,f,None,g) } fieldDecl: | opt_mutable opt_access ident COLON typ { let rhsm = rhs2 parseState 3 5 (fun attrs stat -> Field(attrs, stat,Some $3,$5,$1,grabXmlDoc(parseState,3),$2,rhsm)) } exconDefn: | exconCore opt_classDefn { ExceptionDefn($1,$2, lhs(parseState)) } exconSpfn: | exconCore opt_classSpfn { ExceptionSig($1,$2,lhs(parseState)) } exceptionAndGrabDoc: | EXCEPTION { grabXmlDoc(parseState,1) } exconCore: | exceptionAndGrabDoc opt_attributes opt_access exconIntro exconRepr { ExceptionDefnRepr($2,$4, $5,$1,$3,lhs(parseState)) } exconIntro: | ident { UnionCase ( [], $1,UnionCaseFields [],PreXmlDoc.Empty,None,lhs(parseState)) } | ident OF unionCaseRepr { UnionCase ( [], $1,UnionCaseFields $3,PreXmlDoc.Empty,None,lhs(parseState)) } exconRepr: | { None } | EQUALS path { Some ($2) } openDecl: | OPEN path { $2 } defnBindings: | LET opt_rec localBindings { let letm = rhs parseState 1 let isUse,isRec,bindingsPreAttrs = $1,$2,$3 // the first binding swallow any attributes prior to the 'let' BindingSetPreAttrs(rhs parseState 1,isRec,isUse,(fun attrs vis -> let binds = bindingsPreAttrs attrs vis letm if not isRec && List.length binds > 1 then reportParseErrorAt letm (FSComp.SR.parsLetAndForNonRecBindings()); [],binds)) } | cPrototype { BindingSetPreAttrs(lhs(parseState), false,false,$1) } doBinding: | DO typedSeqExprBlock { let letm = rhs parseState 1 let wholem = rhs2 parseState 1 2 // any attributes prior to the 'let' are left free, e.g. become top-level attributes // associated with the module, 'main' function or assembly depending on their target BindingSetPreAttrs(letm,false,false,(fun attrs vis -> attrs,[mkSynDoBinding (vis,true,$2,wholem)])) } hardwhiteLetBindings: | OLET opt_rec localBindings hardwhiteDefnBindingsTerminator { $4 (rhs parseState 1); // report unterminated error let letm = rhs parseState 1 let isUse,isRec,bindingsPreAttrs = $1,$2,$3 // the first binding swallow any attributes prior to the 'let' BindingSetPreAttrs(letm,isRec,isUse,(fun attrs vis -> let binds = bindingsPreAttrs attrs vis letm if not isRec && List.length binds > 1 then reportParseErrorAt letm (FSComp.SR.parsLetAndForNonRecBindings()); [],bindingsPreAttrs attrs vis letm)) } hardwhiteDoBinding: | ODO typedSeqExprBlock hardwhiteDefnBindingsTerminator { $3 (rhs parseState 1); // report unterminated error let letm = rhs parseState 1 let wholem = unionRanges letm $2.Range let seqPt = NoSequencePointAtDoBinding // any attributes prior to the 'let' are left free, e.g. become top-level attributes // associated with the module, 'main' function or assembly depending on their target BindingSetPreAttrs(letm,false,false,(fun attrs vis -> attrs,[mkSynDoBinding (vis,true,$2,wholem)])), $2 } classDefnBindings: | defnBindings { $1 } | doBinding { $1 } | hardwhiteLetBindings { $1 } | hardwhiteDoBinding { fst $1 } hardwhiteDefnBindingsTerminator: | ODECLEND { (fun m -> ()) } | recover { (fun m -> reportParseErrorAt m (FSComp.SR.parsUnmatchedLetOrDo())) } cPrototype: | EXTERN cRetType opt_access ident opt_HIGH_PRECEDENCE_APP LPAREN cArgs RPAREN { let rty,vis,nm,args = $2,$3,$4,$7 let xmlDoc = grabXmlDoc(parseState,1) let nmm = rhs parseState 3 let argsm = rhs parseState 6 let bindm = lhs(parseState) let wholem = lhs(parseState) let rhsm = lhs(parseState) let rhsExpr = SynExpr.App(ExprAtomicFlag.NonAtomic, SynExpr.Ident(ident("failwith",rhsm)),SynExpr.Const(SynConst.String("extern was not given a DllImport attribute",rhsm),rhsm),rhsm) (fun attrs vis -> let binding = mkSynBinding (xmlDoc,SynPat.LongIdent ([nm],None,Some(noInferredTypars),[SynPat.Tuple(args,argsm)],vis,nmm)) (vis,false,false,bindm,NoSequencePointAtInvisibleBinding,wholem,Some(rty),rhsExpr,rhsm,[],attrs,None) [], [binding]) } cArgs: | cMoreArgs { List.rev $1 } | cArg { [$1] } | { [] } cMoreArgs: | cMoreArgs COMMA cArg { $3 :: $1 } | cArg COMMA cArg { [$3; $1] } cArg: | opt_attributes cType { let m = lhs(parseState) in SynPat.Typed(SynPat.Wild m,$2,m) |> addAttribs $1 } | opt_attributes cType ident { let m = lhs(parseState) in SynPat.Typed(SynPat.Named (SynPat.Wild m,$3,false,None,m),$2,m) |> addAttribs $1 } cType: | path { let m = lhs(parseState) SynType.App(SynType.LongIdent($1,m),[],false,m) } | cType opt_HIGH_PRECEDENCE_APP LBRACK RBRACK { let m = lhs(parseState) SynType.App(SynType.LongIdent([ident("[]",m)],m),[$1],true,m) } | cType STAR { let m = lhs(parseState) SynType.App(SynType.LongIdent([ident("nativeptr",m)],m),[$1],true,m) } | cType AMP { let m = lhs(parseState) SynType.App(SynType.LongIdent([ident("byref",m)],m),[$1],true,m) } | VOID STAR { let m = lhs(parseState) SynType.App(SynType.LongIdent([ident("nativeint",m)],m),[],true,m) } cRetType: | opt_attributes cType { ($2,SynArgInfo($1,false,None)),rhs parseState 2 } | opt_attributes VOID { let m = rhs parseState 2 (SynType.App(SynType.LongIdent([ident("unit",m)],m),[],false,m),SynArgInfo($1,false,None)),m } localBindings: | attr_localBinding moreLocalBindings { (fun attrs vis letm -> match $1 with | Some f -> (f attrs vis letm true :: $2) | None -> $2) } moreLocalBindings: | AND attr_localBinding moreLocalBindings { let letm = (rhs parseState 1) (match $2 with | Some f -> f [] None letm false :: $3 | None -> $3) } | %prec prec_no_more_attr_bindings { [] } attr_localBinding: | opt_attributes localBinding { Some(fun attrs vis letm _ -> $2 (attrs@$1) vis letm) } | error { None } localBinding: | opt_inline opt_mutable bindingPattern opt_topReturnTypeWithTypeConstraints EQUALS typedExprWithStaticOptimizationsBlock { let (expr:SynExpr),opts = $6 let eqm = rhs parseState 5 let rhsm = expr.Range let optReturnType = $4 let bindingBuilder, bindm = $3 (fun attrs vis letm -> let wholem = unionRanges letm rhsm let spBind = if IsControlFlowExpression expr then NoSequencePointAtLetBinding else SequencePointAtBinding(wholem) bindingBuilder (vis,$1,$2,bindm,spBind,wholem,optReturnType,expr,rhsm,opts,attrs,None)) } | opt_inline opt_mutable bindingPattern opt_topReturnTypeWithTypeConstraints EQUALS error { let wholem = rhs2 parseState 3 5 let rhsm = rhs parseState 5 let optReturnType = $4 let bindingBuilder,bindm = $3 (fun attrs vis letm -> let spBind = SequencePointAtBinding(unionRanges letm rhsm) bindingBuilder (vis,$1,$2,bindm,spBind,wholem,optReturnType,arbExpr(parseState),rhsm,[],attrs,None)) } typedExprWithStaticOptimizationsBlock: | OBLOCKBEGIN typedExprWithStaticOptimizations OBLOCKEND { $2 } | OBLOCKBEGIN typedExprWithStaticOptimizations recover { if not $3 then reportParseErrorAt (rhs parseState 3) (FSComp.SR.parsUnexpectedEndOfFile()); $2 } | typedExprWithStaticOptimizations { $1 } typedExprWithStaticOptimizations : | typedSeqExpr opt_staticOptimizations { $1, List.rev $2 } opt_staticOptimizations: | opt_staticOptimizations staticOptimization { $2 :: $1 } | { [] } staticOptimization: | WHEN staticOptimizationConditions EQUALS typedSeqExprBlock { ($2,$4) } staticOptimizationConditions: | staticOptimizationConditions AND staticOptimizationCondition { $3 :: $1 } | staticOptimizationCondition { [$1 ] } staticOptimizationCondition: | typar COLON typ { WhenTyparTyconEqualsTycon($1,$3,lhs(parseState)) } | typar STRUCT { WhenTyparIsStruct($1,lhs(parseState)) } | TRUE {WhenInlined(rhs parseState 1) } rawConstant: | INT8 { if snd $1 then errorR(Error(FSComp.SR.lexOutsideEightBitSigned(), lhs(parseState))); SynConst.SByte (fst $1) } | UINT8 { SynConst.Byte $1 } | INT16 { if snd $1 then errorR(Error(FSComp.SR.lexOutsideSixteenBitSigned(), lhs(parseState))); SynConst.Int16 (fst $1) } | UINT16 { SynConst.UInt16 $1 } | INT32 { if snd $1 then errorR(Error(FSComp.SR.lexOutsideThirtyTwoBitSigned(), lhs(parseState))); SynConst.Int32 (fst $1) } | UINT32 { SynConst.UInt32 $1 } | INT64 { if snd $1 then errorR(Error(FSComp.SR.lexOutsideSixtyFourBitSigned(), lhs(parseState))); SynConst.Int64 (fst $1) } | UINT64 { SynConst.UInt64 $1 } | NATIVEINT { SynConst.IntPtr $1 } | UNATIVEINT { SynConst.UIntPtr $1 } | IEEE32 { SynConst.Single $1 } | IEEE64 { SynConst.Double $1 } | CHAR { SynConst.Char $1 } | DECIMAL { SynConst.Decimal $1 } | BIGNUM { SynConst.UserNum $1 } | stringOrKeywordString { SynConst.String ($1,lhs(parseState)) } | BYTEARRAY { SynConst.Bytes ($1,lhs(parseState)) } constant: | rawConstant { $1 } | rawConstant HIGH_PRECEDENCE_TYAPP measureTypeArg { SynConst.Measure($1, $3) } bindingPattern: | headBindingPattern { let xmlDoc = grabXmlDoc(parseState,1) mkSynBinding (xmlDoc,$1), rhs parseState 1 } /* sp = v | sp:typ | attrs sp */ simplePattern: | ident { SynSimplePat.Id ($1,false,false,false,rhs parseState 1) } | QMARK ident { SynSimplePat.Id ($2,false,false,true,rhs parseState 2) } | simplePattern COLON typeWithTypeConstraints { let lhsm = lhs(parseState) SynSimplePat.Typed($1,$3,lhsm) } | attributes simplePattern %prec paren_pat_attribs { let lhsm = lhs(parseState) SynSimplePat.Attrib($2,$1,lhsm) } simplePatternCommaList: | simplePattern { [$1] } | simplePattern COMMA simplePatternCommaList { $1 :: $3 } simplePatterns: | LPAREN simplePatternCommaList RPAREN { $2 } | LPAREN RPAREN { [] } | LPAREN simplePatternCommaList recover { reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnmatchedParen()); [] } | LPAREN error RPAREN { (* silent recovery *) [] } | LPAREN recover { reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnmatchedParen()); [] } headBindingPattern: | headBindingPattern AS ident { SynPat.Named ($1,$3,false,None,rhs2 parseState 1 3) } | headBindingPattern BAR headBindingPattern { SynPat.Or($1,$3,rhs2 parseState 1 3) } | headBindingPattern COLON_COLON headBindingPattern { SynPat.LongIdent (mkSynCaseName (rhs parseState 2) opNameCons, None, None,[SynPat.Tuple ([$1;$3],rhs2 parseState 1 3)],None,lhs(parseState)) } | tuplePatternElements %prec pat_tuple { SynPat.Tuple(List.rev $1, lhs(parseState)) } | conjPatternElements %prec pat_conj { SynPat.Ands(List.rev $1, lhs(parseState)) } | constrPattern { $1 } tuplePatternElements: | tuplePatternElements COMMA headBindingPattern { $3 :: $1 } | headBindingPattern COMMA headBindingPattern { $3 :: $1 :: [] } conjPatternElements: | conjPatternElements AMP headBindingPattern { $3 :: $1 } | headBindingPattern AMP headBindingPattern { $3 :: $1 :: [] } constrPattern: | atomicPatternLongIdent explicitValTyparDecls { let vis,lid = $1 in SynPat.LongIdent (lid,None,Some $2,[],vis,lhs(parseState)) } | atomicPatternLongIdent opt_explicitValTyparDecls2 atomicPatterns %prec pat_app { let vis,lid = $1 in SynPat.LongIdent (lid,None,$2,$3,vis,lhs(parseState)) } | atomicPatternLongIdent opt_explicitValTyparDecls2 HIGH_PRECEDENCE_PAREN_APP atomicPatterns { let vis,lid = $1 in SynPat.LongIdent (lid,None,$2,$4,vis,lhs(parseState)) } | atomicPatternLongIdent opt_explicitValTyparDecls2 HIGH_PRECEDENCE_BRACK_APP atomicPatterns { let vis,lid = $1 in SynPat.LongIdent (lid,None,$2,$4,vis,lhs(parseState)) } | COLON_QMARK atomType %prec pat_isinst { SynPat.IsInst($2,lhs(parseState)) } | atomicPattern { $1 } atomicPatterns: | atomicPattern atomicPatterns %prec pat_args { $1 :: $2 } | atomicPattern HIGH_PRECEDENCE_BRACK_APP atomicPatterns { reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsSuccessivePatternsShouldBeSpacedOrTupled()); $1 :: $3 } | atomicPattern HIGH_PRECEDENCE_PAREN_APP atomicPatterns { reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsSuccessivePatternsShouldBeSpacedOrTupled()); $1 :: $3 } | atomicPattern { [$1] } atomicPattern: | quoteExpr { SynPat.QuoteExpr($1,lhs(parseState)) } | CHAR DOT_DOT CHAR { SynPat.DeprecatedCharRange ($1,$3,rhs2 parseState 1 3) } | LBRACE recordPatternElements RBRACE { $2 } | LBRACK listPatternElements RBRACK { SynPat.ArrayOrList(false,$2,lhs(parseState)) } | LBRACK_BAR listPatternElements BAR_RBRACK { SynPat.ArrayOrList(true,$2, lhs(parseState)) } | UNDERSCORE { SynPat.Wild (lhs(parseState)) } | QMARK ident { SynPat.OptionalVal($2,lhs(parseState)) } | atomicPatternLongIdent %prec prec_atompat_pathop { let vis,lid = $1 if List.length lid > 1 || (let c = (List.head lid).idText.[0] in Char.IsUpper(c) && not (Char.IsLower c)) then mkSynPatMaybeVar lid vis (lhs(parseState)) else mkSynPatVar vis (List.head lid) } | constant { SynPat.Const ($1,$1.Range (lhs(parseState))) } | FALSE { SynPat.Const(SynConst.Bool false,lhs(parseState)) } | TRUE { SynPat.Const(SynConst.Bool true,lhs(parseState)) } | NULL { SynPat.Null(lhs(parseState)) } | LPAREN parenPatternBody RPAREN { let m = (lhs(parseState)) in SynPat.Paren($2 m,m) } | LPAREN parenPatternBody recover { reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnmatchedParen()); $2 (rhs2 parseState 1 2) } | LPAREN error RPAREN { (* silent recovery *) SynPat.Wild (lhs(parseState)) } | LPAREN recover { reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnmatchedParen()); SynPat.Wild (lhs(parseState))} parenPatternBody: | parenPattern { (fun m -> $1) } | { (fun m -> SynPat.Const(SynConst.Unit,m)) } /* This duplicates out 'patterns' in order to give type annotations */ /* the desired precedence w.r.t. patterns, tuple patterns in particular. */ /* Duplication requried to minimize the disturbance to the grammar, */ /* in particular the expected property that "pat" parses the same as */ /* "(pat)"! Here are some examples: */ /* a,b parses as (a,b) */ /* (a,b) also parses as (a,b) */ /* (a,b : t) parses as (a, (b:t)) */ /* a,b as t parses as ((a,b) as t) */ /* (a,b as t) also parses as ((a,b) as t) */ /* a,b | c,d parses as ((a,b) | (c,d)) */ /* (a,b | c,d) also parses as ((a,b) | (c,d)) */ /* (a : t,b) parses as ((a:t),b) */ /* (a : t1,b : t2) parses as ((a:t),(b:t2)) */ /* (a,b as nm : t) parses as (((a,b) as nm) : t) */ /* (a,b :: c : t) parses as (((a,b) :: c) : t) */ /* */ /* Probably the most unexpected thing here is that 'as nm' binds the */ /* whole pattern to the left, whereas ': t' binds only the pattern */ /* immediately preceding in the tuple. */ /* */ /* Also, it is unexpected that '(a,b : t)' in a pattern binds differently to */ /* '(a,b : t)' in an expression. It's not that easy to solve that without */ /* duplicating the entire expression grammar, or making a fairly severe breaking change */ /* to the language. */ parenPattern: | parenPattern AS ident { SynPat.Named ($1,$3,false,None,rhs2 parseState 1 3) } | parenPattern BAR parenPattern { SynPat.Or($1,$3,rhs2 parseState 1 3) } | tupleParenPatternElements { SynPat.Tuple(List.rev $1,lhs(parseState)) } | conjParenPatternElements { SynPat.Ands(List.rev $1,rhs2 parseState 1 3) } | parenPattern COLON typeWithTypeConstraints %prec paren_pat_colon { let lhsm = lhs(parseState) SynPat.Typed($1,$3,lhsm) } | attributes parenPattern %prec paren_pat_attribs { let lhsm = lhs(parseState) SynPat.Attrib($2,$1,lhsm) } | parenPattern COLON_COLON parenPattern { SynPat.LongIdent (mkSynCaseName (rhs parseState 2) opNameCons, None, None, [ SynPat.Tuple ([$1;$3],rhs2 parseState 1 3) ],None,lhs(parseState)) } | constrPattern { $1 } tupleParenPatternElements: | tupleParenPatternElements COMMA parenPattern { $3 :: $1 } | parenPattern COMMA parenPattern { $3 :: $1 :: [] } conjParenPatternElements: | conjParenPatternElements AMP parenPattern { $3 :: $1 } | parenPattern AMP parenPattern { $3 :: $1 :: [] } recordPatternElements: | recordPatternElementsAux { let rs,m = $1 in SynPat.Record (rs,m) } recordPatternElementsAux: /* Fix 1190 */ | recordPatternElement opt_seps { [$1],lhs(parseState) } | recordPatternElement seps recordPatternElementsAux { let r = $1 in let (rs,dropMark) = $3 in (r :: rs),lhs(parseState) } recordPatternElement: | path EQUALS parenPattern { (List.frontAndBack $1,$3) } listPatternElements: /* Fix 3569 */ | { [] } | parenPattern opt_seps { [$1] } | parenPattern seps listPatternElements { $1 :: $3 } /* The lexfilter likes to insert OBLOCKBEGIN/OBLOCKEND pairs */ typedSeqExprBlock: | OBLOCKBEGIN typedSeqExpr OBLOCKEND { $2 } | OBLOCKBEGIN typedSeqExpr recover { if not $3 then reportParseErrorAt (rhs parseState 3) (FSComp.SR.parsUnexpectedEndOfFile()); $2 } | typedSeqExpr { $1 } /* The lexfilter likes to insert OBLOCKBEGIN/OBLOCKEND pairs */ declExprBlock: | OBLOCKBEGIN typedSeqExpr OBLOCKEND { $2 } | declExpr { $1 } /* For some constructs the lex filter can't be sure to insert a matching OBLOCKEND, e.g. "function a -> b | c -> d" all in one line */ /* for these it only inserts a trailing ORIGHT_BLOCK_END */ typedSeqExprBlockR: | typedSeqExpr ORIGHT_BLOCK_END { $1 } | typedSeqExpr { $1 } typedSeqExpr: | seqExpr COLON typeWithTypeConstraints { SynExpr.Typed ($1,$3, unionRanges $1.Range $3.Range) } | seqExpr { $1 } seqExpr: | declExpr seps seqExpr { SynExpr.Seq(SequencePointsAtSeq,true,$1,$3,unionRanges $1.Range $3.Range) } | declExpr seps { $1 } | declExpr %prec SEMICOLON { $1 } | declExpr THEN seqExpr %prec prec_then_before { SynExpr.Seq(SequencePointsAtSeq,false,$1,$3,unionRanges $1.Range $3.Range ) } | declExpr OTHEN OBLOCKBEGIN typedSeqExpr OBLOCKEND %prec prec_then_before { SynExpr.Seq(SequencePointsAtSeq,false,$1,$4,unionRanges $1.Range $4.Range) } | hardwhiteLetBindings %prec prec_args_error { let letm,isUse = match $1 with (BindingSetPreAttrs(m,_,isUse,_)) -> m,isUse reportParseErrorAt letm (FSComp.SR.parsExpectedStatementAfterLet(if isUse then "use" else "let")); mkLocalBindings (rhs2 parseState 1 2,$1,arbExpr(parseState)) } /* Use this as the last terminal when performing error recovery */ /* The contract for using this is that (a) if EOF occurs then the */ /* the using production must report an error and (b) the using production */ /* can report an error anyway if it is helpful, e.g. "unclosed '('" (giving two errors) */ recover: | error { true } | EOF { false } declExpr: | defnBindings IN typedSeqExpr %prec expr_let { mkLocalBindings (rhs2 parseState 1 3,$1,$3) } | defnBindings IN error %prec expr_let { mkLocalBindings (rhs2 parseState 1 2,$1,arbExpr(parseState)) } /* | defnBindings error %prec expr_let { reportParseErrorAt (match $1 with (BindingSetPreAttrs(m,_,_,_)) -> m) (FSComp.SR.parsNoMatchingInForLet()); mkLocalBindings (rhs parseState 1,$1,arbExpr(parseState)) } */ | hardwhiteLetBindings typedSeqExprBlock %prec expr_let { mkLocalBindings (unionRanges (rhs parseState 1) $2.Range,$1,$2) } | hardwhiteLetBindings error %prec expr_let { reportParseErrorAt (match $1 with (BindingSetPreAttrs(m,_,_,_)) -> m) (FSComp.SR.parsErrorInReturnForLetIncorrectIndentation()); mkLocalBindings (rhs2 parseState 1 2,$1,arbExpr(parseState)) } | hardwhiteLetBindings OBLOCKSEP typedSeqExprBlock %prec expr_let { mkLocalBindings (unionRanges (rhs2 parseState 1 2) $3.Range ,$1,$3) } | hardwhiteLetBindings OBLOCKSEP error %prec expr_let { //reportParseErrorAt (match $1 with (BindingSetPreAttrs(m,_,_,_)) -> m) (FSComp.SR.parsErrorInReturnForLetIncorrectIndentation()); mkLocalBindings (rhs2 parseState 1 2,$1,arbExpr(parseState)) } | hardwhiteDoBinding %prec expr_let { let e = snd $1 SynExpr.Do(e,e.Range) } | anonMatchingExpr %prec expr_function { $1 } | anonLambdaExpr %prec expr_fun { $1 } | MATCH typedSeqExpr withClauses %prec expr_match { let mMatch = (rhs parseState 1) let mWith,(clauses,mLast) = $3 let spBind = SequencePointAtBinding(unionRanges mMatch mWith) SynExpr.Match(spBind, $2,clauses,false,unionRanges mMatch mLast) } | MATCH typedSeqExpr recover %prec expr_match { if not $3 then reportParseErrorAt (rhs parseState 3) (FSComp.SR.parsUnexpectedEndOfFile()); // Produce approximate expression during error recovery SynExpr.DiscardAfterError($2,rhs2 parseState 1 2) } | TRY typedSeqExprBlockR withClauses %prec expr_try { let mTry = (rhs parseState 1) let spTry = SequencePointAtTry(mTry) let mWith,(clauses,mLast) = $3 let spWith = SequencePointAtWith(mWith) let mTryToWith = unionRanges mTry mWith let mWithToLast = unionRanges mWith mLast let mTryToLast = unionRanges mTry mLast SynExpr.TryWith($2, mTryToWith, clauses,mWithToLast, mTryToLast,spTry,spWith) } | TRY typedSeqExprBlockR recover %prec expr_try { // Produce approximate expression during error recovery // Include any expressions to make sure they gets type checked in case that generates useful results for intellisense if not $3 then reportParseErrorAt (rhs parseState 3) (FSComp.SR.parsUnexpectedEndOfFile()); $2 } | TRY typedSeqExprBlockR FINALLY typedSeqExprBlock %prec expr_try { let mTry = rhs parseState 1 let spTry = SequencePointAtTry(mTry) let spFinally = SequencePointAtFinally(rhs parseState 3) let mTryToLast = unionRanges mTry $4.Range SynExpr.TryFinally($2, $4,mTryToLast,spTry,spFinally) } | IF declExpr ifExprCases %prec expr_if { let mIf = (rhs parseState 1) $3 $2 mIf } | IF declExpr recover %prec expr_if { reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnmatchedIf()); // Produce an approximate expression during error recovery. // Include expressions to make sure they get type checked in case that generates useful results for intellisense. // Generate a throwAway for the expression so it isn't forced to have a type 'bool' // from the context it is used in. SynExpr.DiscardAfterError($2, rhs2 parseState 1 2) } | IF recover %prec expr_if { if not $2 then reportParseErrorAt (rhs parseState 2) (FSComp.SR.parsUnexpectedEndOfFile()); arbExpr parseState } | LAZY declExpr %prec expr_lazy { SynExpr.Lazy($2,unionRanges (rhs parseState 1) $2.Range) } | ASSERT declExpr %prec expr_assert { SynExpr.Assert($2, unionRanges (rhs parseState 1) $2.Range) } | ASSERT %prec expr_assert { raiseParseErrorAt (rhs parseState 1) (FSComp.SR.parsAssertIsNotFirstClassValue()) } | OLAZY declExprBlock %prec expr_lazy { SynExpr.Lazy($2,unionRanges (rhs parseState 1) $2.Range) } | OASSERT declExprBlock %prec expr_assert { SynExpr.Assert($2, unionRanges (rhs parseState 1) $2.Range) } | OASSERT %prec expr_assert { raiseParseErrorAt (rhs parseState 1) (FSComp.SR.parsAssertIsNotFirstClassValue()) } | WHILE declExpr doToken typedSeqExprBlock doneDeclEnd { let mWhile = unionRanges (rhs parseState 1) $2.Range let spWhile = SequencePointAtWhileLoop(mWhile) SynExpr.While(spWhile,$2,$4,unionRanges (rhs parseState 1) $4.Range) } | WHILE declExpr doToken typedSeqExprBlock recover { reportParseErrorAt (rhs parseState 4) (FSComp.SR.parsDoneExpected()) ; arbExpr(parseState) } | WHILE declExpr doToken error doneDeclEnd { (* silent recovery *) arbExpr(parseState) } | WHILE declExpr recover { reportParseErrorAt (rhs parseState 2) (FSComp.SR.parsDoExpected()) ; arbExpr(parseState) } | WHILE error doneDeclEnd { (* silent recovery *) arbExpr(parseState) } | FOR forLoopBinder doToken typedSeqExprBlock doneDeclEnd { let spBind = SequencePointAtForLoop(rhs2 parseState 1 3) let (a,b) = $2 in SynExpr.ForEach(spBind,SeqExprOnly(false),a,b,$4,unionRanges (rhs parseState 1) $4.Range) } | FOR forLoopBinder recover { if not $3 then reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnclosedFor()) ; let spBind = SequencePointAtForLoop(rhs2 parseState 1 2) let (a,b) = $2 in SynExpr.ForEach(spBind,SeqExprOnly(false),a,b,arbExpr(parseState),lhs(parseState)) } | FOR forLoopBinder doToken error doneDeclEnd { let spBind = SequencePointAtForLoop(rhs2 parseState 1 3) let (a,b) = $2 in SynExpr.ForEach(spBind,SeqExprOnly(false),a,b,arbExpr(parseState),rhs2 parseState 1 3) } | FOR forLoopRange doToken typedSeqExprBlock doneDeclEnd { let spBind = SequencePointAtForLoop(rhs2 parseState 1 3) let (a,b,c,d) = $2 in SynExpr.For(spBind,a,b,c,d,$4,unionRanges (rhs parseState 1) $4.Range) } | FOR forLoopRange doToken typedSeqExprBlock recover { reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnclosedFor()) ; arbExpr(parseState) } | FOR forLoopRange doToken error doneDeclEnd { (* silent recovery *) arbExpr(parseState) } | FOR error doToken typedSeqExprBlock doneDeclEnd { (* silent recovery *) $4 } /* do not include this one - though for fairly bizarre reasons! If the user has simply typed 'for'as the start of a variable name, and intellisense parsing kicks in, then we can't be sure we're parsing a for-loop. The general rule is that you shoudn't commit to aggressive look-for-a-matching-construct error recovery until you're sure you're parsing a particular construct. This probably affects 'and' as well, but it's hard to change that. 'for' is a particularly common prefix of identifiers. | FOR error doneDeclEnd { reportParseErrorAt (rhs parseState 2) (FSComp.SR.parsIdentifierExpected()); arbExpr(parseState) } */ | FOR parenPattern error doneDeclEnd { reportParseErrorAt (rhs parseState 3) (FSComp.SR.parsEqualExpected()); arbExpr(parseState) } /* START MONADIC SYNTAX ONLY */ | YIELD declExpr { SynExpr.YieldOrReturn(($1,not $1),$2, unionRanges (rhs parseState 1) $2.Range) } | YIELD_BANG declExpr { SynExpr.YieldOrReturnFrom(($1,not $1), $2, unionRanges (rhs parseState 1) $2.Range) } | BINDER headBindingPattern EQUALS typedSeqExprBlock IN opt_OBLOCKSEP typedSeqExprBlock %prec expr_let { let spBind = SequencePointAtBinding(rhs2 parseState 1 5) let m = rhs parseState 1 SynExpr.LetOrUseBang(spBind,($1 = "use"),$2,$4,$7, lhs parseState) } | OBINDER headBindingPattern EQUALS typedSeqExprBlock hardwhiteDefnBindingsTerminator opt_OBLOCKSEP typedSeqExprBlock %prec expr_let { let spBind = SequencePointAtBinding(unionRanges (rhs parseState 1) $4.Range) let m = rhs parseState 1 SynExpr.LetOrUseBang(spBind,($1 = "use"),$2,$4,$7, lhs parseState) } | OBINDER headBindingPattern EQUALS typedSeqExprBlock hardwhiteDefnBindingsTerminator opt_OBLOCKSEP error %prec expr_let { // error recovery that allows intellisense when writing incomplete computation expressions let spBind = SequencePointAtBinding(unionRanges (rhs parseState 1) $4.Range) let m = rhs parseState 1 SynExpr.LetOrUseBang(spBind,($1 = "use"),$2,$4, SynExpr.ImplicitZero m, lhs parseState) } | DO_BANG typedSeqExpr IN opt_OBLOCKSEP typedSeqExprBlock %prec expr_let { let spBind = NoSequencePointAtDoBinding SynExpr.LetOrUseBang(spBind,false,SynPat.Const(SynConst.Unit,$2.Range),$2,$5, unionRanges (rhs parseState 1) $5.Range) } | ODO_BANG typedSeqExprBlock hardwhiteDefnBindingsTerminator %prec expr_let { SynExpr.DoBang($2, unionRanges (rhs parseState 1) $2.Range) } | FOR forLoopBinder opt_OBLOCKSEP monadicSingleLineQualifiersThenArrowThenExprR %prec expr_let { let spBind = SequencePointAtForLoop(rhs2 parseState 1 2) let a,b= $2 in SynExpr.ForEach(spBind,SeqExprOnly(true),a,b,$4 (rhs parseState 3),rhs2 parseState 1 3) } | RARROW typedSeqExprBlockR { errorR(Error(FSComp.SR.parsArrowUseIsLimited(),lhs parseState)); SynExpr.YieldOrReturn((true,true),$2, lhs parseState) } /* END MONADIC SYNTAX ONLY */ | declExpr COLON_QMARK typ { SynExpr.TypeTest($1,$3, unionRanges $1.Range $3.Range) } | declExpr COLON_GREATER typ { SynExpr.Upcast($1,$3, unionRanges $1.Range $3.Range) } | declExpr COLON_QMARK_GREATER typ { SynExpr.Downcast($1,$3, unionRanges $1.Range $3.Range) } /* NOTE: any change to the "INFIX" tokens (or their definitions) should be reflected in PrettyNaming.IsInfixOperator */ | declExpr COLON_EQUALS declExpr { mkSynInfix (rhs parseState 2) (lhs(parseState)) $1 ":=" $3 } | minusExpr LARROW declExprBlock { mkSynAssign (unionRanges $1.Range $3.Range) $1 $3 } | tupleExpr %prec expr_tuple { SynExpr.Tuple( List.rev $1,lhs(parseState)) } | declExpr BAR_BAR declExpr { mkSynInfix (rhs parseState 2) (lhs(parseState)) $1 "||" $3 } | declExpr INFIX_BAR_OP declExpr { mkSynInfix (rhs parseState 2) (lhs(parseState)) $1 $2 $3 } | declExpr OR declExpr { mkSynInfix (rhs parseState 2) (lhs(parseState)) $1 "or" $3 } | declExpr AMP declExpr { mkSynInfix (rhs parseState 2) (lhs(parseState)) $1 "&" $3 } | declExpr AMP_AMP declExpr { mkSynInfix (rhs parseState 2) (lhs(parseState)) $1 "&&" $3 } | declExpr INFIX_AMP_OP declExpr { mkSynInfix (rhs parseState 2) (lhs(parseState)) $1 $2 $3 } | declExpr EQUALS declExpr { mkSynInfix (rhs parseState 2) (unionRanges $1.Range $3.Range) $1 "=" $3 } | declExpr INFIX_COMPARE_OP declExpr { mkSynInfix (rhs parseState 2) (lhs(parseState)) $1 $2 $3 } | declExpr DOLLAR declExpr { mkSynInfix (rhs parseState 2) (lhs(parseState)) $1 "$" $3 } | declExpr LESS declExpr { mkSynInfix (rhs parseState 2) (lhs(parseState)) $1 "<" $3 } | declExpr GREATER declExpr { mkSynInfix (rhs parseState 2) (lhs(parseState)) $1 ">" $3 } | declExpr INFIX_AT_HAT_OP declExpr { mkSynInfix (rhs parseState 2) (lhs(parseState)) $1 $2 $3 } | declExpr PERCENT_OP declExpr { mkSynInfix (rhs parseState 2) (lhs(parseState)) $1 $2 $3 } | declExpr COLON_COLON declExpr { SynExpr.App (ExprAtomicFlag.NonAtomic, mkSynIdGet (rhs parseState 2) opNameCons,SynExpr.Tuple ([$1;$3],lhs(parseState)),lhs(parseState)) } | declExpr PLUS_MINUS_OP declExpr { mkSynInfix (rhs parseState 2) (lhs(parseState)) $1 $2 $3 } | declExpr MINUS declExpr { mkSynInfix (rhs parseState 2) (lhs(parseState)) $1 "-" $3 } | declExpr STAR declExpr { mkSynInfix (rhs parseState 2) (lhs(parseState)) $1 "*" $3 } | declExpr INFIX_STAR_DIV_MOD_OP declExpr { mkSynInfix (rhs parseState 2) (lhs(parseState)) $1 $2 $3 } | declExpr INFIX_STAR_STAR_OP declExpr { mkSynInfix (rhs parseState 2) (lhs(parseState)) $1 $2 $3 } | minusExpr %prec expr_prefix_plus_minus { $1 } dynamicArg: | IDENT { let con = SynConst.String ($1,rhs parseState 1) let arg2 = SynExpr.Const (con,con.Range (rhs parseState 1)) arg2 } | LPAREN typedSeqExpr RPAREN { $2 } withClauses: | WITH withPatternClauses { rhs parseState 1, $2 } | OWITH withPatternClauses OEND { rhs parseState 1, $2 } | OWITH withPatternClauses recover { if not $3 then reportParseErrorAt (rhs parseState 3) (FSComp.SR.parsUnexpectedEndOfFile()); rhs parseState 1, $2 } withPatternClauses: | patternClauses { $1 } | BAR patternClauses { $2 } | BAR error { // silent recovery let mLast = rhs parseState 1 [], mLast } | error { // silent recovery let mLast = rhs parseState 1 [], mLast } patternAndGuard: | parenPattern patternGuard { $1, $2, rhs parseState 1 } patternClauses: | patternAndGuard patternResult %prec prec_pat_pat_action { let pat,guard,patm = $1 let mLast = $2.Range [Clause(pat,guard,$2,patm,SequencePointAtTarget)], mLast } | patternAndGuard patternResult BAR patternClauses { let pat,guard,patm = $1 let clauses,mLast = $4 (Clause(pat,guard,$2,patm,SequencePointAtTarget) :: clauses), mLast } | patternAndGuard patternResult BAR error { let pat,guard,patm = $1 let mLast = rhs parseState 3 // silent recovery [Clause(pat,guard,$2,patm,SequencePointAtTarget)], mLast } | patternAndGuard patternResult error { let pat,guard,patm = $1 let mLast = $2.Range // silent recovery [Clause(pat,guard,$2,patm,SequencePointAtTarget)], mLast } patternGuard: | WHEN declExpr { Some $2 } | { None } patternResult: | RARROW typedSeqExprBlockR { $2 } ifExprCases: | ifExprThen ifExprElifs { let exprThen,mThen = $1 (fun exprGuard mIf -> let mIfToThen = unionRanges mIf mThen let lastBranch : SynExpr = match $2 with None -> exprThen | Some e -> e let mIfToEndOfLastBranch = unionRanges mIf lastBranch.Range let spIfToThen = SequencePointAtBinding(mIfToThen) SynExpr.IfThenElse(exprGuard,exprThen,$2,spIfToThen,mIfToThen,mIfToEndOfLastBranch)) } ifExprThen: | THEN declExpr %prec prec_then_if { $2, rhs parseState 1 } | OTHEN OBLOCKBEGIN typedSeqExpr OBLOCKEND %prec prec_then_if { $3,rhs parseState 1 } | OTHEN OBLOCKBEGIN typedSeqExpr recover %prec prec_then_if { if not $4 then reportParseErrorAt (rhs parseState 4) (FSComp.SR.parsUnexpectedEndOfFile()); $3,rhs parseState 1 } ifExprElifs: | { None } | ELSE declExpr { Some $2 } | OELSE OBLOCKBEGIN typedSeqExpr OBLOCKEND { Some $3 } | OELSE OBLOCKBEGIN typedSeqExpr recover { if not $4 then reportParseErrorAt (rhs parseState 4) (FSComp.SR.parsUnexpectedEndOfFile()); Some $3 } | ELIF declExpr ifExprCases { let mElif = rhs parseState 1 Some ($3 $2 mElif) } | ELIF declExpr recover { Some $2 } tupleExpr: | tupleExpr COMMA declExpr { $3 :: $1 } | declExpr COMMA declExpr { $3 :: $1 :: [] } minusExpr: | MINUS minusExpr %prec expr_prefix_plus_minus { mkSynPrefix (rhs parseState 1) (unionRanges (rhs parseState 1) $2.Range) "~-" $2 } | PLUS_MINUS_OP minusExpr { if not (IsValidPrefixOperatorUse $1) then reportParseErrorAt $2.Range (FSComp.SR.parsInvalidPrefixOperator()); mkSynPrefix (rhs parseState 1) (unionRanges (rhs parseState 1) $2.Range) ("~"^($1)) $2 } | ADJACENT_PREFIX_OP minusExpr { if not (IsValidPrefixOperatorUse $1) then reportParseErrorAt $2.Range (FSComp.SR.parsInvalidPrefixOperator()); if $1 = "&" then SynExpr.AddressOf(true,$2,rhs parseState 1,unionRanges (rhs parseState 1) $2.Range) elif $1 = "&&" then SynExpr.AddressOf(false,$2,rhs parseState 1,unionRanges (rhs parseState 1) $2.Range) else mkSynPrefix (rhs parseState 1) (unionRanges (rhs parseState 1) $2.Range) ("~"^($1)) $2 } | PERCENT_OP minusExpr { if not (IsValidPrefixOperatorUse $1) then reportParseErrorAt $2.Range (FSComp.SR.parsInvalidPrefixOperator()); mkSynPrefix (rhs parseState 1) (unionRanges (rhs parseState 1) $2.Range) ("~"^($1)) $2 } | AMP minusExpr { SynExpr.AddressOf(true,$2,rhs parseState 1,unionRanges (rhs parseState 1) $2.Range) } | AMP_AMP minusExpr { SynExpr.AddressOf(false,$2,rhs parseState 1, unionRanges (rhs parseState 1) $2.Range) } | NEW appTypeNonAtomicDeprecated opt_HIGH_PRECEDENCE_APP atomicExprAfterType { SynExpr.New(false,$2,$4,unionRanges (rhs parseState 1) $4.Range) } | NEW appTypeNonAtomicDeprecated opt_HIGH_PRECEDENCE_APP error { SynExpr.New(false,$2,arbExpr(parseState),unionRanges (rhs parseState 1) ($2).Range) } | NEW error { arbExpr(parseState) } | UPCAST minusExpr { SynExpr.InferredUpcast($2,unionRanges (rhs parseState 1) $2.Range) } | DOWNCAST minusExpr { SynExpr.InferredDowncast($2,unionRanges (rhs parseState 1) $2.Range)} | appExpr { $1 } appExpr: | appExpr argExpr %prec expr_app { SynExpr.App (ExprAtomicFlag.NonAtomic, $1,$2,unionRanges $1.Range $2.Range) } | atomicExpr { let arg,_ = $1 arg } argExpr: | ADJACENT_PREFIX_OP atomicExpr { let arg2,hpa2 = $2 if not (IsValidPrefixOperatorUse $1) then reportParseErrorAt arg2.Range (FSComp.SR.parsInvalidPrefixOperator()); if hpa2 then reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsSuccessiveArgsShouldBeSpacedOrTupled()); mkSynPrefix (rhs parseState 1) (unionRanges (rhs parseState 1) arg2.Range) ("~"^($1)) arg2 } | atomicExpr { let arg,hpa = $1 if hpa then reportParseErrorAt arg.Range (FSComp.SR.parsSuccessiveArgsShouldBeSpacedOrTupled()); arg } atomicExpr: | atomicExpr HIGH_PRECEDENCE_BRACK_APP atomicExpr { let arg1,_ = $1 let arg2,_ = $3 SynExpr.App (ExprAtomicFlag.Atomic, arg1,arg2,unionRanges arg1.Range arg2.Range),true } | atomicExpr HIGH_PRECEDENCE_PAREN_APP atomicExpr { let arg1,_ = $1 let arg2,_ = $3 SynExpr.App (ExprAtomicFlag.Atomic, arg1,arg2,unionRanges arg1.Range arg2.Range),true } | atomicExpr HIGH_PRECEDENCE_TYAPP typeArgsActual { let arg1,_ = $1 SynExpr.TypeApp (arg1,$3,lhs(parseState)),false } | PREFIX_OP atomicExpr { let arg2,hpa2 = $2 if not (IsValidPrefixOperatorUse $1) then reportParseErrorAt arg2.Range (FSComp.SR.parsInvalidPrefixOperator()); mkSynPrefix (rhs parseState 1) (unionRanges (rhs parseState 1) arg2.Range) $1 arg2,hpa2 } | atomicExpr DOT atomicExprQualification { let arg1,hpa1 = $1 $3 arg1 (lhs(parseState)) (rhs parseState 2),hpa1 } | BASE DOT atomicExprQualification { let arg1 = SynExpr.Ident(ident("base",rhs parseState 1)) $3 arg1 (lhs(parseState)) (rhs parseState 2),false } | QMARK nameop { SynExpr.LongIdent (true,[$2],rhs parseState 2),false } | atomicExpr QMARK dynamicArg { let arg1,hpa1 = $1 mkSynInfix (rhs parseState 2) (lhs(parseState)) arg1 "?" $3, hpa1 } | GLOBAL { SynExpr.Ident (ident(MangledGlobalName,rhs parseState 1)), false } | nameop { SynExpr.Ident ($1),false } | LBRACK listExprElements RBRACK { $2 (lhs(parseState)) false,false } | LBRACK listExprElements recover { reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnmatchedBracket()); $2 (rhs2 parseState 1 2) false, false } | LBRACK error RBRACK { // silent recovery SynExpr.ArrayOrList(false,[ ], lhs(parseState)),false } | atomicExprAfterType { $1,false } atomicExprQualification: | identOrOp { let idm = rhs parseState 1 (fun e lhsm dotm -> mkSynDot lhsm e $1) } | recover { (fun e lhsm dotm -> reportParseErrorAt dotm (FSComp.SR.parsMissingQualificationAfterDot()); // Include 'e' in the returned expression but throw it away SynExpr.DiscardAfterError(e,lhsm)) } | LPAREN COLON_COLON RPAREN DOT INT32 { (fun e lhsm dotm -> libraryOnlyError(lhs(parseState)); SynExpr.LibraryOnlyUnionCaseFieldGet (e,mkSynCaseName lhsm opNameCons,(fst $5),lhsm)) } | LPAREN typedSeqExpr RPAREN { (fun e lhsm dotm -> mlCompatWarning (FSComp.SR.parsParenFormIsForML()) (lhs(parseState)); mkSynDotParenGet lhsm e $2) } | LBRACK typedSeqExpr RBRACK { (fun e lhsm dotm -> mkSynDotBrackGet lhsm dotm e $2) } | LBRACK optRange RBRACK { (fun e lhsm dotm -> mkSynDotBrackSliceGet lhsm dotm e $2) } | LBRACK optRange COMMA optRange RBRACK %prec slice_comma { (fun e lhsm dotm -> mkSynDotBrackSlice2Get lhsm dotm e $2 $4) } | LBRACK optRange COMMA optRange COMMA optRange RBRACK %prec slice_comma { (fun e lhsm dotm -> mkSynDotBrackSlice3Get lhsm dotm e $2 $4 $6) } | LBRACK optRange COMMA optRange COMMA optRange COMMA optRange RBRACK %prec slice_comma { (fun e lhsm dotm -> mkSynDotBrackSlice4Get lhsm dotm e $2 $4 $6 $8) } optRange: | declExpr DOT_DOT declExpr { mkSynOptionalExpr (rhs parseState 1) (Some $1), mkSynOptionalExpr (rhs parseState 3) (Some $3) } | declExpr DOT_DOT { mkSynOptionalExpr (rhs parseState 1) (Some $1), mkSynOptionalExpr (rhs parseState 2) None } | DOT_DOT declExpr { mkSynOptionalExpr (rhs parseState 1) None, mkSynOptionalExpr (rhs parseState 2) (Some $2) } | STAR { mkSynOptionalExpr (rhs parseState 1) None, mkSynOptionalExpr (rhs parseState 1) None } /* the start et of atomicExprAfterType must not overlap with the valid postfix tokens of the type syntax, e.g. new List(...) */ atomicExprAfterType: | constant { SynExpr.Const ($1,$1.Range (lhs(parseState))) } | parenExpr { $1 } | braceExpr { $1 } | NULL { SynExpr.Null(lhs(parseState)) } | FALSE { SynExpr.Const(SynConst.Bool false,lhs(parseState)) } | TRUE { SynExpr.Const(SynConst.Bool true,lhs(parseState)) } | quoteExpr { $1 } | arrayExpr { $1 } | beginEndExpr { $1 } beginEndExpr: | BEGIN typedSeqExpr END { SynExpr.Paren($2,rhs2 parseState 1 3) } | BEGIN typedSeqExpr recover { reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnmatchedBegin()); $2 } | BEGIN error END { (* silent recovery *) arbExpr(parseState) } | BEGIN END { mkSynUnit (lhs(parseState)) } quoteExpr: | LQUOTE typedSeqExpr RQUOTE { if $1 <> $3 then reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsMismatchedQuote(fst $1)); (SynExpr.Quote(mkSynIdGet (lhs(parseState)) (CompileOpName (fst $1)), snd $1, $2,lhs(parseState))) } | LQUOTE typedSeqExpr recover { reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnmatched(fst $1)); // Note: deliberately use this smaller range for the expression: see FSHarp 1.0 bug 3225 let mExpr = rhs2 parseState 1 1 SynExpr.Quote(mkSynIdGet (lhs(parseState)) (CompileOpName (fst $1)),snd $1, $2,mExpr) } | LQUOTE error RQUOTE { (* silent recovery *) SynExpr.Quote(mkSynIdGet (lhs(parseState)) (CompileOpName (fst $1)),snd $1, arbExpr(parseState),lhs(parseState)) } arrayExpr: | LBRACK_BAR listExprElements BAR_RBRACK { $2 (lhs(parseState)) true } | LBRACK_BAR listExprElements recover { reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnmatchedBracketBar()); $2 (rhs2 parseState 1 2) true} | LBRACK_BAR error BAR_RBRACK { (* silent recovery *) SynExpr.ArrayOrList(true,[ ], lhs(parseState)) } parenExpr: | LPAREN parenExprBody RPAREN { $2 (rhs2 parseState 1 3) } | LPAREN parenExprBody recover { reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnmatchedParen()); let lhsm = rhs2 parseState 1 2 in SynExpr.Paren($2 lhsm,lhsm) } | LPAREN error RPAREN { (* silent recovery *) arbExpr(parseState) } | LPAREN recover %prec prec_atomexpr_lparen_error { reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnmatchedParen()); arbExpr(parseState) } parenExprBody: | { (fun m -> SynExpr.Const(SynConst.Unit,m)) } | TYPE typ { (fun m -> SynExpr.DeprecatedTypeOf($2,m)) } | staticallyKnownHeadTypars COLON LPAREN classMemberSpfn RPAREN typedSeqExpr { (fun m -> SynExpr.TraitCall($1,$4,$6,m)) } /* disambiguate: x $a.id(x) */ | typedSeqExpr { (fun m -> SynExpr.Paren($1,m)) } | inlineAssemblyExpr { $1 } staticallyKnownHeadTypars: | staticallyKnownHeadTypar { [$1] } | LPAREN staticallyKnownHeadTypar OR staticallyKnownHeadTypar RPAREN { [$2 ; $4 ] } braceExpr: | LBRACE braceExprBody RBRACE { $2 (rhs2 parseState 1 3) } | LBRACE braceExprBody recover { reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnmatchedBrace()) ; $2 (rhs2 parseState 1 2) } | LBRACE error RBRACE { (* silent recovery *) arbExpr(parseState) } braceExprBody: | recdExpr { (fun m -> let a,b,c = $1 in SynExpr.Record(a,b,c,m)) } | objExpr { $1 } | monadicExprInitial { $1 false } listExprElements: | monadicExprInitial { (fun lhsm isArray -> SynExpr.ArrayOrListOfSeqExpr(isArray, $1 true lhsm,lhsm)) } | { (fun lhsm isArray -> SynExpr.ArrayOrList(isArray,[ ], lhsm)) } monadicExprInitial: | seqExpr { (fun isArrayOrList lhsm -> SynExpr.CompExpr(isArrayOrList,ref(isArrayOrList),$1,lhsm)) } | rangeSequenceExpr { $1 } rangeSequenceExpr: | declExpr DOT_DOT declExpr { (fun _ m -> mkSynInfix m m $1 ".." $3) } | declExpr DOT_DOT declExpr DOT_DOT declExpr { (fun _ m -> mkSynTrifix m ".. .." $1 $3 $5) } /* Allow a naked yield (no "yield" or "return" or "->") immediately after a "->" */ /* Allow a naked yield (no "yield!" or "return!" or "->>") immediately after a "->>" */ /* In both cases multiple 'for' and 'when' bindings can precede */ monadicSingleLineQualifiersThenArrowThenExprR: | RARROW typedSeqExprBlockR { (fun m -> SynExpr.YieldOrReturn((true,false),$2,m)) } forLoopBinder: | parenPattern IN declExpr { ($1, $3) } | parenPattern IN rangeSequenceExpr { ($1, $3 false (rhs parseState 3)) } | parenPattern IN recover { if not $3 then reportParseErrorAt (rhs parseState 3) (FSComp.SR.parsUnexpectedEndOfFile()); ($1, arbExpr(parseState)) } forLoopRange: | parenPattern EQUALS declExpr forLoopDirection declExpr { idOfPat (rhs parseState 1) $1,$3,$4,$5 } inlineAssemblyExpr: | HASH stringOrKeywordString opt_inlineAssemblyTypeArg opt_curriedArgExprs opt_inlineAssemblyReturnTypes opt_HASH { libraryOnlyWarning (lhs(parseState)); let s,sm = $2,rhs parseState 2 (fun m -> SynExpr.LibraryOnlyILAssembly (ParseAssemblyCodeInstructions s sm,$3,List.rev $4,$5,m)) } opt_curriedArgExprs: | opt_curriedArgExprs argExpr %prec expr_args { $2 :: $1 } | { [] } opt_atomicExprAfterType: | { None } | atomicExprAfterType { Some($1) } opt_inlineAssemblyTypeArg: | { [] } | TYPE LPAREN typ RPAREN { [$3] } opt_inlineAssemblyReturnTypes: | { [] } | COLON typ { [$2] } | COLON LPAREN RPAREN { [] } recdExpr: | { (None,None, []) } | INHERIT appTypeNonAtomicDeprecated opt_HIGH_PRECEDENCE_APP opt_atomicExprAfterType recdExprBindings opt_seps { let arg = match $4 with None -> mkSynUnit (lhs(parseState)) | Some e -> e (Some($2,arg,rhs2 parseState 2 4),None, $5) } | appExpr EQUALS declExprBlock recdExprBindings opt_seps { match $1 with | LongOrSingleIdent(false,v,m) -> (None,None, (List.frontAndBack v,$3) :: List.rev $4) | _ -> raiseParseErrorAt (rhs parseState 2) (FSComp.SR.parsFieldBinding()) } | appExpr WITH path EQUALS declExprBlock recdExprBindings opt_seps { (None,Some $1,(List.frontAndBack $3,$5):: List.rev $6) } | appExpr OWITH path EQUALS declExprBlock recdExprBindings opt_seps OEND { (None,Some $1,(List.frontAndBack $3,$5):: List.rev $6) } recdExprBindings: | recdExprBindings seps path EQUALS declExprBlock { (List.frontAndBack $3,$5) :: $1 } | { [] } /* There is a minor conflict between seq { new ty() } // sequence expression with one very odd 'action' expression and { new ty() } // object expression with no interfaces and no overrides Hence we make sure the latter is not permitted by the grammar */ objExpr: | objExprBaseCall objExprBindings opt_OBLOCKSEP opt_objExprInterfaces { (fun m -> let (a,b) = $1 in SynExpr.ObjExpr(a,b,$2,$4, m)) } | objExprBaseCall opt_OBLOCKSEP objExprInterfaces { (fun m -> let (a,b) = $1 in SynExpr.ObjExpr(a,b,[],$3, m)) } | NEW appTypeNonAtomicDeprecated { (fun m -> let (a,b) = $2,None in SynExpr.ObjExpr(a,b,[],[], m)) } objExprBaseCall: | NEW appTypeNonAtomicDeprecated opt_HIGH_PRECEDENCE_APP atomicExprAfterType baseSpec { ($2, Some($4,Some($5))) } | NEW appTypeNonAtomicDeprecated opt_HIGH_PRECEDENCE_APP atomicExprAfterType { ($2, Some($4,None)) } | NEW appTypeNonAtomicDeprecated { $2,None } opt_objExprBindings: | objExprBindings { $1 } | { [] } objExprBindings: | WITH localBindings { let letm = (rhs parseState 1) ($2 [] None letm) } | OWITH localBindings OEND { let letm = (rhs parseState 1) ($2 [] None letm) } | WITH objectImplementationBlock opt_declEnd { $2 |> (List.choose (function | SynMemberDefn.Member(b,m) -> Some b | SynMemberDefn.ImplicitInherit (_, _, _, m) | SynMemberDefn.ImplicitCtor (_,_,_, _, m) | SynMemberDefn.LetBindings(_,_,_,m) | SynMemberDefn.AbstractSlot(_,_,m) | SynMemberDefn.Interface(_,_,m) | SynMemberDefn.Inherit(_,_,m) | SynMemberDefn.ValField(_,m) | SynMemberDefn.Open(_,m) | SynMemberDefn.NestedType(_,_,m) -> errorR(Error(FSComp.SR.parsMemberIllegalInObjectImplementation(),m)); None)) } objExprInterfaces: | objExprInterface opt_objExprInterfaces { $1 :: $2 } opt_objExprInterfaces: | %prec prec_interfaces_prefix { [] } | objExprInterface opt_objExprInterfaces { $1 :: $2 } | error opt_objExprInterfaces { (* silent recovery *) $2 } objExprInterface: | interfaceMember appType opt_objExprBindings opt_declEnd opt_OBLOCKSEP { InterfaceImpl($2, $3, lhs(parseState)) } forLoopDirection: | TO { true } | DOWNTO { false } anonLambdaExpr: | FUN atomicPatterns RARROW typedSeqExprBlock { let mAll = unionRanges (rhs parseState 1) $4.Range mkSynFunMatchLambdas false mAll $2 $4 } | FUN atomicPatterns RARROW error { let mAll = rhs2 parseState 1 3 mkSynFunMatchLambdas false mAll $2 (arbExpr(parseState)) } | OFUN atomicPatterns RARROW typedSeqExprBlockR OEND { let mAll = unionRanges (rhs parseState 1) $4.Range mkSynFunMatchLambdas false mAll $2 $4 } | OFUN atomicPatterns RARROW ORIGHT_BLOCK_END OEND { reportParseErrorAt (rhs2 parseState 1 3) (FSComp.SR.parsMissingFunctionBody()) ; mkSynFunMatchLambdas false (rhs2 parseState 1 3) $2 (arbExpr(parseState)) } | OFUN atomicPatterns RARROW recover { reportParseErrorAt (rhs2 parseState 1 3) (FSComp.SR.parsMissingFunctionBody()) ; mkSynFunMatchLambdas false (rhs2 parseState 1 3) $2 (arbExpr(parseState)) } anonMatchingExpr: | FUNCTION opt_bar patternClauses %prec expr_function { let clauses,mLast = $3 let mAll = unionRanges (rhs parseState 1) mLast mkSynMatchLambda(false,false,mAll,clauses,NoSequencePointAtInvisibleBinding) } | OFUNCTION opt_bar patternClauses OEND %prec expr_function { let clauses,mLast = $3 let mAll = unionRanges (rhs parseState 1) mLast mkSynMatchLambda(false,false,mAll,clauses,NoSequencePointAtInvisibleBinding) } | OFUNCTION opt_bar patternClauses error OEND %prec expr_function { reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsErrorInFunctionBlock()); let clauses,mLast = $3 let mAll = unionRanges (rhs parseState 1) mLast mkSynMatchLambda(false,false,mAll,clauses,NoSequencePointAtInvisibleBinding) } /*--------------------------------------------------------------------------*/ /* TYPE ALGEBRA */ typeWithTypeConstraints: | typ %prec prec_wheretyp_prefix { $1 } | typ WHEN typeConstraints { SynType.WithGlobalConstraints($1, List.rev $3,lhs(parseState)) } topTypeWithTypeConstraints: | topType { $1 } | topType WHEN typeConstraints { let ty,arity = $1 // nb. it doesn't matter where the constraints go in the structure of the type. SynType.WithGlobalConstraints(ty,List.rev $3,lhs(parseState)), arity } opt_topReturnTypeWithTypeConstraints: | { None } | COLON topTypeWithTypeConstraints { let ty,arity = $2 let arity = (match arity with SynValInfo([],rmdata)-> rmdata | _ -> SynInfo.unnamedRetVal) Some ((ty,arity),rhs parseState 2) } topType: | topTupleType RARROW topType { let dty,dmdata= $1 let rty,(SynValInfo(dmdatas,rmdata)) = $3 SynType.Fun(dty,rty,lhs(parseState)), (SynValInfo(dmdata::dmdatas, rmdata)) } | topTupleType { let ty,rmdata = $1 in ty, (SynValInfo([],(match rmdata with [md] -> md | _ -> SynInfo.unnamedRetVal))) } topTupleType: | topAppType STAR topTupleTypeElements { let ty,mdata = $1 in let tys,mdatas = List.unzip $3 in (SynType.Tuple(List.map (fun ty -> (false,ty)) (ty ::tys), lhs(parseState))),(mdata :: mdatas) } | topAppType { let ty,mdata = $1 in ty,[mdata] } topTupleTypeElements: | topAppType STAR topTupleTypeElements { $1 :: $3 } | topAppType %prec prec_toptuptyptail_prefix { [$1] } topAppType: | attributes appType COLON appType { match $2 with | SynType.LongIdent([id],_) -> $4,SynArgInfo($1,false,Some id) | _ -> raiseParseErrorAt (rhs parseState 2) (FSComp.SR.parsSyntaxErrorInLabeledType()) } | attributes QMARK ident COLON appType { $5,SynArgInfo($1,true,Some $3) } | attributes appType { ($2,SynArgInfo($1,false,None)) } | appType COLON appType { match $1 with | SynType.LongIdent([id],_) -> $3,SynArgInfo([],false,Some id) | _ -> raiseParseErrorAt (rhs parseState 2) (FSComp.SR.parsSyntaxErrorInLabeledType()) } | QMARK ident COLON appType { $4,SynArgInfo([],true,Some $2) } | appType { $1,SynArgInfo([],false,None) } /* Any tokens in this grammar must be added to the lex filter rule 'peekAdjacentTypars' */ /* See the F# specification "Lexical analysis of type applications and type parameter definitions" */ typ: | tupleType RARROW typ { SynType.Fun($1,$3,lhs(parseState)) } | tupleType %prec prec_typ_prefix { $1 } tupleType: | appType STAR tupleOrQuotTypeElements { SynType.Tuple((false,$1) :: $3,lhs(parseState)) } | INFIX_STAR_DIV_MOD_OP tupleOrQuotTypeElements { if $1 <> "/" then reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnexpectedInfixOperator()); SynType.Tuple((true, SynType.MeasureOne (lhs(parseState))):: $2, lhs(parseState)) } | appType INFIX_STAR_DIV_MOD_OP tupleOrQuotTypeElements { if $2 <> "/" then reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnexpectedInfixOperator()); SynType.Tuple((true,$1) :: $3, lhs(parseState)) } | appType %prec prec_tuptyp_prefix { $1 } tupleOrQuotTypeElements: | appType STAR tupleOrQuotTypeElements { (false,$1) :: $3 } | appType INFIX_STAR_DIV_MOD_OP tupleOrQuotTypeElements { if $2 <> "/" then reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnexpectedInfixOperator()); (true,$1) :: $3 } | appType %prec prec_tuptyptail_prefix { [(false,$1)] } tupleTypeElements: | appType STAR tupleTypeElements { $1 :: $3 } | appType %prec prec_tuptyptail_prefix { [$1] } appTypeCon: | path %prec prec_atomtyp_path { SynType.LongIdent($1, lhs(parseState)) } | typar { SynType.Var($1, lhs(parseState)) } appTypeConPower: | appTypeCon INFIX_AT_HAT_OP INT32 { if $2 <> "^" && $2 <> "^-" then reportParseErrorAt (rhs parseState 2) (FSComp.SR.parsUnexpectedInfixOperator()); if $2 = "^-" then SynType.MeasurePower($1, -(fst $3), lhs(parseState)) else SynType.MeasurePower($1, fst $3, lhs(parseState)) } | appTypeCon { $1 } appType: | appType arrayTypeSuffix { SynType.Array($2,$1,lhs(parseState)) } | appType HIGH_PRECEDENCE_BRACK_APP arrayTypeSuffix /* only HPA for "name[]" allowed here */ { SynType.Array($3,$1,lhs(parseState)) } | appType appTypeConPower { SynType.App($2,[$1],true,lhs(parseState)) } | LPAREN appTypePrexifArguments RPAREN appTypeConPower { mlCompatWarning (FSComp.SR.parsMultiArgumentGenericTypeFormDeprecated()) (lhs(parseState)); SynType.App($4,$2, true, lhs(parseState)) } | powerType { $1 } | typar COLON_GREATER typ { let tp,typ = $1,$3 let m = lhs(parseState) SynType.WithGlobalConstraints(SynType.Var (tp, rhs parseState 1), [WhereTyparSubtypeOfType(tp,typ,m)],m) } | UNDERSCORE COLON_GREATER typ %prec COLON_GREATER { SynType.HashConstraint($3, lhs(parseState)) } arrayTypeSuffix: | LBRACK RBRACK { 1 } | LBRACK COMMA RBRACK { 2 } | LBRACK COMMA COMMA RBRACK { 3 } | LBRACK COMMA COMMA COMMA RBRACK { 4 } appTypePrexifArguments: | typ COMMA typ typeListElements { $1 :: $3 :: List.rev $4 } typeListElements: | typeListElements COMMA typ { $3 :: $1 } | { [] } powerType: | atomType { $1 } | atomType INFIX_AT_HAT_OP INT32 { if $2 <> "^" && $2 <> "^-" then reportParseErrorAt (rhs parseState 2) (FSComp.SR.parsUnexpectedInfixOperator()); if $2 = "^-" then SynType.MeasurePower($1, - (fst $3), lhs(parseState)) else SynType.MeasurePower($1, fst $3, lhs(parseState)) } | atomType INFIX_AT_HAT_OP MINUS INT32 { if $2 <> "^" then reportParseErrorAt (rhs parseState 2) (FSComp.SR.parsUnexpectedInfixOperator()); SynType.MeasurePower($1, - (fst $4), lhs(parseState)) } /* Like appType but gives a deprecation warning if a non-atomic type is used */ appTypeNonAtomicDeprecated: | appType arrayTypeSuffix { deprecatedWithError (FSComp.SR.parsNonAtomicType()) (lhs parseState); SynType.Array($2,$1,lhs(parseState)) } | appType HIGH_PRECEDENCE_BRACK_APP arrayTypeSuffix /* only HPA for "name[]" allowed here */ { deprecatedWithError (FSComp.SR.parsNonAtomicType()) (lhs parseState); SynType.Array($3,$1,lhs(parseState)) } | appType appTypeConPower { deprecatedWithError (FSComp.SR.parsNonAtomicType()) (lhs parseState); SynType.App($2,[$1],true,lhs(parseState)) } | LPAREN appTypePrexifArguments RPAREN appTypeConPower { mlCompatWarning (FSComp.SR.parsMultiArgumentGenericTypeFormDeprecated()) (lhs(parseState)); SynType.App($4,$2, true, lhs(parseState)) } | powerTypeNonAtomicDeprecated { $1 } | typar COLON_GREATER typ { deprecatedWithError (FSComp.SR.parsNonAtomicType()) (lhs parseState); let tp,typ = $1,$3 let m = lhs(parseState) SynType.WithGlobalConstraints(SynType.Var (tp, rhs parseState 1), [WhereTyparSubtypeOfType(tp,typ,m)],m) } | UNDERSCORE COLON_GREATER typ %prec COLON_GREATER { deprecatedWithError (FSComp.SR.parsNonAtomicType()) (lhs parseState); SynType.HashConstraint($3, lhs(parseState)) } /* Like powerType but gives a deprecation warning if a non-atomic type is used */ powerTypeNonAtomicDeprecated: | atomType { $1 } | atomType INFIX_AT_HAT_OP INT32 { if $2 <> "^" && $2 <> "^-" then reportParseErrorAt (rhs parseState 2) (FSComp.SR.parsUnexpectedInfixOperator()); deprecatedWithError (FSComp.SR.parsNonAtomicType()) (lhs parseState); if $2 = "^-" then SynType.MeasurePower($1, - (fst $3), lhs(parseState)) else SynType.MeasurePower($1, fst $3, lhs(parseState)) } | atomType INFIX_AT_HAT_OP MINUS INT32 { if $2 <> "^" then reportParseErrorAt (rhs parseState 2) (FSComp.SR.parsUnexpectedInfixOperator()); deprecatedWithError (FSComp.SR.parsNonAtomicType()) (lhs parseState); SynType.MeasurePower($1, - (fst $4), lhs(parseState)) } /* Any tokens in this grammar must be added to the lex filter rule 'peekAdjacentTypars' */ /* See the F# specification "Lexical analysis of type applications and type parameter definitions" */ atomType: | HASH atomType { SynType.HashConstraint($2, lhs(parseState)) } | appTypeConPower %prec prec_atomtyp_path { $1 } | UNDERSCORE { SynType.Anon (lhs(parseState)) } | LPAREN typ RPAREN { $2 } | LPAREN typ recover { reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnmatchedParen()) ; $2 } | INT32 { if fst $1 <> 1 then reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnexpectedIntegerLiteral()); SynType.MeasureOne (lhs(parseState)) } | LPAREN error RPAREN { (* silent recovery *) SynType.Anon (lhs(parseState)) } | appTypeCon typeArgsNoHpaDeprecated %prec prec_atomtyp_path { SynType.App($1,$2,false,lhs(parseState)) } | atomType DOT path %prec prec_atomtyp_get_path { SynType.LongIdentApp($1,$3,[],lhs(parseState)) } | atomType DOT path typeArgsNoHpaDeprecated %prec prec_atomtyp_get_path { SynType.LongIdentApp($1,$3,$4,lhs(parseState)) } typeArgsNoHpaDeprecated: | typeArgsActual { warning(Error(FSComp.SR.parsNonAdjacentTyargs(),rhs parseState 1)); $1 } | HIGH_PRECEDENCE_TYAPP typeArgsActual { $2 } typeArgsActual: | LESS GREATER { [] } | LESS typ GREATER { [$2] } | LESS typ COMMA typ typeListElements GREATER { $2 :: $4 :: List.rev $5 } measureTypeArg: | LESS measureTypeExpr GREATER { $2 } | LESS UNDERSCORE GREATER { SynMeasure.Anon (lhs(parseState)) } measureTypeAtom: | path { SynMeasure.Named($1, lhs(parseState)) } | typar { SynMeasure.Var($1, lhs(parseState)) } | LPAREN measureTypeExpr RPAREN { $2 } measureTypePower: | measureTypeAtom { $1 } | measureTypeAtom INFIX_AT_HAT_OP INT32 { if $2 <> "^" && $2 <> "^-" then reportParseErrorAt (rhs parseState 2) (FSComp.SR.parsUnexpectedOperatorForUnitOfMeasure()); if $2 = "^-" then SynMeasure.Power($1, - (fst $3), lhs(parseState)) else SynMeasure.Power($1, fst $3, lhs(parseState)) } | measureTypeAtom INFIX_AT_HAT_OP MINUS INT32 { if $2 <> "^" then reportParseErrorAt (rhs parseState 2) (FSComp.SR.parsUnexpectedOperatorForUnitOfMeasure()); SynMeasure.Power($1, - (fst $4), lhs(parseState)) } | INT32 { if fst $1 <> 1 then reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnexpectedIntegerLiteralForUnitOfMeasure()); SynMeasure.One } measureTypeSeq: | measureTypePower { [$1] } | measureTypePower measureTypeSeq { $1 :: $2 } measureTypeExpr: | measureTypeSeq { SynMeasure.Seq($1, lhs(parseState)) } | measureTypeExpr STAR measureTypeExpr { SynMeasure.Product($1, $3, lhs(parseState)) } | measureTypeExpr INFIX_STAR_DIV_MOD_OP measureTypeExpr { if $2 <> "*" && $2 <> "/" then reportParseErrorAt (rhs parseState 2) (FSComp.SR.parsUnexpectedOperatorForUnitOfMeasure()); if $2 = "*" then SynMeasure.Product($1, $3, lhs(parseState)) else SynMeasure.Divide($1, $3, lhs(parseState)) } | INFIX_STAR_DIV_MOD_OP measureTypeExpr { if $1 <> "/" then reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnexpectedOperatorForUnitOfMeasure()); SynMeasure.Divide(SynMeasure.One, $2, lhs(parseState)) } typar: | QUOTE ident { let id = mkSynId (lhs(parseState)) ($2).idText Typar(id ,NoStaticReq,false) } | staticallyKnownHeadTypar { $1 } staticallyKnownHeadTypar: | INFIX_AT_HAT_OP ident { if $1 <> "^" then reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnexpectedTypeParameter()); Typar($2,HeadTypeStaticReq,false) } ident: | IDENT { ident($1,rhs parseState 1) } path: | GLOBAL { [ident(MangledGlobalName,rhs parseState 1)] } | ident { [$1] } | path DOT ident { (* silent recovery *) $1 @ [$3] } | path DOT error { (* silent recovery *) $1 } opName: | LPAREN operatorName RPAREN { ident(CompileOpName $2,rhs parseState 2) } | LPAREN_STAR_RPAREN { ident(CompileOpName "*",rhs parseState 1) } /* active pattern value names */ | LPAREN barNames BAR RPAREN { let text = ("|"^String.concat "|" (List.rev $2) ^ "|") ident(text,rhs2 parseState 2 3) } | LPAREN barNames BAR UNDERSCORE BAR RPAREN { let text = ("|"^String.concat "|" (List.rev $2) ^ "|_|" ) ident(text,rhs2 parseState 2 5) } operatorName: | PREFIX_OP { if not (IsValidPrefixOperatorDefinitionName $1) then reportParseErrorAt (lhs(parseState)) (FSComp.SR.parsInvalidPrefixOperatorDefinition()); $1 } | INFIX_STAR_STAR_OP { $1 } | INFIX_COMPARE_OP { $1 } | INFIX_AT_HAT_OP { $1 } | INFIX_BAR_OP { $1 } | INFIX_AMP_OP { $1 } | PLUS_MINUS_OP { $1 } | INFIX_STAR_DIV_MOD_OP { $1 } | DOLLAR { "$" } | ADJACENT_PREFIX_OP { $1 } | MINUS { "-" } | STAR { "*" } | EQUALS { "=" } | OR { "or" } | LESS { "<" } | GREATER { ">" } | QMARK { "?" } | AMP { "&" } | AMP_AMP { "&&" } | BAR_BAR { "||" } | COLON_EQUALS { ":=" } | FUNKY_OPERATOR_NAME { if $1 <> ".[]" && $1 <> ".()" && $1 <> ".()<-" then deprecatedOperator (lhs(parseState)); $1 } | PERCENT_OP { $1 } | DOT_DOT { (* deprecatedOperator (lhs(parseState)); *) ".." } | DOT_DOT DOT_DOT { (* deprecatedOperator (lhs(parseState)); *) ".. .." } | LQUOTE RQUOTE { if $1 <> $2 then reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsMismatchedQuotationName(fst $1)); fst $1 } barName: | IDENT { if not (String.isUpper $1) then reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsActivePatternCaseMustBeginWithUpperCase()); $1 } barNames: | BAR barName { [$2] } | barNames BAR barName { $3 :: $1 } identOrOp: | ident { $1 } | opName { $1 } /* path ending in an op */ /* note, only used in atomicPatternLongIdent */ pathOp: | ident { [$1] } | opName { [$1] } | ident DOT pathOp { $1 :: $3 } | ident DOT error { (* silent recovery *) [$1] } /* nameop is identOrOp not used as part of a path */ nameop: | identOrOp { $1 } topSeparator: | SEMICOLON { } | SEMICOLON_SEMICOLON { } | OBLOCKSEP { } topSeparators: | topSeparator { } | topSeparator topSeparators { } interactiveSeparator: | SEMICOLON { } | OBLOCKSEP { } interactiveSeparators: | interactiveSeparator { } | interactiveSeparator interactiveSeparators { } opt_interactiveSeparators: | interactiveSeparator opt_interactiveSeparators { } | { } opt_topSeparators: | topSeparator opt_topSeparators { } | { } seps: | OBLOCKSEP { } | SEMICOLON { } | OBLOCKSEP SEMICOLON { } | SEMICOLON OBLOCKSEP { } /* An 'end' that's optional only in #light, where an ODECLEND gets inserted, and explicit 'end's get converted to OEND */ declEnd: | ODECLEND { } | OEND { } | END {} /* An 'end' that's optional in both #light and #heavy */ opt_declEnd: | ODECLEND {} | OEND { } | END {} | {} opt_ODECLEND: | ODECLEND { } | { } deprecated_opt_equals: | EQUALS { deprecatedWithError (FSComp.SR.parsNoEqualShouldFollowNamespace()) (lhs(parseState)) } | { } opt_OBLOCKSEP: | OBLOCKSEP { } | { } opt_seps: | seps { } | { } opt_rec: | REC { true } | { false } opt_bar: | BAR { } | { } opt_inline: | INLINE { true } | { false } opt_mutable: | MUTABLE { true } | { false } doToken: | DO { } | ODO { } doneDeclEnd: | DONE { } | ODECLEND { } /* DONE gets thrown away by the lexfilter in favour of ODECLEND */ structOrBegin: | STRUCT { mlCompatWarning (FSComp.SR.parsSyntaxModuleStructEndDeprecated()) (lhs(parseState)); } | BEGIN { } sigOrBegin: | SIG { mlCompatWarning (FSComp.SR.parsSyntaxModuleSigEndDeprecated()) (lhs(parseState)); } | BEGIN { } colonOrEquals: | COLON { mlCompatWarning (FSComp.SR.parsSyntaxModuleSigEndDeprecated()) (lhs(parseState)); } | EQUALS { } opt_HASH: | HASH {} opt_HIGH_PRECEDENCE_APP: | HIGH_PRECEDENCE_BRACK_APP { } | HIGH_PRECEDENCE_PAREN_APP { } | { } opt_HIGH_PRECEDENCE_TYAPP: | HIGH_PRECEDENCE_TYAPP { } | { }