diff --git a/chapter1/astAccessors.coffee b/chapter1/astAccessors.coffee index 413461c..d1e007b 100644 --- a/chapter1/astAccessors.coffee +++ b/chapter1/astAccessors.coffee @@ -1,8 +1,9 @@ -{car, cdr} = require 'cons-lists/lists' +{car, cdr, listp} = require 'cons-lists/lists' symbol = (form) -> (car form) module.exports = + astObject: (form) -> typeof (car form) == "string" aSymbol: symbol aValue: (form) -> (car cdr form) isAList: (form) -> (symbol form) == 'list' diff --git a/chapter1/astToList.coffee b/chapter1/astToList.coffee index 2a0010e..f9861de 100644 --- a/chapter1/astToList.coffee +++ b/chapter1/astToList.coffee @@ -1,7 +1,8 @@ -{car, cdr, cons, listp, nilp, nil, list, listToString} = require 'cons-lists/lists' -{aSymbol, aValue} = require './astAccessors' +{car, cdr, cons, listp, nilp, nil, list, pairp, listToString} = require 'cons-lists/lists' +{aSymbol, aValue, astObject} = require './astAccessors' # RICH_AST -> LISP_AST + normalizeForm = (form) -> listToRecord1 = (l) -> @@ -41,6 +42,10 @@ normalizeForms = (forms) -> # Yes, this reifies the expectation than an empty list and 'nil' are # the same. return nil if nilp forms + + # Handle dotted list. + if (astObject forms) + return normalizeForm(forms) cons(normalizeForm(car forms), normalizeForms(cdr forms)) module.exports = diff --git a/chapter1/reader.coffee b/chapter1/reader.coffee index e2b349f..a90a78d 100644 --- a/chapter1/reader.coffee +++ b/chapter1/reader.coffee @@ -102,13 +102,20 @@ makeReadPair = (delim, type) -> return makeObj(type, nil, line, column) # IO -> (IO, Node) | Error + dotted = false readEachPair = (inStream) -> [line, column] = inStream.position() obj = read inStream, true, null, true - if inStream.peek() == delim then return cons obj, nil + if inStream.peek() == delim + if dotted then return obj + return cons obj, nil if inStream.done() then return handleError("Unexpected end of input")(line, column) + if dotted then return handleError("More than one symbol after dot") return obj if (car obj) == 'error' - cons obj, readEachPair(inStream) + if (car obj) == 'symbol' and (car cdr obj) == '.' + dotted = true + return readEachPair inStream + cons obj, readEachPair inStream ret = makeObj type, readEachPair(inStream), line, column inStream.next()