Skip to content

Commit

Permalink
Merge pull request #70 from shwestrick/allow-or-pats
Browse files Browse the repository at this point in the history
SuccessorML or-pattern syntax
  • Loading branch information
shwestrick committed Jan 6, 2023
2 parents a3667e2 + 9be42c4 commit 33fc9fd
Show file tree
Hide file tree
Showing 11 changed files with 98 additions and 22 deletions.
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,4 +114,7 @@ not top-level expressions (terminated by a semicolon) are allowed.
SuccessorML optional bar syntax is allowed.

`-allow-record-pun-exps [true|false]` (default `false`) controls whether or not
SuccessorML record punning syntax is allowed.
SuccessorML record punning syntax is allowed.

`-allow-or-pats [true|false]` (default `false`) controls whether or not
SuccessorML or-pattern syntax is allowed.
1 change: 1 addition & 0 deletions src/ast/Ast.sml
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ struct
(case opp of
SOME t => t
| NONE => id)
| Or {elems, ...} => leftMostToken (Seq.nth elems 0)
end

structure Exp =
Expand Down
6 changes: 4 additions & 2 deletions src/ast/AstAllows.sml
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,17 @@
structure AstAllows:
sig
type t
val make: {topExp: bool, optBar: bool, recordPun: bool} -> t
val make: {topExp: bool, optBar: bool, recordPun: bool, orPat: bool} -> t
val topExp: t -> bool
val optBar: t -> bool
val recordPun: t -> bool
val orPat: t -> bool
end =
struct
datatype t = T of {topExp: bool, optBar: bool, recordPun: bool}
datatype t = T of {topExp: bool, optBar: bool, recordPun: bool, orPat: bool}
fun make x = T x
fun topExp (T x) = #topExp x
fun optBar (T x) = #optBar x
fun recordPun (T x) = #recordPun x
fun orPat (T x) = #orPat x
end
4 changes: 4 additions & 0 deletions src/ast/AstType.sml
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,10 @@ struct
, pat: pat
}

(** SuccessorML "or patterns":
* pat | pat | ... | pat *)
| Or of {elems: pat Seq.t, delims: Token.t Seq.t (* `|` between pats *)}

type t = pat
end

Expand Down
6 changes: 3 additions & 3 deletions src/parse/ParseExpAndDec.sml
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ struct
fun parse_tycon i = PS.tycon toks i
fun parse_ty i = PT.ty toks i
fun parse_pat infdict restriction i =
PP.pat toks infdict restriction i
PP.pat allows toks infdict restriction i


fun parse_zeroOrMoreDelimitedByReserved x i =
Expand Down Expand Up @@ -446,7 +446,7 @@ struct
fun parseBranch (*vid*) i =
let
val (i, fname_args) =
ParseFunNameArgs.fname_args toks infdict i
ParseFunNameArgs.fname_args allows toks infdict i

val (i, ty) =
if not (isReserved Token.Colon at i) then
Expand Down Expand Up @@ -721,7 +721,7 @@ struct
fun parse_recordLabel i = PS.recordLabel toks i
fun parse_ty i = PT.ty toks i
fun parse_pat infdict restriction i =
PP.pat toks infdict restriction i
PP.pat allows toks infdict restriction i


fun parse_zeroOrMoreDelimitedByReserved x i =
Expand Down
14 changes: 9 additions & 5 deletions src/parse/ParseFunNameArgs.sml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@ sig
type ('a, 'b) parser = ('a, 'b) ParserCombinators.parser
type tokens = Token.t Seq.t

val fname_args: tokens -> InfixDict.t -> (int, Ast.Exp.fname_args) parser
val fname_args: AstAllows.t
-> tokens
-> InfixDict.t
-> (int, Ast.Exp.fname_args) parser
end =
struct

Expand All @@ -23,7 +26,7 @@ struct
type tokens = Token.t Seq.t


