# Parsing of literal values in the abstract syntax tree.
module literal
-import parser
-import toolcontext
import phase
-import serialization_phase
redef class ToolContext
- var literal_phase: Phase = new LiteralPhase(self, [serialization_phase])
+ # Parses literal values in the whole AST and produces errors if needed
+ var literal_phase: Phase = new LiteralPhase(self, null)
end
private class LiteralPhase
var toolcontext: ToolContext
- init(toolcontext: ToolContext)
- do
- self.toolcontext = toolcontext
- end
-
redef fun visit(n)
do
n.accept_literal(self)
private fun accept_literal(v: LiteralVisitor) do end
end
-redef class AIntExpr
- # The value of the literal int once computed.
- var value: nullable Int
- redef fun accept_literal(v)
+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
- self.value = self.n_number.text.to_i
+ if not self isa AIntegerExpr then return null
+ return self.value.as(not null).to_i
+ end
+end
+
+redef class AIntegerExpr
+ # The value of the literal int once computed.
+ var value: nullable Numeric
+
+ redef fun accept_literal(v) do
+ value = n_integer.text.to_num
+ if value == null then
+ v.toolcontext.error(hot_location, "Error: invalid literal `{n_integer.text}`")
+ end
end
end
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
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
+ 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
+ self.value = txt.substring(behead, txt.length - behead - betail).unescape_nit
end
end