Permalink
Fetching contributors…
Cannot retrieve contributors at this time
5003 lines (3967 sloc) 206 KB
// 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 Internal.Utilities
open Microsoft.FSharp.Compiler.AbstractIL
open Microsoft.FSharp.Compiler.AbstractIL.Internal
open Microsoft.FSharp.Compiler.AbstractIL.Internal.Library
open Microsoft.FSharp.Compiler
open Internal.Utilities.Text.Parsing
open System
open Microsoft.FSharp.Compiler.Range
open Microsoft.FSharp.Compiler.Ast
open Microsoft.FSharp.Compiler.Lib
open Microsoft.FSharp.Compiler.PrettyNaming
open Microsoft.FSharp.Compiler.ErrorLogger
#if DEBUG
let debugPrint(s) =
if Internal.Utilities.Text.Parsing.Flags.debug then
printfn "\n%s" s
#else
let debugPrint(s) = ignore s
#endif
let exprFromParseError (e:SynExpr) = SynExpr.FromParseError(e,e.Range)
let patFromParseError (e:SynPat) = SynPat.FromParseError(e, e.Range)
let mkSynOptionalExpr (m: range) xopt =
let m = m.MakeSynthetic()
match xopt with
| None -> mkSynLidGet m Ast.FSharpLib.CorePath "None"
| Some x -> SynExpr.App(ExprAtomicFlag.NonAtomic, false, mkSynLidGet m Ast.FSharpLib.CorePath "Some",x,m)
// record bindings returned by the recdExprBindings rule has shape:
// (binding, separator-before-this-binding)
// this function converts arguments from form
// binding1 (binding2*sep1, binding3*sep2...) sepN
// to form
// binding1*sep1, binding2*sep2
let rebindRanges first fields lastSep =
let rec run (name, value) l acc =
match l with
| [] -> List.rev ((name, value, lastSep)::acc)
| (f, m)::xs -> run f xs ((name, value, m)::acc)
run first fields []
let mkUnderscoreRecdField m = LongIdentWithDots([ident("_", m)], []), false
let mkRecdField lidwd = lidwd, true
let mkSynDoBinding (vis,strict,expr,m) =
match vis with
| Some vis -> errorR(Error(FSComp.SR.parsDoCannotHaveVisibilityDeclarations (vis.ToString()),m))
| None -> ()
Binding (None,
(if strict then DoBinding else StandaloneExpression),
false,false,[],PreXmlDoc.Empty,SynInfo.emptySynValData,
(if strict then SynPat.Const(SynConst.Unit,m) else SynPat.Wild m),
None,expr,m,NoSequencePointAtDoBinding)
let mkSynDoDecl (e: SynExpr) =
let spExpr = if IsControlFlowExpression e then NoSequencePointAtDoBinding else SequencePointAtBinding e.Range in
SynModuleDecl.DoExpr(spExpr, e, e.Range)
let addAttribs attrs p = SynPat.Attrib(p,attrs,p.Range)
// 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)))
let reportParseErrorAt m s = errorR(Error(s,m))
let unionRangeWithPos (r:range) p =
let r2 = mkRange r.FileName p p
unionRanges r r2
let raiseParseErrorAt m s =
reportParseErrorAt m s;
// This initiates error recovery
raise RecoverableParseError
let checkEndOfFileError t =
match t with
| LexCont.IfDefSkip(_,_,m) -> reportParseErrorAt m (FSComp.SR.parsEofInHashIf())
| LexCont.String (_,m) -> reportParseErrorAt m (FSComp.SR.parsEofInString())
| LexCont.TripleQuoteString (_,m) -> reportParseErrorAt m (FSComp.SR.parsEofInTripleQuoteString())
| LexCont.VerbatimString (_,m) -> reportParseErrorAt m (FSComp.SR.parsEofInVerbatimString())
| LexCont.Comment (_,_,m) -> reportParseErrorAt m (FSComp.SR.parsEofInComment())
| LexCont.SingleLineComment (_,_,m) -> reportParseErrorAt m (FSComp.SR.parsEofInComment())
| LexCont.StringInComment (_,_,m) -> reportParseErrorAt m (FSComp.SR.parsEofInStringInComment())
| LexCont.VerbatimStringInComment (_,_,m) -> reportParseErrorAt m (FSComp.SR.parsEofInVerbatimStringInComment())
| LexCont.TripleQuoteStringInComment (_,_,m) -> reportParseErrorAt m (FSComp.SR.parsEofInTripleQuoteStringInComment())
| LexCont.MLOnly (_,m) -> reportParseErrorAt m (FSComp.SR.parsEofInIfOcaml())
| LexCont.EndLine(LexerEndlineContinuation.Skip(_,_,m)) -> reportParseErrorAt m (FSComp.SR.parsEofInDirective())
| LexCont.EndLine(LexerEndlineContinuation.Token(stack))
| LexCont.Token(stack) ->
match stack with
| [] -> ()
| (_,m) :: _ -> reportParseErrorAt m (FSComp.SR.parsNoHashEndIfFound())
// BindingSetPreAttrs(letRange, isRec, isUse, builderFunction, wholeRange)
type BindingSet = BindingSetPreAttrs of range * bool * bool * (SynAttributes -> SynAccess option -> SynAttributes * SynBinding list) * range
let mkClassMemberLocalBindings(isStatic,initialRangeOpt,attrs,vis,BindingSetPreAttrs(_,isRec,isUse,declsPreAttrs,bindingSetRange)) =
let ignoredFreeAttrs,decls = declsPreAttrs attrs vis
let wholeRange =
match initialRangeOpt with
| None -> bindingSetRange
| Some m -> unionRanges m bindingSetRange
if not (isNil ignoredFreeAttrs) then warning(Error(FSComp.SR.parsAttributesIgnored(),wholeRange));
if isUse then errorR(Error(FSComp.SR.parsUseBindingsIllegalInImplicitClassConstructors(),wholeRange))
SynMemberDefn.LetBindings (decls,isStatic,isRec,wholeRange)
let mkLocalBindings (mWhole,BindingSetPreAttrs(_,isRec,isUse,declsPreAttrs,_),body) =
let ignoredFreeAttrs,decls = declsPreAttrs [] None
if not (isNil ignoredFreeAttrs) then warning(Error(FSComp.SR.parsAttributesIgnored(),mWhole))
SynExpr.LetOrUse (isRec,isUse,decls,body,mWhole)
let mkDefnBindings (mWhole,BindingSetPreAttrs(_,isRec,isUse,declsPreAttrs,_bindingSetRange),attrs,vis,attrsm) =
if isUse then warning(Error(FSComp.SR.parsUseBindingsIllegalInModules(),mWhole))
let freeAttrs,decls = declsPreAttrs attrs vis
let letDecls = [ SynModuleDecl.Let (isRec,decls,mWhole) ]
let attrDecls = if not (isNil freeAttrs) then [ SynModuleDecl.Attributes (freeAttrs,attrsm) ] else []
attrDecls @ letDecls
let idOfPat m p =
match p with
| SynPat.Named (SynPat.Wild _,id,false,_,_) -> id
| SynPat.LongIdent(LongIdentWithDots([id],_),_,_,_,_,_) -> id
| _ -> raiseParseErrorAt m (FSComp.SR.parsIntegerForLoopRequiresSimpleIdentifier())
let checkForMultipleAugmentations m a1 a2 =
if not (isNil a1) && not (isNil a2) then raiseParseErrorAt m (FSComp.SR.parsOnlyOneWithAugmentationAllowed())
a1 @ a2
let grabXmlDoc(parseState:IParseState,elemIdx) =
LexbufLocalXmlDocStore.GrabXmlDocBeforeMarker(parseState.LexBuffer,rhs parseState elemIdx)
let unionRangeWithListBy projectRangeFromThing m listOfThing =
(m, listOfThing) ||> List.fold (fun m thing -> unionRanges m (projectRangeFromThing thing))
let rangeOfNonNilAttrs(attrs:SynAttributes) =
(attrs.Head.Range,attrs.Tail) ||> unionRangeWithListBy (fun a -> a.Range)
let rangeOfLongIdent(lid:LongIdent) =
System.Diagnostics.Debug.Assert(not lid.IsEmpty, "the parser should never produce a long-id that is the empty list")
(lid.Head.idRange,lid) ||> unionRangeWithListBy (fun id -> id.idRange)
%}
%token <byte[]> BYTEARRAY
%token <string> STRING
%token <string> KEYWORD_STRING // Like __SOURCE_DIRECTORY__
%token <string> IDENT
%token <string> INFIX_STAR_STAR_OP
%token <string> INFIX_COMPARE_OP
%token <string> INFIX_AT_HAT_OP
%token <string> INFIX_BAR_OP
%token <string> PREFIX_OP
%token <string> INFIX_STAR_DIV_MOD_OP
%token <string> INFIX_AMP_OP
%token <string> PLUS_MINUS_OP
%token <string> ADJACENT_PREFIX_OP
%token <string> FUNKY_OPERATOR_NAME
/* bool indicates if INT8 was 'bad' max_int+1, e.g. '128' */
%token <sbyte * bool> INT8
%token <int16 * bool> INT16
%token <int32 * bool> INT32 INT32_DOT_DOT
%token <int64 * bool> INT64
%token <byte> UINT8
%token <uint16> UINT16
%token <uint32> UINT32
%token <uint64> UINT64
%token <uint64> UNATIVEINT
%token <int64> NATIVEINT
%token <single> IEEE32
%token <double> IEEE64
%token <char> CHAR
%token <System.Decimal> DECIMAL
%token <(string * string)> BIGNUM
%token <bool> LET YIELD YIELD_BANG
%token <bool> LESS GREATER /* here the bool indicates if the tokens are part of a type application or type parameter declaration, e.g. C<int>, detected by the lex filter */
%token <string> PERCENT_OP BINDER
%token <string * bool> LQUOTE RQUOTE RQUOTE_DOT
%token BAR_BAR UPCAST DOWNCAST NULL RESERVED MODULE NAMESPACE DELEGATE CONSTRAINT BASE
%token AND AS ASSERT OASSERT ASR BEGIN DO DONE DOWNTO ELSE ELIF END DOT_DOT
%token EXCEPTION FALSE FOR FUN FUNCTION IF IN 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 LBRACK_LESS LBRACE
%token LBRACE_LESS BAR_RBRACK GREATER_RBRACE UNDERSCORE
%token BAR RBRACK RBRACE 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<int>(x), but not f (x) */
%token HIGH_PRECEDENCE_TYAPP /* inserted for x<y>, but not x<y */
/* for offside rule */
%token <bool> OLET /* LexFilter #light converts 'LET' tokens to 'OLET' when starting (CtxtLetDecl(blockLet=true)) */
%token <string> OBINDER /* LexFilter #light converts 'BINDER' tokens to 'OBINDER' when starting (CtxtLetDecl(blockLet=true)) */
%token ODO /* LexFilter #light converts 'DO' tokens to 'ODO' */
%token ODO_BANG /* LexFilter #light converts 'DO_BANG' tokens to 'ODO_BANG' */
%token OTHEN /* LexFilter #light converts 'THEN' tokens to 'OTHEN' */
%token OELSE /* LexFilter #light converts 'ELSE' tokens to 'OELSE' except if immeditely followed by 'if', when they become 'ELIF' */
%token OWITH /* LexFilter #light converts SOME (but not all) 'WITH' tokens to 'OWITH' */
%token OFUNCTION /* LexFilter #light converts 'FUNCTION' tokens to 'OFUNCTION' */
%token OFUN /* LexFilter #light converts 'FUN' tokens to 'OFUN' */
%token ORESET /* LexFilter uses internally to force a complete reset on a ';;' */
%token OBLOCKBEGIN /* LexFilter #light inserts for:
- just after first '=' or ':' when in 'CtxtModuleHead', i.e. after 'module' and sequence of dot/identifier/access tokens
- just after first '=' when in 'CtxtMemberHead'
- just after first '=' when in 'CtxtType'
- just after 'do' in any context (when opening CtxtDo)
- just after 'finally' in any context
- just after 'with' (when opening CtxtWithAsAugment)
- just after 'else' (when opening CtxtElse)
- just after 'then' (when opening CtxtThen)
- just after 'interface' (when pushing CtxtParen(INTERFACE), i.e. next token is DEFAULT | OVERRIDE | INTERFACE | NEW | TYPE | STATIC | END | MEMBER | ABSTRACT | INHERIT | LBRACK_LESS)
- just after 'class' (when pushing CtxtParen(CLASS)
- just after 'class'
But not when opening these CtxtSeqBlocks:
- just after first non-dot/identifier token past 'namespace'
- just after first '=' when in 'CtxtLetDecl' or 'CtxtWithAsLet'
- just after 'lazy' in any context
- just after '->' in any context
- when opening CtxtNamespaceHead, CtxtModuleHead
*/
%token OBLOCKSEP /* LexFilter #light inserts when transforming CtxtSeqBlock(NotFirstInSeqBlock,_,AddBlockEnd) to CtxtSeqBlock(FirstInSeqBlock,_,AddBlockEnd) on exact alignment */
/* 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 <token> ODUMMY
/* These are artificial */
%token <string> LEX_FAILURE
%token <Ast.LexerWhitespaceContinuation> COMMENT WHITESPACE HASH_LINE HASH_LIGHT INACTIVECODE LINE_COMMENT STRING_TEXT EOF
%token <range * string * Ast.LexerWhitespaceContinuation> HASH_IF HASH_ELSE HASH_ENDIF
%start signatureFile implementationFile interaction typedSeqExprEOF typEOF
%type <Ast.SynExpr> typedSeqExprEOF
%type <Ast.ParsedImplFile> implementationFile
%type <Ast.ParsedSigFile> signatureFile
%type <Ast.ParsedFsiInteraction> interaction
%type <Ast.Ident> ident
%type <Ast.SynType> typ typEOF
%type <Ast.SynTypeDefnSig list> tyconSpfns
%type <Ast.SynExpr> patternResult
%type <Ast.SynExpr> declExpr
%type <Ast.SynExpr> minusExpr
%type <Ast.SynExpr> appExpr
%type <Ast.SynExpr> argExpr
%type <Ast.SynExpr> declExprBlock
%type <Ast.SynPat> headBindingPattern
%type <Ast.SynExpr> atomicExprAfterType
%type <Ast.SynExpr> typedSeqExprBlock
%type <Ast.SynExpr * bool> atomicExpr
%type <Ast.SynTypeDefnSimpleRepr> tyconDefnOrSpfnSimpleRepr
%type <(Ast.SynEnumCase, Ast.SynUnionCase) Choice list> unionTypeRepr
%type <Ast.SynMemberDefns> tyconDefnAugmentation
%type <Ast.SynExceptionDefn> exconDefn
%type <Ast.SynExceptionDefnRepr> exconCore
%type <Ast.SynModuleDecl list> moduleDefnsOrExprPossiblyEmptyOrBlock
%type <Ast.LongIdentWithDots> openDecl
%type <Ast.LongIdentWithDots> path
%type <Ast.LongIdentWithDots> pathOp
/* LESS GREATER parsedOk typeArgs m for each mWhole */
%type <range * range option * bool * Ast.SynType list * range list * range> typeArgsActual
/* LESS GREATER typeArgs m for each mWhole */
%type <range * range option * Ast.SynType list * range list * range> typeArgsNoHpaDeprecated
%type <Ast.SynTypar> 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 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<T1,T2>" to allow "path . <" shift.
* Extensions: LESS
*/
%nonassoc prec_atomtyp_path /* lower than LESS */
%nonassoc prec_atomtyp_get_path /* lower than LESS */
/* prec_no_more_attr_bindings = precedence of "moreLocalBindings = ."
* Lower precedence than AND so further bindings are shifted.
*/
%nonassoc prec_no_more_attr_bindings /* lower than AND */
%nonassoc OPEN
/* prec_interfaces_prefix - lower than extensions, i.e. INTERFACE */
%nonassoc prec_interfaces_prefix /* lower than INTERFACE */
%nonassoc INTERFACE
%right LARROW
%right COLON_EQUALS
%nonassoc pat_tuple expr_tuple
%left COMMA
%nonassoc slice_expr /* matrix.[e COMMA e] has higher precedence than "e COMMA e" */
%nonassoc DOT_DOT /* for matrix.[1..2,3..4] the ".." has higher precedence than expression "2 COMMA 3" */
%nonassoc slice_comma /* for matrix.[1..2,3..4] the "," has higher precedence than ".." */
%nonassoc paren_pat_colon
%nonassoc paren_pat_attribs
%left OR BAR_BAR JOIN_IN
%left AND /* check */
%left AMP AMP_AMP
%nonassoc pat_conj
%nonassoc expr_not
%left COLON_GREATER COLON_QMARK_GREATER
%left INFIX_COMPARE_OP DOLLAR LESS GREATER EQUALS INFIX_BAR_OP INFIX_AMP_OP
%right INFIX_AT_HAT_OP
%right COLON_COLON
%nonassoc pat_isinst
%left COLON_QMARK
%left PLUS_MINUS_OP MINUS expr_prefix_plus_minus ADJACENT_PREFIX_OP
%left INFIX_STAR_DIV_MOD_OP STAR PERCENT_OP
%right INFIX_STAR_STAR_OP
%left QMARK_QMARK
%left head_expr_adjacent_minus
%left expr_app expr_assert expr_lazy LAZY ASSERT
%left arg_expr_adjacent_minus
%left expr_args
%right matching_bar
%left pat_app
%left pat_args
%left PREFIX_OP
%left DOT QMARK
%left HIGH_PRECEDENCE_BRACK_APP
%left HIGH_PRECEDENCE_PAREN_APP
%left HIGH_PRECEDENCE_TYAPP
%nonassoc prec_interaction_empty
%%
/*--------------------------------------------------------------------------*/
/* F# 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
{ IDefns ($1,lhs parseState) }
| SEMICOLON
{ warning(Error(FSComp.SR.parsUnexpectedSemicolon(),rhs parseState 1))
IDefns ([],lhs parseState) }
| OBLOCKSEP
{ IDefns ([],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_declVisibility 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 [] in
attrDecls @ [ mkSynDoDecl($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
{ ParsedHashDirective ($2,$3,lhs parseState) }
/* The arguments to a #directive */
hashDirectiveArgs:
| /* EMPTY */
{ [] }
| hashDirectiveArgs hashDirectiveArg
{ $1 @ [$2] }
/* One argument to a #directive */
hashDirectiveArg:
| stringOrKeywordString
{ $1 }
/*--------------------------------------------------------------------------*/
/* 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) in
ParsedSigFile([],[emptySigFileFrag]) }
/* The start of a module declaration */
moduleIntro:
| moduleKeyword opt_access opt_rec path
{ $3, $4.Lid, grabXmlDoc(parseState,1), $2 }
/* The start of a namespace declaration */
namespaceIntro:
| NAMESPACE opt_rec path
{ $2, $3.Lid, grabXmlDoc(parseState,1) }
/* The contents of a signature file */
fileNamespaceSpecs:
| fileModuleSpec
{ ParsedSigFile([],[ ($1 (false,[],PreXmlDoc.Empty)) ]) }
| fileModuleSpec fileNamespaceSpecList
{ // If there are namespaces, the first fileModuleImpl may only contain # directives
let decls =
match ($1 (false,[],PreXmlDoc.Empty)) with
| ParsedSigFileFragment.AnonModule(decls,m) -> decls
| ParsedSigFileFragment.NamespaceFragment(_,_,_, decls, _,_,_) -> decls
| ParsedSigFileFragment.NamedModule(SynModuleOrNamespaceSig(_,_,_,_,_,_,_,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 isRec,path,xml = $1 in ($3 (isRec,path,xml)) }
/* The single module declaration that can make up a signature file */
fileModuleSpec:
| opt_attributes opt_declVisibility moduleIntro moduleSpfnsPossiblyEmptyBlock
{ if Option.isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(),rhs parseState 2))
let m2 = rhs parseState 3
let m = (rhs2 parseState 3 4)
let isRec,path2,xml,vis = $3
(fun (isRec2,path,_) ->
if not (isNil path) then errorR(Error(FSComp.SR.parsNamespaceOrModuleNotBoth(),m2))
let lid = path@path2
ParsedSigFileFragment.NamedModule(SynModuleOrNamespaceSig(lid, (isRec || isRec2), true, $4, xml,$1,vis,m))) }
| moduleSpfnsPossiblyEmptyBlock
{ let m = (rhs parseState 1)
(fun (isRec, path, xml) ->
match path with
| [] -> ParsedSigFileFragment.AnonModule($1, m)
| _ -> ParsedSigFileFragment.NamespaceFragment(path, isRec, false, $1, xml,[],m)) }
moduleSpfnsPossiblyEmptyBlock:
| moduleSpfnsPossiblyEmpty
{ $1 }
| OBLOCKBEGIN moduleSpfnsPossiblyEmpty oblockend opt_OBLOCKSEP
{ $2 }
| OBLOCKBEGIN moduleSpfnsPossiblyEmpty recover
{ // The lex filter ensures we can only get a mismatch in OBLOCKBEGIN/OBLOCKEND tokens if there was some other kind of error, hence we don't need to report this error
// reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnClosedBlockInHashLight())
$2
}
| OBLOCKBEGIN error oblockend
{ [] }
moduleSpfnsPossiblyEmpty:
| moduleSpfns
{ $1 }
| error
{ [] }
| /* 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_declVisibility moduleIntro colonOrEquals namedModuleAbbrevBlock
{ if Option.isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(),rhs parseState 2))
let isRec, path, xml, vis = $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())
match vis with
| Some vis -> raiseParseErrorAt (rhs parseState 1) (FSComp.SR.parsIgnoreVisibilityOnModuleAbbreviationAlwaysPrivate(vis.ToString()))
| _ -> SynModuleSigDecl.ModuleAbbrev(List.head path,$5,rhs2 parseState 3 5) }
| opt_attributes opt_declVisibility moduleIntro colonOrEquals moduleSpecBlock
{ let isRec, path, xml, vis = $3
if not (isSingleton path) then raiseParseErrorAt (rhs parseState 3) (FSComp.SR.parsModuleDefnMustBeSimpleName())
if isRec then raiseParseErrorAt (rhs parseState 3) (FSComp.SR.parsInvalidUseOfRec())
let info = ComponentInfo($1,[],[],path,xml,false,vis,rhs parseState 3)
if Option.isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(),rhs parseState 2))
SynModuleSigDecl.NestedModule(info, isRec, $5, rhs2 parseState 3 5) }
| opt_attributes opt_declVisibility tyconSpfns
{ if Option.isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(),rhs parseState 2))
let (TypeDefnSig(ComponentInfo(cas,a,cs,b,c,d,d2,d3),e,f,g)),rest =
match $3 with
| [] -> raiseParseErrorAt (rhs parseState 3) (FSComp.SR.parsUnexpectedEmptyModuleDefn())
| h::t -> h,t
let tc = (TypeDefnSig(ComponentInfo($1@cas,a,cs,b,c,d,d2,d3),e,f,g))in
SynModuleSigDecl.Types (tc::rest,rhs parseState 3) }
| opt_attributes opt_declVisibility exconSpfn
{ if Option.isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(),rhs parseState 2))
let (SynExceptionSig(SynExceptionDefnRepr(cas,a,b,c,d,d2),e,f)) = $3
let ec = (SynExceptionSig(SynExceptionDefnRepr($1@cas,a,b,c,d,d2),e,f))
SynModuleSigDecl.Exception(ec, rhs parseState 3) }
| OPEN path
{ SynModuleSigDecl.Open ($2.Lid, unionRanges (rhs parseState 1) $2.Range) }
valSpfn:
| opt_attributes opt_declVisibility 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),konst = ($1),($4),($5),($6),($7),($8),grabXmlDoc(parseState,3),($9),($11),($12)
if not (isNil attr2) then errorR(Deprecated(FSComp.SR.parsAttributesMustComeBeforeVal(),rhs parseState 4))
let m = rhs2 parseState 3 11
let valSpfn = ValSpfn((attr1@attr2),id,explicitValTyparDecls,ty,arity,isInline,isMutable,doc, vis2,konst,m)
SynModuleSigDecl.Val(valSpfn,m)
}
/* The optional literal value on a literal specification in a signature */
optLiteralValueSpfn:
| /* EMPTY */
{ None }
| EQUALS declExpr
{ Some($2) }
| EQUALS OBLOCKBEGIN declExpr oblockend
{ 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 }
/* #light-syntax, with sig/end or begin/end */
| OBLOCKBEGIN sigOrBegin moduleSpfnsPossiblyEmpty END oblockend
{ $3 }
/* non-#light-syntax, with sig/end or begin/end */
| sigOrBegin moduleSpfnsPossiblyEmpty END
{ $2 }
/* A group of type definitions in a signature */
tyconSpfns:
| typeKeyword tyconSpfnList
{ $2 }
tyconSpfnList:
| tyconSpfn AND tyconSpfnList
{ $1 :: $3 }
| tyconSpfn
{ [$1] }
/* A type definition in a signature */
tyconSpfn:
| typeNameInfo EQUALS tyconSpfnRhsBlock
{ let lhsm = rhs parseState 1
$3 lhsm $1 }
| typeNameInfo opt_classSpfn
{ TypeDefnSig($1,SynTypeDefnSigRepr.Simple (SynTypeDefnSimpleRepr.None (lhs parseState),lhs parseState),$2,lhs parseState) }
/* 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 lhsm nameInfo ->
$2 lhsm nameInfo (checkForMultipleAugmentations m ($4 @ $5) $7)) }
| tyconSpfnRhs opt_classSpfn
{ let m = lhs parseState
(fun lhsm nameInfo ->
$1 lhsm nameInfo $2) }
/* The right-hand-side of a type definition in a signature */
tyconSpfnRhs:
| tyconDefnOrSpfnSimpleRepr
{ let m = $1.Range
(fun lhsm nameInfo augmentation ->
TypeDefnSig(nameInfo,SynTypeDefnSigRepr.Simple ($1,m),augmentation,m)) }
| tyconClassSpfn
{ let m = lhs parseState
let needsCheck,(kind,decls) = $1
(fun nameRange nameInfo augmentation ->
if needsCheck && isNil decls then
reportParseErrorAt nameRange (FSComp.SR.parsEmptyTypeDefinition())
TypeDefnSig(nameInfo,SynTypeDefnSigRepr.ObjectModel (kind,decls,m),augmentation,m)) }
| DELEGATE OF topType
{ let m = lhs parseState
let ty,arity = $3
let invoke = SynMemberSig.Member(ValSpfn([],mkSynId m "Invoke",inferredTyparDecls,ty,arity,false,false,PreXmlDoc.Empty,None,None,m),AbstractMemberFlags MemberKind.Member,m)
(fun nameRange nameInfo augmentation ->
if not (isNil augmentation) then raiseParseErrorAt m (FSComp.SR.parsAugmentationsIllegalOnDelegateType())
TypeDefnSig(nameInfo,SynTypeDefnSigRepr.ObjectModel (TyconDelegate (ty,arity),[invoke],m),[],m)) }
/* The right-hand-side of an object type definition in a signature */
tyconClassSpfn:
| classSpfnBlockKindUnspecified
{ let needsCheck,decls = $1
needsCheck,(TyconUnspecified, decls) }
| classOrInterfaceOrStruct classSpfnBlock END
{ false,($1,$2) }
| classOrInterfaceOrStruct classSpfnBlock recover
{ reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnmatchedClassInterfaceOrStruct())
false,($1,$2) }
| classOrInterfaceOrStruct error END
{ // silent recovery
false,($1,[]) }
/* 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_declVisibility 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),optLiteralValue = $4,grabXmlDoc(parseState,3),$5,$6,$7,$9,$11
let getSetRangeOpt, getSet = $10
let getSetAdjuster arity = match arity,getSet with SynValInfo([],_),MemberKind.Member -> MemberKind.PropertyGet | _ -> getSet
let wholeRange =
let m = rhs parseState 3
match getSetRangeOpt with
| None -> unionRanges m ty.Range
| Some m2 -> unionRanges m m2
let valSpfn = ValSpfn($1,id,explicitValTyparDecls,ty,arity, isInline,false,doc, vis2,optLiteralValue,wholeRange)
let _,flags = $3
SynMemberSig.Member(valSpfn, flags (getSetAdjuster arity),wholeRange) }
| opt_attributes opt_declVisibility 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_declVisibility 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_declVisibility VAL fieldDecl
{ if Option.isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(),rhs parseState 2))
let fld = $4 $1 false
SynMemberSig.ValField(fld,rhs2 parseState 3 4) }
| opt_attributes opt_declVisibility STATIC VAL fieldDecl
{ if Option.isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(),rhs parseState 2))
SynMemberSig.ValField($5 $1 true,rhs2 parseState 3 5) }
| opt_attributes opt_declVisibility STATIC typeKeyword tyconSpfn
{ if Option.isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(),rhs parseState 2))
SynMemberSig.NestedType($5,rhs2 parseState 3 5) }
| opt_attributes opt_declVisibility NEW COLON topTypeWithTypeConstraints
{ let vis,doc,(ty,valSynInfo) = $2,grabXmlDoc(parseState,3),$5
let m = unionRanges (rhs parseState 3) ty.Range
let isInline = false
let valSpfn = ValSpfn ($1, mkSynId (rhs parseState 3) "new", noInferredTypars, ty, valSynInfo, isInline, false, doc, vis, None, m)
SynMemberSig.Member(valSpfn, CtorMemberFlags,m) }
/* The optional "with get,set" on a member in a signature */
classMemberSpfnGetSet:
| /* EMPTY */
{ None, MemberKind.Member }
| WITH classMemberSpfnGetSetElements
{ Some (rhs2 parseState 1 2), $2 }
| OWITH classMemberSpfnGetSetElements OEND
{ Some (rhs2 parseState 1 2), $2 }
| OWITH classMemberSpfnGetSetElements error
{ reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnmatchedWith())
Some (rhs2 parseState 1 2), $2 }
/* The "get,set" on a property member in a signature */
classMemberSpfnGetSetElements:
| nameop
{ (let (id:Ident) = $1
if id.idText = "get" then MemberKind.PropertyGet
else if id.idText = "set" then MemberKind.PropertySet
else raiseParseErrorAt (rhs parseState 1) (FSComp.SR.parsGetOrSetRequired())) }
| nameop COMMA nameop
{ let (id:Ident) = $1
if not ((id.idText = "get" && $3.idText = "set") ||
(id.idText = "set" && $3.idText = "get")) then
raiseParseErrorAt (rhs2 parseState 1 3) (FSComp.SR.parsGetOrSetRequired())
MemberKind.PropertyGetSet }
memberSpecFlags:
| memberFlags { $1 }
| ABSTRACT { (false,AbstractMemberFlags) }
| ABSTRACT MEMBER { (false,AbstractMemberFlags) }
/* Part of an exception definition in a signature file */
exconSpfn:
| exconCore opt_classSpfn
{ SynExceptionSig($1,$2,lhs parseState) }
/* The optional augmentation on a type definition in a signature */
opt_classSpfn:
| WITH classSpfnBlock declEnd
{ $2 }
| /* EMPTY */
{ [] }
/*--------------------------------------------------------------------------*/
/* 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) in
ParsedImplFile([],[emptyImplFileFrag]) }
/* The sequence of namespace definitions or a single module definition that makes up an implementation file */
fileNamespaceImpls:
| fileModuleImpl
{ ParsedImplFile([], [ ($1 (false,[],PreXmlDoc.Empty)) ]) }
| fileModuleImpl fileNamespaceImplList
{ // If there are namespaces, the first fileModuleImpl may only contain # directives
let decls =
match ($1 (false,[],PreXmlDoc.Empty)) with
| ParsedImplFileFragment.AnonModule(decls,m) -> decls
| ParsedImplFileFragment.NamespaceFragment(_,_,_, decls, _,_,_) -> decls
| ParsedImplFileFragment.NamedModule(SynModuleOrNamespace(_,_,_,_,_,_,_,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 isRec, path, xml = $1 in ($3 (isRec, path, xml)) }
/* A single module definition in an implementation file */
fileModuleImpl:
| opt_attributes opt_declVisibility moduleIntro moduleDefnsOrExprPossiblyEmptyOrBlock
{ if Option.isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(),rhs parseState 2))
let m2 = rhs parseState 3
let m = (m2, $4) ||> unionRangeWithListBy (fun modu -> modu.Range)
let isRec2,path2,xml,vis = $3
(fun (isRec, path, _) ->
if not (isNil path) then errorR(Error(FSComp.SR.parsNamespaceOrModuleNotBoth(),m2))
let lid = path@path2
ParsedImplFileFragment.NamedModule(SynModuleOrNamespace(lid, (isRec || isRec2), true, $4, xml,$1,vis,m))) }
| moduleDefnsOrExprPossiblyEmptyOrBlock
{ let m = (rhs parseState 1)
(fun (isRec, path, xml) ->
match path with
| [] -> ParsedImplFileFragment.AnonModule($1,m)
| _ -> ParsedImplFileFragment.NamespaceFragment(path, isRec, false, $1, xml,[],m)) }
/* 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_declVisibility 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 @ mkSynDoDecl ($3) :: $5 }
| opt_attributes opt_declVisibility 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 @ [ mkSynDoDecl($3) ] }
| opt_attributes opt_declVisibility 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 @ [ mkSynDoDecl($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_declVisibility 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_declVisibility 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_declVisibility 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_declVisibility typeKeyword tyconDefn tyconDefnList
{ if Option.isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(),rhs parseState 2))
let (TypeDefn(ComponentInfo(cas ,a,cs,b,c,d,d2,d3),e,f,g)) = $4
let tc = (TypeDefn(ComponentInfo($1@cas,a,cs,b,c,d,d2,d3),e,f,g))
let types = tc :: $5
[ SynModuleDecl.Types(types, (rhs parseState 3, types) ||> unionRangeWithListBy (fun t -> t.Range) ) ] }
/* 'exception' definitions */
| opt_attributes opt_declVisibility exconDefn
{ if Option.isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(),rhs parseState 2))
let (SynExceptionDefn(SynExceptionDefnRepr(cas,a,b,c,d,d2),e,f)) = $3
let f = (f, $1) ||> unionRangeWithListBy (fun a -> a.Range)
let ec = (SynExceptionDefn(SynExceptionDefnRepr($1@cas,a,b,c,d,d2),e,f))
[ SynModuleDecl.Exception(ec, f) ] }
/* 'module' definitions */
| opt_attributes opt_declVisibility moduleIntro EQUALS namedModuleDefnBlock
{ if Option.isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(),rhs parseState 2))
let attribs, (isRec, path, xml, vis) = $1,$3
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 $1) then raiseParseErrorAt (rhs parseState 1) (FSComp.SR.parsIgnoreAttributesOnModuleAbbreviation())
match vis with
| Some vis -> raiseParseErrorAt (rhs parseState 1) (FSComp.SR.parsIgnoreAttributesOnModuleAbbreviationAlwaysPrivate(vis.ToString()))
| _ -> ()
[ SynModuleDecl.ModuleAbbrev(List.head path,eqn,(rhs parseState 3, eqn) ||> unionRangeWithListBy (fun id -> id.idRange) ) ]
| Choice2Of2 def ->
if not (isSingleton path) then raiseParseErrorAt (rhs parseState 3) (FSComp.SR.parsModuleAbbreviationMustBeSimpleName())
let info = ComponentInfo(attribs,[],[],path,xml,false,vis,rhs parseState 3)
[ SynModuleDecl.NestedModule(info, isRec, def, false,(rhs2 parseState 3 4, def) ||> unionRangeWithListBy (fun d -> d.Range) ) ] }
/* unattached custom attributes */
| attributes recover
{ errorR(Error(FSComp.SR.parsAttributeOnIncompleteCode(),rhs parseState 1))
[] }
/* 'open' declarations */
| openDecl
{ [SynModuleDecl.Open($1, $1.Range)] }
/* 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.Lid }
| path
{ $1.Lid }
/* 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.DoExpr (_,LongOrSingleIdent(false,LongIdentWithDots(path,_),None,_),_) ] ->
Choice1Of2 path
| _ ->
Choice2Of2 $2
}
| OBLOCKBEGIN moduleDefnsOrExpr recover
{ // The lex filter ensures we can only get a mismatch in OBLOCKBEGIN/OBLOCKEND tokens if there was some other kind of error, hence we don't need to report this error
// reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnClosedBlockInHashLight())
Choice2Of2 $2 }
| OBLOCKBEGIN error oblockend
{ Choice2Of2 [] }
| wrappedNamedModuleDefn
{ Choice2Of2 $1 }
| path
{ Choice1Of2 $1.Lid }
/* A module definition that inccludes a 'begin'...'end' (rarely used in F# with #light syntax) */
wrappedNamedModuleDefn:
| structOrBegin moduleDefnsOrExprPossiblyEmpty END
{ $2 }
| structOrBegin moduleDefnsOrExprPossiblyEmpty recover
{ reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnmatchedBeginOrStruct())
$2 }
| structOrBegin error END
{ [] }
tyconDefnAugmentation:
| WITH classDefnBlock declEnd
{ $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
{ $2 }
| LBRACK_LESS error GREATER_RBRACK opt_OBLOCKSEP
{ [] }
| LBRACK_LESS attributeListElements opt_seps ends_coming_soon_or_recover
{ if not $4 then reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnmatchedLBrackLess())
$2 }
| LBRACK_LESS ends_coming_soon_or_recover
{ if not $2 then reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnmatchedLBrackLess())
[] }
/* 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
({ TypeName=$1; ArgExpr=arg; Target=None; AppliesToGetterAndSetter=false; Range=$1.Range } : 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
({ TypeName=$2; ArgExpr=arg; Target=$1; AppliesToGetterAndSetter=false; Range=$2.Range } : 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
({ TypeName=$3; ArgExpr=arg; Target=$1; AppliesToGetterAndSetter=false; Range=$3.Range } : 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 { (true,StaticMemberFlags) }
| MEMBER { (false,NonVirtualMemberFlags) }
| OVERRIDE { (false,OverrideMemberFlags) }
| DEFAULT { (false,OverrideMemberFlags) }
/* 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,tpcs1,vis,xmlDoc = $2
let tpcs2 = $3
ComponentInfo($1,typars,(tpcs1 @ tpcs2),lid,xmlDoc,fixity,vis,rangeOfLid lid) }
/* Part of a set of type definitions */
tyconDefnList:
| AND tyconDefn tyconDefnList
{ $2 :: $3 }
|
{ [] }
/* A type definition */
tyconDefn:
| typeNameInfo
{ TypeDefn($1,SynTypeDefnRepr.Simple(SynTypeDefnSimpleRepr.None($1.Range),$1.Range),[],$1.Range) }
| typeNameInfo EQUALS tyconDefnRhsBlock
{ let nameRange = rhs parseState 1
let (tcDefRepr:SynTypeDefnRepr),members = $3 nameRange
let declRange = unionRanges (rhs parseState 1) tcDefRepr.Range
let mWhole = (declRange, members) ||> unionRangeWithListBy (fun (mem:SynMemberDefn) -> mem.Range)
TypeDefn($1, tcDefRepr, members, mWhole) }
| typeNameInfo tyconDefnAugmentation
{ let m = (rhs parseState 1, $2) ||> unionRangeWithListBy (fun mem -> mem.Range)
TypeDefn($1,SynTypeDefnRepr.ObjectModel(TyconAugmentation,[],m),$2,m) }
| typeNameInfo opt_attributes opt_declVisibility opt_HIGH_PRECEDENCE_APP simplePatterns optAsSpec EQUALS tyconDefnRhsBlock
{ let vis,spats, az = $3,$5,$6
let nameRange = rhs parseState 1
let (tcDefRepr,members) = $8 nameRange
let (ComponentInfo(_,_,_,lid,_,_,_,_)) = $1
let memberCtorPattern = SynMemberDefn.ImplicitCtor (vis,$2,spats,az,rangeOfLid lid)
let tcDefRepr =
match tcDefRepr with
| SynTypeDefnRepr.ObjectModel (k,cspec,m) -> SynTypeDefnRepr.ObjectModel (k,memberCtorPattern::cspec,m)
| _ -> reportParseErrorAt (rhs2 parseState 1 5) (FSComp.SR.parsOnlyClassCanTakeValueArguments()); tcDefRepr
let declRange = unionRanges (rhs parseState 1) tcDefRepr.Range
let mWhole = (declRange, members) ||> unionRangeWithListBy (fun (mem:SynMemberDefn) -> mem.Range)
TypeDefn($1,tcDefRepr,members,mWhole) }
/* 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 m = unionRanges (rhs parseState 1) (match $7 with [] -> (match $5 with [] -> (rhs parseState 4) | _ -> (rhs parseState 5)) | _ -> (rhs parseState 7))
(fun nameRange -> $2 nameRange (checkForMultipleAugmentations m ($4 @ $5) $7)) }
| OBLOCKBEGIN tyconDefnRhs opt_OBLOCKSEP classDefnMembers opt_classDefn recover
{ if not $6 then reportParseErrorAt (rhs parseState 6) (FSComp.SR.parsUnexpectedEndOfFileTypeDefinition())
let m = unionRanges (rhs parseState 1) (match $5 with [] -> (rhs parseState 4) | _ -> (rhs parseState 5))
(fun nameRange -> $2 nameRange (checkForMultipleAugmentations m ($4 @ $5) [])) }
| tyconDefnRhs opt_classDefn
{ let m = rhs parseState 1
(fun nameRange -> $1 nameRange $2) }
/* 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 valSpfn = ValSpfn([],mkSynId m "Invoke",inferredTyparDecls,ty,arity,false,false,PreXmlDoc.Empty,None,None,m)
let invoke = SynMemberDefn.AbstractSlot(valSpfn,AbstractMemberFlags MemberKind.Member,m)
if not (isNil augmentation) then raiseParseErrorAt m (FSComp.SR.parsAugmentationsIllegalOnDelegateType())
SynTypeDefnRepr.ObjectModel (TyconDelegate (ty,arity),[invoke],m),[]) }
/* The right-hand-side of a object type definition */
tyconClassDefn:
| classDefnBlockKindUnspecified
{ let needsCheck,decls,mopt = $1
needsCheck,(TyconUnspecified, decls),mopt }
| classOrInterfaceOrStruct classDefnBlock END
{ let m = (rhs parseState 1, $2) ||> unionRangeWithListBy (fun (d:SynMemberDefn) -> d.Range)
false,($1,$2),Some(m) }
| 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(rhs parseState 1) }
/* 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
{ $1 @ $3 }
/* The "with get,set" part of a member definition */
classDefnMemberGetSet:
| WITH classDefnMemberGetSetElements
{ $2 }
| OWITH classDefnMemberGetSetElements OEND
{ $2 }
| OWITH classDefnMemberGetSetElements error
{ reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnmatchedWith())
$2 }
/* The "get,set" part of a member definition */
classDefnMemberGetSetElements:
| classDefnMemberGetSetElement
{ [$1] }
| classDefnMemberGetSetElement AND classDefnMemberGetSetElement
{ [$1;$3] }
classDefnMemberGetSetElement:
| opt_inline opt_attributes bindingPattern opt_topReturnTypeWithTypeConstraints EQUALS typedSeqExprBlock
{ let mRhs = ($6 : SynExpr).Range
($1,$2,$3,$4,$6,mRhs) }
/* The core of a member definition */
memberCore:
/* Methods and simple getter properties */
| opt_inline bindingPattern opt_topReturnTypeWithTypeConstraints EQUALS typedSeqExprBlock
{ let mRhs = $5.Range
let mWhole = unionRanges (rhs2 parseState 3 4) mRhs
let optReturnType = $3
let bindingBuilder,mBindLhs = $2
(fun vis memFlagsBuilder attrs ->
[ SynMemberDefn.Member (bindingBuilder (vis,$1,false,mBindLhs,NoSequencePointAtInvisibleBinding,optReturnType,$5,mRhs,[],attrs,Some(memFlagsBuilder MemberKind.Member)),unionRanges mWhole mBindLhs) ]) }
/* Properties with explicit get/set, also indexer properties */
| opt_inline bindingPattern opt_topReturnTypeWithTypeConstraints classDefnMemberGetSet
{ let mWhole = (rhs parseState 2, $4) ||> unionRangeWithListBy (fun (_,_,_,_,_,m2) -> m2)
let propertyNameBindingBuilder,_ = $2
let optPropertyType = $3
let isMutable = false
(fun visNoLongerUsed memFlagsBuilder attrs ->
let hasGet = ref false
let hasSet = ref false
// Iterate over 1 or 2 'get'/'set' entries
$4 |> List.choose (fun (optInline,optAttrs,(bindingBuilder,mBindLhs),optReturnType,expr,exprm) ->
let optInline = $1 || optInline
// optional attributes are only applied to getters and setters
// the "top level" attrs will be applied to both
let optAttrs = optAttrs |> List.map (fun (a:SynAttribute) -> { a with AppliesToGetterAndSetter=true })
let attrs = attrs @ optAttrs
let binding = bindingBuilder (visNoLongerUsed,optInline,isMutable,mBindLhs,NoSequencePointAtInvisibleBinding,optReturnType,expr,exprm,[],attrs,Some (memFlagsBuilder MemberKind.Member))
let (Binding (vis, _, isInline, _, attrs, doc, valSynData, pv, _, _, mBindLhs, spBind)) = binding
let memberKind =
let getset =
let rec go p =
match p with
| SynPat.LongIdent (LongIdentWithDots([id],_),_,_,_,_,_) -> id.idText
| SynPat.Named (_,nm,_,_,_) -> nm.idText
| SynPat.Typed (p,_,_) -> go p
| SynPat.Attrib (p,_,_) -> go p
| _ -> raiseParseErrorAt mBindLhs (FSComp.SR.parsInvalidDeclarationSyntax())
go pv
if getset = "get" then (
if !hasGet then
reportParseErrorAt mBindLhs (FSComp.SR.parsGetAndOrSetRequired())
None
else
hasGet := true
Some MemberKind.PropertyGet
) else if getset = "set" then (
if !hasSet then
reportParseErrorAt mBindLhs (FSComp.SR.parsGetAndOrSetRequired())
None
else
hasSet := true
Some MemberKind.PropertySet
) else
raiseParseErrorAt mBindLhs (FSComp.SR.parsGetAndOrSetRequired())
match memberKind with
| None -> None
| Some memberKind ->
// REVIEW: It's hard not to ignore the optPropertyType type annotation for 'set' properties. To apply it,
// we should apply it to the last argument, but at this point we've already pushed the patterns that
// make up the arguments onto the RHS. So we just always give a warning.
begin match optPropertyType with
| Some _ -> errorR(Error(FSComp.SR.parsTypeAnnotationsOnGetSet(),mBindLhs))
| None -> ()
end
let optReturnType =
match (memberKind, optReturnType) with
| MemberKind.PropertySet,_ -> optReturnType
| _, None -> optPropertyType
| _ -> optReturnType
// REDO with the correct member kind
let binding = bindingBuilder(vis,isInline,isMutable,mBindLhs,NoSequencePointAtInvisibleBinding,optReturnType,expr,exprm,[],attrs,Some(memFlagsBuilder memberKind))
let (Binding (vis, _, isInline, _, attrs, doc, valSynData, pv, rhsRetInfo, rhsExpr, mBindLhs, spBind)) = binding
let (SynValData(_,valSynInfo,_)) = valSynData
// Setters have all arguments tupled in their internal TAST form, though they don't appear to be
// tupled from the syntax
let memFlags = memFlagsBuilder memberKind
let valSynInfo =
let adjustValueArg valueArg =
match valueArg with
| [_] -> valueArg
| _ -> SynInfo.unnamedTopArg
match memberKind, valSynInfo, memFlags.IsInstance with
| MemberKind.PropertyGet,SynValInfo ([],_ret), false
| MemberKind.PropertyGet,SynValInfo ([_],_ret), true ->
raiseParseErrorAt mBindLhs (FSComp.SR.parsGetterMustHaveAtLeastOneArgument())
| MemberKind.PropertyGet,SynValInfo (thisArg::indexOrUnitArgs::rest,ret), true ->
if not rest.IsEmpty then reportParseErrorAt mBindLhs (FSComp.SR.parsGetterAtMostOneArgument())
SynValInfo ([thisArg; indexOrUnitArgs],ret)
| MemberKind.PropertyGet,SynValInfo (indexOrUnitArgs::rest,ret), false ->
if not rest.IsEmpty then reportParseErrorAt mBindLhs (FSComp.SR.parsGetterAtMostOneArgument())
SynValInfo ([indexOrUnitArgs],ret)
| MemberKind.PropertySet,SynValInfo ([thisArg;valueArg],ret), true ->
SynValInfo ([thisArg; adjustValueArg valueArg],ret)
| MemberKind.PropertySet,SynValInfo (thisArg::indexArgs::valueArg::rest,ret), true ->
if not rest.IsEmpty then reportParseErrorAt mBindLhs (FSComp.SR.parsSetterAtMostTwoArguments())
SynValInfo ([thisArg; indexArgs @ adjustValueArg valueArg],ret)
| MemberKind.PropertySet,SynValInfo ([valueArg],ret), false ->
SynValInfo ([adjustValueArg valueArg],ret)
| MemberKind.PropertySet,SynValInfo (indexArgs::valueArg::rest,ret), _ ->
if not rest.IsEmpty then reportParseErrorAt mBindLhs (FSComp.SR.parsSetterAtMostTwoArguments())
SynValInfo ([indexArgs @ adjustValueArg valueArg],ret)
| _ ->
// should be unreachable, cover just in case
raiseParseErrorAt mBindLhs (FSComp.SR.parsInvalidProperty())
let valSynData = SynValData(Some(memFlags), valSynInfo,None)
// Fold together the information from the first lambda pattern and the get/set binding
// This uses the 'this' variable from the first and the patterns for the get/set binding,
// replacing the get/set identifier. A little gross.
let bindingPatAdjusted, xmlDocAdjusted =
let bindingOuter = propertyNameBindingBuilder(vis,optInline,isMutable,mBindLhs,spBind,optReturnType,expr,exprm,[],attrs,Some(memFlagsBuilder MemberKind.Member))
let (Binding (_,_,_,_,_,doc2,_,bindingPatOuter,_,_,_,_)) = bindingOuter
let lidOuter,lidVisOuter =
match bindingPatOuter with
| SynPat.LongIdent (lid,None,None, SynConstructorArgs.Pats [],lidVisOuter,m) -> lid,lidVisOuter
| SynPat.Named (_,id,_,visOuter,m) -> LongIdentWithDots([id],[]),visOuter
| p -> raiseParseErrorAt mBindLhs (FSComp.SR.parsInvalidDeclarationSyntax())
// Merge the visibility from the outer point with the inner point, e.g.
// member <VIS1> this.Size with <VIS2> get () = m_size
let mergeLidVisOuter lidVisInner =
match lidVisInner,lidVisOuter with
| None,None -> None
| Some lidVisInner,None | None,Some lidVisInner -> Some lidVisInner
| Some _, Some _ ->
errorR(Error(FSComp.SR.parsMultipleAccessibilitiesForGetSet(),mBindLhs))
lidVisInner
// Replace the "get" or the "set" with the right name
let rec go p =
match p with
| SynPat.LongIdent (LongIdentWithDots([id],_),_,tyargs,SynConstructorArgs.Pats args,lidVisInner,m) ->
// Setters have all arguments tupled in their internal form, though they don't
// appear to be tupled from the syntax. Somewhat unfortunate
let args =
if id.idText = "set" then
match args with
| [SynPat.Paren(SynPat.Tuple (indexPats,_),indexPatRange);valuePat] when id.idText = "set" ->
[SynPat.Tuple(indexPats@[valuePat],unionRanges indexPatRange valuePat.Range)]
| [indexPat;valuePat] ->
[SynPat.Tuple(args,unionRanges indexPat.Range valuePat.Range)]
| [valuePat] ->
[valuePat]
| _ ->
raiseParseErrorAt m (FSComp.SR.parsSetSyntax())
else
args
// let idTool : Ident list = lidOuter |> List.map (fun (li:Ident) -> ident(li.idText,id.idRange)) |> List.rev |> List.take 1
SynPat.LongIdent (lidOuter,Some(id),tyargs, SynConstructorArgs.Pats args,mergeLidVisOuter lidVisInner,m)
| SynPat.Named (_,nm,_,lidVisInner,m) -> SynPat.LongIdent (lidOuter,None,None, SynConstructorArgs.Pats [], mergeLidVisOuter lidVisInner,m)
| SynPat.Typed (p,ty,m) -> SynPat.Typed(go p,ty,m)
| SynPat.Attrib (p,attribs,m) -> SynPat.Attrib(go p,attribs,m)
| SynPat.Wild(m) -> SynPat.Wild(m)
| _ -> raiseParseErrorAt mBindLhs (FSComp.SR.parsInvalidDeclarationSyntax())
go pv,PreXmlDoc.Merge doc2 doc
Some <| SynMemberDefn.Member (Binding (vis, NormalBinding, isInline, isMutable, attrs, xmlDocAdjusted, valSynData, bindingPatAdjusted, rhsRetInfo, rhsExpr, mBindLhs, spBind),mWhole)))
}
abstractMemberFlags:
| ABSTRACT {}
| ABSTRACT MEMBER {}
/* A member definition */
classDefnMember:
| opt_attributes opt_declVisibility classDefnBindings
{ if Option.isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(),rhs parseState 2))
[mkClassMemberLocalBindings(false,None,$1,$2,$3)] }
| opt_attributes opt_declVisibility 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_declVisibility memberFlags memberCore opt_ODECLEND
{ if Option.isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(),rhs parseState 2))
let _,flags = $3
$4 $2 flags $1 }
| opt_attributes opt_declVisibility 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 mWhole =
match $5 with
| None -> rhs2 parseState 3 4
| Some(mems) -> (rhs2 parseState 3 4, mems) ||> unionRangeWithListBy (fun (mem:SynMemberDefn) -> mem.Range)
[ SynMemberDefn.Interface ($4, $5, mWhole) ] }
| opt_attributes opt_declVisibility abstractMemberFlags opt_inline nameop opt_explicitValTyparDecls COLON topTypeWithTypeConstraints classMemberSpfnGetSet opt_ODECLEND
{ let ty,arity = $8
let isInline,doc,id,explicitValTyparDecls = $4,grabXmlDoc(parseState,3),$5,$6
let getSetRangeOpt, getSet = $9
let getSetAdjuster arity = match arity,getSet with SynValInfo([],_),MemberKind.Member -> MemberKind.PropertyGet | _ -> getSet
let wholeRange =
let m = rhs parseState 3
match getSetRangeOpt with
| None -> unionRanges m ty.Range
| Some m2 -> unionRanges m m2
if Option.isSome $2 then errorR(Error(FSComp.SR.parsAccessibilityModsIllegalForAbstract(),wholeRange))
let valSpfn = ValSpfn($1,id,explicitValTyparDecls,ty,arity, isInline,false,doc, None,None,wholeRange)
[ SynMemberDefn.AbstractSlot(valSpfn,AbstractMemberFlags (getSetAdjuster arity), wholeRange) ] }
| opt_attributes opt_declVisibility 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_declVisibility valDefnDecl opt_ODECLEND
{ if Option.isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(),rhs parseState 2))
$3 None $1 false }
| opt_attributes opt_declVisibility STATIC valDefnDecl opt_ODECLEND
{ if Option.isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(),rhs parseState 2))
$4 (Some (rhs parseState 3)) $1 true }
| opt_attributes opt_declVisibility memberFlags autoPropsDefnDecl opt_ODECLEND
{ if Option.isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(),rhs parseState 2))
let isStatic, flags = $3
$4 $1 isStatic flags }
| opt_attributes opt_declVisibility NEW atomicPattern optAsSpec EQUALS typedSeqExprBlock opt_ODECLEND
{ let m = unionRanges (rhs2 parseState 3 6) $7.Range
let expr = $7
let valSynData = SynValData (Some CtorMemberFlags, SynValInfo([SynInfo.InferSynArgInfoFromPat $4],SynInfo.unnamedRetVal), $5)
let vis = $2
let declPat = SynPat.LongIdent (LongIdentWithDots([mkSynId (rhs parseState 3) "new"],[]),None,Some noInferredTypars, SynConstructorArgs.Pats [$4],vis,rhs parseState 3)
// Check that 'SynPatForConstructorDecl' matches this correctly
assert (match declPat with SynPatForConstructorDecl _ -> true | _ -> false)
[ SynMemberDefn.Member(Binding (None,NormalBinding,false,false,$1,grabXmlDoc(parseState,3),valSynData, declPat,None,expr,m,NoSequencePointAtInvisibleBinding),m) ] }
| opt_attributes opt_declVisibility STATIC typeKeyword tyconDefn
{ if Option.isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(),rhs parseState 2))
[ SynMemberDefn.NestedType($5,None,rhs2 parseState 3 5) ] }
/* A 'val' definition in an object type definition */
valDefnDecl:
| VAL opt_mutable opt_access ident COLON typ
{ let mRhs = rhs2 parseState 4 6
let doc = grabXmlDoc(parseState,4)
let mValDecl = rhs2 parseState 1 6
(fun mLeft attribs isStatic ->
let mValDecl = match mLeft with None -> mValDecl | Some m -> unionRanges m mValDecl
let fld = Field(attribs,isStatic,Some $4,$6,$2,doc,$3,mRhs)
[ SynMemberDefn.ValField(fld, mValDecl) ]) }
/* An auto-property definition in an object type definition */
autoPropsDefnDecl:
| VAL opt_mutable opt_access ident opt_typ EQUALS typedSeqExprBlock classMemberSpfnGetSet
{ let doc = grabXmlDoc(parseState,5)
let mValDecl = unionRanges (rhs parseState 1) $7.Range
let mGetSetOpt, getSet = $8
if $2 then errorR(Error(FSComp.SR.parsMutableOnAutoPropertyShouldBeGetSet(),rhs parseState 3))
(fun attribs isStatic flags ->
[ SynMemberDefn.AutoProperty(attribs, isStatic, $4, $5, getSet, flags, doc, $3, $7, mGetSetOpt, mValDecl) ]) }
/* An optional type on an auto-property definition */
opt_typ:
| /* EMPTY */ { None }
| COLON typ { Some $2 }
atomicPatternLongIdent:
| GLOBAL DOT pathOp { let (LongIdentWithDots(lid,dotms)) = $3 in (None,LongIdentWithDots(ident(MangledGlobalName,rhs parseState 1)::lid, rhs parseState 2::dotms)) }
| pathOp { (None,$1) }
| access pathOp { (Some($1), $2) }
opt_access:
| /* EMPTY */ { None }
| access { Some($1) }
access:
| PRIVATE { SynAccess.Private }
| PUBLIC { SynAccess.Public }
| INTERNAL { SynAccess.Internal }
/* only valid on 'NEW' */
opt_declVisibility:
| access { Some($1) }
| /* EMPTY */ { None }
opt_interfaceImplDefn:
| WITH objectImplementationBlock declEnd { Some($2) }
| /* EMPTY */ { None }
opt_classDefn:
| WITH classDefnBlock declEnd { $2 }
| /* EMPTY */ { [] }
/* An 'inherits' definition in an object type definition */
inheritsDefn:
| INHERIT appTypeNonAtomicDeprecated optBaseSpec
{ let mDecl = unionRanges (rhs parseState 1) (($2): SynType).Range
SynMemberDefn.Inherit($2,$3,mDecl) }
| INHERIT appTypeNonAtomicDeprecated opt_HIGH_PRECEDENCE_APP atomicExprAfterType optBaseSpec
{ let mDecl = unionRanges (rhs parseState 1) $4.Range
SynMemberDefn.ImplicitInherit($2,$4,$5,mDecl) }
| 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(LongIdentWithDots([], [])), None,mDecl) }
optAsSpec:
| asSpec { Some($1) }
| { None }
asSpec:
| AS ident { $2 }
optBaseSpec:
| baseSpec { Some($1) }
| { None }
baseSpec:
| AS ident
{ if ($2).idText <> "base" then
errorR(Error(FSComp.SR.parsInheritDeclarationsCannotHaveAsBindings(),rhs2 parseState 1 2))
ident("base",rhs parseState 2) }
| AS BASE
{ errorR(Error(FSComp.SR.parsInheritDeclarationsCannotHaveAsBindings(),rhs2 parseState 1 2))
ident("base",rhs parseState 2) }
/* 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 memberOrOverride memberCore opt_ODECLEND
{ $3 None OverrideMemberFlags $1 }
| opt_attributes memberOrOverride autoPropsDefnDecl opt_ODECLEND
{ $3 $1 false OverrideMemberFlags }
| opt_attributes memberOrOverride error
{ [] }
| opt_attributes error memberCore opt_ODECLEND
{ [] }
memberOrOverride:
| MEMBER { }
| OVERRIDE { }
/* 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_declVisibility path LQUOTE STRING recover
{ errorR(Error(FSComp.SR.parsUnexpectedQuotationOperatorInTypeAliasDidYouMeanVerbatimString(), rhs parseState 4))
SynTypeDefnSimpleRepr.TypeAbbrev (ParserDetail.ThereWereSignificantParseErrorsSoDoNotTypecheckThisNode, SynType.LongIdent($3), unionRanges (rhs parseState 1) $3.Range) }
/* A type abbreviation */
| opt_attributes opt_declVisibility 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_declVisibility 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(UnionCase(_,_,_,_,_,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_declVisibility 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_declVisibility LPAREN inlineAssemblyTyconRepr rparen
{ if not (isNil $1) then errorR(Error(FSComp.SR.parsAttributesIllegalHere(),rhs parseState 1))
libraryOnlyError (lhs parseState)
if Option.isSome $2 then errorR(Error(FSComp.SR.parsInlineAssemblyCannotHaveVisibilityDeclarations(),rhs parseState 2))
$4 }
/* 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
{ [] }
inlineAssemblyTyconRepr:
| HASH stringOrKeywordString HASH
{ libraryOnlyError (lhs parseState)
let lhsm = lhs parseState
SynTypeDefnSimpleRepr.LibraryOnlyILAssembly (ParseAssemblyCodeType $2 (rhs parseState 2),lhsm) }
classOrInterfaceOrStruct:
| CLASS { TyconClass }
| INTERFACE { TyconInterface }
| STRUCT { TyconStruct }
interfaceMember:
| INTERFACE { }
| OINTERFACE_MEMBER { }
tyconNameAndTyparDecls:
| opt_access path
{ [], $2.Lid,false,[],$1,grabXmlDoc(parseState,2) }
| opt_access prefixTyparDecls path
{ $2, $3.Lid,false,[],$1,grabXmlDoc(parseState,2) }
| opt_access path postfixTyparDecls
{ let tps,tpcs = $3
tps, $2.Lid,true,tpcs,$1,grabXmlDoc(parseState,2) }
prefixTyparDecls:
| typar { [ TyparDecl([],$1) ] }
| LPAREN typarDeclList rparen { List.rev $2 }
typarDeclList:
| typarDeclList COMMA typarDecl { $3 :: $1 }
| typarDecl { [$1] }
typarDecl :
| opt_attributes typar
{ TyparDecl($1,$2) }
/* Any tokens in this grammar must be added to the lex filter rule 'peekAdjacentTypars' */
/* See the F# specification "Lexical analysis of type applications and type parameter definitions" */
postfixTyparDecls:
| opt_HIGH_PRECEDENCE_TYAPP LESS typarDeclList opt_typeConstraints GREATER
{ if not $2 then warning(Error(FSComp.SR.parsNonAdjacentTypars(),rhs2 parseState 2 5))
List.rev $3, $4 }
/* Any tokens in this grammar must be added to the lex filter rule 'peekAdjacentTypars' */
/* See the F# specification "Lexical analysis of type applications and type parameter definitions" */
explicitValTyparDeclsCore:
| typarDeclList COMMA DOT_DOT
{ (List.rev $1,true) }
| typarDeclList
{ (List.rev $1,false) }
|
{ ([],false) }
explicitValTyparDecls:
| opt_HIGH_PRECEDENCE_TYAPP LESS explicitValTyparDeclsCore opt_typeConstraints GREATER
{ if not $2 then warning(Error(FSComp.SR.parsNonAdjacentTypars(),rhs2 parseState 2 5))
let tps,flex = $3
SynValTyparDecls(tps,flex,$4) }
opt_explicitValTyparDecls:
| explicitValTyparDecls
{ $1 }
|
{ SynValTyparDecls([],true,[]) }
opt_explicitValTyparDecls2:
| explicitValTyparDecls
{ Some $1 }
|
{ None }
/* Any tokens in this grammar must be added to the lex filter rule 'peekAdjacentTypars' */
/* See the F# specification "Lexical analysis of type applications and type parameter definitions" */
opt_typeConstraints:
|
{ [] }
| WHEN typeConstraints
{ List.rev $2 }
/* Any tokens in this grammar must be added to the lex filter rule 'peekAdjacentTypars' */
/* See the F# specification "Lexical analysis of type applications and type parameter definitions" */
typeConstraints:
| typeConstraints AND typeConstraint { $3 :: $1 }
| typeConstraint { [$1] }
/* Any tokens in this grammar must be added to the lex filter rule 'peekAdjacentTypars' */
/* See the F# specification "Lexical analysis of type applications and type parameter definitions" */
typeConstraint:
| DEFAULT typar COLON typ
{ libraryOnlyError (lhs parseState); WhereTyparDefaultsToType($2,$4,lhs parseState) }
| typar COLON_GREATER typ
{ WhereTyparSubtypeOfType($1,$3,lhs parseState) }
| typar COLON STRUCT
{ WhereTyparIsValueType($1,lhs parseState) }
| typar COLON IDENT STRUCT
{ if $3 <> "not" then reportParseErrorAt (rhs parseState 3) (FSComp.SR.parsUnexpectedIdentifier($3))
WhereTyparIsReferenceType($1,lhs parseState) }
| typar COLON NULL
{ WhereTyparSupportsNull($1,lhs parseState) }
| typar COLON LPAREN classMemberSpfn rparen
{ let tp = $1
WhereTyparSupportsMember([ SynType.Var(tp, tp.Range) ],$4,lhs parseState) }
| LPAREN typarAlts rparen COLON LPAREN classMemberSpfn rparen
{ WhereTyparSupportsMember(List.rev($2),$6,lhs parseState) }
| typar COLON DELEGATE typeArgsNoHpaDeprecated
{ let _ltm,_gtm,args,_commas,mWhole = $4 in WhereTyparIsDelegate($1, args, unionRanges $1.Range mWhole) }
| typar COLON IDENT typeArgsNoHpaDeprecated
{ match $3 with
| "enum" -> let _ltm,_gtm,args,_commas,mWhole = $4 in WhereTyparIsEnum($1, args, unionRanges $1.Range mWhole)
| nm -> raiseParseErrorAt (rhs parseState 3) (FSComp.SR.parsUnexpectedIdentifier(nm)) }
| typar COLON IDENT
{ match $3 with
| "comparison" -> WhereTyparIsComparable($1,lhs parseState)
| "equality" -> WhereTyparIsEquatable($1,lhs parseState)
| "unmanaged" -> WhereTyparIsUnmanaged($1,lhs parseState)
| nm -> raiseParseErrorAt (rhs parseState 3) (FSComp.SR.parsUnexpectedIdentifier(nm)) }
typarAlts:
| typarAlts OR appType { $3::$1 }
| 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 { grabXmlDoc(parseState,1) }
attrUnionCaseDecls:
| attrUnionCaseDecl barAndgrabXmlDoc attrUnionCaseDecls { (fun xmlDoc -> $1 xmlDoc :: $3 $2) }
| attrUnionCaseDecl { (fun xmlDoc -> [ $1 xmlDoc ]) }
/* The core of a union case definition */
attrUnionCaseDecl:
| opt_attributes opt_access unionCaseName opt_OBLOCKSEP
{ if Option.isSome $2 then errorR(Error(FSComp.SR.parsUnionCasesCannotHaveVisibilityDeclarations(),rhs parseState 2))
let mDecl = rhs parseState 3
(fun xmlDoc -> Choice2Of2 (UnionCase ( $1, $3,UnionCaseFields [],xmlDoc,None,mDecl)))
}
| opt_attributes opt_access unionCaseName OF unionCaseRepr opt_OBLOCKSEP
{ if Option.isSome $2 then errorR(Error(FSComp.SR.parsUnionCasesCannotHaveVisibilityDeclarations(),rhs parseState 2))
let mDecl = rhs2 parseState 3 5
(fun xmlDoc -> Choice2Of2 (UnionCase ( $1, $3,UnionCaseFields $5,xmlDoc,None,mDecl)))
}
| opt_attributes opt_access unionCaseName COLON topType opt_OBLOCKSEP
{ if Option.isSome $2 then errorR(Error(FSComp.SR.parsUnionCasesCannotHaveVisibilityDeclarations(),rhs parseState 2))
libraryOnlyWarning(lhs parseState)
let mDecl = rhs2 parseState 3 5
(fun xmlDoc -> Choice2Of2 (UnionCase ( $1, $3,UnionCaseFullType $5,xmlDoc,None,mDecl)))
}
| opt_attributes opt_access unionCaseName EQUALS constant opt_OBLOCKSEP
{ if Option.isSome $2 then errorR(Error(FSComp.SR.parsEnumFieldsCannotHaveVisibilityDeclarations(),rhs parseState 2))
let mDecl = rhs2 parseState 3 5
(fun xmlDoc -> Choice1Of2 (EnumCase ( $1, $3,$5,xmlDoc,mDecl)))
}
/* The name of a union case */
unionCaseName:
| nameop
{ $1 }
| LPAREN COLON_COLON rparen
{ ident(opNameCons,rhs parseState 2) }
| LPAREN LBRACK RBRACK rparen
{ ident(opNameNil,rhs2 parseState 2 3) }
firstUnionCaseDeclOfMany:
| ident opt_OBLOCKSEP
{ Choice2Of2 (UnionCase ( [], $1,UnionCaseFields [],PreXmlDoc.Empty,None,rhs parseState 1)) }
| ident EQUALS constant opt_OBLOCKSEP
{ Choice1Of2 (EnumCase ([],$1,$3,PreXmlDoc.Empty,rhs2 parseState 1 3)) }
| firstUnionCaseDecl opt_OBLOCKSEP
{ $1 }
firstUnionCaseDecl:
| ident OF unionCaseRepr
{ Choice2Of2 (UnionCase ( [],$1,UnionCaseFields $3,PreXmlDoc.Empty,None,rhs2 parseState 1 3)) }
| ident EQUALS constant opt_OBLOCKSEP
{ Choice1Of2 (EnumCase ([],$1,$3,PreXmlDoc.Empty,rhs2 parseState 1 3)) }
unionCaseReprElements:
| unionCaseReprElement STAR unionCaseReprElements { $1::$3 }
| unionCaseReprElement %prec prec_toptuptyptail_prefix { [$1] }
unionCaseReprElement:
| ident COLON appType { mkNamedField($1, $3) }
| appType { mkAnonField $1 }
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 fld = $2 $1 false
let (Field(a,b,c,d,e,f,vis,g)) = fld
if Option.isSome vis then errorR(Error(FSComp.SR.parsRecordFieldsCannotHaveVisibilityDeclarations(),rhs parseState 2))
Field(a,b,c,d,e,f,None,g) }
/* Part of a field or val declaration in a record type or object type */
fieldDecl:
| opt_mutable opt_access ident COLON typ
{ let mRhs = rhs2 parseState 3 5
let xmlDoc = grabXmlDoc(parseState,3)
(fun attrs stat -> Field(attrs, stat,Some $3,$5,$1,xmlDoc,$2,mRhs)) }
/* An exception definition */
exconDefn:
| exconCore opt_classDefn
{ SynExceptionDefn($1,$2, ($1.Range,$2) ||> unionRangeWithListBy (fun cd -> cd.Range) ) }
/* Part of an exception definition */
exceptionAndGrabDoc:
| EXCEPTION { grabXmlDoc(parseState,1) }
/* Part of an exception definition */
exconCore:
| exceptionAndGrabDoc opt_attributes opt_access exconIntro exconRepr
{ SynExceptionDefnRepr($2,$4,$5,$1,$3,(match $5 with None -> rhs2 parseState 1 4 | Some p -> unionRanges (rangeOfLongIdent p) (rhs2 parseState 1 4))) }
/* Part of an exception definition */
exconIntro:
| ident
{ UnionCase ( [], $1,UnionCaseFields [],PreXmlDoc.Empty,None,lhs parseState) }
| ident OF unionCaseRepr
{ UnionCase ( [], $1,UnionCaseFields $3,PreXmlDoc.Empty,None,lhs parseState) }
exconRepr:
| { None }
| EQUALS path { Some ($2.Lid) }
openDecl:
| OPEN path { $2 }
/*-------------------------------------------------------------------------*/
/* F# Definitions 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 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 ->
// apply the builder
let binds = localBindingsBuilder attrs vis mLetKwd
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 typedSeqExprBlock
{ 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,true,$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
$4 (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 binds = localBindingsBuilder attrs vis mLetKwd
if not isRec && not (isNilOrSingleton binds) then
reportParseErrorAt mLetKwd (FSComp.SR.parsLetAndForNonRecBindings())
[],binds),
bindingSetRange), (unionRanges mLetKwd bindingSetRange) }
/* A 'do ...' statement */
hardwhiteDoBinding:
| ODO typedSeqExprBlock hardwhiteDefnBindingsTerminator
{ let mLetKwd = rhs parseState 1
let bindingSetRange = unionRanges mLetKwd $2.Range
let seqPt = NoSequencePointAtDoBinding
// any attributes prior to the 'let' are left free, e.g. become top-level attributes
// associated with the module, 'main' function or assembly depending on their target
BindingSetPreAttrs(mLetKwd,false,false,(fun attrs vis -> attrs,[mkSynDoBinding (vis,true,$2,bindingSetRange)]),bindingSetRange), $2 }
/* The bindings in a class type definition */
classDefnBindings:
| defnBindings { $1 }
| doBinding { $1 }
| hardwhiteLetBindings { let b,m = $1 in b }
| hardwhiteDoBinding { fst $1 }
/* The terminator for a 'let ....' binding in the #light syntax */
hardwhiteDefnBindingsTerminator:
| ODECLEND
{ (fun _ m -> ()) }
| recover
{ (fun kwd m -> reportParseErrorAt m (match kwd with
| "let!" -> FSComp.SR.parsUnmatchedLetBang()
| "use!" -> FSComp.SR.parsUnmatchedUseBang()
| "use" -> FSComp.SR.parsUnmatchedUse()
| _ (*"let" *) -> FSComp.SR.parsUnmatchedLet())) }
/* An 'extern' DllImport function definition in C-style syntax */
cPrototype:
| EXTERN cRetType opt_access ident opt_HIGH_PRECEDENCE_APP LPAREN cArgs rparen
{ let rty,vis,nm,args = $2,$3,$4,$7
let xmlDoc = grabXmlDoc(parseState,1)
let nmm = rhs parseState 3
let argsm = rhs parseState 6
let 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",rhs parseState 8),rhs parseState 8),
mRhs)
(fun attrs vis ->
let bindingId = SynPat.LongIdent (LongIdentWithDots([nm],[]), None, Some noInferredTypars, SynConstructorArgs.Pats [SynPat.Tuple(args,argsm)], vis, nmm)
let binding = mkSynBinding
(xmlDoc, bindingId)
(vis, false, false, mBindLhs, NoSequencePointAtInvisibleBinding, Some rty ,rhsExpr, mRhs, [], attrs, None)
[], [binding]) }
/* A list of arguments in an 'extern' DllImport function definition */
cArgs:
| cMoreArgs
{ List.rev $1 }
| cArg
{ [$1] }
|
{ [] }
/* Part of the list of arguments in an 'extern' DllImport function definition */
cMoreArgs:
| cMoreArgs COMMA cArg
{ $3 :: $1 }
| cArg COMMA cArg
{ [$3; $1] }
/* A single argument in an 'extern' DllImport function definition */
cArg:
| opt_attributes cType
{ let m = lhs parseState in SynPat.Typed(SynPat.Wild m,$2,m) |> addAttribs $1 }
| opt_attributes cType ident
{ let m = lhs parseState in SynPat.Typed(SynPat.Named (SynPat.Wild m,$3,false,None,m),$2,m) |> addAttribs $1 }
/* 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(LongIdentWithDots([ident("[]",m)],[])),None,[$1],[],None,true,m) }
| cType STAR
{ let m = lhs parseState
SynType.App(SynType.LongIdent(LongIdentWithDots([ident("nativeptr",m)],[])),None,[$1],[],None,true,m) }
| cType AMP
{ let m = lhs parseState
SynType.App(SynType.LongIdent(LongIdentWithDots([ident("byref",m)],[])),None,[$1],[],None,true,m) }
| VOID STAR
{ let m = lhs parseState
SynType.App(SynType.LongIdent(LongIdentWithDots([ident("nativeint",m)],[])),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(LongIdentWithDots([ident("unit",m)],[])),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 attrs vis mLetKwd -> attrLocalBindingBuilder attrs vis mLetKwd true :: moreBindings)
| None ->
moreLocalBindingsLastRange, (fun _attrs _vis _letm -> moreBindings) }
moreLocalBindings:
| AND attr_localBinding moreLocalBindings
{ let mLetKwd = rhs parseState 1
(match $2 with
| Some (localBindingRange,attrLocalBindingBuilder) -> (attrLocalBindingBuilder [] None mLetKwd 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 attrs vis mLetKwd _ -> localBindingBuilder (attrs@attrs2) vis mLetKwd)
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 eqm = rhs parseState 5
let mRhs = expr.Range
let optReturnType = $4
let bindingBuilder, mBindLhs = $3
let localBindingRange = unionRanges (rhs2 parseState 3 5) mRhs
let localBindingBuilder =
(fun attrs vis mLetKwd ->
let mWhole = unionRanges mLetKwd mRhs
let spBind = if IsControlFlowExpression expr then NoSequencePointAtLetBinding else SequencePointAtBinding(mWhole)
bindingBuilder (vis,$1,$2,mBindLhs,spBind,optReturnType,expr,mRhs,opts,attrs,None))
localBindingRange,localBindingBuilder }
| opt_inline opt_mutable bindingPattern opt_topReturnTypeWithTypeConstraints EQUALS error
{ let mWhole = rhs2 parseState 3 5
let mRhs = rhs parseState 5
let optReturnType = $4
let bindingBuilder,mBindLhs = $3
let localBindingBuilder =
(fun attrs vis mLetKwd ->
let spBind = SequencePointAtBinding(unionRanges mLetKwd mRhs)
let eqm = rhs parseState 5
let zeroWidthAtEnd = eqm.EndRange
bindingBuilder (vis,$1,$2,mBindLhs,spBind,optReturnType,arbExpr("localBinding1",zeroWidthAtEnd),mRhs,[],attrs,None))
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 = match optReturnType with None -> rhs parseState 3 | Some _ -> rhs2 parseState 3 4
let mRhs = mWhole.EndRange // zero-width range at end of last good token
let bindingBuilder,mBindLhs = $3
let localBindingBuilder =
(fun attrs vis mLetKwd ->
let spBind = SequencePointAtBinding(unionRanges mLetKwd mRhs)
bindingBuilder (vis,$1,$2,mBindLhs,spBind,optReturnType,arbExpr("localBinding2",mRhs),mRhs,[],attrs,None))
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 :
| typedSeqExpr opt_staticOptimizations { $1, List.rev $2 }
opt_staticOptimizations:
| opt_staticOptimizations staticOptimization { $2 :: $1 }
| { [] }
staticOptimization:
| WHEN staticOptimizationConditions EQUALS typedSeqExprBlock { ($2,$4) }
staticOptimizationConditions:
| staticOptimizationConditions AND staticOptimizationCondition { $3 :: $1 }
| staticOptimizationCondition { [$1 ] }
staticOptimizationCondition:
| typar COLON typ { WhenTyparTyconEqualsTycon($1,$3,lhs parseState) }
| typar STRUCT { WhenTyparIsStruct($1,lhs parseState) }
rawConstant:
| INT8 { if snd $1 then errorR(Error(FSComp.SR.lexOutsideEightBitSigned(), lhs parseState))
SynConst.SByte (fst $1) }
| UINT8 { SynConst.Byte $1 }
| INT16 { if snd $1 then errorR(Error(FSComp.SR.lexOutsideSixteenBitSigned(), lhs parseState))
SynConst.Int16 (fst $1) }
| UINT16 { SynConst.UInt16 $1 }
| INT32 { if snd $1 then errorR(Error(FSComp.SR.lexOutsideThirtyTwoBitSigned(), lhs parseState))
SynConst.Int32 (fst $1) }
| UINT32 { SynConst.UInt32 $1 }
| INT64 { if snd $1 then errorR(Error(FSComp.SR.lexOutsideSixtyFourBitSigned(), lhs parseState))
SynConst.Int64 (fst $1) }
| UINT64 { SynConst.UInt64 $1 }
| NATIVEINT { SynConst.IntPtr $1 }
| UNATIVEINT { SynConst.UIntPtr $1 }
| IEEE32 { SynConst.Single $1 }
| IEEE64 { SynConst.Double $1 }
| CHAR { SynConst.Char $1 }
| DECIMAL { SynConst.Decimal $1 }
| BIGNUM { SynConst.UserNum $1 }
| stringOrKeywordString { SynConst.String ($1,lhs parseState) }
| BYTEARRAY { SynConst.Bytes ($1,lhs parseState) }
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 }
| rawConstant HIGH_PRECEDENCE_TYAPP measureTypeArg { SynConst.Measure($1, $3) }
bindingPattern:
| headBindingPattern
{ let xmlDoc = grabXmlDoc(parseState,1)
mkSynBinding (xmlDoc,$1), rhs parseState 1 }
/* sp = v | sp:typ | attrs sp */
simplePattern:
| ident
{ SynSimplePat.Id ($1,None,false,false,false,rhs parseState 1) }
| QMARK ident
{ SynSimplePat.Id ($2,None,false,false,true,rhs parseState 2) }
| simplePattern COLON typeWithTypeConstraints
{ let lhsm = lhs parseState
SynSimplePat.Typed($1,$3,lhsm) }
| attributes simplePattern %prec paren_pat_attribs
{ let lhsm = lhs parseState
SynSimplePat.Attrib($2,$1,lhsm) }
simplePatternCommaList:
| simplePattern
{ [$1] }
| simplePattern COMMA simplePatternCommaList
{ $1 :: $3 }
simplePatterns:
| LPAREN simplePatternCommaList rparen
{ $2 }
| LPAREN rparen
{ [] }
| LPAREN simplePatternCommaList recover
{ reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnmatchedParen())
[] }
| LPAREN error rparen
{ (* silent recovery *) [] }
| LPAREN recover
{ reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnmatchedParen())
[] }
headBindingPattern:
| headBindingPattern AS ident
{ SynPat.Named ($1,$3,false,None,rhs2 parseState 1 3) }
| headBindingPattern BAR headBindingPattern
{ SynPat.Or($1,$3,rhs2 parseState 1 3) }
| headBindingPattern COLON_COLON headBindingPattern
{ SynPat.LongIdent (LongIdentWithDots(mkSynCaseName (rhs parseState 2) opNameCons,[]), None, None, SynConstructorArgs.Pats [SynPat.Tuple ([$1;$3],rhs2 parseState 1 3)],None,lhs parseState) }
| tuplePatternElements %prec pat_tuple
{ SynPat.Tuple(List.rev $1, lhs parseState) }
| conjPatternElements %prec pat_conj
{ SynPat.Ands(List.rev $1, lhs parseState) }
| constrPattern
{ $1 }
tuplePatternElements:
| tuplePatternElements COMMA headBindingPattern
{ $3 :: $1 }
| headBindingPattern COMMA headBindingPattern
{ $3 :: $1 :: [] }
conjPatternElements:
| conjPatternElements AMP headBindingPattern
{ $3 :: $1 }
| headBindingPattern AMP headBindingPattern
{ $3 :: $1 :: [] }
namePatPairs:
| namePatPair opt_seps { [$1], lhs parseState }
| namePatPair seps namePatPairs { let (rs, _) = $3 in ($1::rs), lhs parseState }
namePatPair:
| ident EQUALS parenPattern { ($1, $3) }
constrPattern:
| atomicPatternLongIdent explicitValTyparDecls
{ let vis,lid = $1 in SynPat.LongIdent (lid,None,Some $2, SynConstructorArgs.Pats [],vis,lhs parseState) }
| atomicPatternLongIdent opt_explicitValTyparDecls2 atomicPatsOrNamePatPairs %prec pat_app
{ let vis,lid = $1 in SynPat.LongIdent (lid,None,$2, $3,vis,lhs parseState) }
| atomicPatternLongIdent opt_explicitValTyparDecls2 HIGH_PRECEDENCE_PAREN_APP atomicPatsOrNamePatPairs
{ let vis,lid = $1 in SynPat.LongIdent (lid,None,$2, $4,vis,lhs parseState) }
| atomicPatternLongIdent opt_explicitValTyparDecls2 HIGH_PRECEDENCE_BRACK_APP atomicPatsOrNamePatPairs
{ let vis,lid = $1 in SynPat.LongIdent (lid,None,$2, $4,vis,lhs parseState) }
| COLON_QMARK atomType %prec pat_isinst
{ SynPat.IsInst($2,lhs parseState) }
| atomicPattern
{ $1 }
atomicPatsOrNamePatPairs:
| LPAREN namePatPairs rparen { SynConstructorArgs.NamePatPairs $2 }
| atomicPatterns { SynConstructorArgs.Pats $1 }
atomicPatterns:
| atomicPattern atomicPatterns %prec pat_args
{ $1 :: $2 }
| atomicPattern HIGH_PRECEDENCE_BRACK_APP atomicPatterns
{ reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsSuccessivePatternsShouldBeSpacedOrTupled())
$1 :: $3 }
| atomicPattern HIGH_PRECEDENCE_PAREN_APP atomicPatterns
{ reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsSuccessivePatternsShouldBeSpacedOrTupled())
$1 :: $3 }
| atomicPattern { [$1] }
atomicPattern:
| quoteExpr
{ SynPat.QuoteExpr($1,lhs parseState) }
| CHAR DOT_DOT CHAR { SynPat.DeprecatedCharRange ($1,$3,rhs2 parseState 1 3) }
| LBRACE recordPatternElements rbrace
{ $2 }
| LBRACK listPatternElements RBRACK
{ SynPat.ArrayOrList(false,$2,lhs parseState) }
| LBRACK_BAR listPatternElements BAR_RBRACK
{ SynPat.ArrayOrList(true,$2, lhs parseState) }
| UNDERSCORE
{ SynPat.Wild (lhs parseState) }
| QMARK ident
{ SynPat.OptionalVal($2,lhs parseState) }
| atomicPatternLongIdent %prec prec_atompat_pathop
{ let vis,lidwd = $1
if not (isNilOrSingleton lidwd.Lid) || (let c = (List.head lidwd.Lid).idText.[0] in Char.IsUpper(c) && not (Char.IsLower c))
then mkSynPatMaybeVar lidwd vis (lhs parseState)
else mkSynPatVar vis (List.head lidwd.Lid) }
| constant
{ SynPat.Const ($1,$1.Range (lhs parseState)) }
| FALSE
{ SynPat.Const(SynConst.Bool false,lhs parseState) }
| TRUE
{ SynPat.Const(SynConst.Bool true,lhs parseState) }
| NULL
{ SynPat.Null(lhs parseState) }
| LPAREN parenPatternBody rparen
{ let m = (lhs parseState)
SynPat.Paren($2 m,m) }
| LPAREN parenPatternBody recover
{ reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnmatchedParen())
patFromParseError ($2 (rhs2 parseState 1 2)) }
| LPAREN error rparen
{ (* silent recovery *) SynPat.Wild (lhs parseState) }
| LPAREN recover
{ reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnmatchedParen())
SynPat.Wild (lhs parseState)}
| STRUCT LPAREN tupleParenPatternElements rparen
{ SynPat.StructTuple(List.rev $3,lhs parseState) }
| STRUCT LPAREN tupleParenPatternElements recover
{ reportParseErrorAt (rhs parseState 2) (FSComp.SR.parsUnmatchedParen());
SynPat.StructTuple(List.rev $3,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) }
|
{ (fun m -> SynPat.Const(SynConst.Unit,m)) }
/* This duplicates out 'patterns' in order to give type annotations */
/* the desired precedence w.r.t. patterns, tuple patterns in particular. */
/* Duplication requried to minimize the disturbance to the grammar, */
/* in particular the expected property that "pat" parses the same as */
/* "(pat)"! Here are some examples: */
/* a,b parses as (a,b) */
/* (a,b) also parses as (a,b) */
/* (a,b : t) parses as (a, (b:t)) */
/* a,b as t parses as ((a,b) as t) */
/* (a,b as t) also parses as ((a,b) as t) */
/* a,b | c,d parses as ((a,b) | (c,d)) */
/* (a,b | c,d) also parses as ((a,b) | (c,d)) */
/* (a : t,b) parses as ((a:t),b) */
/* (a : t1,b : t2) parses as ((a:t),(b:t2)) */
/* (a,b as nm : t) parses as (((a,b) as nm) : t) */
/* (a,b :: c : t) parses as (((a,b) :: c) : t) */
/* */
/* Probably the most unexpected thing here is that 'as nm' binds the */
/* whole pattern to the left, whereas ': t' binds only the pattern */
/* immediately preceding in the tuple. */
/* */
/* Also, it is unexpected that '(a,b : t)' in a pattern binds differently to */
/* '(a,b : t)' in an expression. It's not that easy to solve that without */
/* duplicating the entire expression grammar, or making a fairly severe breaking change */
/* to the language. */
parenPattern:
| parenPattern AS ident
{ SynPat.Named ($1,$3,false,None,rhs2 parseState 1 3) }
| parenPattern BAR parenPattern
{ SynPat.Or($1,$3,rhs2 parseState 1 3) }
| tupleParenPatternElements
{ SynPat.Tuple(List.rev $1,lhs parseState) }
| conjParenPatternElements
{ SynPat.Ands(List.rev $1,rhs2 parseState 1 3) }
| parenPattern COLON typeWithTypeConstraints %prec paren_pat_colon
{ let lhsm = lhs parseState
SynPat.Typed($1,$3,lhsm) }
| attributes parenPattern %prec paren_pat_attribs
{ let lhsm = lhs parseState
SynPat.Attrib($2,$1,lhsm) }
| parenPattern COLON_COLON parenPattern
{ SynPat.LongIdent (LongIdentWithDots(mkSynCaseName (rhs parseState 2) opNameCons,[]), None, None, SynConstructorArgs.Pats [ SynPat.Tuple ([$1;$3],rhs2 parseState 1 3) ],None,lhs parseState) }
| constrPattern { $1 }
tupleParenPatternElements:
| tupleParenPatternElements COMMA parenPattern
{ $3 :: $1 }
| parenPattern COMMA parenPattern
{ $3 :: $1 :: [] }
conjParenPatternElements:
| conjParenPatternElements AMP parenPattern
{ $3 :: $1 }
| parenPattern AMP parenPattern
{ $3 :: $1 :: [] }
recordPatternElements:
| recordPatternElementsAux { let rs,m = $1 in SynPat.Record (rs,m) }
recordPatternElementsAux: /* Fix 1190 */
| recordPatternElement opt_seps
{ [$1],lhs parseState }
| recordPatternElement seps recordPatternElementsAux
{ let r = $1 in let (rs,dropMark) = $3 in (r :: rs),lhs parseState }
recordPatternElement:
| path EQUALS parenPattern { (List.frontAndBack $1.Lid,$3) }
listPatternElements: /* Fix 3569 */
|
{ [] }
| parenPattern opt_seps
{ [$1] }
| parenPattern seps listPatternElements
{ $1 :: $3 }
/* The lexfilter likes to insert OBLOCKBEGIN/OBLOCKEND pairs */
typedSeqExprBlock:
| OBLOCKBEGIN typedSeqExpr oblockend
{ $2 }
| OBLOCKBEGIN typedSeqExpr recover
{ if not $3 then reportParseErrorAt (rhs parseState 3) (FSComp.SR.parsUnexpectedEndOfFileExpression())
exprFromParseError $2 }
| typedSeqExpr
{ $1 }
/* The lexfilter likes to insert OBLOCKBEGIN/OBLOCKEND pairs */
declExprBlock:
| OBLOCKBEGIN typedSeqExpr oblockend
{ $2 }
| declExpr
{ $1 }
/* For some constructs the lex filter can't be sure to insert a matching OBLOCKEND, e.g. "function a -> b | c -> d" all in one line */
/* for these it only inserts a trailing ORIGHT_BLOCK_END */
typedSeqExprBlockR:
| typedSeqExpr ORIGHT_BLOCK_END { $1 }
| typedSeqExpr { $1 }
typedSeqExpr:
| seqExpr COLON typeWithTypeConstraints { SynExpr.Typed ($1,$3, unionRanges $1.Range $3.Range) }
| seqExpr { $1 }
typedSeqExprEOF:
| typedSeqExpr EOF { checkEndOfFileError $2; $1 }
seqExpr:
| declExpr seps seqExpr
{ SynExpr.Sequential(SequencePointsAtSeq,true,$1,$3,unionRanges $1.Range $3.Range) }
| declExpr seps
{ $1 }
| declExpr %prec SEMICOLON
{ $1 }
| declExpr THEN seqExpr %prec prec_then_before
{ SynExpr.Sequential(SequencePointsAtSeq,false,$1,$3,unionRanges $1.Range $3.Range ) }
| declExpr OTHEN OBLOCKBEGIN typedSeqExpr oblockend %prec prec_then_before
{ SynExpr.Sequential(SequencePointsAtSeq,false,$1,$4,unionRanges $1.Range $4.Range) }
| hardwhiteLetBindings %prec prec_args_error
{ let hwlb,m = $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,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 }
declExpr:
| defnBindings IN typedSeqExpr %prec expr_let
{ mkLocalBindings (unionRanges (rhs2 parseState 1 2) $3.Range,$1,$3) }
| defnBindings IN error %prec expr_let
{ mkLocalBindings (rhs2 parseState 1 2,$1,arbExpr("declExpr1",(rhs parseState 3))) }
/*
FSComp.SR.parsNoMatchingInForLet() -- leave this in for now - it's an unused error string
*/
| hardwhiteLetBindings typedSeqExprBlock %prec expr_let
{ let hwlb,m = $1
mkLocalBindings (unionRanges m $2.Range,hwlb,$2) }
| hardwhiteLetBindings error %prec expr_let
{ let hwlb,m = $1
reportParseErrorAt (match hwlb with (BindingSetPreAttrs(m,_,_,_,_)) -> m) (FSComp.SR.parsErrorInReturnForLetIncorrectIndentation())
mkLocalBindings (m,hwlb,arbExpr("declExpr2",(rhs parseState 2))) }
| hardwhiteLetBindings OBLOCKSEP typedSeqExprBlock %prec expr_let
{ let hwlb,m = $1
mkLocalBindings (unionRanges m $3.Range ,hwlb,$3) }
| hardwhiteLetBindings OBLOCKSEP error %prec expr_let
{ let hwlb,m = $1
//reportParseErrorAt (match hwlb with (BindingSetPreAttrs(m,_,_,_,_)) -> m) (FSComp.SR.parsErrorInReturnForLetIncorrectIndentation())
mkLocalBindings (unionRanges m (rhs parseState 3),hwlb,arbExpr("declExpr3",(rhs parseState 3))) }
| hardwhiteDoBinding %prec expr_let
{ let e = snd $1
SynExpr.Do(e,e.Range) }
| anonMatchingExpr %prec expr_function
{ $1 }
| anonLambdaExpr %prec expr_fun
{ $1 }
| MATCH typedSeqExpr withClauses %prec expr_match
{ let mMatch = (rhs parseState 1)
let mWith,(clauses,mLast) = $3
let spBind = SequencePointAtBinding(unionRanges mMatch mWith)
SynExpr.Match(spBind, $2,clauses,false,unionRanges mMatch mLast) }
| MATCH typedSeqExpr recover %prec expr_match
{ if not $3 then reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnexpectedEndOfFileMatch())
// Produce approximate expression during error recovery
exprFromParseError $2 }
| MATCH_BANG typedSeqExpr withClauses %prec expr_match
{ let mMatch = (rhs parseState 1)
let mWith,(clauses,mLast) = $3
let spBind = SequencePointAtBinding(unionRanges mMatch mWith)
SynExpr.MatchBang(spBind, $2,clauses,false,unionRanges mMatch mLast) }
| MATCH_BANG typedSeqExpr recover %prec expr_match
{ if not $3 then reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnexpectedEndOfFileMatch())
// Produce approximate expression during error recovery
exprFromParseError $2 }
| TRY typedSeqExprBlockR withClauses %prec expr_try
{ let mTry = (rhs parseState 1)
let spTry = SequencePointAtTry(mTry)
let mWith,(clauses,mLast) = $3
let spWith = SequencePointAtWith(mWith)
let mTryToWith = unionRanges mTry mWith
let mWithToLast = unionRanges mWith mLast
let mTryToLast = unionRanges mTry mLast
SynExpr.TryWith($2, mTryToWith, clauses,mWithToLast, mTryToLast,spTry,spWith) }
| TRY typedSeqExprBlockR recover %prec expr_try
{ // Produce approximate expression during error recovery
// Include any expressions to make sure they gets type checked in case that generates useful results for intellisense
if not $3 then reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnexpectedEndOfFileTry())
exprFromParseError $2 }
| TRY typedSeqExprBlockR FINALLY typedSeqExprBlock %prec expr_try
{ let mTry = rhs parseState 1
let spTry = SequencePointAtTry(mTry)
let spFinally = SequencePointAtFinally(rhs parseState 3)
let mTryToLast = unionRanges mTry $4.Range
SynExpr.TryFinally($2, $4,mTryToLast,spTry,spFinally) }
| IF declExpr ifExprCases %prec expr_if
{ let mIf = (rhs parseState 1)
$3 $2 mIf }
| IF declExpr recover %prec expr_if
{ reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsIncompleteIf())
// Produce an approximate expression during error recovery.
// Include expressions to make sure they get type checked in case that generates useful results for intellisense.
// Generate a throwAway for the expression so it isn't forced to have a type 'bool'
// from the context it is used in.
exprFromParseError $2 }
| IF recover %prec expr_if
{ reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsIncompleteIf())
// Produce an approximate expression during error recovery. There can still be value in doing this even
// for this pathological case.
let m = (rhs parseState 1)
let mEnd = m.EndRange
let spIfToThen = SequencePointAtBinding mEnd
exprFromParseError (SynExpr.IfThenElse(arbExpr("ifGuard1",mEnd),arbExpr("thenBody1",mEnd),None,spIfToThen,true,m,m)) }
| LAZY declExpr %prec expr_lazy
{ SynExpr.Lazy($2,unionRanges (rhs parseState 1) $2.Range) }
| ASSERT declExpr %prec expr_assert
{ SynExpr.Assert($2, unionRanges (rhs parseState 1) $2.Range) }
| ASSERT %prec expr_assert
{ raiseParseErrorAt (rhs parseState 1) (FSComp.SR.parsAssertIsNotFirstClassValue()) }
| OLAZY declExprBlock %prec expr_lazy
{ SynExpr.Lazy($2,unionRanges (rhs parseState 1) $2.Range) }
| OASSERT declExprBlock %prec expr_assert
{ SynExpr.Assert($2, unionRanges (rhs parseState 1) $2.Range) }
| OASSERT %prec expr_assert
{ raiseParseErrorAt (rhs parseState 1) (FSComp.SR.parsAssertIsNotFirstClassValue()) }
| WHILE declExpr doToken typedSeqExprBlock doneDeclEnd
{ let mWhileHeader = unionRanges (rhs parseState 1) $2.Range
let spWhile = SequencePointAtWhileLoop mWhileHeader
let mWhileAll = unionRanges (rhs parseState 1) $4.Range
SynExpr.While(spWhile,$2,$4,mWhileAll) }
| WHILE declExpr doToken typedSeqExprBlock recover
{ if not $5 then reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnexpectedEndOfFileWhile())
let mWhileHeader = unionRanges (rhs parseState 1) $2.Range
let spWhile = SequencePointAtWhileLoop 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 = SequencePointAtWhileLoop 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 = SequencePointAtWhileLoop 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 = SequencePointAtWhileLoop 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 typedSeqExprBlock doneDeclEnd
{ let spBind = SequencePointAtForLoop(rhs2 parseState 1 3)
let (a,b,_) = $2
SynExpr.ForEach(spBind,SeqExprOnly false,true,a,b,$4,unionRanges (rhs parseState 1) $4.Range) }
| FOR forLoopBinder doToken typedSeqExprBlock ends_coming_soon_or_recover
{ if not $5 then reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnexpectedEndOfFileFor())
let spBind = SequencePointAtForLoop(rhs2 parseState 1 3)
let (a,b,_) = $2
let mForLoopAll = unionRanges (rhs parseState 1) $4.Range
SynExpr.ForEach(spBind,SeqExprOnly false,true,a,b,$4,mForLoopAll) }
| FOR forLoopBinder doToken error doneDeclEnd
{ // Silent recovery
let mForLoopHeader = rhs2 parseState 1 3
let spBind = SequencePointAtForLoop mForLoopHeader
let (a,b,_) = $2
let mForLoopBodyArb = rhs parseState 5
let mForLoopAll = rhs2 parseState 1 5
SynExpr.ForEach(spBind,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 mForLoopHeader = rhs2 parseState 1 3
let spBind = SequencePointAtForLoop mForLoopHeader
let (a,b,_) = $2
let mForLoopBodyArb = rhs parseState 3
let mForLoopAll = rhs2 parseState 1 3
SynExpr.ForEach(spBind,SeqExprOnly false,true,a,b,arbExpr("forLoopBody2",mForLoopBodyArb),mForLoopAll) }
| FOR forLoopBinder ends_coming_soon_or_recover
{ let (a,b,ok) = $2
if not $3 then reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsForDoExpected())
let mForLoopHeader = rhs2 parseState 1 3
let spBind = SequencePointAtForLoop mForLoopHeader
let mForLoopBodyArb = rhs parseState 3
let mForLoopAll = rhs2 parseState 1 3
SynExpr.ForEach(spBind,SeqExprOnly false,true,a,b,arbExpr("forLoopBody1",mForLoopBodyArb),mForLoopAll) }
| FOR forLoopRange doToken typedSeqExprBlock doneDeclEnd
{ let mForLoopHeader = rhs2 parseState 1 3
let spBind = SequencePointAtForLoop mForLoopHeader
let (a,b,c,d) = $2
let mForLoopAll = unionRanges (rhs parseState 1) $4.Range
SynExpr.For(spBind,a,b,c,d,$4,mForLoopAll) }
| FOR forLoopRange doToken typedSeqExprBlock recover
{ if not $5 then reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnexpectedEndOfFileFor())
// Still produce an expression
let mForLoopHeader = rhs2 parseState 1 3
let spBind = SequencePointAtForLoop mForLoopHeader
let (a,b,c,d) = $2
let mForLoopAll = unionRanges (rhs parseState 1) $4.Range
exprFromParseError (SynExpr.For(spBind,a,b,c,d,$4,mForLoopAll)) }
| FOR forLoopRange doToken error doneDeclEnd
{ // silent recovery
let mForLoopHeader = rhs2 parseState 1 3
let spBind = SequencePointAtForLoop mForLoopHeader
let (a,b,c,d) = $2
let mForLoopBodyArb = rhs parseState 5
let mForLoopAll = rhs2 parseState 1 5
SynExpr.For(spBind,a,b,c,d,arbExpr("declExpr11",mForLoopBodyArb),mForLoopAll) }
| FOR forLoopRange doToken recover
{ if not $4 then reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnexpectedEndOfFileFor())
let mForLoopHeader = rhs2 parseState 1 3
let spBind = SequencePointAtForLoop mForLoopHeader
let (a,b,c,d) = $2
let mForLoopBodyArb = rhs parseState 3
let mForLoopAll = rhs2 parseState 1 3
exprFromParseError (SynExpr.For(spBind,a,b,c,d,arbExpr("declExpr11",mForLoopBodyArb),mForLoopAll)) }
| FOR forLoopRange recover
{ if not $3 then reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnexpectedEndOfFileFor())
let mForLoopHeader = rhs2 parseState 1 2
let spBind = SequencePointAtForLoop mForLoopHeader
let (a,b,c,d) = $2
let mForLoopBodyArb = (rhs parseState 2).EndRange
let mForLoopAll = rhs2 parseState 1 2
exprFromParseError (SynExpr.For(spBind,a,b,c,d,arbExpr("declExpr11",mForLoopBodyArb),mForLoopAll)) }
| FOR error doToken typedSeqExprBlock doneDeclEnd
{ // silent recovery
let mForLoopHeader = rhs2 parseState 1 2
let mForLoopAll = unionRanges (rhs parseState 1) $4.Range
let spBind = SequencePointAtForLoop(mForLoopHeader)
SynExpr.For(spBind,mkSynId mForLoopHeader "_loopVar",arbExpr("startLoopRange1",mForLoopHeader),true,arbExpr("endLoopRange1",rhs parseState 3),$4,mForLoopAll) }
/* do not include this one - though for fairly bizarre reasons!
If the user has simply typed 'for'as the
start of a variable name, and intellisense parsing
kicks in, then we can't be sure we're parsing a for-loop. The general rule is that you shoudn't
commit to aggressive look-for-a-matching-construct error recovery until
you're sure you're parsing a particular construct.
This probably affects 'and' as well, but it's hard to change that.
'for' is a particularly common prefix of identifiers.
| FOR error doneDeclEnd { reportParseErrorAt (rhs parseState 2) (FSComp.SR.parsIdentifierExpected()); arbExpr("declExpr12",(lhs parseState)) }
*/
| 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 mForLoopHeader = rhs2 parseState 1 2
let spBind = SequencePointAtForLoop mForLoopHeader
let mForLoopBodyArb = rhs parseState 4
let mForLoopAll = rhs2 parseState 1 4
SynExpr.ForEach(spBind,SeqExprOnly false,true,$2,arbExpr("forLoopCollection",mForLoopHeader),arbExpr("forLoopBody3",mForLoopBodyArb),mForLoopAll) }
| FOR parenPattern recover
{ if not $3 then reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnexpectedEndOfFileFor())
let mForLoopHeader = rhs2 parseState 1 2
let spBind = SequencePointAtForLoop mForLoopHeader
let mForLoopBodyArb = (rhs parseState 2).EndRange
let mForLoopAll = rhs2 parseState 1 2
exprFromParseError (SynExpr.ForEach(spBind,SeqExprOnly false,true,$2,arbExpr("forLoopCollection",mForLoopHeader),arbExpr("forLoopBody3",mForLoopBodyArb),mForLoopAll)) }
/* START MONADIC SYNTAX ONLY */
| YIELD declExpr
{ SynExpr.YieldOrReturn(($1,not $1),$2, unionRanges (rhs parseState 1) $2.Range) }
| YIELD_BANG declExpr
{ SynExpr.YieldOrReturnFrom(($1,not $1), $2, unionRanges (rhs parseState 1) $2.Range) }
| BINDER headBindingPattern EQUALS typedSeqExprBlock IN opt_OBLOCKSEP typedSeqExprBlock %prec expr_let
{ let spBind = SequencePointAtBinding(rhs2 parseState 1 5)
let m = unionRanges (rhs parseState 1) $7.Range
SynExpr.LetOrUseBang(spBind,($1 = "use"),true,$2,$4,$7,m) }
| OBINDER headBindingPattern EQUALS typedSeqExprBlock hardwhiteDefnBindingsTerminator opt_OBLOCKSEP typedSeqExprBlock %prec expr_let
{ $5 (if $1 = "use" then "use!" else "let!") (rhs parseState 1) // report unterminated error
let spBind = SequencePointAtBinding(unionRanges (rhs parseState 1) $4.Range)
let m = unionRanges (rhs parseState 1) $7.Range
SynExpr.LetOrUseBang(spBind,($1 = "use"),true,$2,$4,$7,m) }
| OBINDER headBindingPattern EQUALS typedSeqExprBlock hardwhiteDefnBindingsTerminator opt_OBLOCKSEP error %prec expr_let
{ // error recovery that allows intellisense when writing incomplete computation expressions
let spBind = SequencePointAtBinding(unionRanges (rhs parseState 1) $4.Range)
let mAll = unionRanges (rhs parseState 1) (rhs parseState 7)
let m = $4.Range.EndRange // zero-width range
SynExpr.LetOrUseBang(spBind,($1 = "use"),true,$2,$4, SynExpr.ImplicitZero m, mAll) }
| DO_BANG typedSeqExpr IN opt_OBLOCKSEP typedSeqExprBlock %prec expr_let
{ let spBind = NoSequencePointAtDoBinding
SynExpr.LetOrUseBang(spBind,false,true,SynPat.Const(SynConst.Unit,$2.Range),$2,$5, unionRanges (rhs parseState 1) $5.Range) }
| ODO_BANG typedSeqExprBlock hardwhiteDefnBindingsTerminator %prec expr_let
{ SynExpr.DoBang($2, unionRanges (rhs parseState 1) $2.Range) }
| FOR forLoopBinder opt_OBLOCKSEP arrowThenExprR %prec expr_let
{ let spBind = SequencePointAtForLoop(rhs2 parseState 1 2)
let (a,b,_) = $2 in SynExpr.ForEach(spBind,SeqExprOnly true,true,a,b,$4,unionRanges (rhs parseState 1) $4.Range) }
| FIXED declExpr
{ SynExpr.Fixed($2, (unionRanges (rhs parseState 1) $2.Range)) }
| RARROW typedSeqExprBlockR
{ errorR(Error(FSComp.SR.parsArrowUseIsLimited(),lhs parseState))
SynExpr.YieldOrReturn((true,true),$2, (unionRanges (rhs parseState 1) $2.Range)) }
/* END MONADIC SYNTAX ONLY */
| declExpr COLON_QMARK typ { SynExpr.TypeTest($1,$3, unionRanges $1.Range $3.Range) }
| declExpr COLON_GREATER typ { SynExpr.Upcast($1,$3, unionRanges $1.Range $3.Range) }
| declExpr COLON_QMARK_GREATER typ { SynExpr.Downcast($1,$3, unionRanges $1.Range $3.Range) }
/* NOTE: any change to the "INFIX" tokens (or their definitions) should be reflected in PrettyNaming.IsInfixOperator */
| declExpr COLON_EQUALS declExpr { mkSynInfix (rhs parseState 2) $1 ":=" $3 }
| minusExpr LARROW declExprBlock { mkSynAssign $1 $3 }
/* | minusExpr LARROW recover { mkSynAssign $1 (arbExpr("assignRhs",rhs parseState 2)) } */
| tupleExpr %prec expr_tuple { let exprs,commas = $1 in SynExpr.Tuple(List.rev exprs, List.rev commas, (commas.Head, exprs) ||> unionRangeWithListBy (fun e -> e.Range) ) }
| 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 { SynExpr.App (ExprAtomicFlag.NonAtomic, true, mkSynIdGet (rhs parseState 2) opNameCons,SynExpr.Tuple ([$1;$3],[rhs parseState 2],unionRanges $1.Range $3.Range),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 OBLOCKEND_COMING_SOON { reportParseErrorAt (rhs parseState 2) (FSComp.SR.parsUnfinishedExpression("="))
exprFromParseError(mkSynInfix (rhs parseState 2) $1 "=" (arbExpr("declExprInfix",(rhs parseState 3).StartRange))) }
| 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 { 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("::"))
SynExpr.App (ExprAtomicFlag.NonAtomic, true, mkSynIdGet (rhs parseState 2) opNameCons,SynExpr.Tuple ([$1;(arbExpr("declExprInfix",(rhs parseState 3).StartRange))],[rhs parseState 2],unionRanges $1.Range (rhs parseState 3).StartRange),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))) }
| minusExpr %prec expr_prefix_plus_minus { $1 }
dynamicArg:
| IDENT
{ let con = SynConst.String ($1,rhs parseState 1)
let arg2 = SynExpr.Const (con,con.Range (rhs parseState 1))
arg2 }
| LPAREN typedSeqExpr rparen
{ $2 }
withClauses:
| WITH withPatternClauses
{ rhs parseState 1, $2 }
| OWITH withPatternClauses OEND
{ rhs parseState 1, $2 }
| OWITH withPatternClauses recover
{ if not $3 then reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnexpectedEndOfFileWith())
rhs parseState 1, $2 }
withPatternClauses:
| patternClauses
{ $1 }
| BAR patternClauses
{ $2 }
| BAR error
{ // silent recovery
let mLast = rhs parseState 1
[], mLast }
| error
{ // silent recovery
let mLast = rhs parseState 1
[], mLast }
patternAndGuard:
| parenPattern patternGuard
{ $1, $2, rhs parseState 1 }
patternClauses:
| patternAndGuard patternResult %prec prec_pat_pat_action
{ let pat,guard,patm = $1
let mLast = $2.Range
[Clause(pat,guard,$2,patm,SequencePointAtTarget)], mLast }
| patternAndGuard patternResult BAR patternClauses
{ let pat,guard,patm = $1
let clauses,mLast = $4
(Clause(pat,guard,$2,patm,SequencePointAtTarget) :: clauses), mLast }
| patternAndGuard patternResult BAR error
{ let pat,guard,patm = $1
let mLast = rhs parseState 3
// silent recovery
[Clause(pat,guard,$2,patm,SequencePointAtTarget)], mLast }
| patternAndGuard patternResult error
{ let pat,guard,patm = $1
let mLast = $2.Range
// silent recovery
[Clause(pat,guard,$2,patm,SequencePointAtTarget)], mLast }
| patternAndGuard error
{ let pat,guard,patm = $1
let mLast = rhs parseState 2
// silent recovery
[Clause(pat,guard,SynExpr.Const(SynConst.Unit,mLast.EndRange),patm,SequencePointAtTarget)], mLast }
patternGuard:
| WHEN declExpr
{ Some $2 }
|
{ None }
patternResult:
| RARROW typedSeqExprBlockR
{ $2 }
ifExprCases:
| ifExprThen ifExprElifs
{ let exprThen,mThen = $1
(fun exprGuard mIf ->
let mIfToThen = unionRanges mIf mThen
let lastBranch : SynExpr = match $2 with None -> exprThen | Some e -> e
let mIfToEndOfLastBranch = unionRanges mIf lastBranch.Range
let spIfToThen = SequencePointAtBinding(mIfToThen)
SynExpr.IfThenElse(exprGuard,exprThen,$2,spIfToThen,false,mIfToThen,mIfToEndOfLastBranch)) }
ifExprThen:
| THEN declExpr %prec prec_then_if
{ $2, rhs parseState 1 }
| OTHEN OBLOCKBEGIN typedSeqExpr oblockend %prec prec_then_if
{ $3,rhs parseState 1 }
| OTHEN OBLOCKBEGIN typedSeqExpr recover %prec prec_then_if
{ if not $4 then reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnexpectedEndOfFileThen())
exprFromParseError $3,rhs parseState 1 }
ifExprElifs:
|
{ None }
| ELSE declExpr
{ Some $2 }
| OELSE OBLOCKBEGIN typedSeqExpr oblockend
{ Some $3 }
| OELSE OBLOCKBEGIN typedSeqExpr recover
{ if not $4 then reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnexpectedEndOfFileElse())
Some (exprFromParseError $3) }
| ELIF declExpr ifExprCases
{ let mElif = rhs parseState 1
Some ($3 $2 mElif) }
| ELIF declExpr recover
{ Some (exprFromParseError $2) }
tupleExpr:
| tupleExpr COMMA declExpr
{ let exprs,commas = $1 in ($3 :: exprs),((rhs parseState 2)::commas) }
| tupleExpr COMMA ends_coming_soon_or_recover
{ if not $3 then reportParseErrorAt (rhs parseState 2) (FSComp.SR.parsExpectedExpressionAfterToken())
let exprs,commas = $1
let zeroWidthAtNextToken = (rhs parseState 3).StartRange
((arbExpr("tupleExpr1",zeroWidthAtNextToken)) :: exprs), (rhs parseState 2)::commas }
| declExpr COMMA ends_coming_soon_or_recover
{ if not $3 then reportParseErrorAt (rhs parseState 2) (FSComp.SR.parsExpectedExpressionAfterToken())
let zeroWidthAtNextToken = (rhs parseState 3).StartRange
((arbExpr("tupleExpr2",zeroWidthAtNextToken)) :: [$1]), [rhs parseState 2] }
| declExpr COMMA declExpr
{ [$3 ; $1], [rhs parseState 2] }
minusExpr:
| MINUS minusExpr %prec expr_prefix_plus_minus
{ mkSynPrefix (rhs parseState 1) (unionRanges (rhs parseState 1) $2.Range) "~-" $2 }
| PLUS_MINUS_OP minusExpr
{ if not (IsValidPrefixOperatorUse $1) then reportParseErrorAt $2.Range (FSComp.SR.parsInvalidPrefixOperator())
mkSynPrefix (rhs parseState 1) (unionRanges (rhs parseState 1) $2.Range) ("~"^($1)) $2 }
| ADJACENT_PREFIX_OP minusExpr
{ if not (IsValidPrefixOperatorUse $1) then reportParseErrorAt $2.Range (FSComp.SR.parsInvalidPrefixOperator())
mkSynPrefix (rhs parseState 1) (unionRanges (rhs parseState 1) $2.Range) ("~"^($1)) $2 }
| PERCENT_OP minusExpr
{ if not (IsValidPrefixOperatorUse $1) then reportParseErrorAt $2.Range (FSComp.SR.parsInvalidPrefixOperator())
mkSynPrefix (rhs parseState 1) (unionRanges (rhs parseState 1) $2.Range) ("~"^($1)) $2 }
| AMP minusExpr
{ SynExpr.AddressOf(true,$2,rhs parseState 1,unionRanges (rhs parseState 1) $2.Range) }
| AMP_AMP minusExpr
{ SynExpr.AddressOf(false,$2,rhs parseState 1, unionRanges (rhs parseState 1) $2.Range) }
| NEW appTypeNonAtomicDeprecated opt_HIGH_PRECEDENCE_APP atomicExprAfterType
{ SynExpr.New(false,$2,$4,unionRanges (rhs parseState 1) $4.Range) }
| NEW appTypeNonAtomicDeprecated opt_HIGH_PRECEDENCE_APP error
{ SynExpr.New(false,$2,arbExpr("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,_ = $3
SynExpr.App (ExprAtomicFlag.Atomic, false, arg1,arg2,unionRanges arg1.Range arg2.Range),true }
| 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 }
| atomicExpr DOT atomicExprQualification
{ let arg1,hpa1 = $1
$3 arg1 (lhs parseState) (rhs parseState 2),hpa1 }
| BASE DOT atomicExprQualification
{ let arg1 = SynExpr.Ident(ident("base",rhs parseState 1))
$3 arg1 (lhs parseState) (rhs parseState 2),false }
| QMARK nameop
{ SynExpr.LongIdent (true,LongIdentWithDots([$2],[]),None,rhs parseState 2),false }
| atomicExpr QMARK dynamicArg
{ let arg1,hpa1 = $1
mkSynInfix (rhs parseState 2) arg1 "?" $3, hpa1 }
| GLOBAL
{ SynExpr.Ident (ident(MangledGlobalName,rhs parseState 1)), false }
| nameop
{ SynExpr.Ident ($1),false }
| LBRACK listExprElements RBRACK
{ $2 (lhs parseState) false,false }
| LBRACK listExprElements recover
{ reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnmatchedBracket())
exprFromParseError ($2 (rhs2 parseState 1 2) false), 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 in SynExpr.StructTuple(List.rev exprs, List.rev commas, (commas.Head, exprs) ||> unionRangeWithListBy (fun e -> e.Range) ), false }
| STRUCT LPAREN tupleExpr recover
{ reportParseErrorAt (rhs parseState 2) (FSComp.SR.parsUnmatchedBracket());
let exprs,commas = $3 in SynExpr.StructTuple(List.rev exprs, List.rev commas, (commas.Head, exprs) ||> unionRangeWithListBy (fun e -> e.Range) ), false }
| atomicExprAfterType
{ $1,false }
atomicExprQualification:
| identOrOp
{ let idm = rhs parseState 1
(fun e lhsm dotm -> mkSynDot dotm lhsm e $1) }
| GLOBAL
{ (fun e lhsm dotm ->
reportParseErrorAt (rhs parseState 3) (FSComp.SR.nrGlobalUsedOnlyAsFirstName())
let fixedLhsm = mkRange lhsm.FileName lhsm.Start dotm.End // previous lhsm is wrong after 'recover'
mkSynDotMissing dotm fixedLhsm e) }
| /* empty */
{ (fun e lhsm dotm ->
reportParseErrorAt dotm (FSComp.SR.parsMissingQualificationAfterDot())
let fixedLhsm = mkRange lhsm.FileName lhsm.Start dotm.End // previous lhsm is wrong after 'recover'
mkSynDotMissing dotm fixedLhsm e) }
| recover
{ (fun e lhsm dotm ->
reportParseErrorAt dotm (FSComp.SR.parsMissingQualificationAfterDot())
let fixedLhsm = mkRange lhsm.FileName lhsm.Start dotm.End // previous lhsm is wrong after 'recover'
// Include 'e' in the returned expression but throw it away
SynExpr.DiscardAfterMissingQualificationAfterDot(e,fixedLhsm)) }
| LPAREN COLON_COLON rparen DOT INT32
{ (fun e lhsm dotm ->
libraryOnlyError(lhs parseState)
SynExpr.LibraryOnlyUnionCaseFieldGet (e,mkSynCaseName lhsm opNameCons,(fst $5),lhsm)) }
| LPAREN typedSeqExpr rparen
{ (fun e lhsm dotm ->
mlCompatWarning (FSComp.SR.parsParenFormIsForML()) (lhs parseState)
mkSynDotParenGet lhsm dotm e $2) }
| LBRACK typedSeqExpr RBRACK
{ (fun e lhsm dotm -> mkSynDotBrackGet lhsm dotm e $2) }
| LBRACK typedSeqExpr recover
{ reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnmatchedBracket())
(fun e lhsm dotm -> exprFromParseError (mkSynDotBrackGet lhsm dotm e $2)) }
| LBRACK optRangeSeqExpr RBRACK
{ (fun e lhsm dotm -> mkSynDotBrackSeqSliceGet lhsm dotm e $2) }
| LBRACK optRangeSeqExpr recover
{ reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnmatchedBracket())
(fun e lhsm dotm -> exprFromParseError (mkSynDotBrackSeqSliceGet lhsm dotm e $2)) }
| LBRACK error RBRACK
{ let mArg = rhs2 parseState 1 3
(fun e lhsm dotm -> mkSynDotBrackGet lhsm dotm e (arbExpr("indexerExpr1",mArg))) }
| LBRACK recover
{ reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnmatchedBracket())
let mArg = (rhs parseState 1).EndRange
(fun e lhsm dotm -> exprFromParseError (mkSynDotBrackGet lhsm dotm e (arbExpr("indexerExpr2",mArg)))) }
optRangeSeqExpr:
| optRange COMMA optRangeSeqExpr %prec slice_comma { $1::$3 }
| optRange { [$1] }
optRange:
| declExpr DOT_DOT declExpr
{ SynIndexerArg.Two(mkSynOptionalExpr (rhs parseState 1) (Some $1), mkSynOptionalExpr (rhs parseState 3) (Some $3)) }
| declExpr DOT_DOT
{ SynIndexerArg.Two(mkSynOptionalExpr (rhs parseState 1) (Some $1), mkSynOptionalExpr (rhs parseState 2) None) }
| DOT_DOT declExpr
{ SynIndexerArg.Two(mkSynOptionalExpr (rhs parseState 1) None, mkSynOptionalExpr (rhs parseState 2) (Some $2)) }
| STAR
{ SynIndexerArg.Two(mkSynOptionalExpr (rhs parseState 1) None, mkSynOptionalExpr (rhs parseState 1) None) }
| declExpr %prec slice_expr
{ SynIndexerArg.One($1) }
/* the start et of atomicExprAfterType must not overlap with the valid postfix tokens of the type syntax, e.g. new List<T>(...) */
atomicExprAfterType:
| constant
{ SynExpr.Const ($1,$1.Range (lhs parseState)) }
| parenExpr
{ $1 }
| braceExpr
{ $1 }
| NULL
{ SynExpr.Null(lhs parseState) }
| FALSE
{ SynExpr.Const(SynConst.Bool false,lhs parseState) }
| TRUE
{ SynExpr.Const(SynConst.Bool true,lhs parseState) }
| quoteExpr
{ $1 }
| arrayExpr
{ $1 }
| beginEndExpr
{ $1 }
beginEndExpr:
| BEGIN typedSeqExpr END
{ SynExpr.Paren($2, rhs parseState 1, Some(rhs parseState 3), rhs2 parseState 1 3) }
| BEGIN typedSeqExpr 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 typedSeqExpr RQUOTE
{ if $1 <> $3 then reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsMismatchedQuote(fst $1))
(SynExpr.Quote(mkSynIdGet (lhs parseState) (CompileOpName (fst $1)), snd $1, $2, false, lhs parseState)) }
| LQUOTE typedSeqExpr 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 listExprElements BAR_RBRACK
{ $2 (lhs parseState) true }
| LBRACK_BAR listExprElements recover
{ reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnmatchedBracketBar())
exprFromParseError ($2 (rhs2 parseState 1 2) true) }
| 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 lhsm = unionRangeWithPos (rhs parseState 1) (rhs parseState 3).Start
SynExpr.Paren(exprFromParseError ($2 lhsm), rhs parseState 1, None, lhsm) }
| 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 lhsm = unionRangeWithPos (rhs parseState 1) (rhs parseState 2).Start
arbExpr("parenExpr2tcs", lhsm) }
| LPAREN MODULE_COMING_SOON
{ reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnmatchedParen())
let lhsm = unionRangeWithPos (rhs parseState 1) (rhs parseState 2).Start
arbExpr("parenExpr2mcs", lhsm) }
| LPAREN RBRACE_COMING_SOON
{ reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnmatchedParen())
let lhsm = unionRangeWithPos (rhs parseState 1) (rhs parseState 2).Start
arbExpr("parenExpr2rbcs", lhsm) }
| LPAREN OBLOCKEND_COMING_SOON
{ reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnmatchedParen())
let lhsm = unionRangeWithPos (rhs parseState 1) (rhs parseState 2).Start
arbExpr("parenExpr2obecs", lhsm) }
| 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 lhsm = if $2 then unionRangeWithPos mLeftParen (rhs parseState 2).Start else mLeftParen
//arbExpr("parenExpr2",lhsm) }
parenExprBody:
| staticallyKnownHeadTypars COLON LPAREN classMemberSpfn rparen typedSeqExpr
{ (fun m -> SynExpr.TraitCall($1,$4,$6,m)) } /* disambiguate: x $a.id(x) */
| typedSeqExpr
{ (fun _m -> $1) }
| inlineAssemblyExpr
{ $1 }
staticallyKnownHeadTypars:
| staticallyKnownHeadTypar
{ [$1] }
| LPAREN staticallyKnownHeadTyparAlts rparen
{ List.rev $2 }
staticallyKnownHeadTyparAlts:
| staticallyKnownHeadTyparAlts OR staticallyKnownHeadTypar
{$3 :: $1}
| staticallyKnownHeadTypar
{ [$1] }
braceExpr:
| LBRACE braceExprBody rbrace
{ let m,r = $2 in 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 }
| monadicExprInitial
{ let m,r = $1 in (m, r false) }
listExprElements:
| monadicExprInitial
{ let m,r = $1 in (fun lhsm isArray -> SynExpr.ArrayOrListOfSeqExpr(isArray, r true m, lhsm)) }
|
{ (fun lhsm isArray -> SynExpr.ArrayOrList(isArray,[ ], lhsm)) }
monadicExprInitial:
| seqExpr
{ $1.Range, (fun isArrayOrList lhsm -> SynExpr.CompExpr(isArrayOrList,ref(isArrayOrList),$1,lhsm)) }
| rangeSequenceExpr
{ $1 }
rangeSequenceExpr:
| declExpr DOT_DOT declExpr
{ let opm = (rhs parseState 2)
(unionRanges $1.Range $3.Range),(fun _isArray wholem ->
// in the case of "{ 1 .. 10 }", we want the range of the expression to include the curlies, that comes from a higher level rule in the grammar,
// passed down as 'wholem', so patch up that range here
match (mkSynInfix opm $1 ".." $3) with
| SynExpr.App(a,b,c,d,_) -> SynExpr.App(a,b,c,d,wholem)
| _ -> failwith "impossible") }
| declExpr DOT_DOT declExpr DOT_DOT declExpr
{ (unionRanges $1.Range $5.Range),(fun _isArray wholem -> mkSynTrifix wholem ".. .." $1 $3 $5) }
| declExpr DOT_DOT recover
{ if not $3 then reportParseErrorAt (rhs parseState 3) (FSComp.SR.parsUnexpectedEndOfFileExpression())
let opm = (rhs parseState 2)
let e = arbExpr("rangeSeqError1", (rhs parseState 3).StartRange)
(unionRanges $1.Range e.Range),(fun _isArray wholem ->
// in the case of "{ 1 .. 10 }", we want the range of the expression to include the curlies, that comes from a higher level rule in the grammar,
// passed down as 'wholem', so patch up that range here
match (mkSynInfix opm $1 ".." e) with
| SynExpr.App(a,b,c,d,_) -> SynExpr.App(a,b,c,d,wholem)
| _ -> failwith "impossible") }
arrowThenExprR:
| RARROW typedSeqExprBlockR
{ SynExpr.YieldOrReturn((true,false), $2, unionRanges (rhs parseState 1) $2.Range) }
forLoopBinder:
| parenPattern IN declExpr
{ ($1, $3, true) }
| parenPattern IN rangeSequenceExpr
{ let m,r = $3 in ($1, r false m, true) }
| 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) }
| 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) }
forLoopRange:
| parenPattern EQUALS declExpr forLoopDirection declExpr
{ idOfPat (rhs parseState 1) $1,$3,$4,$5 }
| parenPattern EQUALS rangeSequenceExpr
{ raiseParseErrorAt (rhs parseState 2) (FSComp.SR.parsUnexpectedSymbolEqualsInsteadOfIn()) }
inlineAssemblyExpr:
| HASH stringOrKeywordString opt_inlineAssemblyTypeArg opt_curriedArgExprs opt_inlineAssemblyReturnTypes HASH
{ libraryOnlyWarning (lhs parseState)
let s,sm = $2,rhs parseState 2
(fun m -> SynExpr.LibraryOnlyILAssembly (ParseAssemblyCodeInstructions s sm,$3,List.rev $4,$5,m)) }
opt_curriedArgExprs:
| opt_curriedArgExprs argExpr %prec expr_args
{ $2 :: $1 }
|
{ [] }
opt_atomicExprAfterType:
|
{ None }
| atomicExprAfterType
{ Some($1) }
opt_inlineAssemblyTypeArg:
| { [] }
| typeKeyword LPAREN typ rparen { [$3] }
opt_inlineAssemblyReturnTypes:
|
{ [] }
| COLON typ
{ [$2] }
| COLON LPAREN rparen
{ [] }
recdExpr:
| INHERIT appTypeNonAtomicDeprecated 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 (LongIdentWithDots([], [])) // dummy identifier, it will be discarded
let l = rebindRanges (dummyField, None) l $6
let (_, _, inheritsSep) = List.head l
let bindings = List.tail l
(Some ($2,arg,rhs2 parseState 2 4, inheritsSep, rhs parseState 1), None, bindings) }
| appExpr EQUALS declExprBlock recdExprBindings opt_seps_recd
{ match $1 with
| LongOrSingleIdent(false, (LongIdentWithDots(_,_) as f),None,m) ->
let f = mkRecdField f
let l = List.rev $4
let l = rebindRanges (f, Some $3) l $5
(None, 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, None, [ f, None, None ]) }
| UNDERSCORE EQUALS
{ let m = rhs parseState 1
reportParseErrorAt m (FSComp.SR.parsUnderscoreInvalidFieldName())
let f = mkUnderscoreRecdField m
reportParseErrorAt (rhs2 parseState 1 2) (FSComp.SR.parsFieldBinding())
(None, None, [f, None, None]) }
| UNDERSCORE EQUALS declExprBlock recdExprBindings opt_seps_recd
{ reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnderscoreInvalidFieldName())
let f = mkUnderscoreRecdField (rhs parseState 1)
let l = List.rev $4
let l = rebindRanges (f, Some $3) l $5
(None, 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