Add float type and float constants
authorNick Downing <nick@ndcode.org>
Sat, 14 May 2022 23:44:47 +0000 (09:44 +1000)
committerNick Downing <nick@ndcode.org>
Mon, 16 May 2022 15:48:42 +0000 (01:48 +1000)
ndcode/pitree/pitree.l
ndcode/pitree/pitree.t
ndcode/pitree/pitree.y

index 20709f0..01649e9 100644 (file)
@@ -64,6 +64,7 @@
   "bool"                       return y_tab.KEYWORD_BOOL
   "class"                      return y_tab.KEYWORD_CLASS
   "dict"                       return y_tab.KEYWORD_DICT
+  "float"                      return y_tab.KEYWORD_FLOAT
   "int"                                return y_tab.KEYWORD_INT
   "list"                       return y_tab.KEYWORD_LIST
   "ref"                                return y_tab.KEYWORD_REF
     base = 10,
     digits = yy_groups[3]
   }(-?)([0-9]+))               return y_tab.LITERAL_INT
+  (?E{
+    t_def.AST.LiteralFloat,
+    sign = yy_groups[2],
+    integer_digits = yy_groups[4] if yy_groups[4] is not None else yy_groups[6],
+    fraction_digits = yy_groups[5] if yy_groups[5] is not None else yy_groups[7],
+    exponent_sign = yy_groups[9] if yy_groups[8] is not None else '',
+    exponent_digits = yy_groups[10] if yy_groups[8] is not None else ''
+  }(-?)(([0-9]+)\.([0-9]*)|([0-9]*)\.([0-9]+))([Ee]([+-]?)([0-9]+))?) return y_tab.LITERAL_FLOAT
   "'" {
     BEGIN(SINGLE_QUOTED)
     return ord('\'')
index 0e01f2a..b76f489 100644 (file)
@@ -45,6 +45,13 @@ class AST {
     int base = -1;
     str digits = '';
   };
+  class LiteralFloat: Expression {
+    str sign = '';
+    str integer_digits = '';
+    str fraction_digits = '';
+    str exponent_sign = '';
+    str exponent_digits = '';
+  };
   class LiteralList: Expression;
   class LiteralRef: Expression;
   class LiteralSet: Expression;
@@ -69,6 +76,7 @@ class AST {
   class TypeBool: Type;
   class TypeDict: Type;
   class TypeInt: Type;
+  class TypeFloat: Type;
   class TypeList: Type;
   class TypeRef: Type;
   class TypeSet: Type;
@@ -340,6 +348,10 @@ def generate_expression(self, _type):
 def generate_expression(self, _type):
   assert isinstance(_type, AST.TypeInt)
   return str(self.get_value())
+@method(AST.LiteralFloat)
+def generate_expression(self, _type):
+  assert isinstance(_type, AST.TypeFloat)
+  return str(self.get_value())
 @method(AST.LiteralList)
 def generate_expression(self, _type):
   assert isinstance(_type, AST.TypeList)
@@ -407,6 +419,10 @@ def generate_expression_json(self, _type):
 def generate_expression_json(self, _type):
   assert isinstance(_type, AST.TypeInt)
   return self.get_value()
+@method(AST.LiteralFloat)
+def generate_expression_json(self, _type):
+  assert isinstance(_type, AST.TypeFloat)
+  return self.get_value()
 @method(AST.LiteralList)
 def generate_expression_json(self, _type):
   assert isinstance(_type, AST.TypeList)
@@ -611,6 +627,9 @@ del generate_deserialize
 def is_mutable(self):
   return True
 @method(AST.TypeInt)
+def is_mutable(self):
+  return False
+@method(AST.TypeFloat)
 def is_mutable(self):
   return False
 @method(AST.TypeBool)
@@ -633,6 +652,9 @@ def null_value(self):
 @method(AST.TypeInt)
 def null_value(self):
   return '0'
+@method(AST.TypeFloat)
+def null_value(self):
+  return '0.'
 @method(AST.TypeList)
 def null_value(self):
   return '[]'
@@ -665,7 +687,25 @@ del get_text
 @method(AST.LiteralInt)
 def get_value(self):
   value = int(self.digits, self.base)
-  return -value if len(self.sign) else value
+  if self.sign == '-':
+    value = -value
+  return value
+del get_value
+
+@method(AST.LiteralFloat)
+def get_value(self):
+  exponent = 0
+  if len(self.exponent_digits):
+    exponent = int(self.exponent_digits)
+    if self.exponent_sign == '-':
+      exponent = -exponent
+  value = (
+    int(self.integer_digits + self.fraction_digits) *
+      10. ** (exponent - len(self.fraction_digits))
+  )
+  if self.sign == '-':
+    value = -value
+  return value
 del get_value
 
 @method(AST)
@@ -700,6 +740,9 @@ def post_process(self):
   self.children[1].post_process()
   self.is_json = isinstance(self.children[0], AST.TypeString) and self.children[1].is_json
 @method(AST.TypeInt)
+def post_process(self):
+  self.is_json = True
+@method(AST.TypeFloat)
 def post_process(self):
   self.is_json = True
 @method(AST.TypeList)
index 7d9852a..fac0116 100644 (file)
@@ -23,9 +23,9 @@
 %}
 
 %token CODEBLOCK_START CODEBLOCK_END SECTION2_START SECTION3_START
-%token KEYWORD_BOOL KEYWORD_CLASS KEYWORD_DICT KEYWORD_INT KEYWORD_LIST
+%token KEYWORD_BOOL KEYWORD_CLASS KEYWORD_DICT KEYWORD_INT KEYWORD_FLOAT KEYWORD_LIST
 %token KEYWORD_REF KEYWORD_SET KEYWORD_STR IDENTIFIER LITERAL_BOOL LITERAL_DICT
-%token LITERAL_INT LITERAL_REF
+%token LITERAL_INT LITERAL_FLOAT LITERAL_REF
 
 %start pitree
 
@@ -64,6 +64,7 @@ type
   : %space (?E{t_def.AST.TypeBool}KEYWORD_BOOL)
   | %space (?E{t_def.AST.TypeDict}KEYWORD_DICT '(' type ',' type ')')
   | %space (?E{t_def.AST.TypeInt}KEYWORD_INT)
+  | %space (?E{t_def.AST.TypeFloat}KEYWORD_FLOAT)
   | %space (?E{t_def.AST.TypeList}KEYWORD_LIST '(' type ')')
   | %space (?E{t_def.AST.TypeRef}KEYWORD_REF)
   | %space (?E{t_def.AST.TypeSet}KEYWORD_SET '(' type ')')
@@ -79,6 +80,7 @@ expression
   : LITERAL_BOOL
   | %space (?E{t_def.AST.LiteralDict}'{' dict_initializer_list_opt '}')
   | LITERAL_INT
+  | LITERAL_FLOAT
   | %space (?E{t_def.AST.LiteralList}'[' expression_list_opt ']')
   | LITERAL_REF
   | %space (?E{t_def.AST.LiteralSet}KEYWORD_SET '(' set_initializer_opt ')')