X-Git-Url: http://nitlanguage.org diff --git a/src/literal.nit b/src/literal.nit index bdea381..bc361ab 100644 --- a/src/literal.nit +++ b/src/literal.nit @@ -17,8 +17,18 @@ # Parsing of literal values in the abstract syntax tree. module literal -import parser -import toolcontext +import phase + +redef class ToolContext + # Parses literal values in the whole AST and produces errors if needed + var literal_phase: Phase = new LiteralPhase(self, null) +end + +private class LiteralPhase + super Phase + + redef fun process_nmodule(nmodule) do nmodule.do_literal(toolcontext) +end redef class AModule # Visit the module to compute the real value of the literal-related node of the AST. @@ -35,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 @@ -53,23 +56,63 @@ 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 redef fun accept_literal(v) do - # FIXME: no method to_f on string so just go ugly - var parts = self.n_float.text.split_with(".") - self.value = parts.first.to_i.to_f + self.value = self.n_float.text.to_f end end @@ -83,7 +126,7 @@ redef class ACharExpr v.toolcontext.error(self.hot_location, "Invalid character literal {txt}") return end - self.value = txt[1] + self.value = txt.chars[1] end end @@ -92,55 +135,14 @@ redef class AStringFormExpr var value: nullable String redef fun accept_literal(v) do - var txt - if self isa AStringExpr then - txt = self.n_string.text - else if self isa AStartStringExpr then - txt = self.n_string.text - else if self isa AMidStringExpr then - txt = self.n_string.text - else if self isa AEndStringExpr then - txt = self.n_string.text - else abort - self.value = txt.substring(1, txt.length-2).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 txt = self.n_string.text + 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