From f0099384d94a6a424e798f9019e3fad691406e83 Mon Sep 17 00:00:00 2001 From: Eduardo Julian Date: Thu, 31 Dec 2015 20:25:24 -0400 Subject: - Implemented multi-line text literals. --- src/lux/lexer.clj | 56 ++++++++++++++++++++++++++++++++++++++++++--------- src/lux/type/host.clj | 2 +- 2 files changed, 48 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/lux/lexer.clj b/src/lux/lexer.clj index e82e22ee4..0200ef8a9 100644 --- a/src/lux/lexer.clj +++ b/src/lux/lexer.clj @@ -4,7 +4,8 @@ ;; You can obtain one at http://mozilla.org/MPL/2.0/. (ns lux.lexer - (:require [clojure.template :refer [do-template]] + (:require (clojure [template :refer [do-template]] + [string :as string]) (lux [base :as & :refer [deftags |do return* return fail fail*]] [reader :as &reader]) [lux.analyser.module :as &module])) @@ -40,13 +41,50 @@ :else (fail (str "[Lexer Error] Unknown escape character: " escaped)))) -(defn ^:private lex-text-body [_] - (&/try-all% (&/|list (|do [[_ [prefix escaped]] (&reader/read-regex2 #"(?s)^([^\"\\]*)(\\.)") - unescaped (escape-char escaped) - postfix (lex-text-body nil)] - (return (str prefix unescaped postfix))) - (|do [[_ body] (&reader/read-regex #"(?s)^([^\"\\]*)")] - (return body))))) +(defn ^:private escape-char* [escaped] + (cond (.equals ^Object escaped "\\t") "\t" + (.equals ^Object escaped "\\b") "\b" + (.equals ^Object escaped "\\n") "\n" + (.equals ^Object escaped "\\r") "\r" + (.equals ^Object escaped "\\f") "\f" + (.equals ^Object escaped "\\\"") "\"" + (.equals ^Object escaped "\\\\") "\\" + :else + (assert false (str "[Lexer Error] Unknown escape character: " escaped)))) + +(defn ^:private clean-line [raw-line] + (string/replace raw-line #"\\." escape-char*)) + +(def ^:private lex-text-line + (&reader/read-regex #"^(.*) \\$")) + +(def ^:private lext-text-line-prefix + (&reader/read-regex #"^(\s*\\ )")) + +(defn ^:private lex-text-next-line [within-multiline? lex-text-body] + (&/try-all% (&/|list (if within-multiline? + (|do [[_ blank-line] (&reader/read-regex #"^()$") + next-part (lex-text-next-line within-multiline? lex-text-body)] + (return (str "\n" next-part))) + (fail "")) + (|do [[_ line-prefix] lext-text-line-prefix + next-part lex-text-body] + (return (str "\n" next-part)))))) + +(defn ^:private lex-text-body [within-multiline?] + (&/try-all% (&/|list (|do [[_ ^String this-line*] lex-text-line + :let [this-line (.substring this-line* 0 (- (.length this-line*) 2))] + next-lines (lex-text-next-line true (lex-text-body true))] + (return (str (clean-line this-line) + next-lines)) + ) + (|do [[_ ^String pre-quotes] (&reader/read-regex #"^([^\"]*)") + post-quotes (if (.endsWith pre-quotes "\\") + (|do [_ (&reader/read-regex #"^([\"])") + next-part (lex-text-body within-multiline?)] + (return (str "\"" next-part))) + (return ""))] + (return (clean-line (str pre-quotes post-quotes))))))) (def ^:private +ident-re+ #"^([a-zA-Z\-\+\_\=!@$%^&*<>\.,/\\\|'`:\~\?][0-9a-zA-Z\-\+\_\=!@$%^&*<>\.,/\\\|'`:\~\?]*)" ;; #"^([^0-9\[\]\(\)\{\};#\s\"][^\[\]\(\)\{\};#\s\"]*)" @@ -98,7 +136,7 @@ (def ^:private lex-text (|do [[meta _] (&reader/read-text "\"") - token (lex-text-body nil) + token (lex-text-body false) _ (&reader/read-text "\"")] (return (&/T meta (&/V $Text token))))) diff --git a/src/lux/type/host.clj b/src/lux/type/host.clj index ddb40f21d..9a7546ca4 100644 --- a/src/lux/type/host.clj +++ b/src/lux/type/host.clj @@ -237,7 +237,7 @@ (defn gtype->gclass [gtype] "(-> GenericType GenericClass)" (cond (instance? Class gtype) - (&/V &/$GenericClass (&/T (.getName gtype) &/Nil$)) + (&/V &/$GenericClass (&/T (.getName ^Class gtype) &/Nil$)) (instance? GenericArrayType gtype) (&/V &/$GenericArray (gtype->gclass (.getGenericComponentType ^GenericArrayType gtype))) -- cgit v1.2.3