Skip to content

Commit

Permalink
bugfix: errors at eof (fixes #19)
Browse files Browse the repository at this point in the history
  • Loading branch information
shwestrick committed Sep 26, 2021
1 parent 3e64571 commit 3bd4a65
Show file tree
Hide file tree
Showing 17 changed files with 97 additions and 61 deletions.
9 changes: 6 additions & 3 deletions src/base/Error.sml
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,13 @@ struct
val {line=lineNum, col=colStart} = Source.absoluteStart pos
val {line=lineNum', col=colEnd} = Source.absoluteEnd pos
val _ =
if lineNum = lineNum' then ()
if lineNum = lineNum' orelse colEnd = 1 then ()
else raise Fail "ErrorReport.show: end of position past end of line"

val startOffset = Source.absoluteStartOffset pos
val stopOffset = Source.absoluteEndOffset pos
val pointyLen = stopOffset - startOffset

val line = Source.wholeLine pos lineNum

val lineNumStr = Int.toString lineNum
Expand All @@ -99,7 +103,6 @@ struct
val leftMargin = lineNumStr ^ " | "

val colOffset = colStart-1
val highlightLen = colEnd - colStart

val leftSpaces =
spaces (String.size leftMargin + colOffset)
Expand Down Expand Up @@ -130,7 +133,7 @@ struct
[ filestyle ($ (spaces marginSize ^ "| "))
, $ (spaces (colOffset + numTabsBefore))
, TCS.bold (TCS.foreground brightred
($ (TextFormat.repeatChar highlightLen #"^")))
($ (TextFormat.repeatChar pointyLen #"^")))
]
(* , spaces marginSize ^ "|" *)
]
Expand Down
37 changes: 20 additions & 17 deletions src/parse/ParseExpAndDec.sml
Original file line number Diff line number Diff line change
Expand Up @@ -356,8 +356,8 @@ struct
else if isReserved Token.Abstype at i then
consume_decAbstype (tok i) (i+1, infdict)
else
ParserUtils.error
{ pos = Token.getSource (tok i)
ParserUtils.tokError toks
{ pos = i
, what = "Unexpected token."
, explain = SOME "Expected to see the beginning of a declaration."
}
Expand Down Expand Up @@ -600,8 +600,8 @@ struct

val result =
if Seq.length elems = 0 then
ParserUtils.error
{ pos = Token.getSource (tok i)
ParserUtils.tokError toks
{ pos = i
, what = "Unexpected token. Missing identifier."
, explain = NONE
}
Expand Down Expand Up @@ -639,8 +639,8 @@ struct

val result =
if Seq.length elems = 0 then
ParserUtils.error
{ pos = Token.getSource (tok i)
ParserUtils.tokError toks
{ pos = i
, what = "Unexpected token. Missing identifier."
, explain = NONE
}
Expand Down Expand Up @@ -796,8 +796,8 @@ struct
if Restriction.anyOkay restriction then
consume_expIfThenElse infdict (tok i) (i+1)
else
ParserUtils.error
{ pos = Token.getSource (tok i)
ParserUtils.tokError toks
{ pos = i
, what = "Unexpected if-then-else expression."
, explain = SOME "Try using parentheses: (if ... then ... else ...)"
}
Expand All @@ -806,8 +806,8 @@ struct
if Restriction.anyOkay restriction then
consume_expRaise infdict (i+1)
else
ParserUtils.error
{ pos = Token.getSource (tok i)
ParserUtils.tokError toks
{ pos = i
, what = "Unexpected raise exception."
, explain = SOME "Try using parentheses: (raise ...)"
}
Expand All @@ -816,8 +816,8 @@ struct
if Restriction.anyOkay restriction then
consume_expFn infdict (i+1)
else
ParserUtils.error
{ pos = Token.getSource (tok i)
ParserUtils.tokError toks
{ pos = i
, what = "Unexpected beginning of anonymous function."
, explain = SOME "Try using parentheses: (fn ... => ...)"
}
Expand All @@ -826,8 +826,8 @@ struct
if Restriction.anyOkay restriction then
consume_expWhile infdict (i+1)
else
ParserUtils.error
{ pos = Token.getSource (tok i)
ParserUtils.tokError toks
{ pos = i
, what = "Unexpected beginning of while-loop."
, explain = SOME "Try using parentheses: (while ... do ...)"
}
Expand All @@ -836,8 +836,8 @@ struct
consume_expAfterUnderscore infdict restriction (tok i) (i+1)

else
ParserUtils.error
{ pos = Token.getSource (tok i)
ParserUtils.tokError toks
{ pos = i
, what = "Unexpected token."
, explain = SOME "Expected beginning of expression."
}
Expand Down Expand Up @@ -1336,7 +1336,10 @@ struct
val lett = tok (i-1)
val ((i, infdict), dec) = consume_dec (i, infdict)
val (i, inn) = parse_reserved Token.In i
handle Error.Error _ =>
handle Error.Error e =>
if i >= numToks then
raise Error.Error e
else
raise Error.Error
{ header = "PARSE ERROR"
, content =
Expand Down
12 changes: 6 additions & 6 deletions src/parse/ParsePat.sml
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,8 @@ struct
else if isReserved Token.OpenCurlyBracket i then
consume_patRecord infdict (tok i) (i+1)
else
ParserUtils.error
{ pos = Token.getSource (tok i)
ParserUtils.tokError toks
{ pos = i
, what = "Parser bug!"
, explain = NONE
}
Expand Down Expand Up @@ -211,8 +211,8 @@ struct
if isReserved Token.CloseCurlyBracket (i+1) then
(i+1, Ast.Pat.DotDotDot (tok i))
else
ParserUtils.error
{ pos = Token.getSource (tok i)
ParserUtils.tokError toks
{ pos = i
, what = "Unexpected token."
, explain = SOME "This can only appear at the end of the record."
}
Expand Down Expand Up @@ -265,8 +265,8 @@ struct
)
end
else
ParserUtils.error
{ pos = Token.getSource (tok i)
ParserUtils.tokError toks
{ pos = i
, what = "Invalid token. Expected row of record pattern."
, explain = NONE
}
Expand Down
4 changes: 2 additions & 2 deletions src/parse/ParseSigExpAndSpec.sml
Original file line number Diff line number Diff line change
Expand Up @@ -680,8 +680,8 @@ struct
else if isReserved Token.Include i then
consume_sigSpecInclude (i+1)
else
ParserUtils.error
{ pos = Token.getSource (tok i)
ParserUtils.tokError toks
{ pos = i
, what = "Unexpected token."
, explain = SOME "Expected element of signature."
}
Expand Down
44 changes: 22 additions & 22 deletions src/parse/ParseSimple.sml
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@ struct
if isReserved toks rc i then
(i+1, Seq.nth toks i)
else
ParserUtils.error
{ pos = Token.getSource (Seq.nth toks i)
ParserUtils.tokError toks
{ pos = i
, what =
"Unexpected token. Expected to see "
^ "'" ^ Token.reservedToString rc ^ "'"
Expand All @@ -70,8 +70,8 @@ struct
if check toks Token.isTyVar i then
(i+1, Seq.nth toks i)
else
ParserUtils.error
{ pos = Token.getSource (Seq.nth toks i)
ParserUtils.tokError toks
{ pos = i
, what = "Expected tyvar."
, explain = NONE
}
Expand All @@ -81,8 +81,8 @@ struct
if check toks Token.isStrIdentifier i then
(i+1, Seq.nth toks i)
else
ParserUtils.error
{ pos = Token.getSource (Seq.nth toks i)
ParserUtils.tokError toks
{ pos = i
, what = "Expected structure identifier."
, explain = SOME "Must be alphanumeric, and cannot start with a\
\ prime (')"
Expand All @@ -93,8 +93,8 @@ struct
if check toks Token.isStrIdentifier i then
(i+1, Seq.nth toks i)
else
ParserUtils.error
{ pos = Token.getSource (Seq.nth toks i)
ParserUtils.tokError toks
{ pos = i
, what = "Expected signature identifier."
, explain = SOME "Must be alphanumeric, and cannot start with a\
\ prime (')"
Expand All @@ -105,8 +105,8 @@ struct
if check toks Token.isStrIdentifier i then
(i+1, Seq.nth toks i)
else
ParserUtils.error
{ pos = Token.getSource (Seq.nth toks i)
ParserUtils.tokError toks
{ pos = i
, what = "Expected functor identifier."
, explain = SOME "Must be alphanumeric, and cannot start with a\
\ prime (')"
Expand All @@ -117,8 +117,8 @@ struct
if check toks Token.isValueIdentifier i then
(i+1, Seq.nth toks i)
else
ParserUtils.error
{ pos = Token.getSource (Seq.nth toks i)
ParserUtils.tokError toks
{ pos = i
, what = "Unexpected token. Expected value identifier."
, explain = NONE
}
Expand All @@ -128,8 +128,8 @@ struct
if check toks Token.isMaybeLongIdentifier i then
(i+1, MaybeLongToken.make (Seq.nth toks i))
else
ParserUtils.error
{ pos = Token.getSource (Seq.nth toks i)
ParserUtils.tokError toks
{ pos = i
, what = "Expected (possibly long) value identifier."
, explain = NONE
}
Expand All @@ -138,8 +138,8 @@ struct
if check toks Token.isRecordLabel i then
(i+1, Seq.nth toks i)
else
ParserUtils.error
{ pos = Token.getSource (Seq.nth toks i)
ParserUtils.tokError toks
{ pos = i
, what = "Expected record label."
, explain = NONE
}
Expand All @@ -149,8 +149,8 @@ struct
if check toks Token.isTyCon i then
(i+1, Seq.nth toks i)
else
ParserUtils.error
{ pos = Token.getSource (Seq.nth toks i)
ParserUtils.tokError toks
{ pos = i
, what = "Unexpected token. Invalid type constructor."
, explain = NONE
}
Expand All @@ -160,8 +160,8 @@ struct
if check toks Token.isMaybeLongTyCon i then
(i+1, MaybeLongToken.make (Seq.nth toks i))
else
ParserUtils.error
{ pos = Token.getSource (Seq.nth toks i)
ParserUtils.tokError toks
{ pos = i
, what = "Unexpected token. Invalid (possibly qualified)\
\ type constructor."
, explain = NONE
Expand All @@ -172,8 +172,8 @@ struct
if check toks Token.isMaybeLongStrIdentifier i then
(i+1, MaybeLongToken.make (Seq.nth toks i))
else
ParserUtils.error
{ pos = Token.getSource (Seq.nth toks i)
ParserUtils.tokError toks
{ pos = i
, what = "Unexpected token. Invalid (possibly qualified)\
\ structure identifier."
, explain = NONE
Expand Down
12 changes: 6 additions & 6 deletions src/parse/ParseTy.sml
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,8 @@ struct
}
)
else
ParserUtils.error
{ pos = Token.getSource (tok i)
ParserUtils.tokError toks
{ pos = i
, what = "Parser bug!"
, explain = NONE
}
Expand Down Expand Up @@ -201,8 +201,8 @@ struct
parse_tyParensOrSequence leftParen (ty :: tys) (comma :: delims) i
end
else
ParserUtils.error
{ pos = Token.getSource (tok i)
ParserUtils.tokError toks
{ pos = i
, what = "Unexpected token."
, explain = NONE
}
Expand Down Expand Up @@ -244,8 +244,8 @@ struct
}
)
else
ParserUtils.error
{ pos = Token.getSource (tok i)
ParserUtils.tokError toks
{ pos = i
, what = "Unexpected token."
, explain = SOME "Expected to see a type constructor."
}
Expand Down
8 changes: 4 additions & 4 deletions src/parse/Parser.sml
Original file line number Diff line number Diff line change
Expand Up @@ -250,8 +250,8 @@ struct
consume_strexpLetInEnd infdict (tok i) (i+1)

else
ParserUtils.error
{ pos = Token.getSource (tok i)
ParserUtils.tokError toks
{ pos = i
, what = "Unexpected token."
, explain = SOME "Expected structure expression."
}
Expand Down Expand Up @@ -590,8 +590,8 @@ struct
((i, infdict), Ast.StrDec strdec)
end
else
ParserUtils.error
{ pos = Token.getSource (tok i)
ParserUtils.tokError toks
{ pos = i
, what = "Unexpected token."
, explain = SOME "Invalid start of top-level declaration."
}
Expand Down
23 changes: 22 additions & 1 deletion src/parse/ParserUtils.sml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@

structure ParserUtils:
sig
val error: {what: string, pos: Source.t, explain: string option} -> 'a
val error: {pos: Source.t, what: string, explain: string option} -> 'a
val tokError:
Token.t Seq.t -> {pos: int, what: string, explain: string option} -> 'a

val errorIfInfixNotOpped: InfixDict.t -> Token.t option -> Token.t -> unit

Expand All @@ -21,6 +23,25 @@ struct
, explain = explain
})

fun tokError toks {what, pos, explain} =
if pos >= Seq.length toks then
let
val wholeSrc = Source.wholeFile (Token.getSource (Seq.nth toks 0))
val src = Source.drop wholeSrc (Source.length wholeSrc - 1)
in
error
{ pos = src
, what = "Unexpected end of file."
, explain = NONE
}
end
else
error
{ pos = Token.getSource (Seq.nth toks pos)
, what = what
, explain = explain
}

fun errorIfInfixNotOpped infdict opp vid =
if InfixDict.isInfix infdict vid andalso not (Option.isSome opp) then
error
Expand Down
1 change: 1 addition & 0 deletions test/fail/unexpected-eof-10.sml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
structure X: sig end = struct
1 change: 1 addition & 0 deletions test/fail/unexpected-eof-2.sml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
val _ = let
1 change: 1 addition & 0 deletions test/fail/unexpected-eof-3.sml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
structure
1 change: 1 addition & 0 deletions test/fail/unexpected-eof-4.sml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
functor
1 change: 1 addition & 0 deletions test/fail/unexpected-eof-5.sml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
functor F
Loading

0 comments on commit 3bd4a65

Please sign in to comment.