compiler: Added prefix and suffix support for `Char`
authorLucas Bajolet <r4pass@hotmail.com>
Mon, 30 Nov 2015 17:18:48 +0000 (12:18 -0500)
committerLucas Bajolet <r4pass@hotmail.com>
Tue, 22 Mar 2016 19:00:25 +0000 (15:00 -0400)
Signed-off-by: Lucas Bajolet <r4pass@hotmail.com>

src/compiler/abstract_compiler.nit
src/literal.nit
src/modelize/modelize_property.nit
src/semantize/typing.nit

index 1fad40d..17e44c7 100644 (file)
@@ -3549,7 +3549,11 @@ redef class AFloatExpr
 end
 
 redef class ACharExpr
-       redef fun expr(v) do return v.char_instance(self.value.as(not null))
+       redef fun expr(v) do
+               if is_ascii then return v.byte_instance(value.as(not null).ascii)
+               if is_code_point then return v.int_instance(value.as(not null).code_point)
+               return v.char_instance(self.value.as(not null))
+       end
 end
 
 redef class AArrayExpr
index b183301..72df12b 100644 (file)
@@ -95,17 +95,66 @@ redef class AFloatExpr
        end
 end
 
+# Any kind of literal which supports a prefix or a suffix
+class AAugmentedLiteral
+       # Returns the text of the token
+       private fun text: String is abstract
+
+       # Is the combination of prefixes and suffixes in `self` valid ?
+       fun is_valid_augmentation: Bool is abstract
+
+       private fun delimiter_start: Char is abstract
+
+       private fun delimiter_end: Char is abstract
+
+       # Prefix for the entity, "" if no prefix is found
+       protected var prefix: String is lazy do return text.substring(0, text.index_of(delimiter_start))
+
+       # Suffix for the entity, "" if no prefix is found
+       protected var suffix: String is lazy do return text.substring_from(text.last_index_of(delimiter_end) + 1)
+
+       # Content of the entity, without prefix nor suffix
+       protected var content: String is lazy do return text.substring_from(text.index_of(delimiter_start)).substring(0, text.last_index_of(delimiter_end) + 1)
+end
+
 redef class ACharExpr
+       super AAugmentedLiteral
        # The value of the literal char once computed.
-       var value: nullable Char
+       var value: nullable Char = null
+
+       redef fun delimiter_start do return '\''
+
+       redef fun delimiter_end do return '\''
+
+       # Is the expression returning an ASCII byte value ?
+       fun is_ascii: Bool do return prefix == "b"
+
+       # Is the expression returning a Code Point ?
+       fun is_code_point: Bool do return prefix == "u"
+
+       redef fun text do return n_char.text
+
+       redef fun is_valid_augmentation do
+               if suffix != "" then return false
+               if is_ascii then return true
+               if is_code_point then return true
+               if prefix != "" then return false
+               return true
+       end
+
        redef fun accept_literal(v)
        do
-               var txt = self.n_char.text.unescape_nit
+               if not is_valid_augmentation then
+                       v.toolcontext.error(hot_location, "Syntax Error: invalid prefix/suffix combination {prefix}/{suffix}")
+                       return
+               end
+               var txt = content.unescape_nit
                if txt.length != 3 then
                        v.toolcontext.error(self.hot_location, "Syntax Error: invalid character literal `{txt}`.")
                        return
                end
                self.value = txt.chars[1]
+               if is_ascii and txt.chars[1].code_point > 127 then v.toolcontext.error(self.hot_location, "Syntax Error: usage of byte prefix on multibyte character.")
        end
 end
 
index 6588268..1a95c3e 100644 (file)
@@ -1390,7 +1390,14 @@ redef class AAttrPropdef
                                        var cla = modelbuilder.try_get_mclass_by_name(nexpr, mmodule, "Float")
                                        if cla != null then mtype = cla.mclass_type
                                else if nexpr isa ACharExpr then
-                                       var cla = modelbuilder.try_get_mclass_by_name(nexpr, mmodule, "Char")
+                                       var cla: nullable MClass
+                                       if nexpr.is_ascii then
+                                               cla = modelbuilder.try_get_mclass_by_name(nexpr, mmodule, "Byte")
+                                       else if nexpr.is_code_point then
+                                               cla = modelbuilder.try_get_mclass_by_name(nexpr, mmodule, "Int")
+                                       else
+                                               cla = modelbuilder.try_get_mclass_by_name(nexpr, mmodule, "Char")
+                                       end
                                        if cla != null then mtype = cla.mclass_type
                                else if nexpr isa ABoolExpr then
                                        var cla = modelbuilder.try_get_mclass_by_name(nexpr, mmodule, "Bool")
index ddc87e2..08f3d65 100644 (file)
@@ -1455,9 +1455,15 @@ redef class AFloatExpr
 end
 
 redef class ACharExpr
-       redef fun accept_typing(v)
-       do
-               var mclass = v.get_mclass(self, "Char")
+       redef fun accept_typing(v) do
+               var mclass: nullable MClass = null
+               if is_ascii then
+                       mclass = v.get_mclass(self, "Byte")
+               else if is_code_point then
+                       mclass = v.get_mclass(self, "Int")
+               else
+                       mclass = v.get_mclass(self, "Char")
+               end
                if mclass == null then return # Forward error
                self.mtype = mclass.mclass_type
        end