fun fname_args toks infdict i =
fun fname_args allows toks infdict i =
let
val numToks = Seq.length toks
fun tok i = Seq.nth toks i
Expand All @@ -41,7 +44,8 @@ struct
fun continue i =
not (isReserved Token.Colon i orelse isReserved Token.Equal i)
in
PC.zeroOrMoreWhile continue (PP.pat toks infdict Restriction.At) i
PC.zeroOrMoreWhile continue
(PP.pat allows toks infdict Restriction.At) i
end


Expand Down Expand Up @@ -75,13 +79,13 @@ struct
fun infixedFun larg id i =
let
(* val _ = print ("infixedFun\n") *)
val (i, rarg) = PP.pat toks infdict Restriction.At i
val (i, rarg) = PP.pat allows toks infdict Restriction.At i
in
(i, Ast.Exp.InfixedFun {larg = larg, id = id, rarg = rarg})
end


val (i, firstPat) = PP.pat toks infdict Restriction.At i
val (i, firstPat) = PP.pat allows toks infdict Restriction.At i

fun err () =
ParserUtils.error
Expand Down
50 changes: 42 additions & 8 deletions src/parse/ParsePat.sml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
(** Copyright (c) 2020-2021 Sam Westrick
(** Copyright (c) 2020-2023 Sam Westrick
*
* See the file LICENSE for details.
*)
Expand All @@ -8,7 +8,8 @@ sig
type ('a, 'b) parser = ('a, 'b) ParserCombinators.parser
type tokens = Token.t Seq.t

val pat: tokens
val pat: AstAllows.t
-> tokens
-> InfixDict.t
-> ExpPatRestriction.t
-> (int, Ast.Pat.pat) parser
Expand Down Expand Up @@ -59,7 +60,7 @@ struct
end


fun pat toks infdict restriction start =
fun pat allows toks infdict restriction start =
let
val numToks = Seq.length toks
fun tok i = Seq.nth toks i
Expand All @@ -78,6 +79,21 @@ struct
fun parse_ty i = PT.ty toks i

fun consume_pat infdict restriction i =
if not (Restriction.anyOkay restriction andalso AstAllows.orPat allows) then
consume_onePat infdict restriction i
else
let
val (i, {elems, delims}) =
parse_oneOrMoreDelimitedByReserved
{ parseElem = consume_onePat infdict restriction
, delim = Token.Bar
} i
in
if Seq.length elems = 1 then (i, Seq.nth elems 0)
else (i, Ast.Pat.Or {elems = elems, delims = delims})
end

and consume_onePat infdict restriction i =
let
val (i, pat) =
if isReserved Token.Underscore i then
Expand All @@ -96,7 +112,11 @@ struct
consume_patRecord infdict (tok i) (i + 1)
else
ParserUtils.tokError toks
{pos = i, what = "Parser bug!", explain = NONE}
{ pos = i
, what =
"Unexpected token. Expected to see beginning of pattern."
, explain = NONE
}
in
consume_afterPat infdict restriction pat i
end
Expand Down Expand Up @@ -137,7 +157,6 @@ struct
(true, consume_patCon infdict (Ast.Pat.unpackForConPat pat) i)

else if

isReserved Token.Colon i andalso Restriction.anyOkay restriction
then
(true, consume_patTyped infdict pat (tok i) (i + 1))
Expand All @@ -151,6 +170,21 @@ struct
(i + 1)
)

else if
isReserved Token.Bar i andalso Restriction.anyOkay restriction
andalso not (AstAllows.orPat allows)
then
ParserUtils.tokError toks
{ pos = i
, what = "Unexpected '|' after pattern."
, explain = SOME
"This might be the beginning of an \"or-pattern\", written \
\`<pat1> | <pat2> | ...`, which matches any one of multiple \
\patterns. Or-patterns are disallowed in Standard ML, but \
\allowed in SuccessorML. To enable or-patterns, use the \
\command-line argument '-allow-or-pats true'."
}

