Advertisement
Guest User

Untitled

a guest
Jan 23rd, 2018
105
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #!/home/jbw/jbw-cvs/bin/smlnj-script
  2. (*-*-SML-*-*) (* Tell Emacs to use SML mode even though name does not end with “.sml”. *)
  3. (* #!/usr/bin/env smlnj-script *) (* This is better 1st line if smlnj-script is in your PATH. *)
  4.  
  5. (* Author of template portion: Joe Wells *)
  6.  
  7. (* STUDENT'S SOURCE CODE MUST HAVE A STATEMENT (INCLUDING THEIR NAME) OF WHAT PORTION THEY HAVE AUTHORED!!! *)
  8.  
  9. (**********************************************************************
  10.  * INSTRUCTIONS FOR USING THIS FILE
  11.  * (DELETE THIS COMMENT AFTER UNDERSTANDING IT.)
  12.  *
  13.  * These instructions assume this file is named Xyzzy.  When reading
  14.  * these instructions, replace Xyzzy in your mind by the actual file
  15.  * name.
  16.  *
  17.  * This is an SML/NJ _*script*_.  You do not need to compile it.  It
  18.  * should be runnable as is.  This means if this file is in the
  19.  * current directory, you should be able to type ./Xyzzy at a shell
  20.  * command prompt and this program will run.  If you put this file in
  21.  * one of the directories listed in your PATH environment variable,
  22.  * then you can run this by just typing “Xyzzy”.
  23.  *
  24.  * There are a few things that can go wrong, and here is a short guide
  25.  * to how to fix them:
  26.  *
  27.  * 1. The permissions on this file might be wrong.  Do “chmod a+rx
  28.  *    Xyzzy” (assuming you own the file).
  29.  *
  30.  * 2. smlnj-script might not be installed anywhere on the computer you
  31.  *    are using.  Install it.
  32.  *
  33.  * 3. If the first line reads “#!/usr/bin/env smlnj-script”, then
  34.  *    “smlnj-script” might not be in any of the directories found via
  35.  *    your PATH environment variable.  Fix your PATH.
  36.  *
  37.  *    Alternatively, if the first line is of the form
  38.  *    “#!/directory/path/to/smlnj-script”, then the path
  39.  *    “/directory/path/to/smlnj-script” might be the wrong path to
  40.  *    smlnj-script.  Fix it.
  41.  *
  42.  * Fuller instructions for smlnj-script can be found in the README
  43.  * file in the smlnj-script git repository.  As of 2016-01, you can
  44.  * find a copy of this repository at
  45.  * /home/jbw/smlnj-script-git/smlnj-script on the UNIX NFS file
  46.  * systems of the Heriot-Watt University Computer Science department.
  47.  * Do “git clone
  48.  * ssh://MACHINE.macs.hw.ac.uk/~jbw/smlnj-script-git/smlnj-script”
  49.  * (where you must replace MACHINE by the name of some machine that
  50.  * works, e.g., linux01 worked for me) to get your own copy of this
  51.  * repository.
  52.  **********************************************************************)
  53.  
  54. (* *************************)
  55. (*** support for debugging *)
  56. (* *************************)
  57.  
  58. (* Comments that begin with “*SKALPEL-” help Skalpel, a tool for SML type errors. *)
  59. (* Semicolons after Skalpel magic comments are needed by Skalpel. *)
  60. (**SKALPEL-USE-FILE /home/jbw/smlnj-script-git/smlnj-script/smlnj-script-for-skalpel.sml *);
  61.  
  62. val () = U.raisePrintingLimitsToMax (); (* Comment to hide details in compiler messages. *)
  63.  
  64. (* val () = U.interact (); *) (* Move this to where you want to enter interactive mode and uncomment. *)
  65.  
  66. val () = silenceCompiler (); (* Because next 3 function calls print a lot. *)
  67.  
  68. (* These two help you avoid shooting yourself in the foot. *)
  69. val () = Student.strongerPatternErrorsAndWarnings ();
  70. val () = Student.disableBadPartialFunctions ();
  71.  
  72. (* This helps you avoid getting a lower mark by violating the prohibition on string building. *)
  73. val () = Student.disableStringBuilding ();
  74.  
  75. val () = U.clearCompilerOutputStash ();
  76.  
  77. val () = unsilenceCompiler (); (* Comment when your script is finally completely working. *)
  78.  
  79. (* *********************************************************************)
  80. (*** utilities for processing mathematical definitions encoded in JSON *)
  81. (* *********************************************************************)
  82.  
  83. structure J = JSON;
  84.  
  85. (* The JSON structure represents JSON objects as association lists.  Parse results are not
  86. guaranteed to have object fields in any particular order.  Because this makes pattern matching
  87. tedious, the sortJsonFields function is used to sort the JSON object fields.  This also will help
  88. with detecting bad JSON having two fields with the same name (which I suspect the JSON structure
  89. allows). *)
  90. fun 'value sortJsonFields (fields : (string * 'value) list) : (string * 'value) list =
  91.     ListMergeSort.sort (fn ((key1,value1),(key2,value2)) =>
  92.                            U.isGreater (String.compare (key1,key2)))
  93.                        fields;
  94.  
  95. (* Error exceptions have (string list) rather than string so as to abide by the prohibition of
  96. run-time string building *)
  97. exception BadJsonMath of J.value * (string list);
  98. exception BadVariableName of string list;
  99.  
  100. (* Identifies which operators are allowed and how many arguments each expects. *)
  101. val operatorArgSpecs : (string * (int option)) list =
  102.     List.concat
  103.         (map (fn (argSpec, operList) =>
  104.                  (map (fn oper => (oper, argSpec))
  105.                       operList))
  106.              [(SOME 1, ["domain", "inverse", "is-function"]),
  107.               (SOME 2, ["pair", "apply-function", "equal", "member", "function-space", "union"]),
  108.               (SOME 4, ["diagonalize"]),
  109.               (NONE, ["set"])]);
  110.  
  111. (* Enforces the rules for valid variable names and converts them to integers. *)
  112. fun parseVariableName (varName : string) : IntInf.int =
  113.     case String.explode varName
  114.      of #"x" :: #"0" :: _ :: _ =>
  115.         raise (BadVariableName ["purported variable name contains character(s) after x0: ",
  116.                                 varName])
  117.       | #"x" :: digits =>
  118.         foldl (fn (c as (#"0"|(#"1")|(#"2")|(#"3")|(#"4")|(#"5")|(#"6")|(#"7")|(#"8")|(#"9")),
  119.                    num : IntInf.int)
  120.                   => (num * 10) + (IntInf.fromInt (Char.ord c - Char.ord #"0"))
  121.               | _ =>
  122.                 raise (BadVariableName
  123.                            ["purported variable name contains non-digit after the first position: ",
  124.                             varName]))
  125.               (0 : IntInf.int)
  126.               digits
  127.       | _ :: _ => raise (BadVariableName ["purported variable name does not start with x: ",
  128.                                           varName])
  129.       | nil => raise (BadVariableName ["purported variable name is empty string"]);
  130.  
  131. (* Detects whether a JSON.value is a valid representation of a mathematical expression and if it
  132. is calls one of the 3 functions it is supplied for the different cases. *)
  133. fun ('result)
  134.     caseJsonMathExp
  135.         {intFn : IntInf.int                                   -> 'result,
  136.          opFn  : {op_name : string, arguments : J.value list} -> 'result,
  137.          varFn : IntInf.int                                   -> 'result,
  138.          j     : J.value}
  139.     : 'result =
  140.     case j
  141.      of (J.INT i) => intFn i
  142.       | (J.OBJECT fields) =>
  143.         (case sortJsonFields fields
  144.           of [("variable", J.STRING varName)] =>
  145.              varFn (parseVariableName varName)
  146.            | [("variable", _)] =>
  147.              raise (BadJsonMath (j, ["JSON object does not represent a variable reference: ",
  148.                                      "the contents of its field is not a string"]))
  149.            | [("arguments", J.ARRAY args),
  150.               ("operator", J.STRING operName)] => let
  151.                val numArgs : int = length args
  152.                val maybeArgSpec : int option option =
  153.                    Option.map (# 2) (List.find (fn (operName2, argSpec) =>
  154.                                                    operName2 = operName)
  155.                                                operatorArgSpecs)
  156.                val () =
  157.                    case maybeArgSpec
  158.                     of NONE =>
  159.                        raise (BadJsonMath (j, ["JSON object does not represent a math expression: ",
  160.                                                "bad operator name: ", operName]))
  161.                      | SOME NONE => ()
  162.                      | SOME (SOME requiredNumArgs) =>
  163.                        if requiredNumArgs = numArgs
  164.                        then ()
  165.                        else raise (BadJsonMath
  166.                                        (j, ["JSON object does not represent a math expression: ",
  167.                                             "operator ",operName," requires ",
  168.                                             Int.toString requiredNumArgs,
  169.                                             " arguments but got ",Int.toString numArgs]))
  170.              in opFn {op_name = operName, arguments = args} end
  171.            | [("arguments", J.ARRAY _),
  172.               ("operator", _)] =>
  173.              raise (BadJsonMath (j, ["JSON object does not represent an operation: ",
  174.                                      "the contents of its operator field is not a string"]))
  175.            | [("arguments", _),
  176.               ("operator", J.STRING _)] =>
  177.              raise (BadJsonMath (j, ["JSON object does not represent an operation: ",
  178.                                      "the contents of its arguments field is not an array"]))
  179.            | _ => raise (BadJsonMath (j, ["JSON object does not represent a math expression: ",
  180.                                           "wrong fields"])))
  181.       | _ => raise (BadJsonMath (j, ["JSON value does not represent a math expression: ",
  182.                                      "neither integer nor object"]));
  183.  
  184. (* Detects whether a JSON.value is a valid representation of a mathematical definition and if it
  185. is extracts the variable and the JSON representing what the variable is being defined to be. *)
  186. fun extractJsonMathDec (j as J.OBJECT fields) =
  187.     (case sortJsonFields fields
  188.       of [("declared-variable", J.STRING var),
  189.           ("value", exp)] =>
  190.          (parseVariableName var, exp)
  191.        | _ => raise (BadJsonMath (j, ["JSON object does not represent a math declaration: ",
  192.                                       "wrong fields or declared-variable not a string"])))
  193.   | extractJsonMathDec j =
  194.     raise (BadJsonMath (j, ["JSON value does not represent a math declaration: not an object"]));
  195.  
  196. (* Detects whether a JSON.value is a valid representation of a list of mathematical definitions
  197. and if it is extracts the list. *)
  198. fun extractJsonMathDecList (J.OBJECT [("declaration-list", J.ARRAY decs)]) = decs
  199.   | extractJsonMathDecList j =
  200.     raise (BadJsonMath (j, ["JSON value does not represent a math declaration list: ",
  201.                             "not an object or object with wrong fields"]));
  202.  
  203. (* ********************)
  204. (*** output utilities *)
  205. (* ********************)
  206.  
  207. val outFile = TextIO.openOut "output.txt";
  208.  
  209. fun printToFile s = TextIO.output (outFile, s);
  210. fun printToFileAndConsole s = (printOut s; print s);
  211. fun printError s = TextIO.output (TextIO.stdErr, s);
  212.  
  213. (* *************************************************************************** *
  214.  * Code implementation of Part 1 by Nasr Herzallah - H00......                 *                                                                          *
  215.  * *************************************************************************** *)
  216.  
  217. datatype DATA = INT of IntInf.int | VAR of (IntInf.int * DATA) | PAIR of (DATA * DATA) | SET of DATA list;
  218.  
  219. exception DataTreeException of string;
  220.  
  221. fun printDataTree (INT i) = printInt i
  222.   | printDataTree (VAR v) = printVar v
  223.   | printDataTree (PAIR p) = printPair p
  224.   | printDataTree (SET s) = let
  225.         val () = printToFile "{";
  226.         val () = printSet s;
  227.         val () = printToFile "}";
  228.     in () end
  229.  
  230. and printInt i = let
  231.         val () = if i < 0 then printToFile "-" else (); (* Check if number is negative *)
  232.         val j = IntInf.abs i; (* Get the absolute value of the integer (positive) *)
  233.     in printToFile (IntInf.toString newInt) end
  234.  
  235. and printVar (i, d) = let
  236.         val () = printToFile "Let x";
  237.         val () = printToFile (IntInf.toString i);
  238.         val () = printToFile " be ";
  239.         val () = printDataTree d;
  240.     in () end
  241.  
  242. and printPair (d1, d2) = let
  243.         val () = printToFile "(";
  244.         val () = printDataTree d1;
  245.         val () = printToFile ", ";
  246.         val () = printDataTree d2;
  247.         val () = printToFile ")";
  248.     in () end
  249.  
  250. and printSet (hd::snd::tl) = let
  251.         val () = printDataTree hd;
  252.         val () = printToFile ", ";
  253.         val () = printSet (snd::tl); (* Loop the rest of the list *)
  254.     in () end
  255.   | printSet (hd::tl) = let
  256.         val () = printDataTree hd;
  257.     in () end
  258.   | printSet [] = ();
  259.  
  260. fun JSONToDataTree (data : J.value, node : int) = let
  261.         val result = caseJsonMathExp {intFn = JSONToINT, varFn = JSONToVAR, opFn = traverseOp, j = data};
  262.     in result end
  263.  
  264. and JSONToINT (i : IntInf.int) = INT i
  265.  
  266. and JSONToVAR (varNum : IntInf.int) = let
  267.         val () = raise DataTreeException "Not required for part-1";
  268.     in INT 0 end
  269.  
  270. and JSONToOperator {op_name : string, arguments : J.value list} = let
  271.         val result = (case op_name of
  272.                         "pair" => JSONToPAIR {arguments = arguments} |
  273.                         "set" => JSONToSET {arguments = arguments} |
  274.                         _ => raise DataTreeException "Not required for part-1";
  275.                      )
  276.     in result end
  277.  
  278. and JSONToPAIR {arguments} = (case arguments
  279.             of [i, j] => let
  280.                     val args
  281.                 in PAIR((JSONToDataTree ..?), (JSONToDataTree ..?))
  282.              | _ => raise DataTreeException "Bad variable name!";
  283.         )
  284.  
  285. and JSONToSET {arguments} = let
  286.         (*fun loop vars (h::t) = (JSONToDataTree ..?)...*)
  287.         (* what the fuck *)
  288.         (* val set = loop ... *)
  289.     in (SET([])) end; (* replace [] with set *)
  290.  
  291. fun traverseJSONObj (dec : J.value, node : int) = let
  292.         val (var_num : IntInf.int, exp : J.value) = extractJsonMathDec dec;
  293.         val () = printToFile "Let x";
  294.         val () = printToFile (IntInf.toString var_num)
  295.         val () = printToFile " be ";
  296.         val n2 : int = JSONToDataTree (exp, node + 1)
  297.         val () = printDataTree n2;
  298.         val () = printToFile " which is ";
  299.         val () = printDataTree n2;
  300.         val () = printToFile ".\n";
  301.     in 2 end; (* random int return *)
  302.  
  303. fun traverseJSONList list = let
  304.     fun loop ((dec : J.value) :: decs, node : int) : unit =
  305.             loop (decs, traverseJSONObj (dec, node))
  306.       | loop ([], _) = ();
  307.     val () = loop (decs, 2);
  308. in () end;
  309.  
  310. val jsonInput = JSONParser.parseFile "input.json";
  311. val json = extractJsonMathDecList jsonInput;
  312. val () = traverseJSONList decs;
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement