@@ -39,7 +39,7 @@ module Parser =
3939
4040 let private isStartAtom ( k : TokenKind ) =
4141 match k with
42- | Ident _ | IntLit _ | FloatLit _ | StringLit _ | InterpString _ | BoolLit _ | LParen | LBracket | LBrace | Hash | Let | Fun | If | Raise | For | Match | Typeof | Nameof -> true
42+ | Ident _ | IntLit _ | FloatLit _ | StringLit _ | InterpString _ | BoolLit _ | LParen | LBracket | LBrace | Let | Fun | If | Raise | For | Match | Typeof | Nameof -> true
4343 | _ -> false
4444
4545 let private isUpperIdent ( name : string ) =
@@ -494,105 +494,107 @@ module Parser =
494494 | LBrace ->
495495 let lb = stream.Next()
496496 if stream.Match( RBrace) then
497- ERecord ([], mkSpanFrom lb.Span lb.Span)
497+ EMap ([], mkSpanFrom lb.Span lb.Span)
498498 else
499- let mark = stream.Mark()
500- let tryRecordUpdate () =
501- let baseExpr = parseExpr()
499+ let mapMark = stream.Mark()
500+ stream.SkipNewlines()
501+ let hasMapIndent = stream.Match( Indent)
502+ stream.SkipNewlines()
503+ if stream.Peek() .Kind = LBracket then
504+ let parseMapEntry () =
505+ stream.Expect( LBracket, " Expected '[' in map entry key" ) |> ignore
506+ let keyExpr = parseExpr()
507+ stream.Expect( RBracket, " Expected ']' after map entry key" ) |> ignore
508+ stream.SkipNewlines()
509+ stream.Expect( Equals, " Expected '=' in map entry" ) |> ignore
510+ let value = parseExpr()
511+ keyExpr, value, ( Ast.spanOfExpr value) .End.Line
512+
502513 stream.SkipNewlines()
503- if not ( stream.Match( With)) then
504- stream.Restore( mark)
505- None
514+ if hasMapIndent && stream.Peek() .Kind = Dedent then
515+ stream.Next() |> ignore
516+
517+ if stream.Peek() .Kind = RBrace then
518+ let rb = stream.Expect( RBrace, " Expected '}' in map literal" )
519+ EMap([], mkSpanFrom lb.Span rb.Span)
506520 else
507- let updates = ResizeArray< string * Expr>()
508- let parseUpdateField () =
509- let nameTok = stream.ExpectIdent( " Expected field name in record update" )
521+ let entries = ResizeArray< Expr * Expr>()
522+ let firstKey , firstValue , firstLine = parseMapEntry()
523+ entries.Add( firstKey, firstValue)
524+
525+ let rec parseTail ( lastEntryEndLine : int ) =
526+ stream.SkipNewlines()
527+ if hasMapIndent && stream.Peek() .Kind = Dedent then
528+ stream.Next() |> ignore
529+ if stream.Peek() .Kind = RBrace then
530+ ()
531+ elif stream.Match( Semicolon) then
532+ stream.SkipNewlines()
533+ if hasMapIndent && stream.Peek() .Kind = Dedent then
534+ stream.Next() |> ignore
535+ if stream.Peek() .Kind = RBrace then
536+ ()
537+ else
538+ let key , value , valueLine = parseMapEntry()
539+ entries.Add( key, value)
540+ parseTail valueLine
541+ else
542+ let next = stream.Peek()
543+ if next.Span.Start.Line > lastEntryEndLine then
544+ let key , value , valueLine = parseMapEntry()
545+ entries.Add( key, value)
546+ parseTail valueLine
547+ else
548+ raise ( ParseException { Message = " Expected ';', newline, or '}' in map literal" ; Span = next.Span })
549+
550+ parseTail firstLine
551+ let rb = stream.Expect( RBrace, " Expected '}' in map literal" )
552+ EMap( entries |> Seq.toList, mkSpanFrom lb.Span rb.Span)
553+ else
554+ stream.Restore( mapMark)
555+ let mark = stream.Mark()
556+ let tryRecordUpdate () =
557+ let baseExpr = parseExpr()
558+ stream.SkipNewlines()
559+ if not ( stream.Match( With)) then
560+ stream.Restore( mark)
561+ None
562+ else
563+ let updates = ResizeArray< string * Expr>()
564+ let parseUpdateField () =
565+ let nameTok = stream.ExpectIdent( " Expected field name in record update" )
566+ let name =
567+ match nameTok.Kind with
568+ | Ident n -> n
569+ | _ -> " "
570+ stream.SkipNewlines()
571+ stream.Expect( Equals, " Expected '=' in record update field" ) |> ignore
572+ let value = parseExpr()
573+ updates.Add( name, value)
574+ parseUpdateField()
575+ while stream.Match( Semicolon) do
576+ parseUpdateField()
577+ let rb = stream.Expect( RBrace, " Expected '}' in record update" )
578+ Some ( ERecordUpdate( baseExpr, updates |> Seq.toList, mkSpanFrom lb.Span rb.Span))
579+ match tryRecordUpdate() with
580+ | Some updateExpr -> updateExpr
581+ | None ->
582+ let fields = ResizeArray< string * Expr>()
583+ let parseField () =
584+ let nameTok = stream.ExpectIdent( " Expected field name in record literal" )
510585 let name =
511586 match nameTok.Kind with
512587 | Ident n -> n
513588 | _ -> " "
514589 stream.SkipNewlines()
515- stream.Expect( Equals, " Expected '=' in record update field" ) |> ignore
590+ stream.Expect( Equals, " Expected '=' in record field" ) |> ignore
516591 let value = parseExpr()
517- updates.Add( name, value)
518- parseUpdateField()
519- while stream.Match( Semicolon) do
520- parseUpdateField()
521- let rb = stream.Expect( RBrace, " Expected '}' in record update" )
522- Some ( ERecordUpdate( baseExpr, updates |> Seq.toList, mkSpanFrom lb.Span rb.Span))
523- match tryRecordUpdate() with
524- | Some updateExpr -> updateExpr
525- | None ->
526- let fields = ResizeArray< string * Expr>()
527- let parseField () =
528- let nameTok = stream.ExpectIdent( " Expected field name in record literal" )
529- let name =
530- match nameTok.Kind with
531- | Ident n -> n
532- | _ -> " "
533- stream.SkipNewlines()
534- stream.Expect( Equals, " Expected '=' in record field" ) |> ignore
535- let value = parseExpr()
536- fields.Add( name, value)
537- parseField()
538- while stream.Match( Semicolon) do
592+ fields.Add( name, value)
539593 parseField()
540- let rb = stream.Expect( RBrace, " Expected '}' in record literal" )
541- ERecord( fields |> Seq.toList, mkSpanFrom lb.Span rb.Span)
542- | Hash ->
543- let hashTok = stream.Next()
544- let lb = stream.Expect( LBrace, " Expected '{' after '#' for map literal" )
545- let mapStart = mkSpanFrom hashTok.Span lb.Span
546- stream.SkipNewlines()
547- let hasIndent = stream.Match( Indent)
548-
549- let parseMapEntry () =
550- let key = parsePostfix()
551- stream.SkipNewlines()
552- stream.Expect( Equals, " Expected '=' in map entry" ) |> ignore
553- let value = parseExpr()
554- key, value, ( Ast.spanOfExpr value) .End.Line
555-
556- stream.SkipNewlines()
557- if hasIndent && stream.Peek() .Kind = Dedent then
558- stream.Next() |> ignore
559-
560- if stream.Peek() .Kind = RBrace then
561- let rb = stream.Expect( RBrace, " Expected '}' in map literal" )
562- EMap([], mkSpanFrom mapStart rb.Span)
563- else
564- let entries = ResizeArray< Expr * Expr>()
565- let firstKey , firstValue , firstLine = parseMapEntry()
566- entries.Add( firstKey, firstValue)
567-
568- let rec parseTail ( lastEntryEndLine : int ) =
569- stream.SkipNewlines()
570- if hasIndent && stream.Peek() .Kind = Dedent then
571- stream.Next() |> ignore
572- if stream.Peek() .Kind = RBrace then
573- ()
574- elif stream.Match( Semicolon) then
575- stream.SkipNewlines()
576- if hasIndent && stream.Peek() .Kind = Dedent then
577- stream.Next() |> ignore
578- if stream.Peek() .Kind = RBrace then
579- ()
580- else
581- let key , value , valueLine = parseMapEntry()
582- entries.Add( key, value)
583- parseTail valueLine
584- else
585- let next = stream.Peek()
586- if next.Span.Start.Line > lastEntryEndLine then
587- let key , value , valueLine = parseMapEntry()
588- entries.Add( key, value)
589- parseTail valueLine
590- else
591- raise ( ParseException { Message = " Expected ';', newline, or '}' in map literal" ; Span = next.Span })
592-
593- parseTail firstLine
594- let rb = stream.Expect( RBrace, " Expected '}' in map literal" )
595- EMap( entries |> Seq.toList, mkSpanFrom mapStart rb.Span)
594+ while stream.Match( Semicolon) do
595+ parseField()
596+ let rb = stream.Expect( RBrace, " Expected '}' in record literal" )
597+ ERecord( fields |> Seq.toList, mkSpanFrom lb.Span rb.Span)
596598 | Let ->
597599 parseLetExpr()
598600 | Fun ->
0 commit comments