else
(false, (i, pat))
in
Expand Down Expand Up @@ -252,7 +286,7 @@ struct
*)
and consume_patAs infdict {opp, id, ty} ass i =
let
val (i, pat) = consume_pat infdict Restriction.None i
val (i, pat) = consume_onePat infdict Restriction.None i
in
( i
, Ast.Pat.Layered {opp = opp, id = id, ty = ty, ass = ass, pat = pat}
Expand All @@ -264,7 +298,7 @@ struct
* ^
*)
and consume_patCon infdict {opp, id} i =
let val (i, atpat) = consume_pat infdict Restriction.At i
let val (i, atpat) = consume_onePat infdict Restriction.At i
in (i, Ast.Pat.Con {opp = opp, id = id, atpat = atpat})
end

Expand All @@ -282,7 +316,7 @@ struct
* ^
*)
and consume_patInfix infdict leftPat vid i =
let val (i, rightPat) = consume_pat infdict Restriction.Inf i
let val (i, rightPat) = consume_onePat infdict Restriction.Inf i
in (i, makeInfixPat infdict (leftPat, vid, rightPat))
end

Expand Down
11 changes: 11 additions & 0 deletions src/prettier-print/PrettierPat.sml
Original file line number Diff line number Diff line change
Expand Up @@ -116,5 +116,16 @@ struct

| Infix {left, id, right} =>
showPat tab left ++ token id ++ withNewChild showPat tab right

| Or {elems, delims} =>
newTab tab (fn tab =>
let
fun f (d, p) =
at tab (token d) ++ withNewChild showPat tab p

val front = at tab (showPat tab (Seq.nth elems 0))
in
Seq.iterate op++ front (Seq.zipWith f (delims, Seq.drop elems 1))
end)
end
end
2 changes: 2 additions & 0 deletions src/pretty-print/PrettyPat.sml
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ struct
]
| Infix {left, id, right} =>
showPat left ++ space ++ token id ++ space ++ showPat right

| Or _ => recordPunFail ()
end

end
7 changes: 7 additions & 0 deletions src/pretty-print/PrettyUtil.sml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,13 @@ struct
\deprecation. Please use `-engine prettier` instead, \
\which supports record punning."

fun orPatFail () =
raise Fail
"unsupported: SuccessorML or-pattern syntax. Note: you are \
\using `-engine pretty`, which is headed towards \
\deprecation. Please use `-engine prettier` instead, \
\which supports or-pattern."

fun seqWithSpaces elems f =
if Seq.length elems = 0 then
empty
Expand Down
14 changes: 11 additions & 3 deletions src/smlfmt.sml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ val optionalArgDesc =
\ Valid options are: true, false\n\
\ (default 'false')\n\
\\n\
\ [-allow-or-pats B] Enable/disable SuccessorML or-pattern syntax.\n\
\ Valid options are: true, false\n\
\ (default 'false')\n\
\\n\
\ [--help] print this message\n"


Expand All @@ -68,16 +72,20 @@ val inputfiles = CommandLineArgs.positional ()
val allowTopExp = CommandLineArgs.parseBool "allow-top-level-exps" true
val allowOptBar = CommandLineArgs.parseBool "allow-opt-bar" false
val allowRecordPun = CommandLineArgs.parseBool "allow-record-pun-exps" false
val allowOrPat = CommandLineArgs.parseBool "allow-or-pats" false
val doDebug = CommandLineArgs.parseFlag "debug-engine"
val doForce = CommandLineArgs.parseFlag "force"
val doHelp = CommandLineArgs.parseFlag "help"
val preview = CommandLineArgs.parseFlag "preview"
val previewOnly = CommandLineArgs.parseFlag "preview-only"
val showPreview = preview orelse previewOnly

val allows =
AstAllows.make
{topExp = allowTopExp, optBar = allowOptBar, recordPun = allowRecordPun}
val allows = AstAllows.make
{ topExp = allowTopExp
, optBar = allowOptBar
, recordPun = allowRecordPun
, orPat = allowOrPat
}

val _ =
if doHelp orelse List.null inputfiles then
Expand Down

0 comments on commit 33fc9fd

Please sign in to comment.