Rename REAMDE to README.md
[nit.git] / src / literal.nit
index e044bee..d6cb84e 100644 (file)
 # Parsing of literal values in the abstract syntax tree.
 module literal
 
-import parser
-import toolcontext
 import phase
 
-import modelbuilder #FIXME useless
-
 redef class ToolContext
+       # Parses literal values in the whole AST and produces errors if needed
        var literal_phase: Phase = new LiteralPhase(self, null)
 end
 
@@ -48,17 +45,10 @@ private class LiteralVisitor
 
        var toolcontext: ToolContext
 
-       init(toolcontext: ToolContext)
-       do
-               self.toolcontext = toolcontext
-       end
-
        redef fun visit(n)
        do
-               if n != null then
-                       n.accept_literal(self)
-                       n.visit_all(self)
-               end
+               n.accept_literal(self)
+               n.visit_all(self)
        end
 end
 
@@ -66,15 +56,57 @@ redef class ANode
        private fun accept_literal(v: LiteralVisitor) do end
 end
 
+redef class AExpr
+       # Get `self` as a `String`.
+       # Return null if not a string.
+       fun as_string: nullable String
+       do
+               if not self isa AStringFormExpr then return null
+               return self.value.as(not null)
+       end
+
+       # Get `self` as an `Int`.
+       # Return null if not an integer.
+       fun as_int: nullable Int
+       do
+               if not self isa AIntExpr then return null
+               return self.value.as(not null)
+       end
+
+       # Get `self` as a single identifier.
+       # Return null if not a single identifier.
+       fun as_id: nullable String
+       do
+               if self isa AMethidExpr then
+                       return self.collect_text
+               end
+               if not self isa ACallExpr then return null
+               if not self.n_expr isa AImplicitSelfExpr then return null
+               if not self.n_args.n_exprs.is_empty then return null
+               return self.n_id.text
+       end
+end
+
+
 redef class AIntExpr
        # The value of the literal int once computed.
        var value: nullable Int
+end
+
+redef class ADecIntExpr
        redef fun accept_literal(v)
        do
                self.value = self.n_number.text.to_i
        end
 end
 
+redef class AHexIntExpr
+       redef fun accept_literal(v)
+       do
+               self.value = self.n_hex_number.text.substring_from(2).to_hex
+       end
+end
+
 redef class AFloatExpr
        # The value of the literal float once computed.
        var value: nullable Float
@@ -91,10 +123,10 @@ redef class ACharExpr
        do
                var txt = self.n_char.text.unescape_nit
                if txt.length != 3 then
-                       v.toolcontext.error(self.hot_location, "Invalid character literal {txt}")
+                       v.toolcontext.error(self.hot_location, "Syntax Error: invalid character literal `{txt}`.")
                        return
                end
-               self.value = txt[1]
+               self.value = txt.chars[1]
        end
 end
 
@@ -104,47 +136,13 @@ redef class AStringFormExpr
        redef fun accept_literal(v)
        do
                var txt = self.n_string.text
-               var skip = 1
-               if txt[0] == txt[1] and txt.length >= 6 then skip = 3
-               self.value = txt.substring(skip, txt.length-(2*skip)).unescape_nit
-       end
-end
-
-redef class String
-       # Return a string where Nit escape sequences are transformed.
-       #
-       # Example:
-       #     var s = "\\n"
-       #     print s.length # -> 2
-       #     var u = s.unescape_nit
-       #     print s.length # -> 1
-       #     print s[0].ascii # -> 10 (the ASCII value of the "new line" character)
-       fun unescape_nit: String
-       do
-               var res = new Buffer.with_capacity(self.length)
-               var was_slash = false
-               for c in self do
-                       if not was_slash then
-                               if c == '\\' then
-                                       was_slash = true
-                               else
-                                       res.add(c)
-                               end
-                               continue
-                       end
-                       was_slash = false
-                       if c == 'n' then
-                               res.add('\n')
-                       else if c == 'r' then
-                               res.add('\r')
-                       else if c == 't' then
-                               res.add('\t')
-                       else if c == '0' then
-                               res.add('\0')
-                       else
-                               res.add(c)
-                       end
+               var behead = 1
+               var betail = 1
+               if txt.chars[0] == txt.chars[1] and txt.length >= 6 then
+                       behead = 3
+                       betail = 3
+                       if txt.chars[0] == '"' and txt.chars[3] == '\n' then behead = 4 # ignore first \n in """
                end
-               return res.to_s
+               self.value = txt.substring(behead, txt.length - behead - betail).unescape_nit
        end
 end