Advertisement
Guest User

Untitled

a guest
Jan 23rd, 2018
64
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 15.06 KB | None | 0 0
  1. #!/home/jbw/jbw-cvs/bin/smlnj-script
  2. (*-*-SML-*-*) (* Tell Emacs to use SML mode even though name does not end with \u201c.sml\u201d. *)
  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 \u201cXyzzy\u201d.
  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 \u201cchmod a+rx
  28. * Xyzzy\u201d (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 \u201c#!/usr/bin/env smlnj-script\u201d, then
  34. * \u201csmlnj-script\u201d 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. * \u201c#!/directory/path/to/smlnj-script\u201d, then the path
  39. * \u201c/directory/path/to/smlnj-script\u201d 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 \u201cgit clone
  48. * ssh://MACHINE.macs.hw.ac.uk/~jbw/smlnj-script-git/smlnj-script\u201d
  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 \u201c*SKALPEL-\u201d 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. * BEGIN STUDENT WORK *
  205. * Code implementation of Part 1 by Nasr Herzallah - H00201083 * *
  206. * *************************************************************************** *)
  207.  
  208. val outFile = TextIO.openOut "output.txt"; (* Open output file *)
  209.  
  210. fun printToFile s = TextIO.output (outFile, s); (* Print to output file *)
  211. fun printToFileAndConsole s = (printToFile s; print s); (* Print to output file and console *)
  212. fun printError s = TextIO.output (TextIO.stdErr, s); (* Print error stream *)
  213.  
  214. (* Create tree data structure for representing the mathematical expressions
  215. of integers, pairs of integers and sets of integers *)
  216. datatype DATA = INT of IntInf.int | VAR of (IntInf.int * DATA) | PAIR of (DATA * DATA) | SET of DATA list;
  217.  
  218. (* Create error exception for 'BAD INPUT:' statements*)
  219. exception DataTreeException of string;
  220.  
  221. (* function to print tree data structure to the output file
  222. - covers all parts of tree to avoid errors *)
  223. fun printDataTree (INT i) = printInt i
  224. | printDataTree (VAR v) = printVar v
  225. | printDataTree (PAIR p) = printPair p
  226. | printDataTree (SET s) = let
  227. val () = printToFile "{";
  228. val () = printSet s;
  229. val () = printToFile "}";
  230. in () end
  231.  
  232. and printInt i = let
  233. val () = if i < 0 then printToFile "-" else (); (* Check if number is negative *)
  234. val j = IntInf.abs i; (* Get the absolute value of the integer (positive) *)
  235. in printToFile (IntInf.toString j) end
  236.  
  237. and printVar (i, d) = let
  238. val () = printToFile "Let x";
  239. val () = printToFile (IntInf.toString i); (* Print xi, where i is the variable number *)
  240. val () = printToFile " be ";
  241. val () = printDataTree d;
  242. in () end
  243.  
  244. and printPair (d1, d2) = let
  245. val () = printToFile "(";
  246. val () = printDataTree d1; (* Print first element of pair *)
  247. val () = printToFile ", ";
  248. val () = printDataTree d2; (* Print last element of pair *)
  249. val () = printToFile ")";
  250. in () end
  251.  
  252. and printSet (hd::snd::tl) = let
  253. val () = printDataTree hd; (* Print first element of the set *)
  254. val () = printToFile ", ";
  255. val () = printSet (snd::tl); (* Print the other elements in the set *)
  256. in () end
  257. | printSet (hd::tl) = let
  258. val () = printDataTree hd; (* Loop the rest of the set's elements *)
  259. in () end
  260. | printSet [] = ();
  261.  
  262. (* Function to parse the JSON input file into the tree data structure elements *)
  263. fun JSONToDataTree (data : J.value, node : int) = let
  264. val result = caseJsonMathExp {intFn = JSONToINT, varFn = JSONToVAR, opFn = JSONToOperator, j = data};
  265. in result end
  266.  
  267. and JSONToINT (i : IntInf.int) = INT i (* Parse integer from JSON to INT in datatype *)
  268.  
  269. (* Variables (VAR) not required for part 1 *)
  270. and JSONToVAR (varNum : IntInf.int) = let (* Parse variable from JSON to VAR in datatype *)
  271. val () = raise DataTreeException "Not required for part-1";
  272. in INT 0 end
  273.  
  274. and JSONToOperator {op_name : string, arguments : J.value list} = let
  275. val result = (case op_name of (* Check if operator is pair or set *)
  276. "pair" => JSONToPAIR arguments |
  277. "set" => JSONToSET arguments |
  278. _ => raise DataTreeException "Not required for part-1" (* Other operators not required for part 1 *)
  279. );
  280. in result end
  281.  
  282. and JSONToPAIR arguments = (case arguments (* Parse pair from JSON to PAIR in datatype *)
  283. of [i, j] => PAIR((JSONToDataTree (i, 0)), (JSONToDataTree (j, 0))) (* Create pair *)
  284. | _ => raise DataTreeException "Bad pair!"
  285. )
  286.  
  287. and JSONToSET arguments = let (* Parse set from JSON to SET in datatype *)
  288. fun loop (h::t) = (JSONToDataTree (h, 0))::(loop t)
  289. | loop [] = [];
  290. val set = loop arguments;
  291. in (SET(set)) end;
  292.  
  293. (* Traverse/loop the JSON object from the JSON object list *)
  294. fun traverseJSONObj (dec : J.value, node : int) = let
  295. val (var_num : IntInf.int, exp : J.value) = extractJsonMathDec dec;
  296. val () = printToFile "Let x";
  297. val () = printToFile (IntInf.toString var_num)
  298. val () = printToFile " be ";
  299. val n2 = JSONToDataTree (exp, node + 1)
  300. val () = printDataTree n2;
  301. val () = printToFile " which is ";
  302. val () = printDataTree n2;
  303. val () = printToFile ".\n";
  304. in 2 end; (* random int return *)
  305.  
  306. (* Traverse/loop the JSON list from the parsed json input file *)
  307. fun traverseJSONList list = let
  308. fun loop ((dec : J.value) :: list, node : int) : unit =
  309. loop (list, traverseJSONObj (dec, node))
  310. | loop ([], _) = ();
  311. val () = loop (list, 2);
  312. in () end;
  313.  
  314. (* Load JSON input file, parse it and then traverse it *)
  315. val jsonInput = JSONParser.parseFile "input.json";
  316. val json = extractJsonMathDecList jsonInput;
  317. val () = traverseJSONList json;
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement