newmm: parse literal floats using String#to_f
[nit.git] / src / literal.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # Copyright 2012 Jean Privat <jean@pryen.org>
4 #
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
8 #
9 # http://www.apache.org/licenses/LICENSE-2.0
10 #
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
16
17 # Parsing of literal values in the abstract syntax tree.
18 module literal
19
20 import parser
21 import toolcontext
22
23 redef class AModule
24 # Visit the module to compute the real value of the literal-related node of the AST.
25 # Warnings and errors are displayed on the toolcontext.
26 fun do_literal(toolcontext: ToolContext)
27 do
28 var v = new LiteralVisitor(toolcontext)
29 v.enter_visit(self)
30 end
31 end
32
33 private class LiteralVisitor
34 super Visitor
35
36 var toolcontext: ToolContext
37
38 init(toolcontext: ToolContext)
39 do
40 self.toolcontext = toolcontext
41 end
42
43 redef fun visit(n)
44 do
45 if n != null then
46 n.accept_literal(self)
47 n.visit_all(self)
48 end
49 end
50 end
51
52 redef class ANode
53 private fun accept_literal(v: LiteralVisitor) do end
54 end
55
56 redef class AIntExpr
57 # The value of the literal int once computed.
58 var value: nullable Int
59 redef fun accept_literal(v)
60 do
61 self.value = self.n_number.text.to_i
62 end
63 end
64
65 redef class AFloatExpr
66 # The value of the literal float once computed.
67 var value: nullable Float
68 redef fun accept_literal(v)
69 do
70 self.value = self.n_float.text.to_f
71 end
72 end
73
74 redef class ACharExpr
75 # The value of the literal char once computed.
76 var value: nullable Char
77 redef fun accept_literal(v)
78 do
79 var txt = self.n_char.text.unescape_nit
80 if txt.length != 3 then
81 v.toolcontext.error(self.hot_location, "Invalid character literal {txt}")
82 return
83 end
84 self.value = txt[1]
85 end
86 end
87
88 redef class AStringFormExpr
89 # The value of the literal string once computed.
90 var value: nullable String
91 redef fun accept_literal(v)
92 do
93 var txt
94 if self isa AStringExpr then
95 txt = self.n_string.text
96 else if self isa AStartStringExpr then
97 txt = self.n_string.text
98 else if self isa AMidStringExpr then
99 txt = self.n_string.text
100 else if self isa AEndStringExpr then
101 txt = self.n_string.text
102 else abort
103 self.value = txt.substring(1, txt.length-2).unescape_nit
104 end
105 end
106
107 redef class String
108 # Return a string where Nit escape sequences are transformed.
109 #
110 # Example:
111 # var s = "\\n"
112 # print s.length # -> 2
113 # var u = s.unescape_nit
114 # print s.length # -> 1
115 # print s[0].ascii # -> 10 (the ASCII value of the "new line" character)
116 fun unescape_nit: String
117 do
118 var res = new Buffer.with_capacity(self.length)
119 var was_slash = false
120 for c in self do
121 if not was_slash then
122 if c == '\\' then
123 was_slash = true
124 else
125 res.add(c)
126 end
127 continue
128 end
129 was_slash = false
130 if c == 'n' then
131 res.add('\n')
132 else if c == 'r' then
133 res.add('\r')
134 else if c == 't' then
135 res.add('\t')
136 else if c == '0' then
137 res.add('\0')
138 else
139 res.add(c)
140 end
141 end
142 return res.to_s
143 end
144 end