1 # This file is part of NIT ( http://www.nitlanguage.org ).
3 # Copyright 2012 Jean Privat <jean@pryen.org>
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
9 # http://www.apache.org/licenses/LICENSE-2.0
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.
17 # Parsing of literal values in the abstract syntax tree.
22 redef class ToolContext
23 # Parses literal values in the whole AST and produces errors if needed
24 var literal_phase
: Phase = new LiteralPhase(self, null)
27 private class LiteralPhase
30 redef fun process_nmodule
(nmodule
) do nmodule
.do_literal
(toolcontext
)
34 # Visit the module to compute the real value of the literal-related node of the AST.
35 # Warnings and errors are displayed on the toolcontext.
36 fun do_literal
(toolcontext
: ToolContext)
38 var v
= new LiteralVisitor(toolcontext
)
43 private class LiteralVisitor
46 var toolcontext
: ToolContext
50 n
.accept_literal
(self)
56 private fun accept_literal
(v
: LiteralVisitor) do end
60 # Get `self` as a `String`.
61 # Return null if not a string.
62 fun as_string
: nullable String
64 if not self isa AStringFormExpr then return null
65 return self.value
.as(not null)
68 # Get `self` as an `Int`.
69 # Return null if not an integer.
70 fun as_int
: nullable Int
72 if not self isa AIntExpr then return null
73 return self.value
.as(not null)
78 private fun remove_underscores
: Text do
79 var b
= new FlatBuffer
81 if i
== '_' then continue
89 # The value of the literal int once computed.
90 var value
: nullable Int
93 redef class ADecIntExpr
94 redef fun accept_literal
(v
)
96 value
= self.n_number
.text
.remove_underscores
.to_i
100 redef class AHexIntExpr
101 redef fun accept_literal
(v
)
103 var s
= self.n_hex_number
.text
.substring_from
(2).remove_underscores
105 v
.toolcontext
.error
(location
, "Error: invalid hexadecimal literal")
112 redef class ABinIntExpr
113 redef fun accept_literal
(v
)
115 var s
= self.n_bin_number
.text
.substring_from
(2).remove_underscores
117 v
.toolcontext
.error
(location
, "Error: invalid binary literal")
124 redef class AOctIntExpr
125 redef fun accept_literal
(v
)
127 var s
= self.n_oct_number
.text
.substring_from
(2).remove_underscores
129 v
.toolcontext
.error
(location
, "Error: invalid octal literal")
136 redef class AByteExpr
137 # The value of the literal int once computed.
138 var value
: nullable Byte
141 redef class ADecByteExpr
142 redef fun accept_literal
(v
)
144 var t
= self.n_bytenum
.text
145 value
= t
.substring
(0, t
.length
- 2).remove_underscores
.to_i
.to_b
149 redef class AHexByteExpr
150 redef fun accept_literal
(v
)
152 var t
= self.n_hex_bytenum
.text
153 var s
= t
.substring
(2, t
.length
- 4).remove_underscores
155 v
.toolcontext
.error
(location
, "Error: invalid hexadecimal literal")
158 value
= s
.to_hex
.to_b
162 redef class ABinByteExpr
163 redef fun accept_literal
(v
)
165 var t
= self.n_bin_bytenum
.text
166 var s
= t
.substring
(2, t
.length
- 4).remove_underscores
168 v
.toolcontext
.error
(location
, "Error: invalid binary literal")
171 value
= s
.to_bin
.to_b
175 redef class AOctByteExpr
176 redef fun accept_literal
(v
)
178 var t
= self.n_oct_bytenum
.text
179 var s
= t
.substring
(2, t
.length
- 4).remove_underscores
181 v
.toolcontext
.error
(location
, "Error: invalid octal literal")
184 value
= s
.to_oct
.to_b
188 redef class AFloatExpr
189 # The value of the literal float once computed.
190 var value
: nullable Float
191 redef fun accept_literal
(v
)
193 self.value
= self.n_float
.text
.to_f
197 redef class ACharExpr
198 # The value of the literal char once computed.
199 var value
: nullable Char
200 redef fun accept_literal
(v
)
202 var txt
= self.n_char
.text
.unescape_nit
203 if txt
.length
!= 3 then
204 v
.toolcontext
.error
(self.hot_location
, "Syntax Error: invalid character literal `{txt}`.")
207 self.value
= txt
.chars
[1]
211 redef class AStringFormExpr
212 # The value of the literal string once computed.
213 var value
: nullable String
214 redef fun accept_literal
(v
)
216 var txt
= self.n_string
.text
219 if txt
.chars
[0] == txt
.chars
[1] and txt
.length
>= 6 then
222 if txt
.chars
[0] == '"' and txt
.chars
[3] == '\n' then behead
= 4 # ignore first \n in """
224 self.value
= txt
.substring
(behead
, txt
.length
- behead
- betail
).unescape_nit