// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. %{ #nowarn "1182" // generated code has lots of unused "parseState" open System open Internal.Utilities open Internal.Utilities.Text.Parsing open Internal.Utilities.Library open Internal.Utilities.Library.Extras open FSharp.Compiler open FSharp.Compiler.AbstractIL open FSharp.Compiler.AbstractIL open FSharp.Compiler.DiagnosticsLogger open FSharp.Compiler.Features open FSharp.Compiler.ParseHelpers open FSharp.Compiler.Syntax open FSharp.Compiler.SyntaxTrivia open FSharp.Compiler.Syntax.PrettyNaming open FSharp.Compiler.SyntaxTreeOps open FSharp.Compiler.Text.Position open FSharp.Compiler.Text.Range open FSharp.Compiler.Xml // 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, ctxt.ParseState.LexBuffer.LexemeRange))) %} // Producing these changes the lex state, e.g. string --> token, or nesting level of braces in interpolated strings %token BYTEARRAY %token STRING %token INTERP_STRING_BEGIN_END %token INTERP_STRING_BEGIN_PART %token INTERP_STRING_PART %token INTERP_STRING_END %token LBRACE RBRACE %token KEYWORD_STRING // Like __SOURCE_DIRECTORY__ %token IDENT %token HASH_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 NATIVEINT %token UINT8 %token UINT16 %token UINT32 %token UINT64 %token UNATIVEINT %token IEEE32 %token IEEE64 %token CHAR %token DECIMAL %token <(string * string)> BIGNUM %token LET YIELD YIELD_BANG AND_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 DOT_DOT_HAT %token EXCEPTION FALSE FOR FUN FUNCTION IF IN JOIN_IN FINALLY DO_BANG %token LAZY OLAZY MATCH MATCH_BANG MUTABLE NEW OF %token OPEN OR REC THEN TO TRUE TRY TYPE VAL INLINE INTERFACE INSTANCE CONST %token WHEN WHILE WITH HASH AMP AMP_AMP QUOTE LPAREN RPAREN RPAREN_COMING_SOON RPAREN_IS_HERE 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 LBRACE_BAR LBRACK_LESS %token BAR_RBRACK BAR_RBRACE UNDERSCORE %token BAR RBRACK RBRACE_COMING_SOON RBRACE_IS_HERE MINUS DOLLAR %token GREATER_RBRACK STRUCT SIG %token STATIC MEMBER CLASS ABSTRACT OVERRIDE DEFAULT CONSTRUCTOR INHERIT %token EXTERN VOID PUBLIC PRIVATE INTERNAL GLOBAL /* for parser 'escape hatch' out of expression context without consuming the 'recover' token */ %token TYPE_COMING_SOON TYPE_IS_HERE MODULE_COMING_SOON MODULE_IS_HERE /* 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 OAND_BANG /* LexFilter #light converts 'AND_BANG' tokens to 'OAND_BANG' 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 */ /* REVIEW: merge OEND, ODECLEND, OBLOCKEND and ORIGHT_BLOCK_END into one token */ %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 OBLOCKEND_COMING_SOON OBLOCKEND_IS_HERE /* LexFilter #light inserts when closing CtxtSeqBlock(_, _, AddBlockEnd) */ %token OINTERFACE_MEMBER /* inserted for non-paranthetical use of 'INTERFACE', i.e. not INTERFACE/END */ %token FIXED %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 typedSequentialExprEOF typEOF %type typedSequentialExprEOF %type implementationFile %type signatureFile %type interaction %type ident %type typ typEOF %type tyconSpfnList %type atomicPatsOrNamePatPairs %type atomicPatterns %type patternResult %type declExpr %type minusExpr %type appExpr %type argExpr %type declExprBlock %type headBindingPattern %type atomicExprAfterType %type typedSequentialExprBlock %type atomicExpr %type tupleExpr %type tyconDefnOrSpfnSimpleRepr %type list> unionTypeRepr %type tyconDefnAugmentation %type exconDefn %type exconCore %type moduleDefnsOrExprPossiblyEmptyOrBlock %type path %type pathOp /* LESS GREATER parsedOk typeArgs m for each mWhole */ %type typeArgsActual /* LESS GREATER typeArgs m for each mWhole */ %type typeArgsNoHpaDeprecated %type typar /* 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 RPAREN_COMING_SOON RPAREN_IS_HERE %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 INTERP_STRING_BEGIN INTERP_STRING_PART INTERP_STRING_END %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 open_range_expr %left DOT_DOT /* for matrix.[1..2, 3..4] the ".." has higher precedence than expression "2 COMMA 3" */ %nonassoc interpolation_fill /* "...{3,N4}..." .NET style fill has higher precedence than "e COMMA e" */ %nonassoc paren_pat_colon %nonassoc paren_pat_attribs %left OR BAR_BAR JOIN_IN %left AND %left AND_BANG %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# Interactive */ /* 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. */ /* An interaction in F# Interactive */ interaction: | interactiveItemsTerminator { ParsedScriptInteraction.Definitions($1, lhs parseState) } | SEMICOLON { warning(Error(FSComp.SR.parsUnexpectedSemicolon(), rhs parseState 1)) ParsedScriptInteraction.Definitions([], lhs parseState) } | OBLOCKSEP { ParsedScriptInteraction.Definitions([], lhs parseState) } interactiveTerminator: | SEMICOLON_SEMICOLON {} | EOF { checkEndOfFileError $1 } /* An group of items considered to be one interaction, plus a terminator */ /* 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. */ /* REVIEW: limiting the input chunks until the next # directive can lead to */ /* discrepencies between whole-file type checking in FSI and FSC. */ interactiveItemsTerminator: | interactiveTerminator { [] } | interactiveDefns interactiveTerminator { $1 } | interactiveExpr interactiveTerminator { $1 } | interactiveHash interactiveTerminator { $1 } | interactiveDefns interactiveSeparators interactiveItemsTerminator { $1 @ $3 } | interactiveExpr interactiveSeparators interactiveItemsTerminator { $1 @ $3 } | interactiveHash interactiveSeparators interactiveItemsTerminator { $1 @ $3 } /* A group of definitions as part of in one interaction in F# Interactive */ interactiveDefns: | moduleDefn { $1 } | moduleDefn interactiveDefns { $1 @ $2 } /* An expression as part of one interaction in F# Interactive */ interactiveExpr: | opt_attributes opt_access declExpr { match $2 with | Some vis -> errorR(Error(FSComp.SR.parsUnexpectedVisibilityDeclaration(vis.ToString()), rhs parseState 3)) | _ -> () let attrDecls = if not (isNil $1) then [ SynModuleDecl.Attributes($1, rangeOfNonNilAttrs $1) ] else [] attrDecls @ [ mkSynExprDecl $3 ] } /* A #directive interaction in F# Interactive */ interactiveHash: | hashDirective { [SynModuleDecl.HashDirective($1, rhs parseState 1)] } /* One or more separators between interactions in F# Interactive */ interactiveSeparators: | interactiveSeparator { } | interactiveSeparator interactiveSeparators { } /* One separator between interactions in F# Interactive */ interactiveSeparator: | SEMICOLON { } | OBLOCKSEP { } /*--------------------------------------------------------------------------*/ /* #directives - used by both F# Interactive directives and #nowarn etc. */ /* A #directive in a module, namespace or an interaction */ hashDirective: | HASH IDENT hashDirectiveArgs { let m = match $3 with [] -> rhs2 parseState 1 2 | _ -> rhs2 parseState 1 3 ParsedHashDirective($2, $3, m) } /* The arguments to a #directive */ hashDirectiveArgs: | /* EMPTY */ { [] } | hashDirectiveArgs hashDirectiveArg { $1 @ [$2] } /* One argument to a #directive */ hashDirectiveArg: | string { let s, kind = $1 ParsedHashDirectiveArgument.String(s, kind, lhs parseState) } | sourceIdentifier { let c, v = $1 ParsedHashDirectiveArgument.SourceIdentifier(c, v, lhs parseState) } /*--------------------------------------------------------------------------*/ /* F# Language Proper - signature files */ /* The contents of a signature file */ 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 = ParsedSigFileFragment.AnonModule([], rhs parseState 1) ParsedSigFile([], [emptySigFileFrag]) } /* The start of a module declaration */ moduleIntro: | moduleKeyword opt_attributes opt_access opt_rec path { if not (isNil $2) then parseState.LexBuffer.CheckLanguageFeatureAndRecover LanguageFeature.AttributesToRightOfModuleKeyword (rhs parseState 4) let mModule = rhs parseState 1 mModule, $4, $5.LongIdent, $3, $2 } /* The start of a namespace declaration */ namespaceIntro: | NAMESPACE opt_rec path { let mNamespace = rhs parseState 1 mNamespace, $2, $3.LongIdent, grabXmlDoc(parseState, [], 1) } /* The contents of a signature file */ fileNamespaceSpecs: | fileModuleSpec { ParsedSigFile([], [ ($1 (None, false, [], PreXmlDoc.Empty)) ]) } | fileModuleSpec fileNamespaceSpecList { // If there are namespaces, the first fileModuleImpl may only contain # directives let decls = match ($1 (None, false, [], PreXmlDoc.Empty)) with | ParsedSigFileFragment.AnonModule(decls, m) -> decls | ParsedSigFileFragment.NamespaceFragment(decls = decls) -> decls | ParsedSigFileFragment.NamedModule(SynModuleOrNamespaceSig(range = 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: | namespaceIntro deprecated_opt_equals fileModuleSpec { let mNamespace, isRec, path, xml = $1 $3 (Some mNamespace, isRec, path, xml) } /* The single module declaration that can make up a signature file */ fileModuleSpec: | opt_attributes opt_access moduleIntro moduleSpfnsPossiblyEmptyBlock { if Option.isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(), rhs parseState 2)) let m2 = rhs parseState 3 let mDeclsAndAttrs = (List.map (fun (a: SynAttributeList) -> a.Range) $1) @ (List.map (fun (d: SynModuleSigDecl) -> d.Range) $4) let mModule, isRec, path2, vis, attribs2 = $3 let xmlDoc = grabXmlDoc(parseState, $1, 1) let m = (m2, mDeclsAndAttrs) ||> unionRangeWithListBy id |> unionRangeWithXmlDoc xmlDoc (fun (mNamespaceOpt, isRec2, path, _) -> if not (isNil path) then errorR(Error(FSComp.SR.parsNamespaceOrModuleNotBoth(), m2)) let lid = path@path2 let trivia: SynModuleOrNamespaceSigTrivia = { LeadingKeyword = SynModuleOrNamespaceLeadingKeyword.Module mModule } ParsedSigFileFragment.NamedModule(SynModuleOrNamespaceSig(lid, (isRec || isRec2), SynModuleOrNamespaceKind.NamedModule, $4, xmlDoc, $1 @ attribs2, vis, m, trivia))) } | moduleSpfnsPossiblyEmptyBlock { let m = (rhs parseState 1) (fun (mNamespaceOpt, isRec, path, xml) -> match path with | [] -> ParsedSigFileFragment.AnonModule($1, m) | _ -> let lastDeclRange = List.tryLast $1 |> Option.map (fun decl -> decl.Range) |> Option.defaultValue (rhs parseState 1) let m = mkRange lastDeclRange.FileName (lhs parseState).Start lastDeclRange.End xml.MarkAsInvalid() let trivia: SynModuleOrNamespaceSigTrivia = match mNamespaceOpt with | None -> { LeadingKeyword = SynModuleOrNamespaceLeadingKeyword.None } | Some mNamespace -> { LeadingKeyword = SynModuleOrNamespaceLeadingKeyword.Namespace mNamespace } ParsedSigFileFragment.NamespaceFragment(path, isRec, SynModuleOrNamespaceKind.DeclaredNamespace, $1, PreXmlDoc.Empty, [], m, trivia)) } 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 { [] } | /* EMPTY */ { [] } moduleSpfns: | moduleSpfn opt_topSeparators moduleSpfns { $1 :: $3 } | error topSeparators moduleSpfns { (* silent recovery *) $3 } | moduleSpfn opt_topSeparators { [$1] } moduleSpfn: | hashDirective { SynModuleSigDecl.HashDirective($1, rhs2 parseState 1 1) } | valSpfn { $1 } | opt_attributes opt_access moduleIntro colonOrEquals namedModuleAbbrevBlock { if Option.isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(), rhs parseState 2)) let mModule, isRec, path, vis, attribs2 = $3 if isRec then raiseParseErrorAt (rhs parseState 3) (FSComp.SR.parsInvalidUseOfRec()) if not (isSingleton path) then raiseParseErrorAt (rhs parseState 3) (FSComp.SR.parsModuleAbbreviationMustBeSimpleName()) if not (isNil $1) then raiseParseErrorAt (rhs parseState 1) (FSComp.SR.parsIgnoreAttributesOnModuleAbbreviation()) if not (isNil attribs2) then raiseParseErrorAt (rhs parseState 3) (FSComp.SR.parsIgnoreAttributesOnModuleAbbreviation()) match vis with | Some vis -> raiseParseErrorAt (rhs parseState 1) (FSComp.SR.parsIgnoreVisibilityOnModuleAbbreviationAlwaysPrivate(vis.ToString())) | _ -> let lid: SynLongIdent = $5 let m = unionRanges mModule lid.Range SynModuleSigDecl.ModuleAbbrev(List.head path, lid.LongIdent, m) } | opt_attributes opt_access moduleIntro colonOrEquals moduleSpecBlock { let mModule, isRec, path, vis, attribs2 = $3 let xmlDoc = grabXmlDoc(parseState, $1, 1) if not (isSingleton path) then raiseParseErrorAt (rhs parseState 3) (FSComp.SR.parsModuleDefnMustBeSimpleName()) if isRec then raiseParseErrorAt (rhs parseState 3) (FSComp.SR.parsInvalidUseOfRec()) let info = SynComponentInfo($1 @ attribs2, None, [], path, xmlDoc, false, vis, rhs parseState 3) if Option.isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(), rhs parseState 2)) let decls, mOptEnd = $5 let m = (rhs2 parseState 1 4, decls) ||> unionRangeWithListBy (fun (d: SynModuleSigDecl) -> d.Range) |> unionRangeWithXmlDoc xmlDoc let m = match mOptEnd with | None -> m | Some mEnd -> unionRanges m mEnd let trivia: SynModuleSigDeclNestedModuleTrivia = { ModuleKeyword = Some mModule; EqualsRange = $4 } SynModuleSigDecl.NestedModule(info, isRec, decls, m, trivia) } | opt_attributes opt_access moduleIntro error { let mModule, isRec, path, vis, attribs2 = $3 let xmlDoc = grabXmlDoc(parseState, $1, 1) if not (isSingleton path) then raiseParseErrorAt (rhs parseState 3) (FSComp.SR.parsModuleDefnMustBeSimpleName()) if isRec then raiseParseErrorAt (rhs parseState 3) (FSComp.SR.parsInvalidUseOfRec()) let info = SynComponentInfo($1 @ attribs2, None, [], path, xmlDoc, false, vis, rhs parseState 3) if Option.isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(), rhs parseState 2)) let mWhole = rhs2 parseState 1 3 |> unionRangeWithXmlDoc xmlDoc let trivia: SynModuleSigDeclNestedModuleTrivia = { ModuleKeyword = Some mModule; EqualsRange = None } SynModuleSigDecl.NestedModule(info, isRec, [], mWhole, trivia) } | opt_attributes opt_access typeKeyword tyconSpfn tyconSpfnList { if Option.isSome $2 then errorR (Error (FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier (), rhs parseState 2)) let leadingKeyword = SynTypeDefnLeadingKeyword.Type(rhs parseState 3) let (SynTypeDefnSig (SynComponentInfo (cas, a, cs, b, _xmlDoc, d, d2, d3), typeRepr, members, range, trivia)) = $4 leadingKeyword _xmlDoc.MarkAsInvalid() let attrs = $1 @ cas let xmlDoc = grabXmlDoc(parseState, $1, 1) let mDefn = (d3, attrs) ||> unionRangeWithListBy (fun (a: SynAttributeList) -> a.Range) |> unionRanges range |> unionRangeWithXmlDoc xmlDoc let tc = (SynTypeDefnSig(SynComponentInfo(attrs, a, cs, b, xmlDoc, d, d2, d3), typeRepr, members, mDefn, trivia)) let m = (mDefn, $5) ||> unionRangeWithListBy (fun (a: SynTypeDefnSig) -> a.Range) |> unionRanges (rhs parseState 3) SynModuleSigDecl.Types(tc :: $5, m) } | opt_attributes opt_access exconSpfn { if Option.isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(), rhs parseState 2)) let (SynExceptionSig(SynExceptionDefnRepr(cas, a, b, c, d, d2), withKeyword, members, range)) = $3 let xmlDoc = grabXmlDoc(parseState, $1, 1) let mDefnReprWithAttributes = (d2, $1) ||> unionRangeWithListBy (fun a -> a.Range) |> unionRangeWithXmlDoc xmlDoc let mWhole = (mDefnReprWithAttributes, members) ||> unionRangeWithListBy (fun (m: SynMemberSig) -> m.Range) let synExnDefn = SynExceptionSig(SynExceptionDefnRepr($1@cas, a, b, xmlDoc, d, mDefnReprWithAttributes), withKeyword, members, mWhole) SynModuleSigDecl.Exception(synExnDefn, mWhole) } | openDecl { SynModuleSigDecl.Open($1, (rhs parseState 1)) } valSpfn: | opt_attributes opt_access VAL opt_attributes opt_inline opt_mutable opt_access nameop opt_explicitValTyparDecls COLON topTypeWithTypeConstraints optLiteralValueSpfn { if Option.isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(), rhs parseState 2)) let attr1, attr2, isInline, isMutable, vis2, id, doc, explicitValTyparDecls, (ty, arity), (mEquals, konst: SynExpr option) = ($1), ($4), (Option.isSome $5), ($6), ($7), ($8), grabXmlDoc(parseState, $1, 1), ($9), ($11), ($12) if not (isNil attr2) then errorR(Deprecated(FSComp.SR.parsAttributesMustComeBeforeVal(), rhs parseState 4)) let m = rhs2 parseState 1 11 |> unionRangeWithXmlDoc doc |> fun m -> match konst with | None -> m | Some e -> unionRanges m e.Range let mVal = rhs parseState 3 let trivia: SynValSigTrivia = { LeadingKeyword = SynLeadingKeyword.Val mVal; InlineKeyword = $5; WithKeyword = None; EqualsRange = mEquals } let valSpfn = SynValSig((attr1@attr2), id, explicitValTyparDecls, ty, arity, isInline, isMutable, doc, vis2, konst, m, trivia) SynModuleSigDecl.Val(valSpfn, m) } /* The optional literal value on a literal specification in a signature */ optLiteralValueSpfn: | /* EMPTY */ { None, None } | EQUALS declExpr { let mEquals = rhs parseState 1 Some(mEquals), Some($2) } | EQUALS OBLOCKBEGIN declExpr oblockend opt_ODECLEND { let mEquals = rhs parseState 1 Some(mEquals), Some($3) } /* A block of definitions in a module in a signature file */ moduleSpecBlock: /* #light-syntax, with no sig/end or begin/end */ | OBLOCKBEGIN moduleSpfns oblockend { $2, None } /* #light-syntax, with sig/end or begin/end */ | OBLOCKBEGIN sigOrBegin moduleSpfnsPossiblyEmpty END oblockend { let mEnd = rhs parseState 4 $3, Some mEnd } /* non-#light-syntax, with sig/end or begin/end */ | sigOrBegin moduleSpfnsPossiblyEmpty END { let mEnd = rhs parseState 3 $2, Some mEnd } tyconSpfnList: | AND tyconSpfn tyconSpfnList { let xmlDoc = grabXmlDoc(parseState, [], 1) let tyconSpfn = let leadingKeyword = SynTypeDefnLeadingKeyword.And(rhs parseState 1) let (SynTypeDefnSig(componentInfo, typeRepr, members, range, trivia) as typeDefnSig) = $2 leadingKeyword let (SynComponentInfo(a, typars, c, lid, _xmlDoc, fixity, vis, mLongId)) = componentInfo if xmlDoc.IsEmpty then if _xmlDoc.IsEmpty then typeDefnSig else let range = unionRangeWithXmlDoc _xmlDoc range SynTypeDefnSig(componentInfo, typeRepr, members, range, trivia) else _xmlDoc.MarkAsInvalid() let range = unionRangeWithXmlDoc xmlDoc range let componentInfo = SynComponentInfo (a, typars, c, lid, xmlDoc, fixity, vis, mLongId) SynTypeDefnSig(componentInfo, typeRepr, members, range, trivia) tyconSpfn :: $3 } | { [] } /* A type definition in a signature */ tyconSpfn: | typeNameInfo EQUALS tyconSpfnRhsBlock { let mLhs = rhs parseState 1 let mEquals = rhs parseState 2 fun leadingKeyword -> $3 leadingKeyword mLhs $1 (Some mEquals) } | typeNameInfo opt_classSpfn { let mWithKwd, members = $2 let (SynComponentInfo(range = range)) = $1 let m = match members with | [] -> match mWithKwd with | None -> range | Some mWithKwd -> unionRanges range mWithKwd | decls -> (range, decls) ||> unionRangeWithListBy (fun (s: SynMemberSig) -> s.Range) fun leadingKeyword -> let trivia: SynTypeDefnSigTrivia = { LeadingKeyword = leadingKeyword; EqualsRange = None; WithKeyword = mWithKwd } SynTypeDefnSig($1, SynTypeDefnSigRepr.Simple(SynTypeDefnSimpleRepr.None m, m), members, m, trivia) } /* The right-hand-side of a type definition in a signature */ 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 leadingKeyword mLhs nameInfo mEquals -> let members = $4 @ (snd $5) $2 leadingKeyword mLhs nameInfo mEquals (checkForMultipleAugmentations m members (snd $7))) } | tyconSpfnRhs opt_classSpfn { let m = lhs parseState (fun leadingKeyword mLhs nameInfo mEquals -> let _, members = $2 $1 leadingKeyword mLhs nameInfo mEquals members) } /* The right-hand-side of a type definition in a signature */ tyconSpfnRhs: | tyconDefnOrSpfnSimpleRepr { (fun leadingKeyword mLhs nameInfo mEquals augmentation -> let declRange = unionRanges mLhs $1.Range let mWhole = (declRange, augmentation) ||> unionRangeWithListBy (fun (mem: SynMemberSig) -> mem.Range) let trivia: SynTypeDefnSigTrivia = { LeadingKeyword = leadingKeyword; WithKeyword = None; EqualsRange = mEquals } SynTypeDefnSig(nameInfo, SynTypeDefnSigRepr.Simple($1, $1.Range), augmentation, mWhole, trivia)) } | tyconClassSpfn { let needsCheck, (kind, decls) = $1 let objectModelRange = match decls with | [] -> lhs parseState | decls -> let start = mkSynRange parseState.ResultStartPosition parseState.ResultStartPosition (start, decls) ||> unionRangeWithListBy (fun (s: SynMemberSig) -> s.Range) (fun leadingKeyword nameRange nameInfo mEquals augmentation -> if needsCheck && isNil decls then reportParseErrorAt nameRange (FSComp.SR.parsEmptyTypeDefinition()) let declRange = unionRanges nameRange objectModelRange let mWhole = (declRange, augmentation) ||> unionRangeWithListBy (fun (mem: SynMemberSig) -> mem.Range) let trivia: SynTypeDefnSigTrivia = { LeadingKeyword = leadingKeyword; WithKeyword = None; EqualsRange = mEquals } SynTypeDefnSig(nameInfo, SynTypeDefnSigRepr.ObjectModel(kind, decls, objectModelRange), augmentation, mWhole, trivia)) } | DELEGATE OF topType { let m = lhs parseState let ty, arity = $3 let flags = AbstractMemberFlags true SynMemberKind.Member let valSig = SynValSig([], (SynIdent(mkSynId m "Invoke", None)), inferredTyparDecls, ty, arity, false, false, PreXmlDoc.Empty, None, None, m, SynValSigTrivia.Zero) let invoke = SynMemberSig.Member(valSig, flags, m, SynMemberSigMemberTrivia.Zero) (fun leadingKeyword nameRange nameInfo mEquals augmentation -> if not (isNil augmentation) then raiseParseErrorAt m (FSComp.SR.parsAugmentationsIllegalOnDelegateType()) let mWhole = unionRanges nameRange m let trivia: SynTypeDefnSigTrivia = { LeadingKeyword = leadingKeyword; WithKeyword = None; EqualsRange = mEquals } SynTypeDefnSig(nameInfo, SynTypeDefnSigRepr.ObjectModel(SynTypeDefnKind.Delegate(ty, arity), [invoke], m), [], mWhole, trivia)) } /* The right-hand-side of an object type definition in a signature */ tyconClassSpfn: | classSpfnBlockKindUnspecified { let needsCheck, decls = $1 needsCheck, (SynTypeDefnKind.Unspecified, 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, []) } /* The right-hand-side of an object type definition in a signature with no explicit kind */ classSpfnBlockKindUnspecified: | OBLOCKBEGIN classSpfnMembers oblockend { true, $2 } | OBLOCKBEGIN classSpfnMembers recover { if not $3 then reportParseErrorAt (rhs parseState 3) (FSComp.SR.parsUnexpectedEndOfFileTypeSignature()) false, $2 } /* NOTE: these rules enable the non-#light syntax to omit the kind of a type. */ | BEGIN classSpfnBlock END { false, $2 } | BEGIN classSpfnBlock recover { false, $2 } /* The right-hand-side of an object type definition in a signature */ classSpfnBlock: | OBLOCKBEGIN classSpfnMembers oblockend { $2 } | OBLOCKBEGIN classSpfnMembers recover { if not $3 then reportParseErrorAt (rhs parseState 3) (FSComp.SR.parsUnexpectedEndOfFileTypeSignature()) $2 } | classSpfnMembers { $1 } /* The members of an object type definition in a signature, possibly empty */ classSpfnMembers: | classSpfnMembersAtLeastOne { $1 } | /* EMPTY */ { [] } /* The members of an object type definition in a signature */ classSpfnMembersAtLeastOne: | classMemberSpfn opt_seps classSpfnMembers { $1 :: $3 } /* A object member in a signature */ classMemberSpfn: | opt_attributes opt_access memberSpecFlags opt_inline opt_access nameop opt_explicitValTyparDecls COLON topTypeWithTypeConstraints classMemberSpfnGetSet optLiteralValueSpfn { if Option.isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(), rhs parseState 2)) let isInline, doc, vis2, id, explicitValTyparDecls, (ty, arity), (mEquals, optLiteralValue) = (Option.isSome $4), grabXmlDoc(parseState, $1, 1), $5, $6, $7, $9, $11 let mWith, (getSet, getSetRangeOpt) = $10 let getSetAdjuster arity = match arity, getSet with SynValInfo([], _), SynMemberKind.Member -> SynMemberKind.PropertyGet | _ -> getSet let mWhole = let m = rhs parseState 3 match getSetRangeOpt with | None -> unionRanges m ty.Range | Some gs -> unionRanges m (gs: GetSetKeywords).Range |> fun m -> (m, $1) ||> unionRangeWithListBy (fun (a: SynAttributeList) -> a.Range) |> unionRangeWithXmlDoc doc |> fun m -> match optLiteralValue with | None -> m | Some e -> unionRanges m e.Range let flags, leadingKeyword = $3 let flags = flags (getSetAdjuster arity) let trivia = { LeadingKeyword = leadingKeyword; InlineKeyword = $4; WithKeyword = mWith; EqualsRange = mEquals } let valSpfn = SynValSig($1, id, explicitValTyparDecls, ty, arity, isInline, false, doc, vis2, optLiteralValue, mWhole, trivia) let trivia: SynMemberSigMemberTrivia = { GetSetKeywords = getSetRangeOpt } SynMemberSig.Member(valSpfn, flags, mWhole, trivia) } | opt_attributes opt_access interfaceMember appType { if Option.isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(), rhs parseState 2)) SynMemberSig.Interface($4, unionRanges (rhs parseState 3) ($4).Range) } | opt_attributes opt_access INHERIT appType { if Option.isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(), rhs parseState 2)) SynMemberSig.Inherit($4, unionRanges (rhs parseState 3) ($4).Range) } | opt_attributes opt_access VAL fieldDecl { let mWhole = rhs2 parseState 1 4 if Option.isSome $2 then errorR (Error (FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier (), rhs parseState 2)) let mVal = rhs parseState 3 let (SynField(xmlDoc = xmlDoc)) as field = $4 $1 false mWhole (Some(SynLeadingKeyword.Val mVal)) let mWhole = unionRangeWithXmlDoc xmlDoc mWhole SynMemberSig.ValField(field, mWhole) } | opt_attributes opt_access STATIC VAL fieldDecl { let mWhole = rhs2 parseState 1 5 if Option.isSome $2 then errorR (Error (FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier (), rhs parseState 2)) let mStatic = rhs parseState 3 let mVal = rhs parseState 4 let (SynField(xmlDoc = xmlDoc)) as field = $5 $1 true mWhole (Some(SynLeadingKeyword.StaticVal(mStatic, mVal))) let mWhole = unionRangeWithXmlDoc xmlDoc mWhole SynMemberSig.ValField(field, mWhole) } | opt_attributes opt_access STATIC typeKeyword tyconSpfn { let leadingKeyword = SynTypeDefnLeadingKeyword.StaticType(rhs parseState 3, rhs parseState 4) if Option.isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(), rhs parseState 2)) SynMemberSig.NestedType($5 leadingKeyword, rhs2 parseState 1 5) } | opt_attributes opt_access NEW COLON topTypeWithTypeConstraints { let vis, doc, (ty, valSynInfo) = $2, grabXmlDoc(parseState, $1, 1), $5 let mNew = rhs parseState 3 let m = unionRanges (rhs parseState 1) ty.Range |> unionRangeWithXmlDoc doc let isInline = false let trivia: SynValSigTrivia = { LeadingKeyword = SynLeadingKeyword.New mNew; InlineKeyword = None; WithKeyword = None; EqualsRange = None } let valSpfn = SynValSig ($1, (SynIdent(mkSynId (rhs parseState 3) "new", None)), noInferredTypars, ty, valSynInfo, isInline, false, doc, vis, None, m, trivia) SynMemberSig.Member(valSpfn, CtorMemberFlags, m, SynMemberSigMemberTrivia.Zero) } /* The optional "with get, set" on a member in a signature */ classMemberSpfnGetSet: | /* EMPTY */ { None, (SynMemberKind.Member, None) } | WITH classMemberSpfnGetSetElements { let mWith = rhs parseState 1 Some mWith, $2 } | OWITH classMemberSpfnGetSetElements OEND { let mWith = rhs parseState 1 Some mWith, $2 } | OWITH classMemberSpfnGetSetElements error { let mWith = rhs parseState 1 reportParseErrorAt mWith (FSComp.SR.parsUnmatchedWith()) Some mWith, $2 } /* The "get, set" on a property member in a signature */ classMemberSpfnGetSetElements: | nameop { (let (SynIdent(id:Ident, _)) = $1 if id.idText = "get" then SynMemberKind.PropertyGet, Some(GetSetKeywords.Get id.idRange) else if id.idText = "set" then SynMemberKind.PropertySet, Some(GetSetKeywords.Set id.idRange) else raiseParseErrorAt (rhs parseState 1) (FSComp.SR.parsGetOrSetRequired())) } | nameop COMMA nameop { let (SynIdent(id, _)) = $1 let (SynIdent(id2, _)) = $3 if not ((id.idText = "get" && id2.idText = "set") || (id.idText = "set" && id2.idText = "get")) then raiseParseErrorAt (rhs2 parseState 1 3) (FSComp.SR.parsGetOrSetRequired()) if id.idText = "get" then SynMemberKind.PropertyGetSet, Some(GetSetKeywords.GetSet(id.idRange, id2.idRange)) else SynMemberKind.PropertyGetSet, Some(GetSetKeywords.GetSet(id2.idRange, id.idRange)) } memberSpecFlags: | memberFlags { $1 } | abstractMemberFlags { $1 } /* Part of an exception definition in a signature file */ exconSpfn: | exconCore opt_classSpfn { let mWithKwd, members = $2 SynExceptionSig($1, mWithKwd, members, lhs parseState) } /* The optional augmentation on a type definition in a signature */ opt_classSpfn: | WITH classSpfnBlock declEnd { let mWithKwd = rhs parseState 1 (Some mWithKwd), $2 } | /* EMPTY */ { None, [] } /*--------------------------------------------------------------------------*/ /* F# Language Proper - implementation files */ /* The contents of an implementation file */ 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 = ParsedImplFileFragment.AnonModule([], rhs parseState 1) ParsedImplFile ([], [emptyImplFileFrag]) } /* The sequence of namespace definitions or a single module definition that makes up an implementation file */ fileNamespaceImpls: | fileModuleImpl { ParsedImplFile ([], [ ($1 (None, false, [], PreXmlDoc.Empty)) ]) } | fileModuleImpl fileNamespaceImplList { // If there are namespaces, the first fileModuleImpl may only contain # directives let decls = match ($1 (None, false, [], PreXmlDoc.Empty)) with | ParsedImplFileFragment.AnonModule(decls, m) -> decls | ParsedImplFileFragment.NamespaceFragment(decls = decls) -> decls | ParsedImplFileFragment.NamedModule(SynModuleOrNamespace(range = 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) } /* The sequence of namespace definitions that can make up an implementation file */ fileNamespaceImplList: | fileNamespaceImpl fileNamespaceImplList { $1 :: $2 } | fileNamespaceImpl { [$1] } /* A single namespace definition in an implementation file */ fileNamespaceImpl: | namespaceIntro deprecated_opt_equals fileModuleImpl { let mNamespace, isRec, path, xml = $1 $3 (Some mNamespace, isRec, path, xml) } /* A single module definition in an implementation file */ fileModuleImpl: | opt_attributes opt_access moduleIntro moduleDefnsOrExprPossiblyEmptyOrBlock { if Option.isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(), rhs parseState 2)) let m2 = rhs parseState 3 let mDeclsAndAttrs = (List.map (fun (a: SynAttributeList) -> a.Range) $1) @ (List.map (fun (d: SynModuleDecl) -> d.Range) $4) let xmlDoc = grabXmlDoc(parseState, $1, 1) let m = (m2, mDeclsAndAttrs) ||> unionRangeWithListBy id |> unionRangeWithXmlDoc xmlDoc let mModule, isRec2, path2, vis, attribs2 = $3 (fun (mNamespaceOpt, isRec, path, _) -> if not (isNil path) then errorR(Error(FSComp.SR.parsNamespaceOrModuleNotBoth(), m2)) let lid = path@path2 let trivia: SynModuleOrNamespaceTrivia = { LeadingKeyword = SynModuleOrNamespaceLeadingKeyword.Module mModule } ParsedImplFileFragment.NamedModule(SynModuleOrNamespace(lid, (isRec || isRec2), SynModuleOrNamespaceKind.NamedModule, $4, xmlDoc, $1@attribs2, vis, m, trivia))) } | moduleDefnsOrExprPossiblyEmptyOrBlock { let m = (rhs parseState 1) (fun (mNamespaceOpt, isRec, path, xml) -> match path with | [] -> ParsedImplFileFragment.AnonModule($1, m) | _ -> let lastDeclRange = List.tryLast $1 |> Option.map (fun decl -> decl.Range) |> Option.defaultValue (rhs parseState 1) let m = mkRange lastDeclRange.FileName (lhs parseState).Start lastDeclRange.End xml.MarkAsInvalid() let trivia: SynModuleOrNamespaceTrivia = match mNamespaceOpt with | None -> { LeadingKeyword = SynModuleOrNamespaceLeadingKeyword.None } | Some mNamespace -> { LeadingKeyword = SynModuleOrNamespaceLeadingKeyword.Namespace mNamespace } ParsedImplFileFragment.NamespaceFragment(path, isRec, SynModuleOrNamespaceKind.DeclaredNamespace, $1, PreXmlDoc.Empty, [], m, trivia)) } /* A collection/block of definitions or expressions making up a module or namespace, possibly empty */ 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 } /* A collection of definitions or expressions making up a module or namespace, possibly empty */ moduleDefnsOrExprPossiblyEmpty: | moduleDefnsOrExpr { $1 } | /* EMPTY */ { [] } /* A collection of definitions or expressions making up a module or namespace */ /* A naked expression is only allowed at the start of a module/file, or straight after a topSeparators */ moduleDefnsOrExpr: | opt_attributes opt_access declExpr topSeparators moduleDefnsOrExpr { match $2 with | Some vis -> errorR(Error(FSComp.SR.parsUnexpectedVisibilityDeclaration(vis.ToString()), rhs parseState 3)) | _ -> () let attrDecls = if not (isNil $1) then [ SynModuleDecl.Attributes($1, rangeOfNonNilAttrs $1) ] else [] attrDecls @ mkSynExprDecl $3 :: $5 } | opt_attributes opt_access declExpr topSeparators { match $2 with | Some vis -> errorR(Error(FSComp.SR.parsUnexpectedVisibilityDeclaration(vis.ToString()), rhs parseState 3)) | _ -> () let attrDecls = if not (isNil $1) then [ SynModuleDecl.Attributes($1, rangeOfNonNilAttrs $1) ] else [] attrDecls @ [ mkSynExprDecl $3 ] } | opt_attributes opt_access declExpr { match $2 with | Some vis -> errorR(Error(FSComp.SR.parsUnexpectedVisibilityDeclaration(vis.ToString()), rhs parseState 3)) | _ -> () let attrDecls = if not (isNil $1) then [ SynModuleDecl.Attributes($1, rangeOfNonNilAttrs $1) ] else [] attrDecls @ [ mkSynExprDecl $3 ] } | moduleDefns { $1 } | opt_attributes error { if not (isNil $1) then [ SynModuleDecl.Attributes($1, rangeOfNonNilAttrs $1) ] else [] } /* A sequence of definitions in a namespace or module */ moduleDefns: | moduleDefnOrDirective moduleDefns { $1 @ $2 } | moduleDefnOrDirective topSeparators moduleDefnsOrExpr { $1 @ $3 } | moduleDefnOrDirective { $1 } | moduleDefnOrDirective topSeparators { $1 } | error topSeparators moduleDefnsOrExpr { $3 } /* A single definition in a namespace, module or F# Interactive file*/ moduleDefnOrDirective: | moduleDefn { $1 } | hashDirective { [ SynModuleDecl.HashDirective($1, rhs2 parseState 1 1) ] } /* A single definition in a namespace, module or interaction. */ /* This is used by both "fsi" interactions and "source file" fragments defined by moduleDefns */ moduleDefn: /* 'let' definitions in non-#light*/ | opt_attributes opt_access defnBindings %prec decl_let { if Option.isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(), rhs parseState 2)) parseState.ResetSynArgNameGenerator() let (BindingSetPreAttrs(_, _, _, _, mWhole)) = $3 mkDefnBindings (mWhole, $3, $1, $2, mWhole) } /* 'let' or 'do' definitions in #light */ | opt_attributes opt_access hardwhiteLetBindings %prec decl_let { let hwlb, m, _ = $3 if Option.isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(), rhs parseState 2)) parseState.ResetSynArgNameGenerator() mkDefnBindings (m, hwlb, $1, $2, m) } /* 'do' definitions in non-#light*/ | opt_attributes opt_access doBinding %prec decl_let { if Option.isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(), rhs parseState 2)) let mWhole = rhs parseState 3 mkDefnBindings (mWhole, $3, $1, $2, mWhole) } /* 'type' definitions */ | opt_attributes opt_access typeKeyword tyconDefn tyconDefnList { if Option.isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(), rhs parseState 2)) let xmlDoc = grabXmlDoc(parseState, $1, 1) let leadingKeyword = SynTypeDefnLeadingKeyword.Type(rhs parseState 3) let (SynTypeDefn(SynComponentInfo(cas, a, cs, b, _xmlDoc, d, d2, d3), e, f, g, h, trivia)) = $4 leadingKeyword _xmlDoc.MarkAsInvalid() let attrs = $1@cas let mDefn = (h, attrs) ||> unionRangeWithListBy (fun (a: SynAttributeList) -> a.Range) |> unionRangeWithXmlDoc xmlDoc let tc = SynTypeDefn(SynComponentInfo(attrs, a, cs, b, xmlDoc, d, d2, d3), e, f, g, mDefn, trivia) let types = tc :: $5 [ SynModuleDecl.Types(types, (rhs parseState 3, types) ||> unionRangeWithListBy (fun t -> t.Range)) ] } /* 'exception' definitions */ | opt_attributes opt_access exconDefn { if Option.isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(), rhs parseState 2)) let (SynExceptionDefn(SynExceptionDefnRepr(cas, a, b, c, d, d2), withKeyword, e, f)) = $3 let xmlDoc = grabXmlDoc(parseState, $1, 1) let defnReprRange = (d2, $1) ||> unionRangeWithListBy (fun a -> a.Range) |> unionRangeWithXmlDoc xmlDoc let mWhole = (f, $1) ||> unionRangeWithListBy (fun a -> a.Range) |> unionRangeWithXmlDoc xmlDoc let synExnDefn = SynExceptionDefn(SynExceptionDefnRepr($1@cas, a, b, xmlDoc, d, defnReprRange), withKeyword, e, mWhole) [ SynModuleDecl.Exception(synExnDefn, mWhole) ] } /* 'module' definitions */ | opt_attributes opt_access moduleIntro EQUALS namedModuleDefnBlock { if Option.isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(), rhs parseState 2)) let attribs, (mModule, isRec, path, vis, attribs2) = $1, $3 let xmlDoc = grabXmlDoc(parseState, $1, 1) match $5 with | Choice1Of2 eqn -> if Option.isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(), rhs parseState 2)) if isRec then raiseParseErrorAt (rhs parseState 3) (FSComp.SR.parsInvalidUseOfRec()) if not (isSingleton path) then raiseParseErrorAt (rhs parseState 3) (FSComp.SR.parsModuleAbbreviationMustBeSimpleName()) if not (isNil attribs) then raiseParseErrorAt (rhs parseState 1) (FSComp.SR.parsIgnoreAttributesOnModuleAbbreviation()) if not (isNil attribs2) then raiseParseErrorAt (rhs parseState 3) (FSComp.SR.parsIgnoreAttributesOnModuleAbbreviation()) match vis with | Some vis -> raiseParseErrorAt (rhs parseState 1) (FSComp.SR.parsIgnoreAttributesOnModuleAbbreviationAlwaysPrivate(vis.ToString())) | None -> () [ SynModuleDecl.ModuleAbbrev(List.head path, eqn, (rhs parseState 3, eqn) ||> unionRangeWithListBy (fun id -> id.idRange)) ] | Choice2Of2 (def, mEndOpt) -> if not (isSingleton path) then raiseParseErrorAt (rhs parseState 3) (FSComp.SR.parsModuleAbbreviationMustBeSimpleName()) let info = SynComponentInfo(attribs @ attribs2, None, [], path, xmlDoc, false, vis, rhs parseState 3) let mEquals = rhs parseState 4 let trivia: SynModuleDeclNestedModuleTrivia = { ModuleKeyword = Some mModule; EqualsRange = Some mEquals } let m = (rhs2 parseState 1 4, def) ||> unionRangeWithListBy (fun (d: SynModuleDecl) -> d.Range) |> unionRangeWithXmlDoc xmlDoc let m = match mEndOpt with | None -> m | Some mEnd -> unionRanges m mEnd [ SynModuleDecl.NestedModule(info, isRec, def, false, m, trivia) ] } /* incomplete 'module' definitions */ | opt_attributes opt_access moduleIntro error { let xmlDoc = grabXmlDoc(parseState, $1, 1) let mWhole = rhs2 parseState 1 3 |> unionRangeWithXmlDoc xmlDoc let attribs, (mModule, isRec, path, vis, attribs2) = $1, $3 let info = SynComponentInfo(attribs @ attribs2, None, [], path, xmlDoc, false, vis, rhs parseState 3) let trivia: SynModuleDeclNestedModuleTrivia = { ModuleKeyword = Some mModule; EqualsRange = None } [ SynModuleDecl.NestedModule(info, isRec, [], false, mWhole, trivia) ] } /* unattached custom attributes */ | attributes recover { errorR(Error(FSComp.SR.parsAttributeOnIncompleteCode(), rhs parseState 1)) [ SynModuleDecl.Attributes($1, rhs parseState 1) ] } /* 'open' declarations */ | openDecl { [ SynModuleDecl.Open($1, (rhs parseState 1)) ] } openDecl: /* 'open' declarations */ | OPEN path { SynOpenDeclTarget.ModuleOrNamespace($2, (rhs parseState 2)) } | OPEN typeKeyword appType { SynOpenDeclTarget.Type($3, (rhs parseState 3)) } /* The right-hand-side of a module abbreviation definition */ /* 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 } /* The right-hand-side of a module definition */ namedModuleDefnBlock: | OBLOCKBEGIN wrappedNamedModuleDefn oblockend { Choice2Of2 $2 } | OBLOCKBEGIN wrappedNamedModuleDefn 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 Choice2Of2 $2 } | OBLOCKBEGIN moduleDefnsOrExpr oblockend { // 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. // 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. // // 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.Expr(LongOrSingleIdent(false, SynLongIdent(path, _, _), None, _), _) ] -> Choice1Of2 path | _ -> Choice2Of2 ($2, None) } | 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, None) } | OBLOCKBEGIN error oblockend { let mEnd = rhs parseState 3 Choice2Of2 ([], Some mEnd) } | wrappedNamedModuleDefn { Choice2Of2 $1 } | path { Choice1Of2 $1.LongIdent } /* A module definition that includes a 'begin'...'end' (rarely used in F# with #light syntax) */ wrappedNamedModuleDefn: | structOrBegin moduleDefnsOrExprPossiblyEmpty END { let mEnd = rhs parseState 3 $2, Some mEnd } | structOrBegin moduleDefnsOrExprPossiblyEmpty recover { reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnmatchedBeginOrStruct()) $2, None } | structOrBegin error END { let mEnd = rhs parseState 3 [], Some mEnd } tyconDefnAugmentation: | WITH classDefnBlock declEnd { let mWithKwd = rhs parseState 1 mWithKwd, $2 } /* An optional list of custom attributes */ opt_attributes: | attributes { $1 } | %prec prec_opt_attributes_none { [] } /* A list of sets of custom attributes */ attributes: | attributeList { $1 } | attributeList attributes { $1 @ $2 } /* One set of custom attributes, including [< ... >] */ attributeList: | LBRACK_LESS attributeListElements opt_seps GREATER_RBRACK opt_OBLOCKSEP { mkAttributeList $2 (rhs2 parseState 1 4) } | LBRACK_LESS error GREATER_RBRACK opt_OBLOCKSEP { mkAttributeList [] (rhs2 parseState 1 3) } | LBRACK_LESS attributeListElements opt_seps ends_coming_soon_or_recover { if not $4 then reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnmatchedLBrackLess()) mkAttributeList $2 (rhs2 parseState 1 2) } | LBRACK_LESS ends_coming_soon_or_recover { if not $2 then reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnmatchedLBrackLess()) mkAttributeList [] (rhs parseState 1) } /* One set of custom attributes, not including [< ... >] */ attributeListElements: | attribute { [$1] } | attributeListElements seps attribute { $1 @ [$3] } /* One custom attribute */ attribute: /* A custom attribute */ | path opt_HIGH_PRECEDENCE_APP opt_atomicExprAfterType { let arg = match $3 with None -> mkSynUnit $1.Range | Some e -> e let m = unionRanges $1.Range arg.Range ({ TypeName = $1; ArgExpr = arg; Target = None; AppliesToGetterAndSetter = false; Range = m }: SynAttribute) } /* A custom attribute with an attribute target */ | attributeTarget path opt_HIGH_PRECEDENCE_APP opt_atomicExprAfterType { let arg = match $4 with None -> mkSynUnit $2.Range | Some e -> e let startRange = match $1 with Some(ident:Ident) -> ident.idRange | None -> $2.Range let m = unionRanges startRange arg.Range ({ TypeName = $2; ArgExpr = arg; Target = $1; AppliesToGetterAndSetter = false; Range = m }: SynAttribute) } /* A custom attribute with an attribute target */ | attributeTarget OBLOCKBEGIN path oblockend opt_HIGH_PRECEDENCE_APP opt_atomicExprAfterType { let arg = match $6 with None -> mkSynUnit $3.Range | Some e -> e let startRange = match $1 with Some ident -> ident.idRange | None -> $3.Range let m = unionRanges startRange arg.Range ({ TypeName = $3; ArgExpr = arg; Target = $1; AppliesToGetterAndSetter = false; Range = m }: SynAttribute) } /* The target of a custom attribute */ attributeTarget: | moduleKeyword COLON { Some(ident("module", (rhs parseState 1))) } | typeKeyword COLON { Some(ident("type", (rhs parseState 1))) } | ident COLON { Some($1) } /* return */ | YIELD COLON { if $1 then reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsSyntaxError()) Some(ident("return", (rhs parseState 1))) } /* Flags on a member */ memberFlags: | STATIC MEMBER { let mStatic = rhs parseState 1 let mMember = rhs parseState 2 StaticMemberFlags, (SynLeadingKeyword.StaticMember(mStatic, mMember)) } | MEMBER { let mMember = rhs parseState 1 NonVirtualMemberFlags, (SynLeadingKeyword.Member mMember) } | OVERRIDE { let mOverride = rhs parseState 1 OverrideMemberFlags, (SynLeadingKeyword.Override mOverride) } | DEFAULT { let mDefault = rhs parseState 1 OverrideMemberFlags, (SynLeadingKeyword.Default mDefault) } /* The name of a type in a signature or implementation, possibly with type parameters and constraints */ typeNameInfo: | opt_attributes tyconNameAndTyparDecls opt_typeConstraints { let typars, lid, fixity, vis = $2 let xmlDoc = grabXmlDoc(parseState, $1, 1) SynComponentInfo ($1, typars, $3, lid, xmlDoc, fixity, vis, rangeOfLid lid) } /* Part of a set of type definitions */ tyconDefnList: | AND tyconDefn tyconDefnList { let xmlDoc = grabXmlDoc(parseState, [], 1) let tyconDefn = let leadingKeyword = SynTypeDefnLeadingKeyword.And(rhs parseState 1) let (SynTypeDefn(componentInfo, typeRepr, members, implicitConstructor, range, trivia) as typeDefn) = $2 leadingKeyword let (SynComponentInfo(a, typars, c, lid, _xmlDoc, fixity, vis, mLongId)) = componentInfo if xmlDoc.IsEmpty then if _xmlDoc.IsEmpty then typeDefn else let range = unionRangeWithXmlDoc _xmlDoc range SynTypeDefn(componentInfo, typeRepr, members, implicitConstructor, range, trivia) else _xmlDoc.MarkAsInvalid() let range = unionRangeWithXmlDoc xmlDoc range let componentInfo = SynComponentInfo (a, typars, c, lid, xmlDoc, fixity, vis, mLongId) SynTypeDefn(componentInfo, typeRepr, members, implicitConstructor, range, trivia) tyconDefn :: $3 } | { [] } /* A type definition */ tyconDefn: | typeNameInfo { fun leadingKeyword -> let trivia: SynTypeDefnTrivia = { LeadingKeyword = leadingKeyword; EqualsRange = None; WithKeyword = None } SynTypeDefn($1, SynTypeDefnRepr.Simple(SynTypeDefnSimpleRepr.None($1.Range), $1.Range), [], None, $1.Range, trivia) } | typeNameInfo opt_equals tyconDefnRhsBlock { match $2 with | Some _ -> () | None -> let (SynComponentInfo(_, _, _, lid, _, _, _, _)) = $1 // While the spec doesn't allow long idents here, the parser doesn't enforce this, so take one ident let typeNameId = List.last lid raiseParseErrorAt (rhs parseState 2) (FSComp.SR.parsEqualsMissingInTypeDefinition(typeNameId.ToString())) let nameRange = rhs parseState 1 let (tcDefRepr: SynTypeDefnRepr), mWith, members = $3 nameRange let declRange = unionRanges (rhs parseState 1) tcDefRepr.Range let mWhole = (declRange, members) ||> unionRangeWithListBy (fun (mem: SynMemberDefn) -> mem.Range) fun leadingKeyword -> let trivia: SynTypeDefnTrivia = { LeadingKeyword = leadingKeyword; EqualsRange = $2; WithKeyword = mWith } SynTypeDefn($1, tcDefRepr, members, None, mWhole, trivia) } | typeNameInfo tyconDefnAugmentation { let mWithKwd, classDefns = $2 let m = (rhs parseState 1, classDefns) ||> unionRangeWithListBy (fun mem -> mem.Range) fun leadingKeyword -> let trivia: SynTypeDefnTrivia = { LeadingKeyword = leadingKeyword; EqualsRange = None; WithKeyword = None } SynTypeDefn($1, SynTypeDefnRepr.ObjectModel(SynTypeDefnKind.Augmentation mWithKwd, [], m), classDefns, None, m, trivia) } | typeNameInfo opt_attributes opt_access opt_HIGH_PRECEDENCE_APP simplePatterns optAsSpec EQUALS tyconDefnRhsBlock { let vis, spats, az = $3, $5, $6 let nameRange = rhs parseState 1 let (tcDefRepr, mWith, members) = $8 nameRange let (SynComponentInfo(_, _, _, lid, _, _, _, _)) = $1 let mEquals = rhs parseState 7 // Gets the XML doc comments prior to the implicit constructor let xmlDoc = grabXmlDoc(parseState, $2, 2) let memberCtorPattern = SynMemberDefn.ImplicitCtor(vis, $2, spats, Option.map snd az, xmlDoc, rangeOfLid lid, { AsKeyword = Option.map fst az }) 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 let declRange = unionRanges (rhs parseState 1) tcDefRepr.Range let mWhole = (declRange, members) ||> unionRangeWithListBy (fun (mem: SynMemberDefn) -> mem.Range) |> unionRangeWithXmlDoc xmlDoc fun leadingKeyword -> let trivia: SynTypeDefnTrivia = { LeadingKeyword = leadingKeyword; EqualsRange = Some mEquals; WithKeyword = mWith } SynTypeDefn($1, tcDefRepr, members, Some memberCtorPattern, mWhole, trivia) } /* The right-hand-side of a type definition */ 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 mWith, optClassDefn = $5 let mWith2, optClassDefn2 = $7 let m = unionRanges (rhs parseState 1) (match optClassDefn2 with [] -> (match optClassDefn with [] -> (rhs parseState 4) | _ -> (rhs parseState 5)) | _ -> (rhs parseState 7)) (fun nameRange -> let tcDefRepr, members = $2 nameRange (checkForMultipleAugmentations m ($4 @ optClassDefn) optClassDefn2) let mWith = Option.orElse mWith2 mWith tcDefRepr, mWith, members) } | OBLOCKBEGIN tyconDefnRhs opt_OBLOCKSEP classDefnMembers opt_classDefn recover { if not $6 then reportParseErrorAt (rhs parseState 6) (FSComp.SR.parsUnexpectedEndOfFileTypeDefinition()) let mWith, optClassDefn = $5 let m = unionRanges (rhs parseState 1) (match optClassDefn with [] -> (rhs parseState 4) | _ -> (rhs parseState 5)) (fun nameRange -> let tcDefRepr, members = $2 nameRange (checkForMultipleAugmentations m ($4 @ optClassDefn) []) tcDefRepr, mWith, members) } | tyconDefnRhs opt_classDefn { let m = rhs parseState 1 let mWith, optClassDefn = $2 (fun nameRange -> let tcDefRepr, members = $1 nameRange optClassDefn tcDefRepr, mWith, members) } /* The right-hand-side of a type definition */ tyconDefnRhs: /* A simple type definition */ | tyconDefnOrSpfnSimpleRepr { let m = $1.Range (fun nameRange augmentation -> SynTypeDefnRepr.Simple($1, m), augmentation) } /* An object type definition */ | tyconClassDefn { let needsCheck, (kind, decls), mopt = $1 let m = match mopt with | None -> (lhs parseState).StartRange // create a zero-width range | Some m -> m (fun nameRange augmentation -> if needsCheck && isNil decls then reportParseErrorAt nameRange (FSComp.SR.parsEmptyTypeDefinition()) SynTypeDefnRepr.ObjectModel(kind, decls, m), augmentation) } /* A delegate type definition */ | DELEGATE OF topType { let m = lhs parseState let ty, arity = $3 (fun nameRange augmentation -> let valSig = SynValSig([], (SynIdent(mkSynId m "Invoke", None)), inferredTyparDecls, ty, arity, false, false, PreXmlDoc.Empty, None, None, m, SynValSigTrivia.Zero) let flags = AbstractMemberFlags true SynMemberKind.Member let invoke = SynMemberDefn.AbstractSlot(valSig, flags, m, SynMemberDefnAbstractSlotTrivia.Zero) if not (isNil augmentation) then raiseParseErrorAt m (FSComp.SR.parsAugmentationsIllegalOnDelegateType()) SynTypeDefnRepr.ObjectModel(SynTypeDefnKind.Delegate(ty, arity), [invoke], m), []) } /* The right-hand-side of a object type definition */ tyconClassDefn: | classDefnBlockKindUnspecified { let needsCheck, decls, mopt = $1 needsCheck, (SynTypeDefnKind.Unspecified, decls), mopt } | classOrInterfaceOrStruct classDefnBlock END { false, ($1, $2), Some(rhs2 parseState 1 3) } | classOrInterfaceOrStruct classDefnBlock recover { reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnmatchedClassInterfaceOrStruct()) let m = (rhs parseState 1, $2) ||> unionRangeWithListBy (fun (d: SynMemberDefn) -> d.Range) false, ($1, $2), Some(m) } | classOrInterfaceOrStruct error END { // silent recovery false, ($1, []), Some(rhs2 parseState 1 3) } /* The right-hand-side of a object type definition where the class/interface/struct kind has not been specified */ classDefnBlockKindUnspecified: | OBLOCKBEGIN classDefnMembers recover { if not $3 then reportParseErrorAt (rhs parseState 3) (FSComp.SR.parsUnexpectedEndOfFileTypeDefinition()) let mopt = match $2 with | _ :: _ -> Some((rhs parseState 1, $2) ||> unionRangeWithListBy (fun (d: SynMemberDefn) -> d.Range)) | _ -> None false, $2, mopt } | OBLOCKBEGIN classDefnMembers oblockend { let mopt = match $2 with | _ :: _ -> Some((rhs parseState 1, $2) ||> unionRangeWithListBy (fun (d: SynMemberDefn) -> d.Range)) | _ -> None true, $2, mopt } /* The contents of an object type definition or type augmentation */ classDefnBlock: | OBLOCKBEGIN classDefnMembers recover { if not $3 then reportParseErrorAt (rhs parseState 3) (FSComp.SR.parsUnexpectedEndOfFileTypeDefinition()) $2 } | OBLOCKBEGIN classDefnMembers oblockend { $2 } | classDefnMembers { $1 } /* The members of an object type definition or type augmentation, possibly empty */ classDefnMembers: | classDefnMembersAtLeastOne { $1 } /* REVIEW: Error recovery rules that are followed by potentially empty productions are suspicious! */ | error classDefnMembers { $2 } | /* EMPTY */ { [] } /* The members of an object type definition or type augmentation */ classDefnMembersAtLeastOne: | classDefnMember opt_seps classDefnMembers { match $1, $3 with | [ SynMemberDefn.Interface(members=Some []; range=m) ], nextMember :: _ -> warning(IndentationProblem(FSComp.SR.lexfltTokenIsOffsideOfContextStartedEarlier(warningStringOfPos m.Start), nextMember.Range)) | _ -> () $1 @ $3 } /* The "with get, set" part of a member definition */ classDefnMemberGetSet: | WITH classDefnMemberGetSetElements { let mWithKwd = rhs parseState 1 mWithKwd, $2 } | OWITH classDefnMemberGetSetElements OEND { let mWithKwd = rhs parseState 1 mWithKwd, $2 } | OWITH classDefnMemberGetSetElements error { let mWithKwd = rhs parseState 1 reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnmatchedWith()) mWithKwd, $2 } /* The "get, set" part of a member definition */ classDefnMemberGetSetElements: | classDefnMemberGetSetElement { [$1], None } | classDefnMemberGetSetElement AND classDefnMemberGetSetElement { let mAnd = rhs parseState 2 [$1;$3], Some mAnd } classDefnMemberGetSetElement: | opt_inline opt_attributes bindingPattern opt_topReturnTypeWithTypeConstraints EQUALS typedSequentialExprBlock { let mEquals = rhs parseState 5 let mRhs = ($6: SynExpr).Range ($1, $2, $3, $4, Some mEquals, $6, mRhs) } /* The core of a member definition */ memberCore: /* Methods and simple getter properties */ | opt_inline bindingPattern opt_topReturnTypeWithTypeConstraints EQUALS typedSequentialExprBlock { let mRhs = $5.Range let optReturnType = $3 let mEquals = rhs parseState 4 let bindingPat, mBindLhs = $2 (fun vis flagsBuilderAndLeadingKeyword attrs rangeStart -> let xmlDoc = grabXmlDocAtRangeStart(parseState, attrs, rangeStart) let memFlagsBuilder, leadingKeyword = flagsBuilderAndLeadingKeyword let memberFlags = memFlagsBuilder SynMemberKind.Member let mWholeBindLhs = (mBindLhs, attrs) ||> unionRangeWithListBy (fun (a: SynAttributeList) -> a.Range) let trivia: SynBindingTrivia = { LeadingKeyword = leadingKeyword; InlineKeyword = $1; EqualsRange = Some mEquals } let binding = mkSynBinding (xmlDoc, bindingPat) (vis, (Option.isSome $1), false, mWholeBindLhs, DebugPointAtBinding.NoneAtInvisible, optReturnType, $5, mRhs, [], attrs, Some memberFlags, trivia) let memberRange = unionRanges rangeStart mRhs |> unionRangeWithXmlDoc xmlDoc [ SynMemberDefn.Member(binding, memberRange) ]) } /* Properties with explicit get/set, also indexer properties */ | opt_inline bindingPattern opt_topReturnTypeWithTypeConstraints classDefnMemberGetSet { let mWith, (classDefnMemberGetSetElements, mAnd) = $4 let mWhole = (rhs parseState 2, classDefnMemberGetSetElements) ||> unionRangeWithListBy (fun (_, _, _, _, _, _, m2) -> m2) let propertyNameBindingPat, _ = $2 let optPropertyType = $3 mkSynMemberDefnGetSet parseState $1 mWith classDefnMemberGetSetElements mAnd mWhole propertyNameBindingPat optPropertyType } abstractMemberFlags: | ABSTRACT { let mAbstract = rhs parseState 1 AbstractMemberFlags true, SynLeadingKeyword.Abstract mAbstract } | ABSTRACT MEMBER { let mAbstract = rhs parseState 1 let mMember = rhs parseState 2 AbstractMemberFlags true, SynLeadingKeyword.AbstractMember(mAbstract, mMember) } | STATIC ABSTRACT { let mWhole = rhs2 parseState 1 2 parseState.LexBuffer.CheckLanguageFeatureAndRecover LanguageFeature.InterfacesWithAbstractStaticMembers mWhole if parseState.LexBuffer.SupportsFeature LanguageFeature.InterfacesWithAbstractStaticMembers then warning(Error(FSComp.SR.tcUsingInterfacesWithStaticAbstractMethods(), mWhole)) let mStatic = rhs parseState 1 let mAbstract = rhs parseState 2 AbstractMemberFlags false, SynLeadingKeyword.StaticAbstract(mStatic, mAbstract) } | STATIC ABSTRACT MEMBER { let mWhole = rhs2 parseState 1 2 parseState.LexBuffer.CheckLanguageFeatureAndRecover LanguageFeature.InterfacesWithAbstractStaticMembers mWhole if parseState.LexBuffer.SupportsFeature LanguageFeature.InterfacesWithAbstractStaticMembers then warning(Error(FSComp.SR.tcUsingInterfacesWithStaticAbstractMethods(), mWhole)) let mStatic = rhs parseState 1 let mAbstract = rhs parseState 2 let mMember = rhs parseState 3 AbstractMemberFlags false, SynLeadingKeyword.StaticAbstractMember(mStatic, mAbstract, mMember) } /* A member definition */ classDefnMember: | opt_attributes opt_access classDefnBindings { if Option.isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(), rhs parseState 2)) [mkClassMemberLocalBindings(false, None, $1, $2, $3)] } | opt_attributes opt_access STATIC classDefnBindings { if Option.isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(), rhs parseState 2)) [mkClassMemberLocalBindings(true, Some(rhs parseState 3), $1, $2, $4)] } | opt_attributes opt_access memberFlags memberCore opt_ODECLEND { let rangeStart = rhs parseState 1 if Option.isSome $2 then errorR (Error (FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier (), rhs parseState 2)) let flags = $3 $4 $2 flags $1 rangeStart } | opt_attributes opt_access interfaceMember appType opt_interfaceImplDefn { if not (isNil $1) then errorR(Error(FSComp.SR.parsAttributesAreNotPermittedOnInterfaceImplementations(), rhs parseState 1)) if Option.isSome $2 then errorR(Error(FSComp.SR.parsInterfacesHaveSameVisibilityAsEnclosingType(), rhs parseState 3)) let mWithKwd, members, mWhole = match $5 with | None -> None, None, rhs2 parseState 1 4 | Some(mWithKwd, members, m) -> Some mWithKwd, Some members, unionRanges (rhs2 parseState 1 4) m [ SynMemberDefn.Interface($4, mWithKwd, members, mWhole) ] } | opt_attributes opt_access abstractMemberFlags opt_inline nameop opt_explicitValTyparDecls COLON topTypeWithTypeConstraints classMemberSpfnGetSet opt_ODECLEND { let ty, arity = $8 let isInline, doc, id, explicitValTyparDecls = (Option.isSome $4), grabXmlDoc(parseState, $1, 1), $5, $6 let mWith, (getSet, getSetRangeOpt) = $9 let getSetAdjuster arity = match arity, getSet with SynValInfo([], _), SynMemberKind.Member -> SynMemberKind.PropertyGet | _ -> getSet let mWhole = let m = rhs parseState 1 match getSetRangeOpt with | None -> unionRanges m ty.Range | Some gs -> unionRanges m gs.Range |> unionRangeWithXmlDoc doc if Option.isSome $2 then errorR(Error(FSComp.SR.parsAccessibilityModsIllegalForAbstract(), mWhole)) let mkFlags, leadingKeyword = $3 let trivia = { LeadingKeyword = leadingKeyword; InlineKeyword = $4; WithKeyword = mWith; EqualsRange = None } let valSpfn = SynValSig($1, id, explicitValTyparDecls, ty, arity, isInline, false, doc, None, None, mWhole, trivia) let trivia: SynMemberDefnAbstractSlotTrivia = { GetSetKeywords = getSetRangeOpt } [ SynMemberDefn.AbstractSlot(valSpfn, mkFlags (getSetAdjuster arity), mWhole, trivia) ] } | opt_attributes opt_access inheritsDefn { if not (isNil $1) then errorR(Error(FSComp.SR.parsAttributesIllegalOnInherit(), rhs parseState 1)) if Option.isSome $2 then errorR(Error(FSComp.SR.parsVisibilityIllegalOnInherit(), rhs parseState 1)) [ $3 ] } | opt_attributes opt_access valDefnDecl opt_ODECLEND { if Option.isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(), rhs parseState 2)) let rangeStart = rhs parseState 1 $3 rangeStart $1 None } | opt_attributes opt_access STATIC valDefnDecl opt_ODECLEND { if Option.isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(), rhs parseState 2)) let mStatic = rhs parseState 3 let rangeStart = rhs parseState 1 $4 rangeStart $1 (Some mStatic) } | opt_attributes opt_access memberFlags autoPropsDefnDecl opt_ODECLEND { let rangeStart = rhs parseState 1 if Option.isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(), rhs parseState 2)) let flags = $3 $4 $1 flags rangeStart } | opt_attributes opt_access NEW atomicPattern optAsSpec EQUALS typedSequentialExprBlock opt_ODECLEND { let mWholeBindLhs = rhs2 parseState 1 (if Option.isSome $5 then 5 else 4) let mNew = rhs parseState 3 let xmlDoc = grabXmlDoc(parseState, $1, 1) let m = unionRanges mWholeBindLhs $7.Range |> unionRangeWithXmlDoc xmlDoc let mEquals = rhs parseState 6 let expr = $7 let valSynData = SynValData (Some CtorMemberFlags, SynValInfo([SynInfo.InferSynArgInfoFromPat $4], SynInfo.unnamedRetVal), Option.map snd $5) let vis = $2 let declPat = SynPat.LongIdent(SynLongIdent([mkSynId (rhs parseState 3) "new"], [], [None]), None, Some noInferredTypars, SynArgPats.Pats [$4], vis, rhs parseState 3) // Check that 'SynPatForConstructorDecl' matches this correctly assert (match declPat with SynPatForConstructorDecl _ -> true | _ -> false) let synBindingTrivia: SynBindingTrivia = { LeadingKeyword = SynLeadingKeyword.New mNew; InlineKeyword = None; EqualsRange = Some mEquals } [ SynMemberDefn.Member(SynBinding (None, SynBindingKind.Normal, false, false, $1, xmlDoc, valSynData, declPat, None, expr, mWholeBindLhs, DebugPointAtBinding.NoneAtInvisible, synBindingTrivia), m) ] } | opt_attributes opt_access STATIC typeKeyword tyconDefn { if Option.isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(), rhs parseState 2)) let leadingKeyword = SynTypeDefnLeadingKeyword.StaticType(rhs parseState 3, rhs parseState 4) [ SynMemberDefn.NestedType($5 leadingKeyword, None, rhs2 parseState 1 5) ] } /* A 'val' definition in an object type definition */ valDefnDecl: | VAL opt_mutable opt_access ident COLON typ { let mVal = rhs parseState 1 let mRhs = rhs2 parseState 4 6 let mValDecl = rhs2 parseState 1 6 (fun rangeStart attribs mStaticOpt -> let isStatic = Option.isSome mStaticOpt let xmlDoc = grabXmlDocAtRangeStart(parseState, attribs, rangeStart) let mValDecl = unionRanges rangeStart mValDecl |> unionRangeWithXmlDoc xmlDoc let leadingKeyword = match mStaticOpt with | None -> SynLeadingKeyword.Val mVal | Some mStatic -> SynLeadingKeyword.StaticVal(mStatic, mVal) let fld = SynField(attribs, isStatic, Some $4, $6, $2, xmlDoc, $3, mRhs, { LeadingKeyword = Some leadingKeyword }) [ SynMemberDefn.ValField(fld, mValDecl) ]) } /* An auto-property definition in an object type definition */ autoPropsDefnDecl: | VAL opt_mutable opt_access ident opt_typ EQUALS typedSequentialExprBlock classMemberSpfnGetSet { let mVal = rhs parseState 1 let mWith, (getSet, getSetOpt) = $8 let mEquals = rhs parseState 6 if $2 then errorR (Error (FSComp.SR.parsMutableOnAutoPropertyShouldBeGetSet (), rhs parseState 3)) (fun attribs flags rangeStart -> let xmlDoc = grabXmlDocAtRangeStart(parseState, attribs, rangeStart) let memberRange = unionRanges rangeStart $7.Range |> unionRangeWithXmlDoc xmlDoc let flags, leadingKeyword = flags let leadingKeyword = appendValToLeadingKeyword mVal leadingKeyword let memberFlags = flags SynMemberKind.Member let memberFlagsForSet = flags SynMemberKind.PropertySet let isStatic = not memberFlags.IsInstance let trivia = { LeadingKeyword = leadingKeyword; WithKeyword = mWith; EqualsRange = Some mEquals; GetSetKeywords = getSetOpt } [ SynMemberDefn.AutoProperty(attribs, isStatic, $4, $5, getSet, memberFlags, memberFlagsForSet, xmlDoc, $3, $7, memberRange, trivia) ]) } /* An optional type on an auto-property definition */ opt_typ: | /* EMPTY */ { None } | COLON typ { Some $2 } atomicPatternLongIdent: | UNDERSCORE DOT pathOp { if not (parseState.LexBuffer.SupportsFeature LanguageFeature.SingleUnderscorePattern) then raiseParseErrorAt (rhs parseState 2) (FSComp.SR.parsUnexpectedSymbolDot()) let underscore = ident("_", rhs parseState 1) let mDot = rhs parseState 2 None, prependIdentInLongIdentWithTrivia (SynIdent(underscore, None)) mDot $3 } | GLOBAL DOT pathOp { let globalIdent = ident(MangledGlobalName, rhs parseState 1) let mDot = rhs parseState 2 None, prependIdentInLongIdentWithTrivia (SynIdent(globalIdent, (Some(IdentTrivia.OriginalNotation "global")))) mDot $3 } | pathOp { (None, $1) } | access UNDERSCORE DOT pathOp { if not (parseState.LexBuffer.SupportsFeature LanguageFeature.SingleUnderscorePattern) then raiseParseErrorAt (rhs parseState 3) (FSComp.SR.parsUnexpectedSymbolDot()) let underscore = ident("_", rhs parseState 2) let mDot = rhs parseState 3 Some($1), prependIdentInLongIdentWithTrivia (SynIdent(underscore, None)) mDot $4 } | access pathOp { (Some($1), $2) } opt_access: | /* EMPTY */ { None } | access { Some($1) } access: | PRIVATE { let m = rhs parseState 1 SynAccess.Private m } | PUBLIC { let m = rhs parseState 1 SynAccess.Public m } | INTERNAL { let m = rhs parseState 1 SynAccess.Internal m } opt_interfaceImplDefn: | WITH objectImplementationBlock declEnd { let mWithKwd = rhs parseState 1 let members = $2 let m = (rhs parseState 1, members) ||> unionRangeWithListBy (fun (mem: SynMemberDefn) -> mem.Range) Some(mWithKwd, members, m) } | WITH { let mWithKwd = rhs parseState 1 Some(mWithKwd, [], mWithKwd) } | /* EMPTY */ { None } opt_classDefn: | WITH classDefnBlock declEnd { let mWithKwd = rhs parseState 1 (Some mWithKwd), $2 } | /* EMPTY */ { None, [] } /* An 'inherits' definition in an object type definition */ inheritsDefn: | INHERIT atomTypeNonAtomicDeprecated optBaseSpec { let mDecl = unionRanges (rhs parseState 1) (($2): SynType).Range SynMemberDefn.Inherit($2, $3, mDecl) } | INHERIT atomTypeNonAtomicDeprecated opt_HIGH_PRECEDENCE_APP atomicExprAfterType optBaseSpec { let mDecl = unionRanges (rhs parseState 1) $4.Range SynMemberDefn.ImplicitInherit($2, $4, $5, mDecl) } | INHERIT ends_coming_soon_or_recover { let mDecl = (rhs parseState 1) if not $2 then errorR(Error(FSComp.SR.parsTypeNameCannotBeEmpty(), mDecl)) SynMemberDefn.Inherit(SynType.LongIdent(SynLongIdent([], [], [])), None, mDecl) } optAsSpec: | asSpec { Some($1) } | /* EMPTY */ { None } asSpec: | AS ident { rhs parseState 1, $2 } optBaseSpec: | baseSpec { Some($1) } | /* EMPTY */ { 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) } /* The members in an object expression or interface implementation */ objectImplementationBlock: | OBLOCKBEGIN objectImplementationMembers oblockend { $2 } | OBLOCKBEGIN objectImplementationMembers recover { if not $3 then reportParseErrorAt (rhs parseState 3) (FSComp.SR.parsUnexpectedEndOfFileObjectMembers()) $2 } | objectImplementationMembers { $1 } /* The members in an object expression or interface implementation */ objectImplementationMembers: | objectImplementationMember opt_seps objectImplementationMembers { $1 @ $3 } | objectImplementationMember opt_seps { $1 } /* One member in an object expression or interface implementation */ objectImplementationMember: | opt_attributes staticMemberOrMemberOrOverride memberCore opt_ODECLEND { let rangeStart = rhs parseState 1 $3 None $2 $1 rangeStart } | opt_attributes staticMemberOrMemberOrOverride autoPropsDefnDecl opt_ODECLEND { let rangeStart = rhs parseState 1 $3 $1 $2 rangeStart } | opt_attributes staticMemberOrMemberOrOverride error { [] } | opt_attributes error memberCore opt_ODECLEND { [] } staticMemberOrMemberOrOverride: | STATIC MEMBER { let mStatic = rhs parseState 1 let mMember = rhs parseState 2 ImplementStaticMemberFlags, (SynLeadingKeyword.StaticMember(mStatic, mMember)) } | MEMBER { let mMember = rhs parseState 1 OverrideMemberFlags, (SynLeadingKeyword.Member mMember) } | OVERRIDE { let mOverride = rhs parseState 1 OverrideMemberFlags, (SynLeadingKeyword.Override mOverride) } /* The core of the right-hand-side of a simple type definition */ tyconDefnOrSpfnSimpleRepr: /* type MyAlias = SomeTypeProvider<@"foo"> is a common error, special-case it */ | opt_attributes opt_access path LQUOTE STRING recover { errorR(Error(FSComp.SR.parsUnexpectedQuotationOperatorInTypeAliasDidYouMeanVerbatimString(), rhs parseState 4)) SynTypeDefnSimpleRepr.TypeAbbrev(ParserDetail.ErrorRecovery, SynType.LongIdent($3), unionRanges (rhs parseState 1) $3.Range) } /* A type abbreviation */ | opt_attributes opt_access typ { if not (isNil $1) then errorR(Error(FSComp.SR.parsAttributesIllegalHere(), rhs parseState 1)) if Option.isSome $2 then errorR(Error(FSComp.SR.parsTypeAbbreviationsCannotHaveVisibilityDeclarations(), rhs parseState 2)) SynTypeDefnSimpleRepr.TypeAbbrev(ParserDetail.Ok, $3, unionRanges (rhs parseState 1) $3.Range) } /* A union type definition */ | opt_attributes opt_access unionTypeRepr { if not (isNil $1) then errorR(Error(FSComp.SR.parsAttributesIllegalHere(), rhs parseState 1)) let rangesOf3 = $3 |> List.map (function Choice1Of2 ec -> ec.Range | Choice2Of2 uc -> uc.Range) let mWhole = (rhs2 parseState 1 2, rangesOf3) ||> List.fold unionRanges if $3 |> List.exists (function Choice1Of2 _ -> true | _ -> false) then ( if Option.isSome $2 then errorR(Error(FSComp.SR.parsEnumTypesCannotHaveVisibilityDeclarations(), rhs parseState 2)) SynTypeDefnSimpleRepr.Enum($3 |> List.choose (function | Choice1Of2 data -> Some(data) | Choice2Of2(SynUnionCase(range=m)) -> errorR(Error(FSComp.SR.parsAllEnumFieldsRequireValues(), m)); None), mWhole) ) else SynTypeDefnSimpleRepr.Union($2, $3 |> List.choose (function Choice2Of2 data -> Some(data) | Choice1Of2 _ -> failwith "huh?"), mWhole) } /* A record type definition */ | opt_attributes opt_access braceFieldDeclList { if not (isNil $1) then errorR(Error(FSComp.SR.parsAttributesIllegalHere(), rhs parseState 1)) SynTypeDefnSimpleRepr.Record($2, $3, lhs parseState) } /* An inline-assembly type definition, for FSharp.Core library only */ | opt_attributes opt_access LPAREN HASH string HASH rparen { if not (isNil $1) then errorR(Error(FSComp.SR.parsAttributesIllegalHere(), rhs parseState 1)) let mLhs = lhs parseState if parseState.LexBuffer.ReportLibraryOnlyFeatures then libraryOnlyError mLhs if Option.isSome $2 then errorR(Error(FSComp.SR.parsInlineAssemblyCannotHaveVisibilityDeclarations(), rhs parseState 2)) let s, _ = $5 let ilType = ParseAssemblyCodeType s parseState.LexBuffer.ReportLibraryOnlyFeatures parseState.LexBuffer.LanguageVersion (rhs parseState 5) SynTypeDefnSimpleRepr.LibraryOnlyILAssembly(box ilType, mLhs) } /* The core of a record type definition */ braceFieldDeclList: | LBRACE recdFieldDeclList rbrace { $2 } | LBRACE recdFieldDeclList recover { reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnmatchedBrace()) $2 } | LBRACE error rbrace { [] } anonRecdType: | STRUCT braceBarFieldDeclListCore { $2, true } | braceBarFieldDeclListCore { $1, false } /* The core of a record type definition */ braceBarFieldDeclListCore: | LBRACE_BAR recdFieldDeclList bar_rbrace { $2 } | LBRACE_BAR recdFieldDeclList recover { reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnmatchedBraceBar()) $2 } | LBRACE_BAR error bar_rbrace { [] } classOrInterfaceOrStruct: | CLASS { SynTypeDefnKind.Class } | INTERFACE { SynTypeDefnKind.Interface } | STRUCT { SynTypeDefnKind.Struct } interfaceMember: | INTERFACE { } | OINTERFACE_MEMBER { } tyconNameAndTyparDecls: | opt_access path { None, $2.LongIdent, false, $1 } | opt_access prefixTyparDecls path { Some $2, $3.LongIdent, false, $1 } | opt_access path postfixTyparDecls { Some $3, $2.LongIdent, true, $1 } prefixTyparDecls: | typar { SynTyparDecls.SinglePrefix(SynTyparDecl([], $1), rhs parseState 1) } | LPAREN typarDeclList rparen { SynTyparDecls.PrefixList(List.rev $2, rhs2 parseState 1 3) } typarDeclList: | typarDeclList COMMA typarDecl { $3 :: $1 } | typarDecl { [$1] } typarDecl : | opt_attributes typar { SynTyparDecl($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 typarDeclList opt_typeConstraints GREATER { let m = rhs2 parseState 2 5 if not $2 then warning(Error(FSComp.SR.parsNonAdjacentTypars(), m)) SynTyparDecls.PostfixList(List.rev $3, $4, m) } /* 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: | typarDeclList COMMA DOT_DOT { (List.rev $1, true) } | typarDeclList { (List.rev $1, false) } | /* EMPTY */ { ([], false) } explicitValTyparDecls: | opt_HIGH_PRECEDENCE_TYAPP LESS explicitValTyparDeclsCore opt_typeConstraints GREATER { let m = rhs2 parseState 2 5 if not $2 then warning(Error(FSComp.SR.parsNonAdjacentTypars(), m)) let tps, flex = $3 let tps = SynTyparDecls.PostfixList(tps, $4, m) SynValTyparDecls(Some tps, flex) } opt_explicitValTyparDecls: | explicitValTyparDecls { $1 } | { SynValTyparDecls(None, true) } /* 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: | /* EMPTY */ { [] } | 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 { if parseState.LexBuffer.ReportLibraryOnlyFeatures then libraryOnlyError (lhs parseState) SynTypeConstraint.WhereTyparDefaultsToType($2, $4, lhs parseState) } | typar COLON_GREATER typ { SynTypeConstraint.WhereTyparSubtypeOfType($1, $3, lhs parseState) } | typar COLON STRUCT { SynTypeConstraint.WhereTyparIsValueType($1, lhs parseState) } | typar COLON IDENT STRUCT { if $3 <> "not" then reportParseErrorAt (rhs parseState 3) (FSComp.SR.parsUnexpectedIdentifier($3)) SynTypeConstraint.WhereTyparIsReferenceType($1, lhs parseState) } | typar COLON NULL { SynTypeConstraint.WhereTyparSupportsNull($1, lhs parseState) } | typar COLON LPAREN classMemberSpfn rparen { let tp = $1 SynTypeConstraint.WhereTyparSupportsMember(SynType.Var(tp, tp.Range), $4, lhs parseState) } | LPAREN typeAlts rparen COLON LPAREN classMemberSpfn rparen { let mParen = rhs2 parseState 1 3 let t = SynType.Paren($2, mParen) SynTypeConstraint.WhereTyparSupportsMember(t, $6, lhs parseState) } | typar COLON DELEGATE typeArgsNoHpaDeprecated { let _ltm, _gtm, args, _commas, mWhole = $4 SynTypeConstraint.WhereTyparIsDelegate($1, args, unionRanges $1.Range mWhole) } | typar COLON IDENT typeArgsNoHpaDeprecated { match $3 with | "enum" -> let _ltm, _gtm, args, _commas, mWhole = $4 SynTypeConstraint.WhereTyparIsEnum($1, args, unionRanges $1.Range mWhole) | nm -> raiseParseErrorAt (rhs parseState 3) (FSComp.SR.parsUnexpectedIdentifier(nm)) } | typar COLON IDENT { match $3 with | "comparison" -> SynTypeConstraint.WhereTyparIsComparable($1, lhs parseState) | "equality" -> SynTypeConstraint.WhereTyparIsEquatable($1, lhs parseState) | "unmanaged" -> SynTypeConstraint.WhereTyparIsUnmanaged($1, lhs parseState) | nm -> raiseParseErrorAt (rhs parseState 3) (FSComp.SR.parsUnexpectedIdentifier(nm)) } | appType { SynTypeConstraint.WhereSelfConstrained($1, lhs parseState) } typeAlts: | typeAlts OR appType { let mOr = rhs parseState 2 let m = unionRanges $1.Range $3.Range SynType.Or($1, $3, m, { OrKeyword = mOr }) } | appType { $1 } /* The core of a union type definition */ unionTypeRepr: /* 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 { let mBar = rhs parseState 1 grabXmlDoc(parseState, [], 1), mBar } attrUnionCaseDecls: | attrUnionCaseDecl barAndgrabXmlDoc attrUnionCaseDecls { (fun xmlDocAndBar -> $1 xmlDocAndBar :: $3 $2) } | attrUnionCaseDecl { (fun xmlDocAndBar -> [ $1 xmlDocAndBar ]) } /* The core of a union case definition */ attrUnionCaseDecl: | opt_attributes opt_access unionCaseName { if Option.isSome $2 then errorR(Error(FSComp.SR.parsUnionCasesCannotHaveVisibilityDeclarations(), rhs parseState 2)) let mDecl = rhs parseState 3 (fun (xmlDoc, mBar) -> let trivia: SynUnionCaseTrivia = { BarRange = Some mBar } let mDecl = unionRangeWithXmlDoc xmlDoc mDecl Choice2Of2 (SynUnionCase ($1, $3, SynUnionCaseKind.Fields [], xmlDoc, None, mDecl, trivia))) } | opt_attributes opt_access recover { if Option.isSome $2 then errorR(Error(FSComp.SR.parsUnionCasesCannotHaveVisibilityDeclarations(), rhs parseState 2)) (fun (xmlDoc, mBar) -> let id = SynIdent(mkSynId mBar.EndRange "", None) let trivia: SynUnionCaseTrivia = { BarRange = Some mBar } let mDecl = unionRangeWithXmlDoc xmlDoc mBar Choice2Of2 (SynUnionCase ($1, id, SynUnionCaseKind.Fields [], xmlDoc, None, mDecl, trivia))) } | opt_attributes opt_access unionCaseName OF unionCaseRepr { if Option.isSome $2 then errorR(Error(FSComp.SR.parsUnionCasesCannotHaveVisibilityDeclarations(), rhs parseState 2)) let mDecl = rhs2 parseState 1 5 (fun (xmlDoc, mBar) -> let trivia: SynUnionCaseTrivia = { BarRange = Some mBar } let mDecl = unionRangeWithXmlDoc xmlDoc mDecl Choice2Of2 (SynUnionCase ($1, $3, SynUnionCaseKind.Fields $5, xmlDoc, None, mDecl, trivia))) } | opt_attributes opt_access OF unionCaseRepr { if Option.isSome $2 then errorR(Error(FSComp.SR.parsUnionCasesCannotHaveVisibilityDeclarations(), rhs parseState 2)) let mOf = rhs parseState 3 let mId = mOf.StartRange errorR (Error(FSComp.SR.parsMissingUnionCaseName(), mOf)) let mDecl = rhs2 parseState 1 4 (fun (xmlDoc, mBar) -> let id = SynIdent(mkSynId mId "", None) let trivia: SynUnionCaseTrivia = { BarRange = Some mBar } let mDecl = unionRangeWithXmlDoc xmlDoc mDecl Choice2Of2(SynUnionCase($1, id, SynUnionCaseKind.Fields $4, xmlDoc, None, mDecl, trivia))) } | opt_attributes opt_access OF recover { if Option.isSome $2 then errorR(Error(FSComp.SR.parsUnionCasesCannotHaveVisibilityDeclarations(), rhs parseState 2)) let mOf = rhs parseState 3 let mId = mOf.StartRange errorR (Error(FSComp.SR.parsMissingUnionCaseName(), mOf)) let mDecl = rhs2 parseState 1 3 (fun (xmlDoc, mBar) -> let id = SynIdent(mkSynId mId "", None) let trivia: SynUnionCaseTrivia = { BarRange = Some mBar } let mDecl = unionRangeWithXmlDoc xmlDoc mDecl Choice2Of2(SynUnionCase($1, id, SynUnionCaseKind.Fields [], xmlDoc, None, mDecl, trivia))) } | opt_attributes opt_access unionCaseName OF recover { if Option.isSome $2 then errorR(Error(FSComp.SR.parsUnionCasesCannotHaveVisibilityDeclarations(), rhs parseState 2)) let mDecl = rhs2 parseState 1 4 (fun (xmlDoc, mBar) -> let trivia: SynUnionCaseTrivia = { BarRange = Some mBar } let mDecl = unionRangeWithXmlDoc xmlDoc mDecl Choice2Of2 (SynUnionCase ($1, $3, SynUnionCaseKind.Fields [], xmlDoc, None, mDecl, trivia))) } | opt_attributes opt_access unionCaseName COLON topType { if Option.isSome $2 then errorR(Error(FSComp.SR.parsUnionCasesCannotHaveVisibilityDeclarations(), rhs parseState 2)) if parseState.LexBuffer.ReportLibraryOnlyFeatures then libraryOnlyWarning(lhs parseState) let mDecl = rhs2 parseState 1 5 (fun (xmlDoc, mBar) -> let trivia: SynUnionCaseTrivia = { BarRange = Some mBar } let mDecl = unionRangeWithXmlDoc xmlDoc mDecl Choice2Of2 (SynUnionCase ($1, $3, SynUnionCaseKind.FullType $5, xmlDoc, None, mDecl, trivia))) } | opt_attributes opt_access unionCaseName EQUALS atomicExpr { if Option.isSome $2 then errorR(Error(FSComp.SR.parsEnumFieldsCannotHaveVisibilityDeclarations(), rhs parseState 2)) let mEquals = rhs parseState 4 let mDecl = rhs2 parseState 1 5 (fun (xmlDoc, mBar) -> let trivia: SynEnumCaseTrivia = { BarRange = Some mBar; EqualsRange = mEquals } let mDecl = unionRangeWithXmlDoc xmlDoc mDecl Choice1Of2 (SynEnumCase ($1, $3, fst $5, xmlDoc, mDecl, trivia))) } /* The name of a union case */ unionCaseName: | nameop { $1 } | LPAREN COLON_COLON rparen { let lpr = rhs parseState 1 let rpr = rhs parseState 3 SynIdent(ident(opNameCons, rhs parseState 2), Some(IdentTrivia.OriginalNotationWithParen(lpr, "::", rpr))) } | LPAREN LBRACK RBRACK rparen { let lpr = rhs parseState 1 let rpr = rhs parseState 3 SynIdent(ident(opNameNil, rhs2 parseState 2 3), Some(IdentTrivia.OriginalNotationWithParen(lpr, "[]", rpr))) } firstUnionCaseDeclOfMany: | ident opt_OBLOCKSEP { let trivia: SynUnionCaseTrivia = { BarRange = None } let xmlDoc = grabXmlDoc(parseState, [], 1) let mDecl = (rhs parseState 1) |> unionRangeWithXmlDoc xmlDoc Choice2Of2 (SynUnionCase ([], (SynIdent($1, None)), SynUnionCaseKind.Fields [], xmlDoc, None, mDecl, trivia)) } | ident EQUALS atomicExpr opt_OBLOCKSEP { let mEquals = rhs parseState 2 let trivia: SynEnumCaseTrivia = { BarRange = None; EqualsRange = mEquals } let xmlDoc = grabXmlDoc(parseState, [], 1) let mDecl = (rhs2 parseState 1 3) |> unionRangeWithXmlDoc xmlDoc Choice1Of2 (SynEnumCase ([], SynIdent($1, None), fst $3, xmlDoc, mDecl, trivia)) } | firstUnionCaseDecl opt_OBLOCKSEP { $1 } firstUnionCaseDecl: | ident OF unionCaseRepr { let trivia: SynUnionCaseTrivia = { BarRange = None } let xmlDoc = grabXmlDoc (parseState, [], 1) let mDecl = rhs2 parseState 1 3 |> unionRangeWithXmlDoc xmlDoc Choice2Of2(SynUnionCase([], SynIdent($1, None), SynUnionCaseKind.Fields $3, xmlDoc, None, mDecl, trivia)) } | ident OF recover { let trivia: SynUnionCaseTrivia = { BarRange = None } let xmlDoc = grabXmlDoc (parseState, [], 1) let mDecl = rhs2 parseState 1 2 |> unionRangeWithXmlDoc xmlDoc Choice2Of2(SynUnionCase([], SynIdent($1, None), SynUnionCaseKind.Fields [], xmlDoc, None, mDecl, trivia)) } | OF unionCaseRepr { let mOf = rhs parseState 1 let mId = mOf.StartRange errorR (Error(FSComp.SR.parsMissingUnionCaseName(), mOf)) let id = SynIdent(mkSynId mId "", None) let trivia: SynUnionCaseTrivia = { BarRange = None } let xmlDoc = grabXmlDoc (parseState, [], 1) let mDecl = rhs2 parseState 1 2 |> unionRangeWithXmlDoc xmlDoc Choice2Of2(SynUnionCase([], id, SynUnionCaseKind.Fields $2, xmlDoc, None, mDecl, trivia)) } | ident EQUALS atomicExpr opt_OBLOCKSEP { let mEquals = rhs parseState 2 let trivia: SynEnumCaseTrivia = { BarRange = None; EqualsRange = mEquals } let xmlDoc = grabXmlDoc (parseState, [], 1) let mDecl = rhs2 parseState 1 3 |> unionRangeWithXmlDoc xmlDoc Choice1Of2(SynEnumCase([], SynIdent($1, None), fst $3, xmlDoc, mDecl, trivia)) } unionCaseReprElements: | unionCaseReprElement STAR unionCaseReprElements { $1 :: $3 } | unionCaseReprElement %prec prec_toptuptyptail_prefix { [$1] } unionCaseReprElement: | ident COLON appType { let xmlDoc = grabXmlDoc(parseState, [], 1) let mWhole = rhs2 parseState 1 3 |> unionRangeWithXmlDoc xmlDoc mkSynNamedField ($1, $3, xmlDoc, mWhole) } | appType { let xmlDoc = grabXmlDoc(parseState, [], 1) mkSynAnonField ($1, xmlDoc) } unionCaseRepr: | braceFieldDeclList { errorR(Deprecated(FSComp.SR.parsConsiderUsingSeparateRecordType(), lhs parseState)) $1 } | unionCaseReprElements { $1 } /* A list of field declarations in a record type */ recdFieldDeclList: | recdFieldDecl seps recdFieldDeclList { $1 :: $3 } | recdFieldDecl opt_seps { [$1] } /* A field declaration in a record type */ recdFieldDecl: | opt_attributes fieldDecl { let mWhole = rhs2 parseState 1 2 let fld = $2 $1 false mWhole None let (SynField (a, b, c, d, e, xmlDoc, vis, mWhole, trivia)) = fld if Option.isSome vis then errorR (Error (FSComp.SR.parsRecordFieldsCannotHaveVisibilityDeclarations (), rhs parseState 2)) let mWhole = unionRangeWithXmlDoc xmlDoc mWhole SynField (a, b, c, d, e, xmlDoc, None, mWhole, trivia) } /* Part of a field or val declaration in a record type or object type */ fieldDecl: | opt_mutable opt_access ident COLON typ { fun attrs stat mWhole leadingKeyword -> let xmlDoc = grabXmlDocAtRangeStart(parseState, attrs, mWhole) SynField(attrs, stat, Some $3, $5, $1, xmlDoc, $2, mWhole, { LeadingKeyword = leadingKeyword }) } /* An exception definition */ exconDefn: | exconCore opt_classDefn { let mWith, optClassDefn = $2 SynExceptionDefn($1, mWith, optClassDefn, ($1.Range, optClassDefn) ||> unionRangeWithListBy (fun cd -> cd.Range)) } /* Part of an exception definition */ exconCore: | EXCEPTION opt_attributes opt_access exconIntro exconRepr { let m = match $5 with | None -> rhs2 parseState 1 4 | Some p -> unionRanges (rangeOfLongIdent p) (rhs2 parseState 1 4) SynExceptionDefnRepr($2, $4, $5, PreXmlDoc.Empty, $3, m) } | EXCEPTION opt_attributes opt_access recover { let m = match $3 with | Some access -> unionRanges (rhs parseState 1) access.Range | _ -> match $2 with | [] -> rhs parseState 1 | attrs -> ((rhs parseState 1), attrs) ||> unionRangeWithListBy (fun (a: SynAttributeList) -> a.Range) let id = SynIdent(mkSynId m.EndRange "", None) let unionCase = SynUnionCase([], id, SynUnionCaseKind.Fields [], PreXmlDoc.Empty, None, m, { BarRange = None }) SynExceptionDefnRepr($2, unionCase, None, PreXmlDoc.Empty, $3, m) } /* Part of an exception definition */ exconIntro: | ident { SynUnionCase([], SynIdent($1, None), SynUnionCaseKind.Fields [], PreXmlDoc.Empty, None, lhs parseState, { BarRange = None }) } | ident OF unionCaseRepr { SynUnionCase([], SynIdent($1, None), SynUnionCaseKind.Fields $3, PreXmlDoc.Empty, None, lhs parseState, { BarRange = None }) } | ident OF recover { SynUnionCase([], SynIdent($1, None), SynUnionCaseKind.Fields [], PreXmlDoc.Empty, None, lhs parseState, { BarRange = None }) } exconRepr: | /* EMPTY */ { None } | EQUALS path { Some($2.LongIdent) } /*-------------------------------------------------------------------------*/ /* F# Definitions, Types, Patterns and Expressions */ /* A 'let ...' or 'do ...' statement in the non-#light syntax */ defnBindings: | LET opt_rec localBindings { let mLetKwd = rhs parseState 1 let isUse = $1 let isRec = $2 let leadingKeyword = if isRec then SynLeadingKeyword.LetRec(mLetKwd, rhs parseState 2) else SynLeadingKeyword.Let(mLetKwd) let localBindingsLastRangeOpt, localBindingsBuilder = $3 // Calculate the precise range of the binding set, up to the end of the last r.h.s. expression let bindingSetRange = match localBindingsLastRangeOpt with | None -> rhs2 parseState 1 2 (* there was some error - this will be an approximate range *) | Some lastRange -> unionRanges mLetKwd lastRange // The first binding swallows any attributes prior to the 'let' BindingSetPreAttrs(mLetKwd, isRec, isUse, (fun attrs vis -> let xmlDoc = grabXmlDoc(parseState, attrs, 1) // apply the builder let binds = localBindingsBuilder xmlDoc attrs vis leadingKeyword if not isRec && not (isNilOrSingleton binds) then reportParseErrorAt mLetKwd (FSComp.SR.parsLetAndForNonRecBindings()) [], binds), bindingSetRange) } | cPrototype { let bindRange = lhs parseState BindingSetPreAttrs(bindRange, false, false, $1, bindRange) } /* A 'do ...' statement in the non-#light syntax */ doBinding: | DO typedSequentialExprBlock { let mDoKwd = rhs parseState 1 let mWhole = unionRanges mDoKwd $2.Range // 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(mDoKwd, false, false, (fun attrs vis -> attrs, [mkSynDoBinding (vis, mDoKwd, $2, mWhole)]), mWhole) } /* A 'let ....' binding in the #light syntax */ hardwhiteLetBindings: | OLET opt_rec localBindings hardwhiteDefnBindingsTerminator { let mLetKwd = rhs parseState 1 let isUse = $1 let isRec = $2 let leadingKeyword = if not isUse && isRec then SynLeadingKeyword.LetRec(mLetKwd, rhs parseState 2) elif isUse && not isRec then SynLeadingKeyword.Use mLetKwd elif isUse && isRec then SynLeadingKeyword.UseRec(mLetKwd, rhs parseState 2) else SynLeadingKeyword.Let(mLetKwd) let report, mIn = $4 report (if isUse then "use" else "let") mLetKwd // report unterminated error let localBindingsLastRangeOpt, localBindingsBuilder = $3 // Calculate the precise range of the binding set, up to the end of the last r.h.s. expression let bindingSetRange = match localBindingsLastRangeOpt with | None -> rhs parseState 1 (* there was some error - this will be an approximate range *) | Some lastRange -> unionRanges mLetKwd lastRange // the first binding swallow any attributes prior to the 'let' BindingSetPreAttrs(mLetKwd, isRec, isUse, (fun attrs vis -> let xmlDoc = grabXmlDoc(parseState, attrs, 1) let binds = localBindingsBuilder xmlDoc attrs vis leadingKeyword if not isRec && not (isNilOrSingleton binds) then reportParseErrorAt mLetKwd (FSComp.SR.parsLetAndForNonRecBindings()) [], binds), bindingSetRange), (unionRanges mLetKwd bindingSetRange), mIn } /* A 'do ...' statement */ hardwhiteDoBinding: | ODO typedSequentialExprBlock hardwhiteDefnBindingsTerminator { let mDoKwd = rhs parseState 1 let bindingSetRange = unionRanges mDoKwd $2.Range let seqPt = DebugPointAtBinding.NoneAtDo // 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(mDoKwd, false, false, (fun attrs vis -> attrs, [mkSynDoBinding (vis, mDoKwd, $2, bindingSetRange)]), bindingSetRange), $2 } /* The bindings in a class type definition */ classDefnBindings: | defnBindings { $1 } | doBinding { $1 } | hardwhiteLetBindings { let b, m, _ = $1 b } | hardwhiteDoBinding { fst $1 } /* The terminator for a 'let ....' binding in the #light syntax */ hardwhiteDefnBindingsTerminator: | ODECLEND { let mToken = rhs parseState 1 // In LexFilter.fs the IN token could have been transformed to an ODECLEND one. let mIn = if (mToken.EndColumn - mToken.StartColumn) = 2 then Some mToken else None (fun _ m -> ()), mIn } | recover { (fun kwd m -> let msg = match kwd with | "let!" -> FSComp.SR.parsUnmatchedLetBang() | "use!" -> FSComp.SR.parsUnmatchedUseBang() | "use" -> FSComp.SR.parsUnmatchedUse() | _ (*"let" *) -> FSComp.SR.parsUnmatchedLet() reportParseErrorAt m msg), None } /* An 'extern' DllImport function definition in C-style syntax */ cPrototype: | EXTERN cRetType opt_access ident opt_HIGH_PRECEDENCE_APP LPAREN externArgs rparen { let mExtern = rhs parseState 1 let rty, vis, nm, (args, commas) = $2, $3, $4, $7 let nmm = rhs parseState 3 let argsm = rhs parseState 6 let mBindLhs = lhs parseState let mWhole = lhs parseState let mRhs = lhs parseState let rhsExpr = SynExpr.App( ExprAtomicFlag.NonAtomic, false, SynExpr.Ident(ident("failwith", rhs parseState 6)), SynExpr.Const(SynConst.String("extern was not given a DllImport attribute", SynStringKind.Regular, rhs parseState 8), rhs parseState 8), mRhs) (fun attrs _ -> let bindingPat = SynPat.LongIdent(SynLongIdent([nm], [], [None]), None, Some noInferredTypars, SynArgPats.Pats [SynPat.Tuple(false, args, commas, argsm)], vis, nmm) let mWholeBindLhs = (mBindLhs, attrs) ||> unionRangeWithListBy (fun (a: SynAttributeList) -> a.Range) let xmlDoc = grabXmlDoc(parseState, attrs, 1) let trivia = { LeadingKeyword = SynLeadingKeyword.Extern mExtern; InlineKeyword = None; EqualsRange = None } let binding = mkSynBinding (xmlDoc, bindingPat) (vis, false, false, mWholeBindLhs, DebugPointAtBinding.NoneAtInvisible, Some(None, rty), rhsExpr, mRhs, [], attrs, None, trivia) [], [binding]) } /* A list of arguments in an 'extern' DllImport function definition */ externArgs: | externMoreArgs { let args, commas = $1 List.rev args, (List.rev commas) } | externArg { [$1], [] } | { [], [] } /* Part of the list of arguments in an 'extern' DllImport function definition */ externMoreArgs: | externMoreArgs COMMA externArg { let args, commas = $1 let mComma = rhs parseState 2 $3 :: args, (mComma :: commas) } | externArg COMMA externArg { let mComma = rhs parseState 2 [$3; $1], [mComma] } /* A single argument in an 'extern' DllImport function definition */ externArg: | opt_attributes cType { let m = lhs parseState SynPat.Typed(SynPat.Wild m, $2, m) |> addAttribs $1 } | opt_attributes cType ident { let m = lhs parseState SynPat.Typed(SynPat.Named(SynIdent($3, None), false, None, m), $2, m) |> addAttribs $1 } /* An type in an 'extern' DllImport function definition */ cType: | path { let m = $1.Range SynType.App(SynType.LongIdent($1), None, [], [], None, false, m) } | cType opt_HIGH_PRECEDENCE_APP LBRACK RBRACK { let m = lhs parseState SynType.App(SynType.LongIdent(SynLongIdent([ident("[]", m)], [], [None])), None, [$1], [], None, true, m) } | cType STAR { let m = lhs parseState SynType.App(SynType.LongIdent(SynLongIdent([ident("nativeptr", m)], [], [ Some(IdentTrivia.OriginalNotation "*") ])), None, [$1], [], None, true, m) } | cType AMP { let m = lhs parseState SynType.App(SynType.LongIdent(SynLongIdent([ident("byref", m)], [], [ Some(IdentTrivia.OriginalNotation "&") ])), None, [$1], [], None, true, m) } | VOID STAR { let m = lhs parseState SynType.App(SynType.LongIdent(SynLongIdent([ident("nativeint", m)], [], [ Some(IdentTrivia.OriginalNotation "void*") ])), None, [], [], None, true, m) } /* A return type in an 'extern' DllImport function definition */ cRetType: | opt_attributes cType { SynReturnInfo(($2, SynArgInfo($1, false, None)), rhs parseState 2) } | opt_attributes VOID { let m = rhs parseState 2 SynReturnInfo((SynType.App(SynType.LongIdent(SynLongIdent([ident("unit", m)], [], [ Some(IdentTrivia.OriginalNotation "void") ])), None, [], [], None, false, m), SynArgInfo($1, false, None)), m) } localBindings: | attr_localBinding moreLocalBindings { let (moreBindings, moreBindingRanges) = List.unzip $2 let moreLocalBindingsLastRange = if moreBindingRanges.IsEmpty then None else Some(List.last moreBindingRanges) match $1 with | Some(localBindingRange, attrLocalBindingBuilder) -> let lastRange = match moreLocalBindingsLastRange with | None -> localBindingRange | Some m -> m Some lastRange, (fun xmlDoc attrs vis leadingKeyword -> attrLocalBindingBuilder xmlDoc attrs vis leadingKeyword true :: moreBindings) | None -> moreLocalBindingsLastRange, (fun _xmlDoc _attrs _vis _leadingKeyword -> moreBindings) } moreLocalBindings: | AND attr_localBinding moreLocalBindings { let leadingKeyword = SynLeadingKeyword.And(rhs parseState 1) (match $2 with | Some(localBindingRange, attrLocalBindingBuilder) -> let xmlDoc = grabXmlDoc(parseState, [], 1) let xmlDoc = if xmlDoc.IsEmpty then grabXmlDoc(parseState, [], 2) else xmlDoc (attrLocalBindingBuilder xmlDoc [] None leadingKeyword false, localBindingRange) :: $3 | None -> $3) } | %prec prec_no_more_attr_bindings { [] } /* A single binding, possibly with custom attributes */ attr_localBinding: | opt_attributes localBinding { let attrs2 = $1 let localBindingRange, localBindingBuilder = $2 let attrLocalBindingBuilder = (fun xmlDoc attrs vis leadingKeyword _ -> localBindingBuilder xmlDoc (attrs@attrs2) vis leadingKeyword) Some(localBindingRange, attrLocalBindingBuilder) } | error { None } /* A single binding in an expression or definition */ localBinding: | opt_inline opt_mutable bindingPattern opt_topReturnTypeWithTypeConstraints EQUALS typedExprWithStaticOptimizationsBlock { let (expr: SynExpr), opts = $6 let mEquals = rhs parseState 5 let mRhs = expr.Range let optReturnType = $4 let bindingPat, mBindLhs = $3 let localBindingRange = unionRanges (rhs2 parseState 1 5) mRhs let localBindingBuilder = (fun xmlDoc attrs vis (leadingKeyword: SynLeadingKeyword) -> let mWhole = (unionRanges leadingKeyword.Range mRhs, attrs) ||> unionRangeWithListBy (fun (a: SynAttributeList) -> a.Range) let spBind = if IsDebugPointBinding bindingPat expr then DebugPointAtBinding.Yes mWhole else DebugPointAtBinding.NoneAtLet let mWholeBindLhs = (mBindLhs, attrs) ||> unionRangeWithListBy (fun (a: SynAttributeList) -> a.Range) let trivia: SynBindingTrivia = { LeadingKeyword = leadingKeyword; InlineKeyword = $1; EqualsRange = Some mEquals } mkSynBinding (xmlDoc, bindingPat) (vis, Option.isSome $1, $2, mWholeBindLhs, spBind, optReturnType, expr, mRhs, opts, attrs, None, trivia)) localBindingRange, localBindingBuilder } | opt_inline opt_mutable bindingPattern opt_topReturnTypeWithTypeConstraints EQUALS error { let mWhole = rhs2 parseState 1 5 let mRhs = rhs parseState 5 let optReturnType = $4 let bindingPat, mBindLhs = $3 let localBindingBuilder = (fun xmlDoc attrs vis leadingKeyword -> let mEquals = rhs parseState 5 let zeroWidthAtEnd = mEquals.EndRange let rhsExpr = arbExpr ("localBinding1", zeroWidthAtEnd) let spBind = if IsDebugPointBinding bindingPat rhsExpr then DebugPointAtBinding.Yes mWhole else DebugPointAtBinding.NoneAtLet let trivia: SynBindingTrivia = { LeadingKeyword = leadingKeyword; InlineKeyword = $1; EqualsRange = Some mEquals } mkSynBinding (xmlDoc, bindingPat) (vis, Option.isSome $1, $2, mBindLhs, spBind, optReturnType, rhsExpr, mRhs, [], attrs, None, trivia)) mWhole, localBindingBuilder } | opt_inline opt_mutable bindingPattern opt_topReturnTypeWithTypeConstraints recover { if not $5 then reportParseErrorAt (rhs parseState 5) (FSComp.SR.parsUnexpectedEndOfFileDefinition()) let optReturnType = $4 let mWhole = rhs2 parseState 1 (match optReturnType with None -> 3 | _ -> 4) let mRhs = mWhole.EndRange // zero-width range at end of last good token let bindingPat, mBindLhs = $3 let localBindingBuilder = (fun xmlDoc attrs vis (leadingKeyword: SynLeadingKeyword) -> let spBind = DebugPointAtBinding.Yes(unionRanges leadingKeyword.Range mRhs) let trivia = { LeadingKeyword = leadingKeyword; InlineKeyword = $1; EqualsRange = None } let rhsExpr = arbExpr ("localBinding2", mRhs) mkSynBinding (xmlDoc, bindingPat) (vis, Option.isSome $1, $2, mBindLhs, spBind, optReturnType, rhsExpr, mRhs, [], attrs, None, trivia)) mWhole, localBindingBuilder } /* A single expression with an optional type annotation, and an optional static optimization block */ typedExprWithStaticOptimizationsBlock: | OBLOCKBEGIN typedExprWithStaticOptimizations oblockend { $2 } | OBLOCKBEGIN typedExprWithStaticOptimizations recover { if not $3 then reportParseErrorAt (rhs parseState 3) (FSComp.SR.parsUnexpectedEndOfFile()) let a, b = $2 (exprFromParseError a, b) } | typedExprWithStaticOptimizations { $1 } typedExprWithStaticOptimizations : | typedSequentialExpr opt_staticOptimizations { $1, List.rev $2 } opt_staticOptimizations: | opt_staticOptimizations staticOptimization { $2 :: $1 } | /* EMPTY */ { [] } staticOptimization: | WHEN staticOptimizationConditions EQUALS typedSequentialExprBlock { ($2, $4) } staticOptimizationConditions: | staticOptimizationConditions AND staticOptimizationCondition { $3 :: $1 } | staticOptimizationCondition { [$1 ] } staticOptimizationCondition: | typar COLON typ { SynStaticOptimizationConstraint.WhenTyparTyconEqualsTycon($1, $3, lhs parseState) } | typar STRUCT { SynStaticOptimizationConstraint.WhenTyparIsStruct($1, lhs parseState) } 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 { if snd $1 then errorR(Error(FSComp.SR.lexOutsideNativeSigned(), lhs parseState)) SynConst.IntPtr(fst $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 } | string { let s, synStringKind = $1 SynConst.String(s, synStringKind, lhs parseState) } | sourceIdentifier { let c, v = $1 SynConst.SourceIdentifier(c, v, lhs parseState) } | BYTEARRAY { let (v, synByteStringKind, _) = $1 SynConst.Bytes(v, synByteStringKind, lhs parseState) } rationalConstant: | INT32 INFIX_STAR_DIV_MOD_OP INT32 { if $2 <> "/" then reportParseErrorAt (rhs parseState 2) (FSComp.SR.parsUnexpectedOperatorForUnitOfMeasure()) if fst $3 = 0 then reportParseErrorAt (rhs parseState 3) (FSComp.SR.parsIllegalDenominatorForMeasureExponent()) if (snd $1) || (snd $3) then errorR(Error(FSComp.SR.lexOutsideThirtyTwoBitSigned(), lhs parseState)) SynRationalConst.Rational(fst $1, fst $3, lhs parseState) } | MINUS INT32 INFIX_STAR_DIV_MOD_OP INT32 { if $3 <> "/" then reportParseErrorAt (rhs parseState 3) (FSComp.SR.parsUnexpectedOperatorForUnitOfMeasure()) if fst $4 = 0 then reportParseErrorAt (rhs parseState 4) (FSComp.SR.parsIllegalDenominatorForMeasureExponent()) if (snd $2) || (snd $4) then errorR(Error(FSComp.SR.lexOutsideThirtyTwoBitSigned(), lhs parseState)) SynRationalConst.Negate(SynRationalConst.Rational(fst $2, fst $4, lhs parseState)) } | INT32 { if snd $1 then errorR(Error(FSComp.SR.lexOutsideThirtyTwoBitSigned(), lhs parseState)) SynRationalConst.Integer(fst $1) } | MINUS INT32 { if snd $2 then errorR(Error(FSComp.SR.lexOutsideThirtyTwoBitSigned(), lhs parseState)) SynRationalConst.Negate(SynRationalConst.Integer(fst $2)) } atomicUnsignedRationalConstant: | INT32 { if snd $1 then errorR(Error(FSComp.SR.lexOutsideThirtyTwoBitSigned(), lhs parseState)) SynRationalConst.Integer(fst $1) } | LPAREN rationalConstant rparen { $2 } atomicRationalConstant: | atomicUnsignedRationalConstant { $1 } | MINUS atomicUnsignedRationalConstant { SynRationalConst.Negate($2) } constant: | rawConstant { $1, rhs parseState 1 } | rawConstant HIGH_PRECEDENCE_TYAPP measureTypeArg { SynConst.Measure($1, rhs parseState 1, $3), lhs parseState } bindingPattern: | headBindingPattern { $1, rhs parseState 1 } // Subset of patterns allowed to be used in implicit ctors. // For a better error recovery we could replace these rules with the actual SynPat parsing // and use allowed patterns only at a later analysis stage reporting errors along the way. simplePattern: | ident { let m = rhs parseState 1 SynPat.Named(SynIdent($1, None), false, None, m) } | QMARK ident { SynPat.OptionalVal($2, rhs parseState 2) } | simplePattern COLON typeWithTypeConstraints { SynPat.Typed($1, $3, lhs parseState) } | simplePattern COLON recover { let mColon = rhs parseState 2 let ty = SynType.FromParseError(mColon.EndRange) SynPat.Typed($1, ty, unionRanges $1.Range mColon) } | attributes simplePattern %prec paren_pat_attribs { SynPat.Attrib($2, $1, lhs parseState) } simplePatternCommaList: | simplePattern { $1 } | simplePattern COMMA simplePatternCommaList { let mComma = rhs parseState 2 match $3 with | SynPat.Tuple(_, pats, commas, _) -> SynPat.Tuple(false, $1 :: pats, mComma :: commas, rhs2 parseState 1 3) | _ -> SynPat.Tuple(false, [$1; $3], [mComma], rhs2 parseState 1 3) } simplePatterns: | LPAREN simplePatternCommaList rparen { let parenPat = SynPat.Paren($2, rhs2 parseState 1 3) let simplePats, _ = SimplePatsOfPat parseState.SynArgNameGenerator parenPat simplePats } | LPAREN rparen { let pat = SynPat.Const(SynConst.Unit, rhs2 parseState 1 2) let simplePats, _ = SimplePatsOfPat parseState.SynArgNameGenerator pat simplePats } | LPAREN simplePatternCommaList recover { reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnmatchedParen()) let parenPat = SynPat.Paren(SynPat.Tuple(false, [], [], rhs2 parseState 1 2), rhs2 parseState 1 2) // todo: report parsed pats anyway? let simplePats, _ = SimplePatsOfPat parseState.SynArgNameGenerator parenPat simplePats } | LPAREN error rparen { let parenPat = SynPat.Paren(SynPat.Wild(rhs parseState 2), rhs2 parseState 1 3) // silent recovery let simplePats, _ = SimplePatsOfPat parseState.SynArgNameGenerator parenPat simplePats } | LPAREN recover { reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnmatchedParen()) let pat = SynPat.Wild(lhs parseState) let simplePats, _ = SimplePatsOfPat parseState.SynArgNameGenerator pat simplePats } headBindingPattern: | headBindingPattern AS constrPattern { SynPat.As($1, $3, rhs2 parseState 1 3) } | headBindingPattern BAR headBindingPattern { let mBar = rhs parseState 2 SynPat.Or($1, $3, rhs2 parseState 1 3, { BarRange = mBar }) } | headBindingPattern COLON_COLON headBindingPattern { let mColonColon = rhs parseState 2 SynPat.ListCons($1, $3, rhs2 parseState 1 3, { ColonColonRange = mColonColon }) } | tuplePatternElements %prec pat_tuple { let pats, commas = $1 let pats, commas = normalizeTuplePat pats commas let m = (rhs parseState 1, pats) ||> unionRangeWithListBy (fun p -> p.Range) SynPat.Tuple(false, List.rev pats, List.rev commas, m) } | conjPatternElements %prec pat_conj { SynPat.Ands(List.rev $1, lhs parseState) } | constrPattern { $1 } tuplePatternElements: | tuplePatternElements COMMA headBindingPattern { let pats, commas = $1 $3 :: pats, (rhs parseState 2 :: commas) } | headBindingPattern COMMA headBindingPattern { [$3; $1], [rhs parseState 2] } | tuplePatternElements COMMA ends_coming_soon_or_recover { let pats, commas = $1 let commaRange = rhs parseState 2 reportParseErrorAt commaRange (FSComp.SR.parsExpectingPatternInTuple ()) let pat2 = SynPat.Wild(commaRange.EndRange) pat2 :: pats, (commaRange :: commas) } | headBindingPattern COMMA ends_coming_soon_or_recover { let commaRange = rhs parseState 2 reportParseErrorAt commaRange (FSComp.SR.parsExpectingPatternInTuple ()) let pat2 = SynPat.Wild(commaRange.EndRange) [pat2; $1], [commaRange] } | COMMA headBindingPattern { let commaRange = rhs parseState 1 reportParseErrorAt commaRange (FSComp.SR.parsExpectingPatternInTuple ()) let pat1 = SynPat.Wild(commaRange.StartRange) [$2; pat1], [commaRange] } | COMMA ends_coming_soon_or_recover { let commaRange = rhs parseState 1 if not $2 then reportParseErrorAt commaRange (FSComp.SR.parsExpectedPatternAfterToken ()) let pat1 = SynPat.Wild(commaRange.StartRange) let pat2 = SynPat.Wild(commaRange.EndRange) [pat2; pat1], [commaRange] } conjPatternElements: | conjPatternElements AMP headBindingPattern { $3 :: $1 } | headBindingPattern AMP headBindingPattern { $3 :: $1 :: [] } namePatPairs: | namePatPair opt_seps { [$1], lhs parseState } | namePatPair seps namePatPairs { let (rs, _) = $3 ($1 :: rs), lhs parseState } namePatPair: | ident EQUALS parenPattern { let mEquals = rhs parseState 2 ($1, Some mEquals, $3) } | ident EQUALS recover { let mEquals = rhs parseState 2 ($1, Some mEquals, patFromParseError (SynPat.Wild mEquals.EndRange)) } | ident recover { ($1, None, patFromParseError (SynPat.Wild $1.idRange.EndRange)) } constrPattern: | atomicPatternLongIdent explicitValTyparDecls { let vis, lid = $1 SynPat.LongIdent(lid, None, Some $2, SynArgPats.Pats [], vis, lhs parseState) } | atomicPatternLongIdent explicitValTyparDecls atomicPatsOrNamePatPairs %prec pat_app { let vis, lid = $1 let args, argsM = $3 let m = unionRanges (rhs2 parseState 1 2) argsM SynPat.LongIdent(lid, None, Some $2, args, vis, m) } | atomicPatternLongIdent explicitValTyparDecls HIGH_PRECEDENCE_PAREN_APP atomicPatsOrNamePatPairs { let vis, lid = $1 let args, argsM = $4 let m = unionRanges (rhs2 parseState 1 2) argsM SynPat.LongIdent(lid, None, Some $2, args, vis, m) } | atomicPatternLongIdent explicitValTyparDecls HIGH_PRECEDENCE_BRACK_APP atomicPatsOrNamePatPairs { let vis, lid = $1 let args, argsM = $4 let m = unionRanges (rhs2 parseState 1 2) argsM SynPat.LongIdent(lid, None, Some $2, args, vis, m) } | atomicPatternLongIdent atomicPatsOrNamePatPairs %prec pat_app { let vis, lid = $1 let args, argsM = $2 let m = unionRanges (rhs parseState 1) argsM SynPat.LongIdent(lid, None, None, args, vis, m) } | atomicPatternLongIdent HIGH_PRECEDENCE_PAREN_APP atomicPatsOrNamePatPairs { let vis, lid = $1 let args, argsM = $3 let m = unionRanges (rhs parseState 1) argsM SynPat.LongIdent(lid, None, None, args, vis, m) } | atomicPatternLongIdent HIGH_PRECEDENCE_BRACK_APP atomicPatsOrNamePatPairs { let vis, lid = $1 let args, argsM = $3 let m = unionRanges (rhs parseState 1) argsM SynPat.LongIdent(lid, None, None, args, vis, m) } | COLON_QMARK atomTypeOrAnonRecdType %prec pat_isinst { SynPat.IsInst($2, lhs parseState) } | atomicPattern { $1 } atomicPatsOrNamePatPairs: | LPAREN namePatPairs rparen { let mParen = rhs2 parseState 1 3 let pats, m = $2 let trivia = { ParenRange = mParen } SynArgPats.NamePatPairs(pats, m, trivia), snd $2 } | atomicPatterns { let mParsed = rhs parseState 1 let mAll = (mParsed.StartRange, $1) ||> unionRangeWithListBy (fun p -> p.Range) SynArgPats.Pats $1, mAll } 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 recordPatternElementsAux rbrace { let rs, m = $2 SynPat.Record(rs, rhs2 parseState 1 3) } | 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, lidwd = $1 if not (isNilOrSingleton lidwd.LongIdent) || String.isLeadingIdentifierCharacterUpperCase (List.head lidwd.LongIdent).idText then mkSynPatMaybeVar lidwd vis (lhs parseState) else let synIdent = List.head lidwd.IdentsWithTrivia let (SynIdent(id, _)) = synIdent SynPat.Named(synIdent, false, vis, id.idRange) } | constant { SynPat.Const(fst $1, snd $1) } | 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 SynPat.Paren($2 m, m) } | LPAREN parenPatternBody recover { reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnmatchedParen()) let m = rhs2 parseState 1 2 let parenPat = SynPat.Paren($2 m, m) patFromParseError parenPat } | LPAREN error rparen { let innerPat = patFromParseError (SynPat.Wild(rhs parseState 2)) SynPat.Paren(innerPat, lhs parseState) } | LPAREN recover { let parenM = rhs parseState 1 reportParseErrorAt parenM (FSComp.SR.parsUnmatchedParen()) let innerPat = patFromParseError (SynPat.Wild parenM.EndRange) let parenPat = SynPat.Paren(innerPat, parenM) patFromParseError parenPat } | STRUCT LPAREN tupleParenPatternElements rparen { let pats, commas = $3 SynPat.Tuple(true, List.rev pats, List.rev commas, lhs parseState) } | STRUCT LPAREN tupleParenPatternElements recover { reportParseErrorAt (rhs parseState 2) (FSComp.SR.parsUnmatchedParen()) let pats, commas = $3 SynPat.Tuple(true, List.rev pats, List.rev commas, lhs parseState) } | STRUCT LPAREN error rparen { (* silent recovery *) SynPat.Wild(lhs parseState) } | STRUCT LPAREN recover { reportParseErrorAt (rhs parseState 2) (FSComp.SR.parsUnmatchedParen()) SynPat.Wild(lhs parseState) } parenPatternBody: | parenPattern { (fun m -> $1) } | /* EMPTY */ { (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 (a, (b: 't)) binds differently to */ /* '(a, b: t)' in an expression ((a, b): 't). 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 constrPattern { SynPat.As($1, $3, rhs2 parseState 1 3) } | parenPattern BAR parenPattern { let mBar = rhs parseState 2 SynPat.Or($1, $3, rhs2 parseState 1 3, { BarRange = mBar }) } | tupleParenPatternElements { let pats, commas = $1 let pats, commas = normalizeTuplePat pats commas let m = (rhs parseState 1, pats) ||> unionRangeWithListBy (fun p -> p.Range) SynPat.Tuple(false, List.rev pats, List.rev commas, m) } | conjParenPatternElements { SynPat.Ands(List.rev $1, rhs2 parseState 1 3) } | parenPattern COLON typeWithTypeConstraints %prec paren_pat_colon { let mLhs = lhs parseState SynPat.Typed($1, $3, mLhs) } | parenPattern COLON recover { let mColon = rhs parseState 2 let ty = SynType.FromParseError(mColon.EndRange) SynPat.Typed($1, ty, unionRanges $1.Range mColon) } | attributes parenPattern %prec paren_pat_attribs { let mLhs = lhs parseState SynPat.Attrib($2, $1, mLhs) } | parenPattern COLON_COLON parenPattern { let mColonColon = rhs parseState 2 SynPat.ListCons($1, $3, rhs2 parseState 1 3, { ColonColonRange = mColonColon }) } | constrPattern { $1 } tupleParenPatternElements: | tupleParenPatternElements COMMA parenPattern { let pats, commas = $1 let mComma = rhs parseState 2 $3 :: pats, (mComma :: commas) } | parenPattern COMMA parenPattern { let mComma = rhs parseState 2 [$3; $1], [mComma] } | tupleParenPatternElements COMMA ends_coming_soon_or_recover { let pats, commas = $1 let commaRange = rhs parseState 2 reportParseErrorAt commaRange (FSComp.SR.parsExpectingPatternInTuple()) let pat2 = SynPat.Wild(commaRange.EndRange) pat2 :: pats, (commaRange :: commas) } | parenPattern COMMA ends_coming_soon_or_recover { let commaRange = rhs parseState 2 reportParseErrorAt commaRange (FSComp.SR.parsExpectingPatternInTuple()) let pat2 = SynPat.Wild(commaRange.EndRange) [pat2; $1], [commaRange] } | COMMA parenPattern { let commaRange = rhs parseState 1 reportParseErrorAt commaRange (FSComp.SR.parsExpectingPatternInTuple()) let pat1 = SynPat.Wild(commaRange.StartRange) [$2; pat1], [commaRange] } | COMMA ends_coming_soon_or_recover { let commaRange = rhs parseState 1 if not $2 then reportParseErrorAt commaRange (FSComp.SR.parsExpectedPatternAfterToken ()) let pat1 = SynPat.Wild(commaRange.StartRange) let pat2 = SynPat.Wild(commaRange.EndRange) [pat2; pat1], [commaRange] } conjParenPatternElements: | conjParenPatternElements AMP parenPattern { $3 :: $1 } | parenPattern AMP parenPattern { $3 :: $1 :: [] } recordPatternElementsAux: /* Fix 1190 */ | recordPatternElement opt_seps { [$1], lhs parseState } | recordPatternElement seps recordPatternElementsAux { let r = $1 let (rs, dropMark) = $3 (r :: rs), lhs parseState } recordPatternElement: | path EQUALS parenPattern { let mEquals = rhs parseState 2 (List.frontAndBack $1.LongIdent, mEquals, $3) } listPatternElements: | /* EMPTY */ { [] } | parenPattern opt_seps { [$1] } | parenPattern seps listPatternElements { $1 :: $3 } /* The lexfilter likes to insert OBLOCKBEGIN/OBLOCKEND pairs */ typedSequentialExprBlock: | OBLOCKBEGIN typedSequentialExpr oblockend { $2 } | OBLOCKBEGIN typedSequentialExpr recover { if not $3 then reportParseErrorAt (rhs parseState 3) (FSComp.SR.parsUnexpectedEndOfFileExpression()) exprFromParseError $2 } | typedSequentialExpr { $1 } /* The lexfilter likes to insert OBLOCKBEGIN/OBLOCKEND pairs */ declExprBlock: | OBLOCKBEGIN typedSequentialExpr 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 */ typedSequentialExprBlockR: | typedSequentialExpr ORIGHT_BLOCK_END { fun _ -> $1 } | typedSequentialExpr { fun _ -> $1 } | recover { fun mStart -> arbExpr ("typedSequentialExprBlockR", mStart) } typedSequentialExpr: | sequentialExpr COLON typeWithTypeConstraints { SynExpr.Typed($1, $3, unionRanges $1.Range $3.Range) } | sequentialExpr COLON recover { let mColon = rhs parseState 2 let ty = SynType.FromParseError(mColon.EndRange) SynExpr.Typed($1, ty, unionRanges $1.Range mColon) } | sequentialExpr { $1 } typedSequentialExprEOF: | typedSequentialExpr EOF { checkEndOfFileError $2; $1 } sequentialExpr: | declExpr seps sequentialExpr { SynExpr.Sequential(DebugPointAtSequential.SuppressNeither, true, $1, $3, unionRanges $1.Range $3.Range) } | declExpr seps { $1 } | declExpr %prec SEMICOLON { $1 } | declExpr THEN sequentialExpr %prec prec_then_before { SynExpr.Sequential(DebugPointAtSequential.SuppressNeither, false, $1, $3, unionRanges $1.Range $3.Range) } | declExpr OTHEN OBLOCKBEGIN typedSequentialExpr oblockend %prec prec_then_before { SynExpr.Sequential(DebugPointAtSequential.SuppressNeither, false, $1, $4, unionRanges $1.Range $4.Range) } | hardwhiteLetBindings %prec prec_args_error { let hwlb, m, mIn = $1 let mLetKwd, isUse = match hwlb with (BindingSetPreAttrs(m, _, isUse, _, _)) -> m, isUse let usedKeyword = if isUse then "use" else "let" reportParseErrorAt mLetKwd (FSComp.SR.parsExpectedExpressionAfterLet(usedKeyword, usedKeyword)) let fauxRange = m.EndRange // zero width range at end of m mkLocalBindings (m, hwlb, mIn, arbExpr ("seqExpr", fauxRange)) } /* 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 { debugPrint("recovering via error"); true } | EOF { debugPrint("recovering via EOF"); false } moreBinders: | AND_BANG headBindingPattern EQUALS typedSequentialExprBlock IN moreBinders %prec expr_let { let spBind = DebugPointAtBinding.Yes(rhs2 parseState 1 5) (* TODO Pretty sure this is wrong *) let mEquals = rhs parseState 3 let m = unionRanges (rhs parseState 1) $4.Range let mIn = rhs parseState 5 SynExprAndBang(spBind, $1, true, $2, $4, m, { EqualsRange = mEquals; InKeyword = Some mIn }) :: $6 } | OAND_BANG headBindingPattern EQUALS typedSequentialExprBlock hardwhiteDefnBindingsTerminator opt_OBLOCKSEP moreBinders %prec expr_let { let report, mIn = $5 report "and!" (rhs parseState 1) // report unterminated error let spBind = DebugPointAtBinding.Yes(rhs2 parseState 1 5) (* TODO Pretty sure this is wrong *) let mEquals = rhs parseState 3 let m = unionRanges (rhs parseState 1) $4.Range SynExprAndBang(spBind, $1, true, $2, $4, m, { EqualsRange = mEquals; InKeyword = mIn }) :: $7 } | %prec prec_no_more_attr_bindings { [] } declExpr: | defnBindings IN typedSequentialExpr %prec expr_let { let mIn = rhs parseState 2 |> Some mkLocalBindings (unionRanges (rhs2 parseState 1 2) $3.Range, $1, mIn, $3) } | defnBindings IN error %prec expr_let { let mIn = rhs parseState 2 |> Some mkLocalBindings (rhs2 parseState 1 2, $1, mIn, arbExpr ("declExpr1", (rhs parseState 3))) } /* FSComp.SR.parsNoMatchingInForLet() -- leave this in for now - it's an unused error string */ | hardwhiteLetBindings typedSequentialExprBlock %prec expr_let { let hwlb, m, mIn = $1 mkLocalBindings (unionRanges m $2.Range, hwlb, mIn, $2) } | hardwhiteLetBindings error %prec expr_let { let hwlb, m, mIn = $1 reportParseErrorAt (match hwlb with (BindingSetPreAttrs(m, _, _, _, _)) -> m) (FSComp.SR.parsErrorInReturnForLetIncorrectIndentation()) mkLocalBindings (m, hwlb, mIn, arbExpr ("declExpr2", (rhs parseState 2))) } | hardwhiteLetBindings OBLOCKSEP typedSequentialExprBlock %prec expr_let { let hwlb, m, mIn = $1 mkLocalBindings (unionRanges m $3.Range, hwlb, mIn, $3) } | hardwhiteLetBindings OBLOCKSEP error %prec expr_let { let hwlb, m, mIn = $1 //reportParseErrorAt (match hwlb with (BindingSetPreAttrs(m, _, _, _, _)) -> m) (FSComp.SR.parsErrorInReturnForLetIncorrectIndentation()) mkLocalBindings (unionRanges m (rhs parseState 3), hwlb, mIn, arbExpr ("declExpr3", (rhs parseState 3))) } | hardwhiteDoBinding %prec expr_let { let e = snd $1 SynExpr.Do(e, unionRanges (rhs parseState 1).StartRange e.Range) } | anonMatchingExpr %prec expr_function { $1 } | anonLambdaExpr %prec expr_fun { $1 } | MATCH typedSequentialExpr withClauses %prec expr_match { let mMatch = rhs parseState 1 let mWith, (clauses, mLast) = $3 let spBind = DebugPointAtBinding.Yes(unionRanges mMatch mWith) let trivia = { MatchKeyword = mMatch; WithKeyword = mWith } SynExpr.Match(spBind, $2, clauses, unionRanges mMatch mLast, trivia) } | MATCH typedSequentialExpr recover %prec expr_match { if not $3 then reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnexpectedEndOfFileMatch()) // Produce approximate expression during error recovery exprFromParseError $2 } | MATCH_BANG typedSequentialExpr withClauses %prec expr_match { let mMatch = (rhs parseState 1) let mWith, (clauses, mLast) = $3 let spBind = DebugPointAtBinding.Yes(unionRanges mMatch mWith) let trivia = { MatchBangKeyword = mMatch; WithKeyword = mWith } SynExpr.MatchBang(spBind, $2, clauses, unionRanges mMatch mLast, trivia) } | MATCH_BANG typedSequentialExpr recover %prec expr_match { if not $3 then reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnexpectedEndOfFileMatch()) // Produce approximate expression during error recovery exprFromParseError $2 } | TRY typedSequentialExprBlockR withClauses %prec expr_try { let mTry = rhs parseState 1 let expr = $2 mTry let spTry = DebugPointAtTry.Yes mTry let mWith, (clauses, mLast) = $3 let spWith = DebugPointAtWith.Yes mWith let mTryToWith = unionRanges mTry mWith let mWithToLast = unionRanges mWith mLast let mTryToLast = unionRanges mTry mLast let trivia: SynExprTryWithTrivia = { TryKeyword = mTry TryToWithRange = mTryToWith WithKeyword = mWith WithToEndRange = mWithToLast } SynExpr.TryWith(expr, clauses, mTryToLast, spTry, spWith, trivia) } | TRY typedSequentialExprBlockR recover %prec expr_try { let mTry = rhs parseState 1 let spTry = DebugPointAtTry.Yes mTry if not $3 then reportParseErrorAt mTry (FSComp.SR.parsUnexpectedEndOfFileTry ()) let expr = $2 mTry let mExpr = expr.Range let mEnd = mExpr.EndRange let spWith = DebugPointAtWith.Yes mEnd let mWhole = unionRanges mTry mEnd let trivia: SynExprTryWithTrivia = { TryKeyword = mTry TryToWithRange = mWhole WithKeyword = mEnd WithToEndRange = mWhole } SynExpr.TryWith(expr, [], mWhole, spTry, spWith, trivia) } | TRY typedSequentialExprBlockR FINALLY typedSequentialExprBlock %prec expr_try { let mTry = rhs parseState 1 let tryExpr = $2 mTry let spTry = DebugPointAtTry.Yes mTry let mFinally = rhs parseState 3 let finallyExpr = $4 let spFinally = DebugPointAtFinally.Yes mFinally let mTryToLast = unionRanges mTry finallyExpr.Range let trivia = { TryKeyword = mTry; FinallyKeyword = mFinally } SynExpr.TryFinally(tryExpr, finallyExpr, mTryToLast, spTry, spFinally, trivia) } | IF declExpr ifExprCases %prec expr_if { let mIf = rhs parseState 1 $3 $2 mIf false } | IF declExpr recover %prec expr_if { errorR (Error(FSComp.SR.parsIncompleteIf (), rhs parseState 1)) let ifExpr = $2 let mIf = rhs parseState 1 let mThen = ifExpr.Range.EndRange let m = unionRanges mIf mThen let spIfToThen = DebugPointAtBinding.Yes m let trivia = { IfKeyword = mIf; IsElif = false; ThenKeyword = mThen; ElseKeyword = None; IfToThenRange = m } SynExpr.IfThenElse($2, arbExpr ("if1", mThen), None, spIfToThen, true, m, trivia) } | IF recover %prec expr_if { errorR (Error(FSComp.SR.parsIncompleteIf (), rhs parseState 1)) let m = rhs parseState 1 let mEnd = m.EndRange let spIfToThen = DebugPointAtBinding.Yes mEnd let trivia = { IfKeyword = m; IsElif = false; ThenKeyword = m; ElseKeyword = None; IfToThenRange = m } SynExpr.IfThenElse(arbExpr ("if2", mEnd), arbExpr ("if3", mEnd), None, spIfToThen, true, m, trivia) } | 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 typedSequentialExprBlock doneDeclEnd { let mWhileHeader = unionRanges (rhs parseState 1) $2.Range let spWhile = DebugPointAtWhile.Yes mWhileHeader let mWhileAll = unionRanges (rhs parseState 1) $4.Range SynExpr.While(spWhile, $2, $4, mWhileAll) } | WHILE declExpr doToken typedSequentialExprBlock recover { if not $5 then reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnexpectedEndOfFileWhile()) let mWhileHeader = unionRanges (rhs parseState 1) $2.Range let spWhile = DebugPointAtWhile.Yes mWhileHeader let mWhileAll = unionRanges (rhs parseState 1) $4.Range exprFromParseError (SynExpr.While(spWhile, $2, $4, mWhileAll)) } | WHILE declExpr doToken error doneDeclEnd { // silent recovery let mWhileHeader = unionRanges (rhs parseState 1) $2.Range let spWhile = DebugPointAtWhile.Yes mWhileHeader let mWhileBodyArb = unionRanges (rhs parseState 4) (rhs parseState 5) let mWhileAll = unionRanges (rhs parseState 1) (rhs parseState 5) SynExpr.While(spWhile, $2, arbExpr ("whileBody1", mWhileBodyArb), mWhileAll) } | WHILE declExpr recover { reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsWhileDoExpected()) let mWhileHeader = unionRanges (rhs parseState 1) $2.Range let spWhile = DebugPointAtWhile.Yes mWhileHeader let mWhileBodyArb = rhs parseState 3 let mWhileAll = unionRanges (rhs parseState 1) (rhs parseState 3) exprFromParseError (SynExpr.While(spWhile, $2, arbExpr ("whileBody2", mWhileBodyArb), mWhileAll)) } | WHILE recover { if not $2 then reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnexpectedEndOfFileWhile()) arbExpr ("whileLoop1", rhs parseState 1) } | WHILE error doneDeclEnd { //silent recovery let mWhileHeader = rhs parseState 1 let spWhile = DebugPointAtWhile.Yes mWhileHeader let mWhileBodyArb = rhs parseState 3 let mWhileAll = unionRanges (rhs parseState 1) (rhs parseState 3) exprFromParseError (SynExpr.While(spWhile, arbExpr ("whileGuard1", mWhileHeader), arbExpr ("whileBody3", mWhileBodyArb), mWhileAll)) } | FOR forLoopBinder doToken typedSequentialExprBlock doneDeclEnd { let mFor = rhs parseState 1 let mDo = rhs parseState 3 let spFor = DebugPointAtFor.Yes mFor let (a, b, _, spIn) = $2 SynExpr.ForEach(spFor, spIn, SeqExprOnly false, true, a, b, $4, unionRanges (rhs parseState 1) $4.Range) } | FOR forLoopBinder doToken typedSequentialExprBlock ends_coming_soon_or_recover { if not $5 then reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnexpectedEndOfFileFor()) let mFor = rhs parseState 1 let spFor = DebugPointAtFor.Yes mFor let (a, b, _, spIn) = $2 let mForLoopAll = unionRanges (rhs parseState 1) $4.Range SynExpr.ForEach(spFor, spIn, SeqExprOnly false, true, a, b, $4, mForLoopAll) } | FOR forLoopBinder doToken error doneDeclEnd { // Silent recovery let mFor = rhs parseState 1 let spFor = DebugPointAtFor.Yes mFor let (a, b, _, spIn) = $2 let mForLoopBodyArb = rhs parseState 5 let mForLoopAll = rhs2 parseState 1 5 SynExpr.ForEach(spFor, spIn, SeqExprOnly false, true, a, b, arbExpr ("forLoopBody2a", mForLoopBodyArb), mForLoopAll) } | FOR forLoopBinder doToken ends_coming_soon_or_recover { if not $4 then reportParseErrorAt (rhs parseState 3) (FSComp.SR.parsExpectedExpressionAfterToken()) let mFor = rhs parseState 1 let spFor = DebugPointAtFor.Yes mFor let (a, b, _, spIn) = $2 let mForLoopBodyArb = rhs parseState 3 let mForLoopAll = rhs2 parseState 1 3 SynExpr.ForEach(spFor, spIn, SeqExprOnly false, true, a, b, arbExpr ("forLoopBody2", mForLoopBodyArb), mForLoopAll) } | FOR forLoopBinder ends_coming_soon_or_recover { let (a, b, ok, spIn) = $2 if not $3 then reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsForDoExpected()) let mFor = rhs parseState 1 let spFor = DebugPointAtFor.Yes mFor let mForLoopBodyArb = rhs parseState 3 let mForLoopAll = rhs2 parseState 1 3 SynExpr.ForEach(spFor, spIn, SeqExprOnly false, true, a, b, arbExpr ("forLoopBody1", mForLoopBodyArb), mForLoopAll) } | FOR forLoopBinder opt_OBLOCKSEP arrowThenExprR %prec expr_let { let spFor = DebugPointAtFor.Yes(rhs parseState 1) let (a, b, _, spIn) = $2 SynExpr.ForEach(spFor, spIn, SeqExprOnly true, true, a, b, $4, unionRanges (rhs parseState 1) $4.Range) } | FOR forLoopRange doToken typedSequentialExprBlock doneDeclEnd { let mFor = rhs parseState 1 let spFor = DebugPointAtFor.Yes mFor let (a, b, c, d, e, spTo) = $2 let mForLoopAll = unionRanges (rhs parseState 1) $4.Range SynExpr.For(spFor, spTo, a, b, c, d, e, $4, mForLoopAll) } | FOR forLoopRange doToken typedSequentialExprBlock recover { if not $5 then reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnexpectedEndOfFileFor()) // Still produce an expression let mFor = rhs parseState 1 let spFor = DebugPointAtFor.Yes mFor let (a, b, c, d, e, spTo) = $2 let mForLoopAll = unionRanges (rhs parseState 1) $4.Range exprFromParseError (SynExpr.For(spFor, spTo, a, b, c, d, e, $4, mForLoopAll)) } | FOR forLoopRange doToken error doneDeclEnd { // silent recovery let mFor = rhs parseState 1 let spFor = DebugPointAtFor.Yes mFor let (a, b, c, d, e, spTo) = $2 let mForLoopBodyArb = rhs parseState 5 let mForLoopAll = rhs2 parseState 1 5 SynExpr.For(spFor, spTo, a, b, c, d, e, arbExpr ("declExpr11", mForLoopBodyArb), mForLoopAll) } | FOR forLoopRange doToken recover { if not $4 then reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnexpectedEndOfFileFor()) let mFor = rhs parseState 1 let spFor = DebugPointAtFor.Yes mFor let (a, b, c, d, e, spTo) = $2 let mForLoopBodyArb = rhs parseState 3 let mForLoopAll = rhs2 parseState 1 3 exprFromParseError (SynExpr.For(spFor, spTo, a, b, c, d, e, arbExpr ("declExpr11", mForLoopBodyArb), mForLoopAll)) } | FOR forLoopRange recover { if not $3 then reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnexpectedEndOfFileFor()) let mFor = rhs parseState 1 let spFor = DebugPointAtFor.Yes mFor let (a, b, c, d, e, spTo) = $2 let mForLoopBodyArb = (rhs parseState 2).EndRange let mForLoopAll = rhs2 parseState 1 2 exprFromParseError (SynExpr.For(spFor, spTo, a, b, c, d, e, arbExpr ("declExpr11", mForLoopBodyArb), mForLoopAll)) } | FOR error doToken typedSequentialExprBlock doneDeclEnd { // silent recovery let mFor = rhs parseState 1 let spToFake = DebugPointAtInOrTo.Yes mFor let mForLoopAll = unionRanges (rhs parseState 1) $4.Range let spFor = DebugPointAtFor.Yes mFor SynExpr.For(spFor, spToFake, mkSynId mFor "_loopVar", None, arbExpr ("startLoopRange1", mFor), true, arbExpr ("endLoopRange1", rhs parseState 3), $4, mForLoopAll) } | FOR ends_coming_soon_or_recover { reportParseErrorAt (rhs parseState 2) (FSComp.SR.parsIdentifierExpected()) arbExpr ("declExpr12", (rhs parseState 1)) } | FOR parenPattern error doneDeclEnd { reportParseErrorAt (rhs parseState 3) (FSComp.SR.parsInOrEqualExpected()) let mFor = rhs parseState 1 let spFor = DebugPointAtFor.Yes mFor let spInFake = DebugPointAtInOrTo.Yes mFor let mForLoopBodyArb = rhs parseState 4 let mForLoopAll = rhs2 parseState 1 4 SynExpr.ForEach(spFor, spInFake, SeqExprOnly false, true, $2, arbExpr ("forLoopCollection", mFor), arbExpr ("forLoopBody3", mForLoopBodyArb), mForLoopAll) } | FOR parenPattern recover { if not $3 then reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnexpectedEndOfFileFor()) let mFor = rhs parseState 1 let mIn = rhs parseState 1 let spFor = DebugPointAtFor.Yes mFor let spIn = DebugPointAtInOrTo.Yes mIn let mForLoopBodyArb = (rhs parseState 2).EndRange let mForLoopAll = rhs2 parseState 1 2 exprFromParseError (SynExpr.ForEach(spFor, spIn, SeqExprOnly false, true, $2, arbExpr ("forLoopCollection", mFor), arbExpr ("forLoopBody3", mForLoopBodyArb), mForLoopAll)) } | 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) } | YIELD recover { let mYieldAll = rhs parseState 1 SynExpr.YieldOrReturn(($1, not $1), arbExpr ("yield", mYieldAll), mYieldAll) } | YIELD_BANG recover { let mYieldAll = rhs parseState 1 SynExpr.YieldOrReturnFrom(($1, not $1), arbExpr ("yield!", mYieldAll), mYieldAll) } | BINDER headBindingPattern EQUALS typedSequentialExprBlock IN opt_OBLOCKSEP moreBinders typedSequentialExprBlock %prec expr_let { let spBind = DebugPointAtBinding.Yes(rhs2 parseState 1 5) let mEquals = rhs parseState 3 let m = unionRanges (rhs parseState 1) $8.Range let trivia: SynExprLetOrUseBangTrivia = { EqualsRange = Some mEquals } SynExpr.LetOrUseBang(spBind, ($1 = "use"), true, $2, $4, $7, $8, m, trivia) } | OBINDER headBindingPattern EQUALS typedSequentialExprBlock hardwhiteDefnBindingsTerminator opt_OBLOCKSEP moreBinders typedSequentialExprBlock %prec expr_let { let report, mIn = $5 report (if $1 = "use" then "use!" else "let!") (rhs parseState 1) // report unterminated error let spBind = DebugPointAtBinding.Yes(unionRanges (rhs parseState 1) $4.Range) let mEquals = rhs parseState 3 let m = unionRanges (rhs parseState 1) $8.Range let trivia: SynExprLetOrUseBangTrivia = { EqualsRange = Some mEquals } SynExpr.LetOrUseBang(spBind, ($1 = "use"), true, $2, $4, $7, $8, m, trivia) } | OBINDER headBindingPattern EQUALS typedSequentialExprBlock hardwhiteDefnBindingsTerminator opt_OBLOCKSEP error %prec expr_let { // error recovery that allows intellisense when writing incomplete computation expressions let spBind = DebugPointAtBinding.Yes(unionRanges (rhs parseState 1) $4.Range) let mEquals = rhs parseState 3 let mAll = unionRanges (rhs parseState 1) (rhs parseState 7) let m = $4.Range.EndRange // zero-width range let trivia: SynExprLetOrUseBangTrivia = { EqualsRange = Some mEquals } SynExpr.LetOrUseBang(spBind, ($1 = "use"), true, $2, $4, [], SynExpr.ImplicitZero m, mAll, trivia) } | DO_BANG typedSequentialExpr IN opt_OBLOCKSEP typedSequentialExprBlock %prec expr_let { let spBind = DebugPointAtBinding.NoneAtDo let trivia: SynExprLetOrUseBangTrivia = { EqualsRange = None } SynExpr.LetOrUseBang(spBind, false, true, SynPat.Const(SynConst.Unit, $2.Range), $2, [], $5, unionRanges (rhs parseState 1) $5.Range, trivia) } | ODO_BANG typedSequentialExprBlock hardwhiteDefnBindingsTerminator %prec expr_let { SynExpr.DoBang($2, unionRanges (rhs parseState 1) $2.Range) } | FIXED declExpr { SynExpr.Fixed($2, (unionRanges (rhs parseState 1) $2.Range)) } | RARROW typedSequentialExprBlockR { errorR(Error(FSComp.SR.parsArrowUseIsLimited(), lhs parseState)) let mArrow = rhs parseState 1 let expr = $2 mArrow SynExpr.YieldOrReturn((true, true), expr, (unionRanges mArrow expr.Range)) } | declExpr COLON_QMARK typ { SynExpr.TypeTest($1, $3, unionRanges $1.Range $3.Range) } | declExpr COLON_QMARK recover { let mColon = rhs parseState 2 let ty = SynType.FromParseError(mColon.EndRange) SynExpr.TypeTest($1, ty, unionRanges $1.Range mColon) } | declExpr COLON_GREATER typ { SynExpr.Upcast($1, $3, unionRanges $1.Range $3.Range) } | declExpr COLON_GREATER recover { let mOp = rhs parseState 2 let ty = SynType.FromParseError(mOp.EndRange) SynExpr.Upcast($1, ty, unionRanges $1.Range mOp) } | declExpr COLON_QMARK_GREATER typ { SynExpr.Downcast($1, $3, unionRanges $1.Range $3.Range) } | declExpr COLON_QMARK_GREATER recover { let mOp = rhs parseState 2 let ty = SynType.FromParseError(mOp.EndRange) SynExpr.Downcast($1, ty, unionRanges $1.Range mOp) } | declExpr COLON_EQUALS declExpr { mkSynInfix (rhs parseState 2) $1 ":=" $3 } | minusExpr LARROW declExprBlock { mkSynAssign $1 $3 } | tupleExpr %prec expr_tuple { let exprs, commas = $1 let m = unionRanges exprs.Head.Range (List.last exprs).Range SynExpr.Tuple(false, List.rev exprs, List.rev commas, m) } | declExpr JOIN_IN declExpr { SynExpr.JoinIn($1, rhs parseState 2, $3, unionRanges $1.Range $3.Range) } | declExpr BAR_BAR declExpr { mkSynInfix (rhs parseState 2) $1 "||" $3 } | declExpr INFIX_BAR_OP declExpr { mkSynInfix (rhs parseState 2) $1 $2 $3 } | declExpr OR declExpr { mkSynInfix (rhs parseState 2) $1 "or" $3 } | declExpr AMP declExpr { mkSynInfix (rhs parseState 2) $1 "&" $3 } | declExpr AMP_AMP declExpr { mkSynInfix (rhs parseState 2) $1 "&&" $3 } | declExpr INFIX_AMP_OP declExpr { mkSynInfix (rhs parseState 2) $1 $2 $3 } | declExpr EQUALS declExpr { mkSynInfix (rhs parseState 2) $1 "=" $3 } | declExpr INFIX_COMPARE_OP declExpr { mkSynInfix (rhs parseState 2) $1 $2 $3 } | declExpr DOLLAR declExpr { mkSynInfix (rhs parseState 2) $1 "$" $3 } | declExpr LESS declExpr { mkSynInfix (rhs parseState 2) $1 "<" $3 } | declExpr LESS recover { if not $3 then reportParseErrorAt (rhs parseState 2) (FSComp.SR.parsUnfinishedExpression("<")) exprFromParseError (mkSynInfix (rhs parseState 2) $1 "<" (arbExpr ("declExprInfix", (rhs parseState 3).StartRange))) } | declExpr GREATER declExpr { mkSynInfix (rhs parseState 2) $1 ">" $3 } | declExpr INFIX_AT_HAT_OP declExpr { mkSynInfix (rhs parseState 2) $1 $2 $3 } | declExpr PERCENT_OP declExpr { mkSynInfix (rhs parseState 2) $1 $2 $3 } | declExpr COLON_COLON declExpr { let tupExpr = SynExpr.Tuple(false, [$1;$3], [rhs parseState 2], unionRanges $1.Range $3.Range) let identExpr = mkSynOperator (rhs parseState 2) "::" SynExpr.App(ExprAtomicFlag.NonAtomic, true, identExpr, tupExpr, unionRanges $1.Range $3.Range) } | declExpr PLUS_MINUS_OP declExpr { mkSynInfix (rhs parseState 2) $1 $2 $3 } | declExpr MINUS declExpr { mkSynInfix (rhs parseState 2) $1 "-" $3 } | declExpr STAR declExpr { mkSynInfix (rhs parseState 2) $1 "*" $3 } | declExpr INFIX_STAR_DIV_MOD_OP declExpr { mkSynInfix (rhs parseState 2) $1 $2 $3 } | declExpr INFIX_STAR_STAR_OP declExpr { mkSynInfix (rhs parseState 2) $1 $2 $3 } | declExpr JOIN_IN OBLOCKEND_COMING_SOON { reportParseErrorAt (rhs parseState 2) (FSComp.SR.parsUnfinishedExpression("in")) exprFromParseError(mkSynInfix (rhs parseState 2) $1 "@in" (arbExpr ("declExprInfix", (rhs parseState 3).StartRange))) } | declExpr BAR_BAR OBLOCKEND_COMING_SOON { reportParseErrorAt (rhs parseState 2) (FSComp.SR.parsUnfinishedExpression("||")) exprFromParseError(mkSynInfix (rhs parseState 2) $1 "||" (arbExpr ("declExprInfix", (rhs parseState 3).StartRange))) } | declExpr INFIX_BAR_OP OBLOCKEND_COMING_SOON { reportParseErrorAt (rhs parseState 2) (FSComp.SR.parsUnfinishedExpression($2)) exprFromParseError(mkSynInfix (rhs parseState 2) $1 $2 (arbExpr ("declExprInfix", (rhs parseState 3).StartRange))) } | declExpr OR OBLOCKEND_COMING_SOON { reportParseErrorAt (rhs parseState 2) (FSComp.SR.parsUnfinishedExpression("or")) exprFromParseError(mkSynInfix (rhs parseState 2) $1 "or" (arbExpr ("declExprInfix", (rhs parseState 3).StartRange))) } | declExpr AMP OBLOCKEND_COMING_SOON { reportParseErrorAt (rhs parseState 2) (FSComp.SR.parsUnfinishedExpression("&")) exprFromParseError(mkSynInfix (rhs parseState 2) $1 "&" (arbExpr ("declExprInfix", (rhs parseState 3).StartRange))) } | declExpr AMP_AMP OBLOCKEND_COMING_SOON { reportParseErrorAt (rhs parseState 2) (FSComp.SR.parsUnfinishedExpression("&&")) exprFromParseError(mkSynInfix (rhs parseState 2) $1 "&&" (arbExpr ("declExprInfix", (rhs parseState 3).StartRange))) } | declExpr INFIX_AMP_OP OBLOCKEND_COMING_SOON { reportParseErrorAt (rhs parseState 2) (FSComp.SR.parsUnfinishedExpression($2)) exprFromParseError(mkSynInfix (rhs parseState 2) $1 $2 (arbExpr ("declExprInfix", (rhs parseState 3).StartRange))) } | declExpr EQUALS ends_coming_soon_or_recover { reportParseErrorAt (rhs parseState 2) (FSComp.SR.parsUnfinishedExpression("=")) let mEquals = rhs parseState 2 mkSynInfix mEquals $1 "=" (arbExpr ("declExprInfixEquals", mEquals.EndRange)) } | declExpr INFIX_COMPARE_OP OBLOCKEND_COMING_SOON { reportParseErrorAt (rhs parseState 2) (FSComp.SR.parsUnfinishedExpression($2)) exprFromParseError(mkSynInfix (rhs parseState 2) $1 $2 (arbExpr ("declExprInfix", (rhs parseState 3).StartRange))) } | declExpr DOLLAR OBLOCKEND_COMING_SOON { reportParseErrorAt (rhs parseState 2) (FSComp.SR.parsUnfinishedExpression("$")) exprFromParseError(mkSynInfix (rhs parseState 2) $1 "$" (arbExpr ("declExprInfix", (rhs parseState 3).StartRange))) } | declExpr LESS OBLOCKEND_COMING_SOON { reportParseErrorAt (rhs parseState 2) (FSComp.SR.parsUnfinishedExpression("<")) exprFromParseError(mkSynInfix (rhs parseState 2) $1 "<" (arbExpr ("declExprInfix", (rhs parseState 3).StartRange))) } | declExpr GREATER OBLOCKEND_COMING_SOON { reportParseErrorAt (rhs parseState 2) (FSComp.SR.parsUnfinishedExpression(">")) exprFromParseError(mkSynInfix (rhs parseState 2) $1 ">" (arbExpr ("declExprInfix", (rhs parseState 3).StartRange))) } | declExpr INFIX_AT_HAT_OP OBLOCKEND_COMING_SOON %prec infix_at_hat_op_binary { reportParseErrorAt (rhs parseState 2) (FSComp.SR.parsUnfinishedExpression($2)) exprFromParseError(mkSynInfix (rhs parseState 2) $1 $2 (arbExpr ("declExprInfix", (rhs parseState 3).StartRange))) } | declExpr PERCENT_OP OBLOCKEND_COMING_SOON { reportParseErrorAt (rhs parseState 2) (FSComp.SR.parsUnfinishedExpression($2)) exprFromParseError(mkSynInfix (rhs parseState 2) $1 $2 (arbExpr ("declExprInfix", (rhs parseState 3).StartRange))) } | declExpr COLON_COLON OBLOCKEND_COMING_SOON { reportParseErrorAt (rhs parseState 2) (FSComp.SR.parsUnfinishedExpression("::")) let identExpr = mkSynOperator (rhs parseState 2) "::" let tupExpr = SynExpr.Tuple(false, [$1;(arbExpr ("declExprInfix", (rhs parseState 3).StartRange))], [rhs parseState 2], unionRanges $1.Range (rhs parseState 3).StartRange) SynExpr.App(ExprAtomicFlag.NonAtomic, true, identExpr, tupExpr, unionRanges $1.Range (rhs parseState 3).StartRange) } | declExpr PLUS_MINUS_OP OBLOCKEND_COMING_SOON { reportParseErrorAt (rhs parseState 2) (FSComp.SR.parsUnfinishedExpression($2)) exprFromParseError(mkSynInfix (rhs parseState 2) $1 $2 (arbExpr ("declExprInfix", (rhs parseState 3).StartRange))) } | declExpr MINUS OBLOCKEND_COMING_SOON { reportParseErrorAt (rhs parseState 2) (FSComp.SR.parsUnfinishedExpression("-")) exprFromParseError(mkSynInfix (rhs parseState 2) $1 "-" (arbExpr ("declExprInfix", (rhs parseState 3).StartRange))) } | declExpr STAR OBLOCKEND_COMING_SOON { reportParseErrorAt (rhs parseState 2) (FSComp.SR.parsUnfinishedExpression("*")) exprFromParseError(mkSynInfix (rhs parseState 2) $1 "*" (arbExpr ("declExprInfix", (rhs parseState 3).StartRange))) } | declExpr INFIX_STAR_DIV_MOD_OP OBLOCKEND_COMING_SOON { reportParseErrorAt (rhs parseState 2) (FSComp.SR.parsUnfinishedExpression($2)) exprFromParseError(mkSynInfix (rhs parseState 2) $1 $2 (arbExpr ("declExprInfix", (rhs parseState 3).StartRange))) } | declExpr INFIX_STAR_STAR_OP OBLOCKEND_COMING_SOON { reportParseErrorAt (rhs parseState 2) (FSComp.SR.parsUnfinishedExpression($2)) exprFromParseError(mkSynInfix (rhs parseState 2) $1 $2 (arbExpr ("declExprInfix", (rhs parseState 3).StartRange))) } | declExpr DOT_DOT declExpr { let wholem = rhs2 parseState 1 3 let mOperator = rhs parseState 2 SynExpr.IndexRange(Some $1, mOperator, Some $3, rhs parseState 1, rhs parseState 3, wholem) } | declExpr DOT_DOT %prec open_range_expr { let wholem = rhs2 parseState 1 2 let mOperator = rhs parseState 2 SynExpr.IndexRange(Some $1, mOperator, None, rhs parseState 1, mOperator, wholem) } | DOT_DOT declExpr %prec open_range_expr { let wholem = rhs2 parseState 1 2 let mOperator = rhs parseState 1 SynExpr.IndexRange(None, mOperator, Some $2, mOperator, rhs parseState 2, wholem) } | STAR { let m = rhs parseState 1 SynExpr.IndexRange(None, m, None, m, m, m) } | minusExpr %prec expr_prefix_plus_minus { $1 } dynamicArg: | IDENT { let m = rhs parseState 1 SynExpr.Ident(Ident($1, m)) } | LPAREN typedSequentialExpr rparen { let lpr = rhs parseState 1 let rpr = rhs parseState 3 let m = unionRanges lpr rpr SynExpr.Paren($2, lpr, Some rpr, m) } withClauses: | WITH withPatternClauses { rhs parseState 1, $2 } | OWITH withPatternClauses OEND { rhs parseState 1, $2 } | OWITH withPatternClauses recover { if not $3 then reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnexpectedEndOfFileWith()) rhs parseState 1, $2 } withPatternClauses: | patternClauses { $1 None } | BAR patternClauses { let mBar = rhs parseState 1 |> Some $2 mBar } | BAR error { // silent recovery let mLast = rhs parseState 1 [], mLast } | error { // silent recovery let mLast = rhs parseState 1 [], mLast } patternAndGuard: | parenPattern patternGuard { $1, $2 } patternClauses: | patternAndGuard patternResult %prec prec_pat_pat_action { let pat, guard = $1 let mArrow, resultExpr = $2 let mLast = resultExpr.Range let m = unionRanges resultExpr.Range pat.Range fun mBar -> [SynMatchClause(pat, guard, resultExpr, m, DebugPointAtTarget.Yes, { ArrowRange = Some mArrow; BarRange = mBar })], mLast } | patternAndGuard patternResult BAR patternClauses { let pat, guard = $1 let mArrow, resultExpr = $2 let mNextBar = rhs parseState 3 |> Some let clauses, mLast = $4 mNextBar let m = unionRanges resultExpr.Range pat.Range fun mBar -> (SynMatchClause(pat, guard, resultExpr, m, DebugPointAtTarget.Yes, { ArrowRange = Some mArrow; BarRange = mBar }) :: clauses), mLast } | patternAndGuard error BAR patternClauses { let pat, guard = $1 let mNextBar = rhs parseState 3 |> Some let clauses, mLast = $4 mNextBar let patm = pat.Range let m = guard |> Option.map (fun e -> unionRanges patm e.Range) |> Option.defaultValue patm fun _mBar -> (SynMatchClause(pat, guard, arbExpr ("patternClauses1", m.EndRange), m, DebugPointAtTarget.Yes, SynMatchClauseTrivia.Zero) :: clauses), mLast } | patternAndGuard patternResult BAR recover { let pat, guard = $1 let mArrow, resultExpr = $2 let mLast = rhs parseState 3 let m = unionRanges resultExpr.Range pat.Range fun mBar -> [SynMatchClause(pat, guard, resultExpr, m, DebugPointAtTarget.Yes, { ArrowRange = Some mArrow; BarRange = mBar })], mLast } | patternAndGuard patternResult recover { let pat, guard = $1 let mArrow, resultExpr = $2 let m = unionRanges resultExpr.Range pat.Range fun mBar -> [SynMatchClause(pat, guard, resultExpr, m, DebugPointAtTarget.Yes, { ArrowRange = Some mArrow; BarRange = mBar })], m } | patternAndGuard recover { let pat, guard = $1 let patm = pat.Range let m = guard |> Option.map (fun e -> unionRanges patm e.Range) |> Option.defaultValue patm fun mBar -> [SynMatchClause(pat, guard, arbExpr ("patternClauses2", m.EndRange), m, DebugPointAtTarget.Yes, { ArrowRange = None; BarRange = mBar })], m } patternGuard: | WHEN declExpr { Some $2 } | /* EMPTY */ { None } patternResult: | RARROW typedSequentialExprBlockR { let mArrow = rhs parseState 1 let expr = $2 mArrow mArrow, expr } ifExprCases: | ifExprThen ifExprElifs { let exprThen, mThen = $1 let mElse, elseExpr = $2 (fun exprGuard mIf isElif -> let mIfToThen = unionRanges mIf mThen let lastBranch: SynExpr = match elseExpr with None -> exprThen | Some e -> e let mIfToEndOfLastBranch = unionRanges mIf lastBranch.Range let spIfToThen = DebugPointAtBinding.Yes(mIfToThen) let trivia = { IfKeyword = mIf; IsElif = isElif; ThenKeyword = mThen; ElseKeyword = mElse; IfToThenRange = mIfToThen } SynExpr.IfThenElse(exprGuard, exprThen, elseExpr, spIfToThen, false, mIfToEndOfLastBranch, trivia)) } ifExprThen: | THEN declExpr %prec prec_then_if { $2, rhs parseState 1 } | THEN recover %prec prec_then_if { let mThen = rhs parseState 1 arbExpr ("ifThen1", mThen.EndRange), mThen } | OTHEN OBLOCKBEGIN typedSequentialExpr oblockend %prec prec_then_if { $3, rhs parseState 1 } | OTHEN OBLOCKBEGIN typedSequentialExpr recover %prec prec_then_if { if not $4 then reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnexpectedEndOfFileThen()) exprFromParseError $3, rhs parseState 1 } | OTHEN recover %prec prec_then_if { let mThen = rhs parseState 1 arbExpr ("ifThen2", mThen.EndRange), mThen } | OTHEN OBLOCKBEGIN recover %prec prec_then_if { let mThen = rhs parseState 1 arbExpr ("ifThen3", mThen.EndRange), mThen } ifExprElifs: | /* EMPTY */ { None, None } | ELSE declExpr { let mElse = rhs parseState 1 Some mElse, Some $2 } | OELSE OBLOCKBEGIN typedSequentialExpr oblockend { let mElse = rhs parseState 1 Some mElse, Some $3 } | OELSE OBLOCKBEGIN typedSequentialExpr recover { let mElse = rhs parseState 1 if not $4 then reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnexpectedEndOfFileElse()) Some mElse, Some(exprFromParseError $3) } | ELIF declExpr ifExprCases { let mElif = rhs parseState 1 // verify if `ELIF` is not a merged token let length = mElif.EndColumn - mElif.StartColumn if length > 4 then let mElse = mkRange mElif.FileName (mkPos mElif.StartLine mElif.StartColumn) (mkPos mElif.StartLine (mElif.StartColumn + 4)) let mIf = mkRange mElif.FileName (mkPos mElif.StartLine (mElif.EndColumn - 2)) (mkPos mElif.StartLine mElif.EndColumn) Some mElse, (Some($3 $2 mIf false)) else None, Some($3 $2 mElif true) } | ELIF declExpr recover { if not $3 then reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnexpectedEndOfFileElif()) None, Some(exprFromParseError $2) } tupleExpr: | tupleExpr COMMA declExpr { let exprs, commas = $1 $3 :: exprs, (rhs parseState 2 :: commas) } | tupleExpr COMMA ends_coming_soon_or_recover { let commaRange = rhs parseState 2 if not $3 then reportParseErrorAt commaRange (FSComp.SR.parsExpectedExpressionAfterToken ()) let exprs, commas = $1 arbExpr ("tupleExpr1", commaRange.EndRange) :: exprs, commaRange :: commas } | tupleExpr COMMA COMMA declExpr { let exprs, commas = $1 let mComma1 = rhs parseState 2 let mComma2 = rhs parseState 3 reportParseErrorAt mComma2 (FSComp.SR.parsExpectingExpressionInTuple ()) let expr = arbExpr ("tupleExpr2", mComma1.EndRange) $4 :: expr :: exprs, (mComma2 :: mComma1 :: commas) } | tupleExpr COMMA COMMA ends_coming_soon_or_recover { let exprs, commas = $1 let mComma1 = rhs parseState 2 let mComma2 = rhs parseState 3 reportParseErrorAt mComma2 (FSComp.SR.parsExpectingExpressionInTuple ()) if not $4 then reportParseErrorAt mComma2 (FSComp.SR.parsExpectedExpressionAfterToken ()) let expr1 = arbExpr ("tupleExpr3", mComma1.EndRange) let expr2 = arbExpr ("tupleExpr4", mComma2.EndRange) expr2 :: expr1 :: exprs, mComma2 :: mComma1 :: commas } | declExpr COMMA ends_coming_soon_or_recover { let commaRange = rhs parseState 2 if not $3 then reportParseErrorAt commaRange (FSComp.SR.parsExpectedExpressionAfterToken ()) [arbExpr ("tupleExpr5", commaRange.EndRange); $1], [commaRange] } | declExpr COMMA declExpr { [$3; $1], [rhs parseState 2] } | declExpr COMMA COMMA ends_coming_soon_or_recover { let mComma1 = rhs parseState 2 let mComma2 = rhs parseState 3 reportParseErrorAt mComma2 (FSComp.SR.parsExpectingExpressionInTuple ()) if not $4 then reportParseErrorAt mComma2 (FSComp.SR.parsExpectedExpressionAfterToken ()) let expr1 = arbExpr ("tupleExpr6", mComma1.EndRange) let expr2 = arbExpr ("tupleExpr7", mComma2.EndRange) [expr2; expr1; $1], [mComma2; mComma1] } | declExpr COMMA COMMA declExpr { let mComma1 = rhs parseState 2 let mComma2 = rhs parseState 3 reportParseErrorAt mComma2 (FSComp.SR.parsExpectingExpressionInTuple ()) let expr = arbExpr ("tupleExpr8", mComma1.EndRange) [$4; expr; $1], [mComma2; mComma1] } minusExpr: | INFIX_AT_HAT_OP minusExpr { if $1 <> "^" then reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsInvalidPrefixOperator()) let m = (rhs2 parseState 1 2) SynExpr.IndexFromEnd($2, m) } | 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()) 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 atomTypeNonAtomicDeprecated opt_HIGH_PRECEDENCE_APP atomicExprAfterType DOT atomicExprQualification { errorR (Error (FSComp.SR.parsNewExprMemberAccess (), rhs parseState 6)) let newExpr = SynExpr.New(false, $2, $4, unionRanges (rhs parseState 1) $4.Range) $6 newExpr (lhs parseState) (rhs parseState 5) } | NEW atomTypeNonAtomicDeprecated opt_HIGH_PRECEDENCE_APP atomicExprAfterType { SynExpr.New(false, $2, $4, unionRanges (rhs parseState 1) $4.Range) } | NEW atomTypeNonAtomicDeprecated opt_HIGH_PRECEDENCE_APP error { SynExpr.New(false, $2, arbExpr ("minusExpr", (rhs parseState 4)), unionRanges (rhs parseState 1) ($2).Range) } | NEW error { arbExpr ("minusExpr2", (rhs parseState 1)) } | 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, false, $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, hpa = $3 SynExpr.App(ExprAtomicFlag.Atomic, false, arg1, arg2, unionRanges arg1.Range arg2.Range), hpa } | atomicExpr HIGH_PRECEDENCE_PAREN_APP atomicExpr { let arg1, _ = $1 let arg2, _ = $3 SynExpr.App(ExprAtomicFlag.Atomic, false, arg1, arg2, unionRanges arg1.Range arg2.Range), true } | atomicExpr HIGH_PRECEDENCE_TYAPP typeArgsActual { let arg1, _ = $1 let mLessThan, mGreaterThan, _, args, commas, mTypeArgs = $3 let mWholeExpr = unionRanges arg1.Range mTypeArgs SynExpr.TypeApp(arg1, mLessThan, args, commas, mGreaterThan, mTypeArgs, mWholeExpr), false } | PREFIX_OP atomicExpr { let arg2, hpa2 = $2 if not (IsValidPrefixOperatorUse $1) then reportParseErrorAt arg2.Range (FSComp.SR.parsInvalidPrefixOperator()) mkSynPrefixPrim (rhs parseState 1) (unionRanges (rhs parseState 1) arg2.Range) $1 arg2, hpa2 } | QUOTE ident { let id = mkSynId (lhs parseState) ($2).idText let typar = SynTypar(id, TyparStaticReq.None, false) let lhsm = rhs2 parseState 1 2 SynExpr.Typar(typar, lhsm), false } | RESERVED { arbExpr ("unfinished identifier", rhs parseState 1), false } | 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 { let (SynIdent(ident, trivia)) = $2 SynExpr.LongIdent(true, SynLongIdent([ident], [], [trivia]), None, rhs parseState 2), false } | atomicExpr QMARK dynamicArg { let m = rhs2 parseState 1 3 let mQmark = rhs parseState 2 let arg1, hpa1 = $1 SynExpr.Dynamic(arg1, mQmark, $3, m), hpa1 } | GLOBAL { let m = rhs parseState 1 let ident = ident(MangledGlobalName, m) SynExpr.LongIdent(false, SynLongIdent([ident], [], [Some(IdentTrivia.OriginalNotation "global")]), None, m), false } | identExpr { $1, false } | LBRACK listExprElements RBRACK { $2 (lhs parseState), false } | LBRACK listExprElements recover { reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnmatchedBracket()) exprFromParseError ($2 (rhs2 parseState 1 2)), false } | LBRACK error RBRACK { // silent recovery SynExpr.ArrayOrList(false, [ ], lhs parseState), false } | LBRACK recover { reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnmatchedBracket()) // silent recovery exprFromParseError (SynExpr.ArrayOrList(false, [ ], rhs parseState 1)), false } | STRUCT LPAREN tupleExpr rparen { let exprs, commas = $3 let m = rhs2 parseState 1 4 SynExpr.Tuple(true, List.rev exprs, List.rev commas, m), false } | STRUCT LPAREN tupleExpr recover { reportParseErrorAt (rhs parseState 2) (FSComp.SR.parsUnmatchedBracket()) let exprs, commas = $3 let m = (rhs parseState 1, exprs) ||> unionRangeWithListBy (fun e -> e.Range) SynExpr.Tuple(true, List.rev exprs, List.rev commas, m), false } | atomicExprAfterType { $1, false } atomicExprQualification: | identOrOp { let idm = rhs parseState 1 (fun e mLhs mDot -> mkSynDot mDot mLhs e $1) } | GLOBAL { (fun e mLhs mDot -> reportParseErrorAt (rhs parseState 3) (FSComp.SR.nrGlobalUsedOnlyAsFirstName()) let fixedLhsm = mkRange mLhs.FileName mLhs.Start mDot.End // previous mLhs is wrong after 'recover' mkSynDotMissing mDot fixedLhsm e) } | /* empty */ { (fun e mLhs mDot -> reportParseErrorAt mDot (FSComp.SR.parsMissingQualificationAfterDot()) let fixedLhsm = mkRange mLhs.FileName mLhs.Start mDot.End // previous mLhs is wrong after 'recover' mkSynDotMissing mDot fixedLhsm e) } | recover { (fun e mLhs mDot -> reportParseErrorAt mDot (FSComp.SR.parsMissingQualificationAfterDot()) let fixedLhsm = mkRange mLhs.FileName mLhs.Start mDot.End // previous mLhs is wrong after 'recover' // Include 'e' in the returned expression but throw it away mkSynDotMissing mDot fixedLhsm e) } | LPAREN COLON_COLON rparen DOT INT32 { (fun e mLhs mDot -> if parseState.LexBuffer.ReportLibraryOnlyFeatures then libraryOnlyError(lhs parseState) SynExpr.LibraryOnlyUnionCaseFieldGet(e, mkSynCaseName mLhs opNameCons, (fst $5), mLhs)) } | LPAREN typedSequentialExpr rparen { let lpr = rhs parseState 1 let rpr = rhs parseState 3 (fun e mLhs mDot -> // Check for expr.(*) // Note that "*" is parsed as an expression (it is allowed in "foo.[3,*]") match $2 with | SynExpr.IndexRange(None, mOperator, None, _m1, _m2, _) -> mkSynDot mDot mLhs e (SynIdent(ident(CompileOpName "*", mOperator), Some(IdentTrivia.OriginalNotationWithParen(lpr, "*", rpr)))) | _ -> if parseState.LexBuffer.SupportsFeature LanguageFeature.MLCompatRevisions then mlCompatError (FSComp.SR.mlCompatMultiPrefixTyparsNoLongerSupported()) (lhs parseState) else mlCompatWarning (FSComp.SR.parsParenFormIsForML()) (lhs parseState) mkSynDotParenGet mLhs mDot e $2) } | LBRACK typedSequentialExpr RBRACK { (fun e mLhs mDot -> mkSynDotBrackGet mLhs mDot e $2) } | LBRACK typedSequentialExpr recover { reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnmatchedBracket()) (fun e mLhs mDot -> exprFromParseError (mkSynDotBrackGet mLhs mDot e $2)) } | LBRACK error RBRACK { let mArg = rhs2 parseState 1 3 (fun e mLhs mDot -> mkSynDotBrackGet mLhs mDot e (arbExpr ("indexerExpr1", mArg))) } | LBRACK recover { reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnmatchedBracket()) let mArg = (rhs parseState 1).EndRange (fun e mLhs mDot -> exprFromParseError (mkSynDotBrackGet mLhs mDot e (arbExpr ("indexerExpr2", mArg)))) } /* the start of atomicExprAfterType must not overlap with the valid postfix tokens of the type syntax, e.g. new List(...) */ atomicExprAfterType: | constant { SynExpr.Const(fst $1, snd $1) } | parenExpr { $1 } | braceExpr { $1 } | braceBarExpr { $1 } | interpolatedString { let parts, synStringKind = $1 SynExpr.InterpolatedString(parts, synStringKind, rhs parseState 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 typedSequentialExpr END { SynExpr.Paren($2, rhs parseState 1, Some(rhs parseState 3), rhs2 parseState 1 3) } | BEGIN typedSequentialExpr recover { reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnmatchedBegin()); exprFromParseError $2 } | BEGIN error END { (* silent recovery *) arbExpr ("beginEndExpr", (lhs parseState)) } | BEGIN END { mkSynUnit (lhs parseState) } quoteExpr: | LQUOTE typedSequentialExpr 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, false, lhs parseState)) } | LQUOTE typedSequentialExpr recover { reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnmatched(fst $1)) let mExpr = rhs2 parseState 1 2 exprFromParseError (SynExpr.Quote(mkSynIdGet (lhs parseState) (CompileOpName (fst $1)), snd $1, $2, false, mExpr)) } | LQUOTE error RQUOTE { (* silent recovery *) SynExpr.Quote(mkSynIdGet (lhs parseState) (CompileOpName (fst $1)), snd $1, arbExpr ("quoteExpr", (rhs parseState 2)), false, lhs parseState) } | LQUOTE recover { reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnmatched(fst $1)) exprFromParseError (SynExpr.Quote(mkSynIdGet (lhs parseState) (CompileOpName (fst $1)), snd $1, arbExpr ("quoteExpr2", (rhs parseState 1).EndRange), false, rhs parseState 1)) } arrayExpr: | LBRACK_BAR arrayExprElements BAR_RBRACK { $2 (lhs parseState) } | LBRACK_BAR arrayExprElements recover { reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnmatchedBracketBar()) exprFromParseError ($2 (rhs2 parseState 1 2)) } | LBRACK_BAR error BAR_RBRACK { (* silent recovery *) SynExpr.ArrayOrList(true, [ ], lhs parseState) } | LBRACK_BAR recover { reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnmatchedBracketBar()) (* silent recovery *) exprFromParseError (SynExpr.ArrayOrList(true, [ ], rhs parseState 1)) } parenExpr: | LPAREN rparen { SynExpr.Const(SynConst.Unit, (rhs2 parseState 1 2)) } | LPAREN parenExprBody rparen { let m = rhs2 parseState 1 3 SynExpr.Paren($2 m, rhs parseState 1, Some(rhs parseState 3), m) } | LPAREN parenExprBody ends_other_than_rparen_coming_soon_or_recover { if not $3 then reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnmatchedParen()) let mLhs = unionRangeWithPos (rhs parseState 1) (rhs parseState 2).End SynExpr.Paren(exprFromParseError ($2 mLhs), rhs parseState 1, None, mLhs) } | LPAREN error rparen { // silent recovery SynExpr.Paren(arbExpr ("parenExpr1", (rhs parseState 1).EndRange), (rhs parseState 1), Some(rhs parseState 3), (rhs2 parseState 1 3)) } | LPAREN TYPE_COMING_SOON { reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnmatchedParen()) let mLhs = unionRangeWithPos (rhs parseState 1) (rhs parseState 2).Start arbExpr ("parenExpr2tcs", mLhs) } | LPAREN MODULE_COMING_SOON { reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnmatchedParen()) let mLhs = unionRangeWithPos (rhs parseState 1) (rhs parseState 2).Start arbExpr ("parenExpr2mcs", mLhs) } | LPAREN RBRACE_COMING_SOON { reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnmatchedParen()) let mLhs = unionRangeWithPos (rhs parseState 1) (rhs parseState 2).Start arbExpr ("parenExpr2rbcs", mLhs) } | LPAREN OBLOCKEND_COMING_SOON { let lparenRange = (rhs parseState 1) reportParseErrorAt lparenRange (FSComp.SR.parsUnmatchedParen()) SynExpr.Paren(arbExpr ("parenExpr2obecs", lparenRange.EndRange), lparenRange, None, lparenRange) } | LPAREN recover %prec prec_atomexpr_lparen_error { reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnmatchedParen()) arbExpr ("parenExpr2", (lhs parseState)) } // This is really what we should be doing, but it fails because param info expects the range of the expression // to extend all the way over the "recover", to the end of the file if necessary // // let mLeftParen = rhs parseState 1 //let mLhs = if $2 then unionRangeWithPos mLeftParen (rhs parseState 2).Start else mLeftParen //arbExpr ("parenExpr2", mLhs) } | LPAREN COMMA declExpr rparen { let mComma = rhs parseState 2 let mLparen = rhs parseState 1 let mRparen = rhs parseState 3 let errorExpr = arbExpr ("tupleExpr3", mComma.EndRange) let mTuple = unionRanges mComma $3.Range let tupleExpr = match $3 with | SynExpr.Tuple(false, exprs, commas, m) -> SynExpr.Tuple(false, errorExpr :: exprs, mComma :: commas, mTuple) | expr -> SynExpr.Tuple(false, [errorExpr; expr], [mComma], mTuple) SynExpr.Paren(tupleExpr, mLparen, Some mRparen, rhs2 parseState 1 4) } parenExprBody: | typars COLON LPAREN classMemberSpfn rparen typedSequentialExpr { (fun m -> SynExpr.TraitCall($1, $4, $6, m)) } /* disambiguate: x $a.id(x) */ | typedSequentialExpr { (fun _m -> $1) } | inlineAssemblyExpr { $1 } typars: | typar { SynType.Var($1, rhs parseState 1) } | LPAREN typarAlts rparen { let m = rhs2 parseState 1 3 SynType.Paren($2, m) } typarAlts: | typarAlts OR appType { let mOr = rhs parseState 2 let m = unionRanges $1.Range $3.Range SynType.Or($1, $3, m, { OrKeyword = mOr }) } | typar { SynType.Var($1, rhs parseState 1) } braceExpr: | LBRACE braceExprBody rbrace { let m, r = $2 r (rhs2 parseState 1 3) } | LBRACE braceExprBody recover { reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnmatchedBrace()) let m, r = $2 // Note, we can't use 'exprFromParseError' because the extra syntax node interferes with some syntax-directed transformations for computation expressions r (unionRanges (rhs parseState 1) m) } | LBRACE error rbrace { // silent recovery arbExpr ("braceExpr", rhs2 parseState 1 3) } | LBRACE recover { reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnmatchedBrace()) // Note, we can't use 'exprFromParseError' because the extra syntax node interferes with some syntax-directed transformations for computation expressions SynExpr.Record(None, None, [], rhs parseState 1) } | LBRACE rbrace { let m = rhs2 parseState 1 2 SynExpr.Record(None, None, [], m) } braceExprBody: | recdExpr { (lhs parseState), (fun m -> let a, b, c = $1 in SynExpr.Record(a, b, c, m)) } | objExpr { $1 } | computationExpr { $1 } listExprElements: | sequentialExpr { (fun mLhs -> SynExpr.ArrayOrListComputed(false, $1, mLhs)) } | { (fun mLhs -> SynExpr.ArrayOrList(false, [ ], mLhs)) } arrayExprElements: | sequentialExpr { (fun mLhs -> SynExpr.ArrayOrListComputed(true, $1, mLhs)) } | { (fun mLhs -> SynExpr.ArrayOrList(true, [ ], mLhs)) } computationExpr: | sequentialExpr { $1.Range, (fun mLhs -> SynExpr.ComputationExpr(false, $1, mLhs)) } arrowThenExprR: | RARROW typedSequentialExprBlockR { let mArrow = rhs parseState 1 let expr = $2 mArrow SynExpr.YieldOrReturn((true, false), expr, unionRanges mArrow expr.Range) } forLoopBinder: | parenPattern IN declExpr { ($1, $3, true, DebugPointAtInOrTo.Yes(rhs parseState 2)) } | parenPattern IN ends_coming_soon_or_recover { if not $3 then reportParseErrorAt (rhs parseState 2) (FSComp.SR.parsExpectedExpressionAfterToken()) ($1, arbExpr ("forLoopBinder", (rhs parseState 2)), false, DebugPointAtInOrTo.Yes(rhs parseState 2)) } | parenPattern ends_coming_soon_or_recover { if not $2 then reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsInOrEqualExpected()) ($1, arbExpr ("forLoopBinder2", (rhs parseState 1).EndRange), false, DebugPointAtInOrTo.Yes(rhs parseState 2)) } forLoopRange: | parenPattern EQUALS declExpr forLoopDirection declExpr { let mEquals = rhs parseState 2 let spTo = DebugPointAtInOrTo.Yes(rhs parseState 4) idOfPat parseState (rhs parseState 1) $1, Some mEquals, $3, $4, $5, spTo } forLoopDirection: | TO { true } | DOWNTO { false } inlineAssemblyExpr: | HASH string opt_inlineAssemblyTypeArg optCurriedArgExprs optInlineAssemblyReturnTypes HASH { if parseState.LexBuffer.ReportLibraryOnlyFeatures then libraryOnlyWarning (lhs parseState) let (s, _), sm = $2, rhs parseState 2 (fun m -> let ilInstrs = ParseAssemblyCodeInstructions s parseState.LexBuffer.ReportLibraryOnlyFeatures parseState.LexBuffer.LanguageVersion sm SynExpr.LibraryOnlyILAssembly(box ilInstrs, $3, List.rev $4, $5, m)) } optCurriedArgExprs: | optCurriedArgExprs argExpr %prec expr_args { $2 :: $1 } | /* EMPTY */ { [] } opt_atomicExprAfterType: | /* EMPTY */ { None } | atomicExprAfterType { Some($1) } opt_inlineAssemblyTypeArg: | /* EMPTY */ { [] } | typeKeyword LPAREN typ rparen { [$3] } optInlineAssemblyReturnTypes: | /* EMPTY */ { [] } | COLON typ { [$2] } | COLON LPAREN rparen { [] } recdExpr: | INHERIT atomTypeNonAtomicDeprecated opt_HIGH_PRECEDENCE_APP opt_atomicExprAfterType recdExprBindings opt_seps_recd { let arg = match $4 with None -> mkSynUnit (lhs parseState) | Some e -> e let l = List.rev $5 let dummyField = mkRecdField (SynLongIdent([], [], [])) // dummy identifier, it will be discarded let l = rebindRanges (dummyField, None, None) l $6 let (SynExprRecordField(_, _, _, inheritsSep)) = List.head l let bindings = List.tail l (Some($2, arg, rhs2 parseState 2 4, inheritsSep, rhs parseState 1), None, bindings) } | recdExprCore { let a, b = $1 None, a, b } recdExprCore: | appExpr EQUALS declExprBlock recdExprBindings opt_seps_recd { match $1 with | LongOrSingleIdent(false, (SynLongIdent _ as f), None, m) -> let f = mkRecdField f let mEquals = rhs parseState 2 let l = List.rev $4 let l = rebindRanges (f, Some mEquals, Some $3) l $5 (None, l) | _ -> raiseParseErrorAt (rhs parseState 2) (FSComp.SR.parsFieldBinding()) } /* handles cases when identifier can start from the underscore */ | UNDERSCORE { let m = rhs parseState 1 reportParseErrorAt m (FSComp.SR.parsUnderscoreInvalidFieldName()) reportParseErrorAt m (FSComp.SR.parsFieldBinding()) let f = mkUnderscoreRecdField m (None, [ SynExprRecordField(f, None, None, None) ]) } | UNDERSCORE EQUALS { let m = rhs parseState 1 reportParseErrorAt m (FSComp.SR.parsUnderscoreInvalidFieldName()) let f = mkUnderscoreRecdField m let mEquals = rhs parseState 2 reportParseErrorAt (rhs2 parseState 1 2) (FSComp.SR.parsFieldBinding()) (None, [ SynExprRecordField(f, Some mEquals, None, None) ]) } | UNDERSCORE EQUALS declExprBlock recdExprBindings opt_seps_recd { reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnderscoreInvalidFieldName()) let f = mkUnderscoreRecdField (rhs parseState 1) let mEquals = rhs parseState 2 let l = List.rev $4 let l = rebindRanges (f, Some mEquals, Some $3) l $5 (None, l) } /* handles case like {x with} */ | appExpr WITH recdBinding recdExprBindings opt_seps_recd { let l = List.rev $4 let l = rebindRanges $3 l $5 (Some($1, (rhs parseState 2, None)), l) } | appExpr OWITH opt_seps_recd OEND { (Some($1, (rhs parseState 2, None)), []) } | appExpr OWITH recdBinding recdExprBindings opt_seps_recd OEND { let l = List.rev $4 let l = rebindRanges $3 l $5 (Some($1, (rhs parseState 2, None)), l) } opt_seps_recd: | seps_recd { Some $1 } | /* EMPTY */ { None } seps_recd: | OBLOCKSEP { (rhs parseState 1), None } | SEMICOLON { let m = (rhs parseState 1) m, Some m.End } | SEMICOLON OBLOCKSEP { (rhs2 parseState 1 2), Some (rhs parseState 1).End } | OBLOCKSEP SEMICOLON { (rhs2 parseState 1 2), Some (rhs parseState 2).End } /* identifier can start from the underscore */ pathOrUnderscore : | path { mkRecdField $1 } | UNDERSCORE { let m = rhs parseState 1 reportParseErrorAt m (FSComp.SR.parsUnderscoreInvalidFieldName()) mkUnderscoreRecdField m } recdExprBindings: | recdExprBindings seps_recd recdBinding { ($3, Some $2) :: $1 } | /* EMPTY */ { [] } recdBinding: | pathOrUnderscore EQUALS declExprBlock { let mEquals = rhs parseState 2 ($1, Some mEquals, Some $3) } | pathOrUnderscore EQUALS { let mEquals = rhs parseState 2 reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsFieldBinding()) ($1, Some mEquals, None) } | pathOrUnderscore EQUALS ends_coming_soon_or_recover { let mEquals = rhs parseState 2 reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsFieldBinding()) ($1, Some mEquals, None) } | pathOrUnderscore { reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsFieldBinding()) ($1, None, None) } | pathOrUnderscore ends_coming_soon_or_recover { reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsFieldBinding()) ($1, None, None) } /* 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 { let mNewExpr = rhs parseState 1 let fullRange = match $4 with [] -> (rhs parseState 1) | _ -> (rhs2 parseState 1 4) let mWithKwd, bindings, members = $2 fullRange, (fun m -> let (a, b) = $1 in SynExpr.ObjExpr(a, b, Some mWithKwd, bindings, members, $4, mNewExpr, m)) } | objExprBaseCall opt_OBLOCKSEP objExprInterfaces { let mNewExpr = rhs parseState 1 let fullRange = match $3 with [] -> (rhs parseState 1) | _ -> (rhs2 parseState 1 3) fullRange, (fun m -> let (a, b) = $1 in SynExpr.ObjExpr(a, b, None, [], [], $3, mNewExpr, m)) } | NEW atomTypeNonAtomicDeprecated { let mNewExpr = rhs parseState 1 (rhs2 parseState 1 2), (fun m -> let (a, b) = $2, None in SynExpr.ObjExpr(a, b, None, [], [], [], mNewExpr, m)) } objExprBaseCall: | NEW atomTypeNonAtomicDeprecated opt_HIGH_PRECEDENCE_APP atomicExprAfterType baseSpec { ($2, Some($4, Some($5))) } | NEW atomTypeNonAtomicDeprecated opt_HIGH_PRECEDENCE_APP atomicExprAfterType { ($2, Some($4, None)) } | NEW atomTypeNonAtomicDeprecated { $2, None } opt_objExprBindings: | objExprBindings { let mWithKwd, bindings, members = $1 Some mWithKwd, bindings, members } | /* EMPTY */ { None, [], [] } objExprBindings: | WITH localBindings { let mWithKwd = (rhs parseState 1) let _localBindingsLastRange, localBindingsBuilder = $2 mWithKwd, (localBindingsBuilder PreXmlDoc.Empty [] None SynLeadingKeyword.Synthetic), [] } | OWITH localBindings OEND { let mWithKwd = (rhs parseState 1) let _localBindingsLastRange, localBindingsBuilder = $2 mWithKwd, (localBindingsBuilder PreXmlDoc.Empty [] None SynLeadingKeyword.Synthetic), [] } | WITH objectImplementationBlock opt_declEnd { let mWithKwd = rhs parseState 1 let memberDefns = $2 |> (List.choose (function | (SynMemberDefn.Member _ | SynMemberDefn.GetSetMember _) as memberDefn -> Some memberDefn | SynMemberDefn.AutoProperty(range = m) -> errorR(Error(FSComp.SR.parsIllegalMemberVarInObjectImplementation(), m)); None | x -> errorR(Error(FSComp.SR.parsMemberIllegalInObjectImplementation(), x.Range)); None)) mWithKwd, [], memberDefns } 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 { let mWithKwd, bindings, members = $3 SynInterfaceImpl($2, mWithKwd, bindings, members, lhs parseState) } braceBarExpr: | STRUCT braceBarExprCore { let mStruct = rhs parseState 1 $2 (Some mStruct) } | braceBarExprCore { $1 None } braceBarExprCore: | LBRACE_BAR recdExprCore bar_rbrace { let orig, flds = $2 let flds = flds |> List.choose (function | SynExprRecordField((synLongIdent, _), mEquals, Some e, _) when orig.IsSome -> Some(synLongIdent, mEquals, e) // copy-and-update, long identifier signifies nesting | SynExprRecordField((SynLongIdent([ _id ], _, _) as synLongIdent, _), mEquals, Some e, _) -> Some(synLongIdent, mEquals, e) // record construction, long identifier not valid | SynExprRecordField((synLongIdent, _), mEquals, None, _) -> Some(synLongIdent, mEquals, arbExpr ("anonField", synLongIdent.Range)) | _ -> reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsInvalidAnonRecdType()); None) let mLeftBrace = rhs parseState 1 let mRightBrace = rhs parseState 3 (fun (mStruct: range option) -> let m = match mStruct with | None -> unionRanges mLeftBrace mRightBrace | Some mStruct -> unionRanges mStruct mRightBrace SynExpr.AnonRecd(mStruct.IsSome, orig, flds, m, { OpeningBraceRange = mLeftBrace })) } | LBRACE_BAR recdExprCore recover { reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnmatchedBraceBar()) let orig, flds = $2 let flds = flds |> List.map (function | SynExprRecordField((synLongIdent, _), mEquals, Some e, _) -> (synLongIdent, mEquals, e) | SynExprRecordField((synLongIdent, _), mEquals, None, _) -> (synLongIdent, mEquals, arbExpr ("anonField", synLongIdent.Range))) let mLeftBrace = rhs parseState 1 let mExpr = rhs parseState 2 (fun (mStruct: range option) -> let m = match mStruct with | None -> unionRanges mLeftBrace mExpr | Some mStruct -> unionRanges mStruct mExpr SynExpr.AnonRecd(mStruct.IsSome, orig, flds, m, { OpeningBraceRange = mLeftBrace })) } | LBRACE_BAR error bar_rbrace { // silent recovery let mLeftBrace = rhs parseState 1 let mRightBrace = rhs parseState 3 (fun (mStruct: range option) -> let m = match mStruct with | None -> unionRanges mLeftBrace mRightBrace | Some mStruct -> unionRanges mStruct mRightBrace arbExpr ("braceBarExpr", m)) } | LBRACE_BAR recover { reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnmatchedBraceBar()) let mLeftBrace = rhs parseState 1 (fun (mStruct: range option) -> let m = match mStruct with | None -> mLeftBrace | Some mStruct -> unionRanges mStruct mLeftBrace SynExpr.AnonRecd(mStruct.IsSome, None, [], m, { OpeningBraceRange = mLeftBrace })) } | LBRACE_BAR bar_rbrace { let mLeftBrace = rhs parseState 1 let mRightBrace = rhs parseState 2 (fun (mStruct: range option) -> let m = match mStruct with | None -> unionRanges mLeftBrace mRightBrace | Some mStruct -> unionRanges mStruct mRightBrace SynExpr.AnonRecd(mStruct.IsSome, None, [], m, { OpeningBraceRange = mLeftBrace })) } anonLambdaExpr: | FUN atomicPatterns RARROW typedSequentialExprBlock { let mAll = unionRanges (rhs parseState 1) $4.Range let mArrow = Some(rhs parseState 3) mkSynFunMatchLambdas parseState.SynArgNameGenerator false mAll $2 mArrow $4 } | FUN atomicPatterns RARROW error { let mAll = rhs2 parseState 1 3 let mArrow = Some(rhs parseState 3) mkSynFunMatchLambdas parseState.SynArgNameGenerator false mAll $2 mArrow (arbExpr ("anonLambdaExpr1", (rhs parseState 4))) } | OFUN atomicPatterns RARROW typedSequentialExprBlockR OEND { let mArrow = rhs parseState 3 let expr = $4 mArrow let mAll = unionRanges (rhs parseState 1) expr.Range mkSynFunMatchLambdas parseState.SynArgNameGenerator false mAll $2 (Some mArrow) expr } | OFUN atomicPatterns RARROW typedSequentialExprBlockR recover { if not $5 then reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnexpectedEndOfFileFunBody ()) let mArrow = rhs parseState 3 let expr = $4 mArrow let mAll = unionRanges (rhs parseState 1) expr.Range exprFromParseError (mkSynFunMatchLambdas parseState.SynArgNameGenerator false mAll $2 (Some mArrow) expr) } | OFUN atomicPatterns RARROW ORIGHT_BLOCK_END OEND { let mLambda = rhs2 parseState 1 3 reportParseErrorAt mLambda (FSComp.SR.parsMissingFunctionBody()) let mArrow = Some(rhs parseState 3) mkSynFunMatchLambdas parseState.SynArgNameGenerator false mLambda $2 mArrow (arbExpr ("anonLambdaExpr2", mLambda.EndRange)) } | OFUN atomicPatterns RARROW recover { if not $4 then reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnexpectedEndOfFileFunBody()) let mLambda = rhs2 parseState 1 3 let mArrow = Some(rhs parseState 3) exprFromParseError (mkSynFunMatchLambdas parseState.SynArgNameGenerator false mLambda $2 mArrow (arbExpr ("anonLambdaExpr3", mLambda.EndRange))) } | OFUN atomicPatterns error OEND { let mLambda = rhs2 parseState 1 2 exprFromParseError (mkSynFunMatchLambdas parseState.SynArgNameGenerator false mLambda $2 None (arbExpr ("anonLambdaExpr4", mLambda.EndRange))) } | OFUN error OEND { exprFromParseError (mkSynFunMatchLambdas parseState.SynArgNameGenerator false (rhs parseState 1) [] None (arbExpr ("anonLambdaExpr5", (rhs parseState 2)))) } anonMatchingExpr: | FUNCTION withPatternClauses %prec expr_function { let clauses, mLast = $2 let mAll = unionRanges (rhs parseState 1) mLast SynExpr.MatchLambda(false, (rhs parseState 1), clauses, DebugPointAtBinding.NoneAtInvisible, mAll) } | OFUNCTION withPatternClauses OEND %prec expr_function { let clauses, mLast = $2 let mAll = unionRanges (rhs parseState 1) mLast SynExpr.MatchLambda(false, (rhs parseState 1), clauses, DebugPointAtBinding.NoneAtInvisible, mAll) } /*--------------------------------------------------------------------------*/ /* 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 mColon = rhs parseState 1 let ty, arity = $2 let arity = (match arity with SynValInfo([], rmdata)-> rmdata | _ -> SynInfo.unnamedRetVal) Some(Some mColon, SynReturnInfo((ty, arity), rhs parseState 2)) } | COLON recover { let mColon = rhs parseState 1 let ty, arity = SynType.FromParseError(mColon.EndRange), SynInfo.unnamedRetVal Some(Some mColon, SynReturnInfo((ty, arity), mColon.EndRange)) } topType: | topTupleType RARROW topType { let dty, dmdata = $1 let rty, (SynValInfo(dmdatas, rmdata)) = $3 let mArrow = rhs parseState 2 SynType.Fun(dty, rty, lhs parseState, { ArrowRange = mArrow }), SynValInfo(dmdata :: dmdatas, rmdata) } | topTupleType RARROW recover { let dty, dmdata = $1 let mArrow = rhs parseState 2 let rty = SynType.FromParseError(mArrow.EndRange) SynType.Fun(dty, rty, lhs parseState, { ArrowRange = mArrow }), SynValInfo([dmdata], SynInfo.unnamedRetVal) } | topTupleType { let ty, rmdata = $1 ty, (SynValInfo([], (match rmdata with [md] -> md | _ -> SynInfo.unnamedRetVal))) } topTupleType: | topAppType STAR topTupleTypeElements { let t, argInfo = $1 let mStar = rhs parseState 2 let path = SynTupleTypeSegment.Type t :: SynTupleTypeSegment.Star mStar :: (List.map fst $3) let mdata = argInfo :: (List.choose snd $3) mkSynTypeTuple path, mdata } | topAppType STAR recover { let ty1, argInfo = $1 let mStar = rhs parseState 2 let ty2 = SynType.FromParseError(mStar.EndRange) let path = [SynTupleTypeSegment.Type ty1; SynTupleTypeSegment.Star mStar; SynTupleTypeSegment.Type ty2] mkSynTypeTuple path, [argInfo] } | STAR topTupleTypeElements { let mStar = rhs parseState 1 let ty = SynType.FromParseError(mStar.EndRange) reportParseErrorAt mStar (FSComp.SR.parsExpectingType ()) let path = SynTupleTypeSegment.Type ty :: SynTupleTypeSegment.Star mStar :: (List.map fst $2) mkSynTypeTuple path, List.choose snd $2 } | topAppType { let ty, mdata = $1 ty, [mdata] } topTupleTypeElements: | topAppType STAR topTupleTypeElements { let t, argInfo = $1 let mStar = rhs parseState 2 (SynTupleTypeSegment.Type t, Some argInfo) :: (SynTupleTypeSegment.Star mStar, None) :: $3 } | topAppType STAR recover { let ty1, argInfo = $1 let mStar = rhs parseState 2 let ty2 = SynType.FromParseError(mStar.EndRange) [(SynTupleTypeSegment.Type ty1, Some argInfo); (SynTupleTypeSegment.Star mStar, None); (SynTupleTypeSegment.Type ty2, None)] } | STAR topTupleTypeElements { let mStar = rhs parseState 1 let ty = SynType.FromParseError(mStar.EndRange) reportParseErrorAt mStar (FSComp.SR.parsExpectingType ()) (SynTupleTypeSegment.Type ty, None) :: (SynTupleTypeSegment.Star mStar, None) :: $2 } | topAppType %prec prec_toptuptyptail_prefix { let t, argInfo = $1 [ SynTupleTypeSegment.Type t, Some argInfo ] } topAppType: | attributes appType COLON appType { match $2 with | SynType.LongIdent(SynLongIdent([id], _, _)) -> let m = unionRanges (rhs parseState 1) $4.Range SynType.SignatureParameter($1, false, Some id, $4, m), SynArgInfo($1, false, Some id) | _ -> raiseParseErrorAt (rhs parseState 2) (FSComp.SR.parsSyntaxErrorInLabeledType()) } | attributes appType COLON recover { match $2 with | SynType.LongIdent(SynLongIdent([id], _, _)) -> let mColon = rhs parseState 2 let m = unionRanges (rhs parseState 1) mColon let ty = SynType.FromParseError(mColon.EndRange) SynType.SignatureParameter($1, false, Some id, ty, m), SynArgInfo($1, false, Some id) | _ -> raiseParseErrorAt (rhs parseState 2) (FSComp.SR.parsSyntaxErrorInLabeledType()) } | attributes QMARK ident COLON appType { let m = unionRanges (rhs parseState 1) $5.Range SynType.SignatureParameter($1, true, Some $3, $5, m), SynArgInfo($1, true, Some $3) } | attributes QMARK ident COLON recover { let mColon = rhs parseState 4 let m = unionRanges (rhs parseState 1) mColon let ty = SynType.FromParseError(mColon.EndRange) SynType.SignatureParameter($1, true, Some $3, ty, m), SynArgInfo($1, true, Some $3) } | attributes appType { let m = unionRanges (rhs parseState 1) $2.Range SynType.SignatureParameter($1, false, None, $2, m), SynArgInfo($1, false, None) } | appType COLON appType { match $1 with | SynType.LongIdent(SynLongIdent([id], _, _)) -> let m = unionRanges (rhs parseState 1) $3.Range SynType.SignatureParameter([], false, Some id, $3, m), SynArgInfo([], false, Some id) | _ -> raiseParseErrorAt (rhs parseState 2) (FSComp.SR.parsSyntaxErrorInLabeledType()) } | appType COLON recover { match $1 with | SynType.LongIdent(SynLongIdent([id], _, _)) -> let mColon = rhs parseState 2 let m = unionRanges $1.Range mColon let ty = SynType.FromParseError(mColon.EndRange) SynType.SignatureParameter([], false, Some id, ty, m), SynArgInfo([], false, Some id) | _ -> raiseParseErrorAt (rhs parseState 2) (FSComp.SR.parsSyntaxErrorInLabeledType()) } | QMARK ident COLON appType { let m = unionRanges (rhs parseState 1) $4.Range SynType.SignatureParameter([], true, Some $2, $4, m), SynArgInfo([], true, Some $2) } | QMARK ident COLON recover { let mColon = rhs parseState 3 let m = unionRanges (rhs parseState 1) mColon let ty = SynType.FromParseError(mColon.EndRange) SynType.SignatureParameter([], true, Some $2, ty, m), 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 { let mArrow = rhs parseState 2 let m = unionRanges (rhs2 parseState 1 2) $3.Range SynType.Fun($1, $3, m, { ArrowRange = mArrow }) } | tupleType RARROW recover { let mArrow = rhs parseState 2 let ty = SynType.FromParseError(mArrow.EndRange) let m = rhs2 parseState 1 2 SynType.Fun($1, ty, m, { ArrowRange = mArrow }) } | tupleType RARROW RARROW typ { let mArrow1 = rhs parseState 2 let mArrow2 = rhs parseState 3 reportParseErrorAt mArrow2 (FSComp.SR.parsExpectingType ()) let ty = SynType.FromParseError(mArrow2.StartRange) let m1 = unionRanges $1.Range $4.Range let m2 = unionRanges mArrow2 $4.Range SynType.Fun($1, SynType.Fun(ty, $4, m2, { ArrowRange = mArrow2 }), m1, { ArrowRange = mArrow1 }) } | tupleType %prec prec_typ_prefix { $1 } typEOF: | typ EOF { checkEndOfFileError $2; $1 } tupleType: | appType STAR tupleOrQuotTypeElements { let mStar = rhs parseState 2 let path = SynTupleTypeSegment.Type $1 :: SynTupleTypeSegment.Star mStar :: $3 mkSynTypeTuple path } | appType STAR recover { let mStar = rhs parseState 2 let ty = SynType.FromParseError(mStar.EndRange) let path = [SynTupleTypeSegment.Type $1; SynTupleTypeSegment.Star mStar; SynTupleTypeSegment.Type ty] mkSynTypeTuple path } | STAR tupleOrQuotTypeElements { let mStar = rhs parseState 1 let ty = SynType.FromParseError(mStar.EndRange) reportParseErrorAt mStar (FSComp.SR.parsExpectingType ()) let path = SynTupleTypeSegment.Type ty :: SynTupleTypeSegment.Star mStar :: $2 mkSynTypeTuple path } | INFIX_STAR_DIV_MOD_OP tupleOrQuotTypeElements { if $1 <> "/" then reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnexpectedInfixOperator ()) let mSlash = rhs parseState 1 let path = SynTupleTypeSegment.Slash mSlash :: $2 mkSynTypeTuple path } | INFIX_STAR_DIV_MOD_OP recover { if $1 <> "/" then reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnexpectedInfixOperator ()) let mSlash = rhs parseState 1 let ty = SynType.FromParseError(mSlash.EndRange) let path = [SynTupleTypeSegment.Slash mSlash; SynTupleTypeSegment.Type ty] mkSynTypeTuple path } | appType INFIX_STAR_DIV_MOD_OP tupleOrQuotTypeElements { if $2 <> "/" then reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnexpectedInfixOperator()) let mSlash = rhs parseState 2 let path = SynTupleTypeSegment.Type $1 :: SynTupleTypeSegment.Slash mSlash :: $3 mkSynTypeTuple path } | appType INFIX_STAR_DIV_MOD_OP recover { if $2 <> "/" then reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnexpectedInfixOperator ()) let mSlash = rhs parseState 2 let ty = SynType.FromParseError(mSlash.EndRange) let path = [SynTupleTypeSegment.Type $1; SynTupleTypeSegment.Slash mSlash; SynTupleTypeSegment.Type ty] mkSynTypeTuple path } | appType %prec prec_tuptyp_prefix { $1 } tupleOrQuotTypeElements: | appType STAR tupleOrQuotTypeElements { let mStar = rhs parseState 2 SynTupleTypeSegment.Type $1 :: SynTupleTypeSegment.Star mStar :: $3 } | appType STAR recover { let mStar = rhs parseState 2 let ty = SynType.FromParseError(mStar.EndRange) [SynTupleTypeSegment.Type $1; SynTupleTypeSegment.Star mStar; SynTupleTypeSegment.Type ty] } | STAR tupleOrQuotTypeElements { let mStar = rhs parseState 1 let ty = SynType.FromParseError(mStar.EndRange) reportParseErrorAt mStar (FSComp.SR.parsExpectingType ()) SynTupleTypeSegment.Type ty :: SynTupleTypeSegment.Star mStar :: $2 } | appType INFIX_STAR_DIV_MOD_OP tupleOrQuotTypeElements { if $2 <> "/" then reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnexpectedInfixOperator ()) let mSlash = rhs parseState 2 SynTupleTypeSegment.Type $1 :: SynTupleTypeSegment.Slash mSlash :: $3 } | appType INFIX_STAR_DIV_MOD_OP recover { if $2 <> "/" then reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnexpectedInfixOperator ()) let mSlash = rhs parseState 2 let ty = SynType.FromParseError(mSlash.EndRange) [SynTupleTypeSegment.Type $1; SynTupleTypeSegment.Slash mSlash; SynTupleTypeSegment.Type ty] } | INFIX_STAR_DIV_MOD_OP tupleOrQuotTypeElements { if $1 <> "/" then reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnexpectedInfixOperator ()) let mSlash = rhs parseState 1 let ty = SynType.FromParseError(mSlash.EndRange) reportParseErrorAt mSlash (FSComp.SR.parsExpectingType ()) SynTupleTypeSegment.Type ty :: SynTupleTypeSegment.Slash mSlash :: $2 } | appType %prec prec_tuptyptail_prefix { [ SynTupleTypeSegment.Type $1 ] } appTypeCon: | path %prec prec_atomtyp_path { SynType.LongIdent($1) } | typar { SynType.Var($1, lhs parseState) } appTypeConPower: | appTypeCon INFIX_AT_HAT_OP atomicRationalConstant { if $2 <> "^" && $2 <> "^-" then reportParseErrorAt (rhs parseState 2) (FSComp.SR.parsUnexpectedInfixOperator()) if $2 = "^-" then SynType.MeasurePower($1, SynRationalConst.Negate($3), lhs parseState) else SynType.MeasurePower($1, $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 /* note: use "rhs parseState 1" to deal with parens in "(int) list" */ { SynType.App($2, None, [$1], [], None, true, unionRanges (rhs parseState 1) $2.Range) } | LPAREN appTypePrefixArguments rparen appTypeConPower { let args, commas = $2 if parseState.LexBuffer.SupportsFeature LanguageFeature.MLCompatRevisions then mlCompatError (FSComp.SR.mlCompatMultiPrefixTyparsNoLongerSupported()) (unionRanges (rhs parseState 1) $4.Range) else mlCompatWarning (FSComp.SR.parsMultiArgumentGenericTypeFormDeprecated()) (unionRanges (rhs parseState 1) $4.Range) SynType.App($4, None, args, commas, None, true, unionRanges (rhs parseState 1) $4.Range) } | powerType { $1 } | typar COLON_GREATER typ { let tp, typ = $1, $3 let m = lhs parseState SynType.WithGlobalConstraints(SynType.Var(tp, rhs parseState 1), [SynTypeConstraint.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 } | LBRACK COMMA COMMA COMMA COMMA RBRACK { 5 } | LBRACK COMMA COMMA COMMA COMMA COMMA RBRACK { 6 } | LBRACK COMMA COMMA COMMA COMMA COMMA COMMA RBRACK { 7 } | LBRACK COMMA COMMA COMMA COMMA COMMA COMMA COMMA RBRACK { 8 } | LBRACK COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA RBRACK { 9 } | LBRACK COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA RBRACK { 10 } | LBRACK COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA RBRACK { 11 } | LBRACK COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA RBRACK { 12 } | LBRACK COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA RBRACK { 13 } | LBRACK COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA RBRACK { 14 } | LBRACK COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA RBRACK { 15 } | LBRACK COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA RBRACK { 16 } | LBRACK COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA RBRACK { 17 } | LBRACK COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA RBRACK { 18 } | LBRACK COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA RBRACK { 19 } | LBRACK COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA RBRACK { 20 } | LBRACK COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA RBRACK { 21 } | LBRACK COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA RBRACK { 22 } | LBRACK COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA RBRACK { 23 } | LBRACK COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA RBRACK { 24 } | LBRACK COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA RBRACK { 25 } | LBRACK COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA RBRACK { 26 } | LBRACK COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA RBRACK { 27 } | LBRACK COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA RBRACK { 28 } | LBRACK COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA RBRACK { 29 } | LBRACK COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA RBRACK { 30 } | LBRACK COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA RBRACK { 31 } | LBRACK COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA COMMA RBRACK { 32 } appTypePrefixArguments: | typeArgActual COMMA typeArgActual typeArgListElements { let typeArgs, commas = $4 $1 :: $3 :: List.rev typeArgs, (rhs parseState 2) :: (List.rev commas) } typeArgListElements: | typeArgListElements COMMA typeArgActual { let typeArgs, commas = $1 $3 :: typeArgs, (rhs parseState 2) :: commas } | typeArgListElements COMMA dummyTypeArg %prec prec_args_error /* NOTE: no "recover" */ { reportParseErrorAt (rhs parseState 2) (FSComp.SR.parsMissingTypeArgs()) let typeArgs, commas = $1 $3 :: typeArgs, (rhs parseState 2) :: commas } | { [], [] } powerType: | atomTypeOrAnonRecdType { $1 } | atomTypeOrAnonRecdType INFIX_AT_HAT_OP atomicRationalConstant { if $2 <> "^" && $2 <> "^-" then reportParseErrorAt (rhs parseState 2) (FSComp.SR.parsUnexpectedInfixOperator()) if $2 = "^-" then SynType.MeasurePower($1, SynRationalConst.Negate($3), lhs parseState) else SynType.MeasurePower($1, $3, lhs parseState) } /* Like appType but gives a deprecation error when a non-atomic type is used */ /* Also, doesn't start with '{|' */ atomTypeNonAtomicDeprecated: | LPAREN appTypePrefixArguments rparen appTypeConPower { let args, commas = $2 if parseState.LexBuffer.SupportsFeature LanguageFeature.MLCompatRevisions then mlCompatError (FSComp.SR.mlCompatMultiPrefixTyparsNoLongerSupported()) (unionRanges (rhs parseState 1) $4.Range) else mlCompatWarning (FSComp.SR.parsMultiArgumentGenericTypeFormDeprecated()) (unionRanges (rhs parseState 1) $4.Range) SynType.App($4, None, args, commas, None, true, unionRanges (rhs parseState 1) $4.Range) } | atomType { $1 } atomTypeOrAnonRecdType: | atomType { $1 } | anonRecdType { let flds, isStruct = $1 let flds2 = flds |> List.choose (function | (SynField([], false, Some id, ty, false, _xmldoc, None, _m, _trivia)) -> Some(id, ty) | _ -> reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsInvalidAnonRecdType()); None) SynType.AnonRecd(isStruct, flds2, rhs parseState 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" */ atomType: | HASH atomType { SynType.HashConstraint($2, lhs parseState) } | appTypeConPower %prec prec_atomtyp_path { $1 } | UNDERSCORE { SynType.Anon(lhs parseState) } | LPAREN typ rparen { SynType.Paren($2, lhs parseState) } | LPAREN typ recover { reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnmatchedParen ()) SynType.Paren($2, lhs parseState) } | STRUCT LPAREN appType STAR tupleOrQuotTypeElements rparen { let mStar = rhs parseState 4 let path = SynTupleTypeSegment.Type $3 :: SynTupleTypeSegment.Star mStar :: $5 let m = rhs2 parseState 1 6 SynType.Tuple(true, path, m) } | STRUCT LPAREN appType STAR tupleOrQuotTypeElements recover { reportParseErrorAt (rhs parseState 2) (FSComp.SR.parsUnmatchedParen()) let mStar = rhs parseState 4 let path = SynTupleTypeSegment.Type $3 :: SynTupleTypeSegment.Star mStar :: $5 let m = rhs2 parseState 1 5 SynType.Tuple(true, path, m) } | STRUCT LPAREN appType STAR recover { reportParseErrorAt (rhs parseState 2) (FSComp.SR.parsUnmatchedParen()) SynType.Anon(lhs parseState) } | STRUCT LPAREN appType recover { reportParseErrorAt (rhs parseState 2) (FSComp.SR.parsUnmatchedParen()) SynType.Anon(lhs parseState) } | STRUCT LPAREN recover { reportParseErrorAt (rhs parseState 2) (FSComp.SR.parsUnmatchedParen()) SynType.Anon(lhs parseState) } | rawConstant { SynType.StaticConstant($1, rhs parseState 1) } | NULL { let m = rhs parseState 1 SynType.StaticConstant(SynConst.String(null, SynStringKind.Regular, m), m) } | CONST atomicExpr { let e, _ = $2 SynType.StaticConstantExpr(e, lhs parseState) } | FALSE { SynType.StaticConstant(SynConst.Bool false, lhs parseState) } | TRUE { SynType.StaticConstant(SynConst.Bool true, lhs parseState) } | LPAREN error rparen { (* silent recovery *) SynType.Anon(lhs parseState) } | appTypeCon typeArgsNoHpaDeprecated %prec prec_atomtyp_path { let mLessThan, mGreaterThan, args, commas, mWhole = $2 SynType.App($1, Some(mLessThan), args, commas, mGreaterThan, false, unionRanges $1.Range mWhole) } | atomType DOT path %prec prec_atomtyp_get_path { SynType.LongIdentApp($1, $3, None, [], [], None, unionRanges (rhs parseState 1) $3.Range) } | atomType DOT path typeArgsNoHpaDeprecated %prec prec_atomtyp_get_path { let mLessThan, mGreaterThan, args, commas, mWhole = $4 SynType.LongIdentApp($1, $3, Some(mLessThan), args, commas, mGreaterThan, unionRanges $1.Range mWhole) } | appTypeCon DOT ends_coming_soon_or_recover { if not $3 then reportParseErrorAt (rhs parseState 2) (FSComp.SR.parsExpectedNameAfterToken()) $1 } typeArgsNoHpaDeprecated: | typeArgsActual { let mLessThan, mGreaterThan, parsedOk, args, commas, mAll = $1 if parsedOk then // if someone has "foo "^" && $2 <> "^-" then reportParseErrorAt (rhs parseState 2) (FSComp.SR.parsUnexpectedOperatorForUnitOfMeasure()) if $2 = "^-" then SynMeasure.Power($1, SynRationalConst.Negate($3), lhs parseState) else SynMeasure.Power($1, $3, 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 SynTypar(id, TyparStaticReq.None, false) } | INFIX_AT_HAT_OP ident { if $1 <> "^" then reportParseErrorAt (rhs parseState 1) (FSComp.SR.tcUnexpectedSymbolInTypeExpression($1)) let id = mkSynId (lhs parseState) ($2).idText SynTypar(id, TyparStaticReq.HeadType, false) } ident: | IDENT { ident($1, rhs parseState 1) } /* A A.B.C path used to an identifier */ path: | GLOBAL { SynLongIdent([ident(MangledGlobalName, rhs parseState 1)], [], [Some(IdentTrivia.OriginalNotation "global")]) } | ident { SynLongIdent([$1], [], [None]) } | path DOT ident { let (SynLongIdent(lid, dotms, trivia)) = $1 SynLongIdent(lid @ [$3], dotms @ [rhs parseState 2], trivia @ [None]) } | path DOT ends_coming_soon_or_recover { if not $3 then reportParseErrorAt (rhs parseState 2) (FSComp.SR.parsExpectedNameAfterToken()) let (SynLongIdent(lid, dotms, trivia)) = $1 SynLongIdent(lid, dotms @ [rhs parseState 2], trivia) } /* An operator name, with surrounding parentheses */ opName: | LPAREN operatorName rparen { let lpr = rhs parseState 1 let rpr = rhs parseState 3 ident(CompileOpName $2, rhs parseState 2), IdentTrivia.OriginalNotationWithParen(lpr, $2, rpr) } | LPAREN error rparen { reportParseErrorAt (lhs parseState) (FSComp.SR.parsErrorParsingAsOperatorName()) let lpr = rhs parseState 1 let rpr = rhs parseState 3 ident(CompileOpName "****", rhs parseState 2), IdentTrivia.HasParenthesis(lpr, rpr) } | LPAREN_STAR_RPAREN { let m = rhs parseState 1 let lpr = mkFileIndexRange m.FileIndex m.Start m.Start let rpr = mkFileIndexRange m.FileIndex m.End m.End ident(CompileOpName "*", rhs parseState 1), IdentTrivia.OriginalNotationWithParen(lpr, "*", rpr) } /* active pattern name */ | LPAREN activePatternCaseNames BAR rparen { let lpr = rhs parseState 1 let text = ("|" + String.concat "|" (List.rev $2) + "|") let rpr = rhs parseState 4 ident(text, rhs2 parseState 2 3), IdentTrivia.HasParenthesis(lpr, rpr) } /* partial active pattern name */ | LPAREN activePatternCaseNames BAR UNDERSCORE BAR rparen { let lpr = rhs parseState 1 let text = ("|" + String.concat "|" (List.rev $2) + "|_|") let rpr = rhs parseState 6 ident(text, rhs2 parseState 2 5), IdentTrivia.HasParenthesis(lpr, rpr) } /* An operator name, without surrounding parentheses */ 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 { ".." } | DOT_DOT DOT_DOT { ".. .." } | LQUOTE RQUOTE { if $1 <> $2 then reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsMismatchedQuotationName(fst $1)) fst $1 } /* One part of an active pattern name */ activePatternCaseName: | IDENT { if not (String.isLeadingIdentifierCharacterUpperCase _1) then reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsActivePatternCaseMustBeginWithUpperCase()) if ($1.IndexOf('|') <> -1) then reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsActivePatternCaseContainsPipe()) $1 } /* Multiple parts of an active pattern name */ activePatternCaseNames: | BAR activePatternCaseName { [$2] } | activePatternCaseNames BAR activePatternCaseName { $3 :: $1 } /* A single item that is an identifier or operator name */ identOrOp: | ident { SynIdent($1, None) } | opName { let ident, trivia = $1 SynIdent(ident, Some trivia) } /* An A.B.C path ending in an identifier or operator name */ /* Note, only used in atomicPatternLongIdent */ pathOp: | ident { SynLongIdent([$1], [], [None]) } | opName { let ident, trivia = $1 SynLongIdent([ident], [], [Some trivia]) } | ident DOT pathOp { prependIdentInLongIdentWithTrivia (SynIdent($1, None)) (rhs parseState 2) $3 } | ident DOT error { (* silent recovery *) SynLongIdent([$1], [rhs parseState 2], [None]) } /* nameop is identOrOp not used as part of a path */ nameop: | identOrOp { $1 } identExpr: | ident { if $1.idText = "" then SynExpr.FromParseError(SynExpr.Ident($1), $1.idRange) else SynExpr.Ident($1) } | opName { let m = lhs parseState let ident, trivia = $1 SynExpr.LongIdent(false, SynLongIdent([ident], [], [Some trivia]), None, m) } topSeparator: | SEMICOLON { } | SEMICOLON_SEMICOLON { } | OBLOCKSEP { } topSeparators: | topSeparator { } | topSeparator topSeparators { } opt_topSeparators: | topSeparator opt_topSeparators { } | /* EMPTY */ { } /* Seprators in either #light or non-#light */ 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 non-#light */ opt_declEnd: | ODECLEND {} | OEND { } | END {} | /* EMPTY */ {} opt_ODECLEND: | ODECLEND { } | /* EMPTY */ { } deprecated_opt_equals: | EQUALS { deprecatedWithError (FSComp.SR.parsNoEqualShouldFollowNamespace()) (lhs parseState); () } | /* EMPTY */ { } opt_equals: | EQUALS { let mEquals = rhs parseState 1 Some mEquals } | /* EMPTY */ { None } opt_OBLOCKSEP: | OBLOCKSEP { } | /* EMPTY */ { } opt_seps: | seps { } | /* EMPTY */ { } opt_rec: | REC { true } | /* EMPTY */ { false } opt_bar: | BAR { } | /* EMPTY */ { } opt_inline: | INLINE { Some(rhs parseState 1) } | /* EMPTY */ { None } opt_mutable: | MUTABLE { true } | /* EMPTY */ { false } /* A 'do' token in either #light or non-#light */ doToken: | DO { } | ODO { } doneDeclEnd: | DONE { } | ODECLEND { } /* DONE gets thrown away by the lexfilter in favour of ODECLEND */ structOrBegin: | STRUCT { if parseState.LexBuffer.SupportsFeature LanguageFeature.MLCompatRevisions then mlCompatError (FSComp.SR.mlCompatStructEndNoLongerSupported()) (lhs parseState) else mlCompatWarning (FSComp.SR.parsSyntaxModuleStructEndDeprecated()) (lhs parseState) } | BEGIN { } sigOrBegin: | SIG { if parseState.LexBuffer.SupportsFeature LanguageFeature.MLCompatRevisions then mlCompatError (FSComp.SR.mlCompatSigEndNoLongerSupported())(lhs parseState) else mlCompatWarning (FSComp.SR.parsSyntaxModuleSigEndDeprecated()) (lhs parseState) } | BEGIN { } colonOrEquals: | COLON { if parseState.LexBuffer.SupportsFeature LanguageFeature.MLCompatRevisions then mlCompatError (FSComp.SR.mlCompatSigColonNoLongerSupported())(lhs parseState) else mlCompatWarning (FSComp.SR.parsSyntaxModuleSigEndDeprecated()) (lhs parseState) None } | EQUALS { let mEquals = rhs parseState 1 Some mEquals } /* A literal string or a string from a keyword like __SOURCE_FILE__ */ string: | STRING { let (s, synStringKind, _) = $1 s, synStringKind } sourceIdentifier: | KEYWORD_STRING { $1 } interpolatedStringFill: | declExpr { ($1, None) } | declExpr COLON ident %prec interpolation_fill { ($1, Some $3) } interpolatedStringParts: | INTERP_STRING_END { [ SynInterpolatedStringPart.String(fst $1, rhs parseState 1) ] } | INTERP_STRING_PART interpolatedStringFill interpolatedStringParts { SynInterpolatedStringPart.String(fst $1, rhs parseState 1) :: SynInterpolatedStringPart.FillExpr $2 :: $3 } | INTERP_STRING_PART interpolatedStringParts { let rbrace = parseState.InputEndPosition 1 let lbrace = parseState.InputStartPosition 2 reportParseErrorAt (mkSynRange rbrace lbrace) (FSComp.SR.parsEmptyFillInInterpolatedString()) SynInterpolatedStringPart.String(fst $1, rhs parseState 1) :: $2 } /* INTERP_STRING_BEGIN_END */ /* INTERP_STRING_BEGIN_PART int32 INTERP_STRING_END */ /* INTERP_STRING_BEGIN_PART int32 INTERP_STRING_PART int32 INTERP_STRING_END */ interpolatedString: | INTERP_STRING_BEGIN_PART interpolatedStringFill interpolatedStringParts { let s, synStringKind, _ = $1 SynInterpolatedStringPart.String(s, rhs parseState 1) :: SynInterpolatedStringPart.FillExpr $2 :: $3, synStringKind } | INTERP_STRING_BEGIN_END { let s, synStringKind, _ = $1 [ SynInterpolatedStringPart.String(s, rhs parseState 1) ], synStringKind } | INTERP_STRING_BEGIN_PART interpolatedStringParts { let s, synStringKind, _ = $1 let rbrace = parseState.InputEndPosition 1 let lbrace = parseState.InputStartPosition 2 reportParseErrorAt (mkSynRange rbrace lbrace) (FSComp.SR.parsEmptyFillInInterpolatedString()) SynInterpolatedStringPart.String(s, rhs parseState 1) :: $2, synStringKind } opt_HIGH_PRECEDENCE_APP: | HIGH_PRECEDENCE_BRACK_APP { } | HIGH_PRECEDENCE_PAREN_APP { } | /* EMPTY */ { } opt_HIGH_PRECEDENCE_TYAPP: | HIGH_PRECEDENCE_TYAPP { } | /* EMPTY */ { } /* A 'type' keyword */ typeKeyword: | TYPE_COMING_SOON typeKeyword { } | TYPE_IS_HERE { } | TYPE { } /* A 'module' keyword */ moduleKeyword: | MODULE_COMING_SOON moduleKeyword { } | MODULE_IS_HERE { } | MODULE { } rbrace: | RBRACE_COMING_SOON rbrace { } | RBRACE_IS_HERE { } | RBRACE { } bar_rbrace: | BAR_RBRACE { } rparen: | RPAREN_COMING_SOON rparen { } | RPAREN_IS_HERE { } | RPAREN { } oblockend: | OBLOCKEND_COMING_SOON oblockend { } | OBLOCKEND_IS_HERE { } | OBLOCKEND { } ends_other_than_rparen_coming_soon_or_recover: | TYPE_COMING_SOON { false } | MODULE_COMING_SOON { false } | RBRACE_COMING_SOON { false } | OBLOCKEND_COMING_SOON { false } | recover { $1 } ends_coming_soon_or_recover: | TYPE_COMING_SOON { false } | MODULE_COMING_SOON { false } | RBRACE_COMING_SOON { false } | RPAREN_COMING_SOON { false } | OBLOCKEND_COMING_SOON { false } | recover { $1 }