Handle some more expressions and statements, add cpp "# line file" extractor
authorNick Downing <nick.downing@lifx.co>
Sun, 19 Jan 2020 03:54:17 +0000 (14:54 +1100)
committerNick Downing <nick.downing@lifx.co>
Sun, 19 Jan 2020 03:54:31 +0000 (14:54 +1100)
ansi_c.t
hashline.py [new file with mode: 0755]

index 4937513..f7d1811 100644 (file)
--- a/ansi_c.t
+++ b/ansi_c.t
@@ -456,6 +456,14 @@ def translate_declaration_or_statement(self, context):
     )
   )
   context.indent = indent_save
+@method(AST.StatementGoto)
+def translate_declaration_or_statement(self, context):
+  context.lines.append(
+    '{0:s}goto {1:s}\n'.format(
+      context.indent,
+      self.children[0].text[0]
+    )
+  )
 @method(AST.StatementIf)
 def translate_declaration_or_statement(self, context):
   context.lines.append(
@@ -490,6 +498,14 @@ def translate_declaration_or_statement(self, context):
       self.children[0].translate_expression(context, 0)
     )
   )
+@method(AST.StatementLabel)
+def translate_declaration_or_statement(self, context):
+  context.lines.append(
+    '{0:s}{1:s}:\n'.format(
+      context.indent,
+      self.children[0].text[0]
+    )
+  )
 @method(AST.StatementSwitch)
 def translate_declaration_or_statement(self, context):
   assert isinstance(self.children[1], AST.StatementBlock)
@@ -697,12 +713,38 @@ def translate_expression(self, context, precedence):
 @method(AST.ExpressionCast)
 def translate_expression(self, context, precedence):
   type, _ = self.children[0].children[1].get_type_and_name(self.children[0].children[0].get_type())
-  text = '{0:s}({1:s})'.format(
-    type.translate_type(context),
-    self.children[1].translate_expression(context, 0)
-  )
-  if 14 < precedence:
-    text = '({0:s})'.format(text)
+  # python unifies the different int types and the different float types,
+  # therefore a lot of casting of constants etc needed in C is not in python
+  if (
+    (
+      isinstance(type, AST.TypeInt) and
+      (
+        isinstance(self.children[1], AST.ExpressionIntLiteral) or
+        (
+          isinstance(self.children[1], AST.ExpressionMinus) and
+          isinstance(self.children[1].children[0], AST.ExpressionIntLiteral)
+        )
+      )
+    ) or
+    (
+      isinstance(type, AST.TypeFloat) and
+      (
+        isinstance(self.children[1], AST.ExpressionFloatLiteral) or
+        (
+          isinstance(self.children[1], AST.ExpressionMinus) and
+          isinstance(self.children[1].children[0], AST.ExpressionFloatLiteral)
+        )
+      )
+    )
+  ):
+    text = self.children[1].translate_expression(context, precedence)
+  else:
+    text = '{0:s}({1:s})'.format(
+      type.translate_type(context),
+      self.children[1].translate_expression(context, 0)
+    )
+    if 14 < precedence:
+      text = '({0:s})'.format(text)
   return text
 @method(AST.ExpressionCharConstant)
 def translate_expression(self, context, precedence):
@@ -738,6 +780,12 @@ def translate_expression(self, context, precedence):
   if 14 < precedence:
     text = '({0:s})'.format(text)
   return text
+@method(AST.ExpressionFloatLiteral)
+def translate_expression(self, context, precedence):
+  text = self.text[0]
+  if text[-1:] == 'f':
+    text = text[:-1]
+  return text
 @method(AST.ExpressionIdentifier)
 def translate_expression(self, context, precedence):
   return self.children[0].translate_identifier(context)
@@ -755,6 +803,10 @@ def translate_expression(self, context, precedence):
   text = self.text[0]
   if text[:2] in octal_prefix:
     text = '0o' + text[1:]
+  if text[-2:] == 'LL':
+    text = text[:-2]
+  elif text[-1:] == 'L':
+    text = text[:-1]
   return text
 @method(AST.ExpressionSizeOfType)
 def translate_expression(self, context, precedence):
@@ -772,6 +824,9 @@ def translate_expression(self, context, precedence):
       for i in self.children
     ]
   )
+@method(AST.ExpressionFunctionName)
+def translate_expression(self, context, precedence):
+  return '__func__'
 del translate_expression
 
 @method(AST.Expression)
@@ -816,6 +871,12 @@ def translate_size(self, context):
 @method(AST.TypeArray)
 def translate_size(self, context):
   return self.element_type.translate_type(context) * self.element_count 
+@method(AST.TypeStruct)
+def translate_size(self, context):
+  return sum([i.type.translate_size(context) for i in self.children])
+@method(AST.TypeUnion)
+def translate_size(self, context):
+  return max([i.type.translate_size(context) for i in self.children])
 del translate_size
 
 @method(AST.Type)
diff --git a/hashline.py b/hashline.py
new file mode 100755 (executable)
index 0000000..0614a3e
--- /dev/null
@@ -0,0 +1,19 @@
+#!/usr/bin/env python3
+
+import sys
+
+EXIT_SUCCESS = 0
+EXIT_FAILURE = 1
+
+if len(sys.argv) < 2:
+  print(f'usage: {sys.argv[0]:s} filename')
+  sys.exit(EXIT_FAILURE)
+filename = sys.argv[1]
+
+output = True
+for line in sys.stdin:
+  if line[:1] == '#':
+    fields = line.split()
+    output = len(fields) >= 3 and fields[2] == f'"{filename:s}"'
+  elif output:
+    sys.stdout.write(line)