This file contains definitions for the OCaml type THING, and the OCaml module
SCANNER, both of which are needed to write the module PARSER for Project 2.
Copyright By PowCoder代写 加微信 powcoder
(* THING. Types of the usual Lisp objects. *)
Closure of thing * thing * environment |
Cons of thing * thing |
Number of int |
Primitive of (thing -> environment -> thing) |
Symbol of string
environment = (string * thing) list ;;
(* SCANNER. Lexical scanner for Lisp from Lab 9. It also ignores comments. *)
module Scanner =
(* TOKEN. A token for an expression in a subset of Lisp. *)
type token =
CloseParenToken |
EndToken |
NumberToken of int |
OpenParenToken |
SymbolToken of string ;;
(* MAKE SCANNER. Return a version of the scanner function NEXT TOKEN that reads
TOKENs from a file whose pathname is the string PATH. INPUT is a channel
connected to the file. CH holds the most recently read CHAR from INPUT. *)
let makeScanner path =
let input = open_in path
in let ch = ref ‘ ‘
(* NEXT CHAR. Advance CH to the next CHAR from INPUT. If there is no next CHAR,
then set CH to ‘\000’. We use this CHAR to represent the end of a file. We’d
like to give this CHAR a name, but then we couldn’t MATCH on that name. *)
let nextChar () =
try ch := input_char input
with End_of_file ->
ch := ‘\000’
(* NEXT CLOSE PAREN TOKEN. Read a CLOSE PAREN TOKEN. *)
let nextCloseParenToken () =
nextChar () ;
CloseParenToken
(* NEXT COMMENT. Skip a comment. It starts with a ‘;’ and ends with a newline
‘\n’ or an end of file ‘\000’. We skip the ‘\n’, but not the ‘\000’. *)
let rec nextComment () =
match ! ch
with ‘\000’ ->
nextChar () |
nextChar () ;
nextComment ()
(* NEXT END TOKEN. Read an END TOKEN. We don’t skip a CHAR because there are no
more CHARs to skip. *)
let nextEndToken () =
(* NEXT NUMBER TOKEN. Read a NUMBER TOKEN that starts with PREFIX. *)
let nextNumberToken prefix =
let rec nextNumbering chars =
match ! ch
with ‘\000’ | ‘\n’ | ‘ ‘ | ‘(‘ | ‘)’ ->
NumberToken (int_of_string chars) |
let otherChars = Char.escaped ! ch
in nextChar () ;
nextNumbering (chars ^ otherChars)
in nextNumbering prefix
(* NEXT OPEN PAREN TOKEN. Read an OPEN PAREN TOKEN. *)
let nextOpenParenToken () =
nextChar () ;
OpenParenToken
(* NEXT SYMBOL TOKEN. Read a SYMBOL TOKEN that starts with PREFIX. *)
let nextSymbolToken prefix =
let rec nextSymboling chars =
match ! ch
with ‘\000’ | ‘\n’ | ‘ ‘ | ‘(‘ | ‘)’ ->
SymbolToken chars |
let otherChars = Char.escaped ! ch
in nextChar () ;
nextSymboling (chars ^ otherChars)
in nextSymboling prefix
(* NEXT NUMBER OR SYMBOL TOKEN. We’ve just read a ‘-‘, but we don’t know yet if
it starts a NUMBER TOKEN or a SYMBOL token. Skip the ‘-‘. If we see a digit,
then it starts a NUMBER TOKEN, otherwise it starts a SYMBOL TOKEN. *)
let nextNumberOrSymbolToken () =
nextChar () ;
match ! ch
with ‘0’ | ‘1’ | ‘2’ | ‘3’ | ‘4’ | ‘5’ | ‘6’ | ‘7’ | ‘8’ | ‘9’ ->
nextNumberToken “-” |
nextSymbolToken “-”
(* NEXT TOKEN. Look at CH to tell what TOKEN is coming next. Dispatch to the
function that will read that TOKEN and return it. *)
let rec nextToken () =
match ! ch
with ‘\000’ ->
nextEndToken () |
‘ ‘ | ‘\n’ ->
nextChar () ;
nextToken () |
nextOpenParenToken () |
nextCloseParenToken () |
nextComment () ;
nextToken () |
nextNumberOrSymbolToken () |
‘0’ | ‘1’ | ‘2’ | ‘3’ | ‘4’ | ‘5’ | ‘6’ | ‘7’ | ‘8’ | ‘9’ ->
nextNumberToken “” |
nextSymbolToken “”
(* Lost? This is MAKE SCANNER’s body. Initialize CH by reading the NEXT CHAR,
and return (but do not call!) NEXT TOKEN. *)
in nextChar () ;
nextToken ;;
*** YOUR CODE GOES HERE! ***
程序代写 CS代考 加微信: powcoder QQ: 1823890830 Email: powcoder@163.com