[cig-commits] r6113 - cs/babel/trunk/spike/Spike/Compiler

leif at geodynamics.org leif at geodynamics.org
Sat Feb 24 18:38:55 PST 2007


Author: leif
Date: 2007-02-24 18:38:54 -0800 (Sat, 24 Feb 2007)
New Revision: 6113

Modified:
   cs/babel/trunk/spike/Spike/Compiler/ExprNodes.py
   cs/babel/trunk/spike/Spike/Compiler/Main.py
   cs/babel/trunk/spike/Spike/Compiler/Nodes.py
   cs/babel/trunk/spike/Spike/Compiler/Parsing.py
   cs/babel/trunk/spike/Spike/Compiler/SpikeTypes.py
   cs/babel/trunk/spike/Spike/Compiler/Symtab.py
   cs/babel/trunk/spike/Spike/Compiler/gram.y
   cs/babel/trunk/spike/Spike/Compiler/parser.pyx
   cs/babel/trunk/spike/Spike/Compiler/scan.l
Log:
Wrote more robust code for declspecs.  Added feedback loop for typedef
names.  Record (file, line, column) in nodes.  Added preliminary code
for C assignment/comma/conditional expressions.  Reworked
SpikeFuncDefNode magic (but it's still not quite right; exported
Python names are now mangled).  Implemented other assorted internal
improvements.


Modified: cs/babel/trunk/spike/Spike/Compiler/ExprNodes.py
===================================================================
--- cs/babel/trunk/spike/Spike/Compiler/ExprNodes.py	2007-02-23 23:35:05 UTC (rev 6112)
+++ cs/babel/trunk/spike/Spike/Compiler/ExprNodes.py	2007-02-25 02:38:54 UTC (rev 6113)
@@ -194,6 +194,11 @@
                         nodes.extend(item)
             self.saved_subexpr_nodes = nodes
         return self.saved_subexpr_nodes
+
+    def add_subexpr(self, expr):
+        # Called when an expression adds a subexpression late in the
+        # game.
+        self.saved_subexpr_nodes.append(expr)
     
     def result_as(self, type = None):
         #  Return the result code cast to the specified C type.
@@ -209,6 +214,14 @@
         return self.result_ctype or self.type
     
     # ------------- Declaration Analysis ----------------
+
+    def analyse_declarations(self, env):
+        self.analyse_subexpr_declarations(env)
+
+    def analyse_subexpr_declarations(self, env):
+        for node in self.subexpr_nodes():
+            if node:
+                node.analyse_declarations(env)
     
     def analyse_target_declaration(self, env):
         error(self.pos, "Cannot assign to or delete this")
@@ -703,7 +716,12 @@
     def analyse_types(self, env):
         self.entry = env.lookup(self.name)
         if not self.entry:
-            self.entry = env.declare_builtin(self.name, self.pos)
+            if False:
+                # ...death, death, I say!
+                self.entry = env.declare_builtin(self.name, self.pos)
+            else:
+                error(self.pos, "'%s' undeclared" % self.name)
+                self.entry = env.declare_var(self.name, SpikeTypes.error_type, self.pos)
         self.analyse_entry(env)
         
     def analyse_entry(self, env):
@@ -734,7 +752,7 @@
     def check_identifier_kind(self):
         entry = self.entry
         if not (entry.is_const or entry.is_variable 
-            or entry.is_builtin or entry.is_cfunction):
+            or entry.is_builtin or entry.is_cfunction or entry.is_spikefunction):
                 if self.entry.as_variable:
                     self.entry = self.entry.as_variable
                 else:
@@ -1226,6 +1244,7 @@
         func_type = self.function_type()
         if func_type.is_pyobject:
             self.arg_tuple = TupleNode(self.pos, args = self.args)
+            self.add_subexpr(self.arg_tuple) # others?
             self.args = None
             self.arg_tuple.analyse_types(env)
             self.type = py_object_type
@@ -1246,6 +1265,8 @@
         # Return the type of the function being called, coercing a function
         # pointer to a function if necessary.
         func_type = self.function.type
+        if func_type.is_spikefunction:
+            func_type = self.function.entry.cfunc.type
         if func_type.is_ptr:
             func_type = func_type.base_type
         return func_type
@@ -1321,7 +1342,7 @@
                     self.arg_tuple.py_result(),
                     self.result_code,
                     code.error_goto(self.pos)))
-        elif func_type.is_cfunction:
+        elif func_type.is_cfunction or func_type.is_spikefunction:
             exc_checks = []
             if self.type.is_pyobject:
                 exc_checks.append("!%s" % self.result_code)
@@ -2627,7 +2648,7 @@
 class CmpNode:
     #  Mixin class containing code common to PrimaryCmpNodes
     #  and CascadedCmpNodes.
-    
+
     def is_python_comparison(self):
         return (self.has_python_operands()
             or (self.cascade and self.cascade.is_python_comparison())
@@ -2786,7 +2807,11 @@
         self.operand1.generate_disposal_code(code)
         self.operand2.generate_disposal_code(code)
 
+    def analyse_declarations(self, env):
+        self.operand1.analyse_declarations(env)
+        self.operand2.analyse_declarations(env)
 
+
 class CascadedCmpNode(Node, CmpNode):
     #  A CascadedCmpNode is not a complete expression node. It 
     #  hangs off the side of another comparison node, shares 
@@ -2846,7 +2871,90 @@
         self.operand2.generate_disposal_code(code)
         code.putln("}")
 
+    def analyse_declarations(self, env):
+        self.operand1.analyse_declarations(env)
+        self.operand2.analyse_declarations(env)
 
+
+class CAssignmentNode(ExprNode):
+    #  C assignment expression
+    #
+    #  operator    string
+    #  lhs         ExprNode
+    #  rhs         ExprNode
+    
+    subexprs = ['lhs', 'rhs']
+
+    def analyse_declarations(self, env):
+        self.lhs.analyse_target_declaration(env)
+        self.rhs.analyse_declarations(env)
+    
+    def analyse_types(self, env):
+        self.rhs.analyse_types(env)
+        self.lhs.analyse_target_types(env)
+        self.rhs = self.rhs.coerce_to(self.lhs.type, env)
+        self.type = self.lhs.type # ???
+    
+    def allocate_subexpr_temps(self, env):
+        self.rhs.allocate_temps(env)
+        self.lhs.allocate_target_temps(env)
+        
+    def release_subexpr_temps(self, env):
+        self.lhs.release_target_temp(env)
+        self.rhs.release_temp(env)		
+    
+    def generate_result_code(self, code):
+        pass
+
+    def calculate_result_code(self):
+        if self.type.is_pyobject:
+            # Assignment generated by generate_assignment_code().
+            return None
+        return "(%s %s %s)" % (
+            self.lhs.result_code,
+            self.operator,
+            self.rhs.result_code)
+
+    def generate_subexpr_evaluation_code(self, code):
+        self.rhs.generate_evaluation_code(code)
+        if self.type.is_pyobject:
+            assert self.operator == "="
+            self.lhs.generate_assignment_code(self.rhs, code)
+        else:
+            self.lhs.generate_evaluation_code(code)
+
+    def generate_disposal_code(self, code):
+        if self.type.is_pyobject:
+            # ??? Already handled by generate_assignment_code()?  I
+            # don't understand this very well yet...
+            pass
+        else:
+            ExprNode.generate_disposal_code(self, code)
+        return
+
+
+class CommaNode(ExprNode):
+    #  C ',' expression
+    #
+    #  lhs         ExprNode
+    #  rhs         ExprNode
+    
+    subexprs = ['lhs', 'rhs']
+
+    def analyse_types(self, env):
+        self.lhs.analyse_types(env)
+        self.rhs.analyse_types(env)
+        self.type = self.rhs.type
+
+    def generate_result_code(self, code):
+        pass
+
+    def calculate_result_code(self):
+        return "(%s, %s)" % (
+            self.lhs.result_code,
+            self.rhs.result_code)
+
+
 binop_node_classes = {
     "or":		BoolBinopNode,
     "and":	BoolBinopNode,
@@ -2871,8 +2979,66 @@
         operand1 = operand1, 
         operand2 = operand2)
 
+
 #-------------------------------------------------------------------
 #
+#  Trinary operator nodes
+#
+#-------------------------------------------------------------------
+
+class ConditionalNode(ExprNode):
+    #  "cond ? expr1 : expr2" conditional expression
+    #
+    #  condition   ExprNode
+    #  if_expr     ExprNode
+    #  else_expr   ExprNode
+    
+    subexprs = ['condition', 'if_expr', 'else_expr']
+
+    def generate_result_code(self, code):
+        pass
+
+    # based on BinopNode
+    
+    def analyse_types(self, env):
+        self.condition.analyse_types(env)
+        self.if_expr.analyse_types(env)
+        self.else_expr.analyse_types(env)
+        self.analyse_c_operation(env)
+    
+    def check_const(self):
+        self.condition.check_const()
+        self.if_expr.check_const()
+        self.else_expr.check_const()
+    
+    # based on NumBinopNode
+
+    def analyse_c_operation(self, env):
+        type1 = self.if_expr.type
+        type2 = self.else_expr.type
+        self.type = self.compute_c_result_type(type1, type2)
+        if not self.type:
+            self.type_error()
+    
+    def compute_c_result_type(self, type1, type2):
+        if self.c_types_okay(type1, type2):
+            return SpikeTypes.widest_numeric_type(type1, type2)
+        else:
+            return None
+    
+    def c_types_okay(self, type1, type2):
+        return type1.is_numeric and type2.is_numeric
+
+    def calculate_result_code(self):
+        return "(%s ? %s : %s)" % (
+            self.condition.result_code,
+            self.if_expr.result_code, 
+            self.else_expr.result_code)
+    
+
+
+#-------------------------------------------------------------------
+#
 #  Coercion nodes
 #
 #  Coercion nodes are special in that they are created during

Modified: cs/babel/trunk/spike/Spike/Compiler/Main.py
===================================================================
--- cs/babel/trunk/spike/Spike/Compiler/Main.py	2007-02-23 23:35:05 UTC (rev 6112)
+++ cs/babel/trunk/spike/Spike/Compiler/Main.py	2007-02-25 02:38:54 UTC (rev 6113)
@@ -146,10 +146,8 @@
     def parse(self, source_filename, type_names, pxd):
         import parser
         import Nodes
-        stats = parser.parse(source_filename)
         initial_pos = (source_filename, 1, 0)
-        pos = initial_pos
-        body = Nodes.StatListNode(pos, stats = stats)
+        body = parser.parse(source_filename, initial_pos)
         tree = Nodes.ModuleNode(initial_pos, doc = None, body = body)
         return tree
 
@@ -289,6 +287,17 @@
 #------------------------------------------------------------------------
 
 def main(command_line = 0):
+    try:
+        import IPython.ultraTB
+    except ImportError:
+        pass
+    else:
+        sys.excepthook = IPython.ultraTB.FormattedTB(
+            mode          = "Verbose",
+            color_scheme  = "Linux",
+            call_pdb      = False
+            )
+        
     args = sys.argv[1:]
     any_failures = 0
     if command_line:

Modified: cs/babel/trunk/spike/Spike/Compiler/Nodes.py
===================================================================
--- cs/babel/trunk/spike/Spike/Compiler/Nodes.py	2007-02-23 23:35:05 UTC (rev 6112)
+++ cs/babel/trunk/spike/Spike/Compiler/Nodes.py	2007-02-25 02:38:54 UTC (rev 6113)
@@ -106,13 +106,22 @@
         self.body.analyse_declarations(env)
     
     def process_implementation(self, env, result):
+        self.declare_builtins(env)
         self.analyse_declarations(env)
         env.check_c_classes()
         self.body.analyse_expressions(env)
         env.return_type = SpikeTypes.c_void_type
         self.generate_c_code(env, result)
         self.generate_h_code(env, result)
-    
+
+    def declare_builtins(self, env):
+        # Declare various built-in Python types for easy access from
+        # Spike code.
+        env.declare_builtin("dict", self.pos)
+        env.declare_builtin("list", self.pos)
+        env.declare_builtin("str", self.pos)
+        env.declare_builtin("tuple", self.pos)
+
     def generate_h_code(self, env, result):
         public_vars_and_funcs = []
         public_extension_types = []
@@ -1445,7 +1454,9 @@
                 type = SpikeTypes.c_ptr_type(type.base_type)
             # Catch attempted C-style func(void) decl
             if type.is_void:
-                error(arg_node.pos, "Function argument cannot be void")
+                if len(self.args) > 1:
+                    error(arg_node.pos, "`void' in parameter list must be the entire list")
+                continue
             func_type_args.append(
                 SpikeTypes.CFuncTypeArg(name, type, arg_node.pos))
             if arg_node.default:
@@ -1652,17 +1663,18 @@
 
 
 class CTypeDefNode(StatNode):
-    #  base_type   CBaseTypeNode
-    #  declarator  CDeclaratorNode
+    #  base_type    CBaseTypeNode
+    #  declarators  [CDeclaratorNode]
     
     def analyse_declarations(self, env):
-        base = self.base_type.analyse(env)
-        name_declarator, type = self.declarator.analyse(base, env)
-        name = name_declarator.name
-        cname = name_declarator.cname
-        if env.in_cinclude:
-            type = CTypedefType(cname or name, type)
-        env.declare_type(name, type, self.pos, cname = cname)
+        for declarator in self.declarators:
+            base = self.base_type.analyse(env)
+            name_declarator, type = declarator.analyse(base, env)
+            name = name_declarator.name
+            cname = name_declarator.cname
+            if env.in_cinclude:
+                type = CTypedefType(cname or name, type)
+            env.declare_type(name, type, self.pos, cname = cname)
     
     def analyse_expressions(self, env):
         pass
@@ -1671,6 +1683,134 @@
         pass
 
 
+class DeclSpecs:
+
+    def __init__(self):
+        self.pos = None
+        self.specifiers = []
+
+    def add(self, token):
+        specifier, pos = token
+        if self.pos is None:
+            self.pos = pos
+        self.specifiers.insert(0, specifier)
+
+    def analyse(self):
+        # defaults
+        storage = 'auto' # ?
+        name = 'int'
+        signed = 1
+        longness = 0
+        # counts
+        signed_specs = 0
+        unsigned_specs = 0
+        short_specs = 0
+        long_specs = 0
+        type_specs = 0
+        storage_specs = 0
+        # loop
+        for specifier in self.specifiers:
+            if specifier == 'signed':
+                signed = 1
+                signed_specs += 1
+            elif specifier == 'unsigned':
+                signed = 0
+                unsigned_specs += 1
+            elif specifier == 'short':
+                longness = -1
+                short_specs += 1
+            elif specifier == 'long':
+                longness += 1 # for "long long"
+                long_specs += 1
+            elif specifier in ['char', 'int', 'float', 'double', 'void', 'obj']:
+                name = specifier
+                type_specs += 1
+            elif specifier in ['typedef', 'extern', 'static', 'auto', 'register']:
+                storage = specifier
+                storage_specs += 1
+        # error check
+        errors = 0
+        if signed_specs and unsigned_specs:
+            error(self.pos, "both signed and unsigned specified")
+            errors += 1
+        if short_specs and long_specs:
+            error(self.pos, "both long and short specified")
+            errors += 1
+        if type_specs > 1:
+            error(self.pos, "multiple data types specified")
+            errors += 1
+        if storage_specs > 1:
+            error(self.pos, "multiple storage classes specified")
+            errors += 1
+        if errors:
+            pass #?
+        # construct base type
+        base_type = CSimpleBaseTypeNode(
+            self.pos,
+            name = name,
+            module_path = [],
+            is_basic_c_type = 1,
+            signed = signed,
+            longness = longness,
+            is_self_arg = 0
+            )
+        return storage, base_type
+
+    def declaration(self, declarators):
+        import parser
+        storage, base_type = self.analyse()
+        # construct decl
+        decl = None
+        if storage == 'typedef':
+            decl = CTypeDefNode(self.pos,
+                                base_type = base_type,
+                                declarators = declarators)
+            for declarator in declarators:
+                name_decl = declarator
+                while not isinstance(name_decl, CNameDeclaratorNode):
+                    name_decl = name_decl.base
+                parser.declare_type_name(name_decl.name)
+        elif storage in ['auto', 'static', 'register', 'extern']:
+            visibility = 'private'
+            if storage == 'extern':
+                visibility = 'extern'
+            decl = CVarDefNode(self.pos,
+                               visibility = visibility,
+                               base_type = base_type,
+                               declarators = declarators)
+        else:
+            error(self.pos, "unimplemented storage class `%s'" % storage)
+        ret = StatListNode(self.pos, stats = [decl])
+        return ret
+
+    def function_definition(self, declarator, function_body):
+        storage, base_type = self.analyse()
+        stats = SpikeFuncDefNode.new_spike_func(
+            self.pos,
+            visibility = 'public',
+            base_type = base_type,
+            declarator = declarator,
+            body = function_body
+            )
+        ret = StatListNode(self.pos, stats = stats)
+        return ret
+
+    def analyse_type(self):
+        # Storage class specifiers are syntactically impossible.
+        _, base_type = self.analyse()
+        return base_type
+
+    def analyse_type_modifiers(self):
+        errors = 0
+        for specifier in self.specifiers:
+            if not specifier in ['const', 'volatile']:
+                errors += 1
+        if errors:
+            # It is probably possible to disallow this syntactically.
+            error(self.pos, "only type modifiers are allowed here")
+        return None # NYI
+
+
 class FuncDefNode(StatNode, BlockNode):
     #  Base class for function definition nodes.
     #
@@ -1995,10 +2135,11 @@
                 desc, self.name, len(self.args), expected_str))
     
     def declare_pyfunction(self, env):
-        self.entry = env.declare_pyfunction(self.name, self.pos)
+        cname = Naming.func_prefix + env.scope_prefix + self.name
+        # Declare as 'cname', since the SpikeFuncDefNode is declared as 'self.name'.
+        self.entry = env.declare_pyfunction(cname, self.pos)
         self.entry.doc = self.doc
-        self.entry.func_cname = \
-            Naming.func_prefix + env.scope_prefix + self.name
+        self.entry.func_cname = cname
         self.entry.doc_cname = \
             Naming.funcdoc_prefix + env.scope_prefix + self.name
         self.entry.pymethdef_cname = \
@@ -2295,99 +2436,81 @@
         return 1
 
 
-class SpikeFuncDefNode(DefNode):
+class SpikeFuncDefNode(StatNode):
     # A Spike function definition.
 
-    def __init__(self, pos, visibility, base_type, declarator, body):
+    def new_spike_func(cls, pos, visibility, base_type, declarator, body):
         import ExprNodes
         args = []
         call_args = []
-        for arg_decl in declarator.args:
+        fdecl = declarator
+        while not isinstance(fdecl, CFuncDeclaratorNode):
+            fdecl = fdecl.base
+        for arg_decl in fdecl.args:
             arg = CArgDeclNode(arg_decl.pos,
                                base_type = arg_decl.base_type,
                                declarator = arg_decl.declarator,
                                not_none = 0,
                                default = None)
             args.append(arg)
-            call_arg = ExprNodes.NameNode(arg_decl.pos, name = arg_decl.declarator.name)
+            name_decl = arg_decl.declarator
+            while not isinstance(name_decl, CNameDeclaratorNode):
+                name_decl = name_decl.base
+            call_arg = ExprNodes.NameNode(arg_decl.pos, name = name_decl.name)
             call_args.append(call_arg)
-        DefNode.__init__(self,
-                         pos,
-                         name = declarator.base.name,
+        name = fdecl.base.name
+        # The C function bears the original name in the generated code...
+        fdecl.base.cname = name
+        # ...but is mangled internally to avoid conflict with the Spike function.
+        cname = "__spike_cf_" + name
+        fdecl.base.name = cname
+        cfunc = CFuncDefNode(pos,
+                             visibility = visibility,
+                             base_type = base_type,
+                             declarator = declarator,
+                             body = body)
+        pybody = cls.construct_body(pos, call_args, base_type, declarator, fdecl)
+        pyfunc = DefNode(pos,
+                         name = name,
                          args = args,
                          star_arg = None,
                          starstar_arg = None,
                          doc = None,
-                         body = None)
-        declarator.base.name = "__spike_cf_" + declarator.base.name
-        self.cfunc = CFuncDefNode(pos,
-                                  visibility = visibility,
-                                  base_type = base_type,
-                                  declarator = declarator,
-                                  body = body)
-        self.construct_body(call_args, base_type)
+                         body = pybody)
+        func = cls(pos, name = name, cfunc = cfunc, pyfunc = pyfunc, cname = name)
+        return [cfunc, pyfunc, func]
+    new_spike_func = classmethod(new_spike_func)
 
-    def construct_body(self, call_args, base_type):
+    def construct_body(cls, pos, call_args, base_type, declarator, fdecl):
         import ExprNodes
-        # NYI: 'base_type' is not correct for the return type.
-        ret_decl = CVarDefNode(self.pos, visibility = 'private', base_type = base_type,
-                               declarators = [CNameDeclaratorNode(self.pos, name = "ret", cname = None)])
-        name = self.cfunc.declarator.base.name
-        function = ExprNodes.NameNode(self.pos, name = name)
-        expr = ExprNodes.SimpleCallNode(self.pos,
+        from copy import copy
+        stats = []
+        name = fdecl.base.name
+        function = ExprNodes.NameNode(pos, name = name)
+        expr = ExprNodes.SimpleCallNode(pos,
                                         function = function,
                                         args = call_args)
-        ret = ExprNodes.NameNode(self.pos, name = "ret")
-        stmt1 = SingleAssignmentNode(self.pos, lhs = ret, rhs = expr)
-        ret = ExprNodes.NameNode(self.pos, name = "ret")
-        stmt2 = ReturnStatNode(self.pos, value = ret)
-        self.body = StatListNode(self.pos, stats = [ret_decl, stmt1, stmt2])
-        return
+        if base_type.name == 'void':
+            stmt = ExprStatNode(pos, expr = expr)
+            stats.append(stmt)
+        else:
+            stmt = ReturnStatNode(pos, value = expr)
+            stats.append(stmt)
+        body = StatListNode(pos, stats = stats)
+        return body
+    construct_body = classmethod(construct_body)
 
-    #
-    # BlockNode protocol
-    #
-    
-    def generate_const_definitions(self, env, code):
-        self.cfunc.generate_const_definitions(env, code)
-        DefNode.generate_const_definitions(self, env, code)
-    
-    def generate_interned_name_decls(self, env, code):
-        self.cfunc.generate_interned_name_decls(env, code)
-        DefNode.generate_interned_name_decls(self, env, code)
-    
-    def generate_py_string_decls(self, env, code):
-        self.cfunc.generate_py_string_decls(env, code)
-        DefNode.generate_py_string_decls(self, env, code)
+    def analyse_declarations(self, env):
+        self.entry = env.declare_spikefunction(self.name, self.cname, self.pos,
+                                               self.cfunc, self.pyfunc)
+        
+    def analyse_expressions(self, env):
+        pass
 
-    #
-    # StatNode protocol
-    
-    def generate_function_definitions(self, env, code):
-        self.cfunc.generate_function_definitions(env, code)
-        DefNode.generate_function_definitions(self, env, code)
-
     def generate_execution_code(self, code):
-        self.cfunc.generate_execution_code(code)
-        DefNode.generate_execution_code(self, code)
+        pass
 
-    #
-    # Node protocol
-    #
-    
-    def analyse_declarations(self, env):
-        self.cfunc.analyse_declarations(env)
-        DefNode.analyse_declarations(self, env)
 
-    def analyse_expressions(self, env):
-        self.cfunc.analyse_expressions(env)
-        DefNode.analyse_expressions(self, env)
-    
-    def generate_code(self, code):
-        self.cfunc.generate_code(code)
-        DefNode.generate_code(self, code)
-
-
 class PyClassDefNode(StatNode, BlockNode):
     #  A Python class definition.
     #
@@ -2578,6 +2701,10 @@
     #
     #  expr   ExprNode
     
+    def analyse_declarations(self, env):
+        # for CAssignmentNode
+        self.expr.analyse_declarations(env)
+
     def analyse_expressions(self, env):
         self.expr.analyse_expressions(env)
         self.expr.release_temp(env)

Modified: cs/babel/trunk/spike/Spike/Compiler/Parsing.py
===================================================================
--- cs/babel/trunk/spike/Spike/Compiler/Parsing.py	2007-02-23 23:35:05 UTC (rev 6112)
+++ cs/babel/trunk/spike/Spike/Compiler/Parsing.py	2007-02-25 02:38:54 UTC (rev 6113)
@@ -1611,7 +1611,7 @@
         declarator = p_c_declarator(s, is_type = 1)
         s.expect_newline("Syntax error in ctypedef statement")
         return Nodes.CTypeDefNode(pos,
-            base_type = base_type, declarator = declarator)
+            base_type = base_type, declarators = [declarator])
 
 def p_def_statement(s):
     # s.sy == 'def'

Modified: cs/babel/trunk/spike/Spike/Compiler/SpikeTypes.py
===================================================================
--- cs/babel/trunk/spike/Spike/Compiler/SpikeTypes.py	2007-02-23 23:35:05 UTC (rev 6112)
+++ cs/babel/trunk/spike/Spike/Compiler/SpikeTypes.py	2007-02-25 02:38:54 UTC (rev 6113)
@@ -19,6 +19,7 @@
     #  is_ptr                boolean     Is a C pointer type
     #  is_null_ptr           boolean     Is the type of NULL
     #  is_cfunction          boolean     Is a C function type
+    #  is_spikefunction      boolean     Is a Spike function type
     #  is_struct_or_union    boolean     Is a C struct or union type
     #  is_enum               boolean     Is a C enum type
     #  is_string             boolean     Is a C char * type
@@ -64,6 +65,7 @@
     is_ptr = 0
     is_null_ptr = 0
     is_cfunction = 0
+    is_spikefunction = 0
     is_struct_or_union = 0
     is_enum = 0
     is_string = 0
@@ -423,6 +425,9 @@
     
     is_ptr = 1
     default_value = 0
+    to_py_function = "PyCObject_FromVoidPtr"
+    from_py_function = "PyCObject_AsVoidPtr"
+    parsetuple_format = "???"
     
     def __init__(self, base_type):
         self.base_type = base_type
@@ -567,6 +572,20 @@
         return self.type.declaration_code(self.cname, for_display)
 
 
+class SpikeFuncType(SpikeType):
+
+    is_spikefunction = 1
+
+    def __repr__(self):
+        return "SpikeFuncType"
+
+    def declaration_code(self, entity_code,
+                         for_display = 0, dll_linkage = None, pyrex = 0):
+        if for_display:
+            return "SpikeFuncType"
+        return ""
+
+
 class CStructOrUnionType(CType):
     #  name          string
     #  cname         string
@@ -690,6 +709,8 @@
 
 py_object_type = PyObjectType()
 
+spike_function_type = SpikeFuncType()
+
 c_void_type =         CVoidType()
 c_void_ptr_type =     CPtrType(c_void_type)
 c_void_ptr_ptr_type = CPtrType(c_void_ptr_type)

Modified: cs/babel/trunk/spike/Spike/Compiler/Symtab.py
===================================================================
--- cs/babel/trunk/spike/Spike/Compiler/Symtab.py	2007-02-23 23:35:05 UTC (rev 6112)
+++ cs/babel/trunk/spike/Spike/Compiler/Symtab.py	2007-02-25 02:38:54 UTC (rev 6113)
@@ -8,6 +8,7 @@
 import Naming
 from SpikeTypes import c_int_type, \
     py_object_type, c_char_array_type, \
+    spike_function_type, \
     CEnumType, CStructOrUnionType, PyExtensionType
 from TypeSlots import \
     pyfunction_signature, pymethod_signature, \
@@ -31,6 +32,7 @@
     #                               class construction
     # is_variable      boolean    Is a variable
     # is_cfunction     boolean    Is a C function
+    # is_spikefunction boolean    Is a Spike function
     # is_cmethod       boolean    Is a C method of an extension type
     # is_type          boolean    Is a type definition
     # is_const         boolean    Is a constant
@@ -108,6 +110,7 @@
     # sue_entries       [Entry]            Struct/union/enum entries
     # arg_entries       [Entry]            Function argument entries
     # var_entries       [Entry]            User-defined variable entries
+    # spikefunc_entries [Entry]            Spike function entries
     # pyfunc_entries    [Entry]            Python function entries
     # cfunc_entries     [Entry]            C function entries
     # c_class_entries   [Entry]            All extension type entries
@@ -149,6 +152,7 @@
         self.sue_entries = []
         self.arg_entries = []
         self.var_entries = []
+        self.spikefunc_entries = []
         self.pyfunc_entries = []
         self.cfunc_entries = []
         self.c_class_entries = []
@@ -290,6 +294,15 @@
     def declare_builtin(self, name, pos):
         return self.outer_scope.declare_builtin(name, pos)
     
+    def declare_spikefunction(self, name, cname, pos, cfunc, pyfunc):
+        # Add an entry for a Spike function.
+        entry = self.declare(name, cname, spike_function_type, pos)
+        entry.is_spikefunction = 1
+        entry.cfunc = cfunc
+        entry.pyfunc = pyfunc
+        self.spikefunc_entries.append(entry)
+        return entry
+    
     def declare_pyfunction(self, name, pos):
         # Add an entry for a Python function.
         entry = self.declare_var(name, py_object_type, pos)

Modified: cs/babel/trunk/spike/Spike/Compiler/gram.y
===================================================================
--- cs/babel/trunk/spike/Spike/Compiler/gram.y	2007-02-23 23:35:05 UTC (rev 6112)
+++ cs/babel/trunk/spike/Spike/Compiler/gram.y	2007-02-25 02:38:54 UTC (rev 6113)
@@ -9,6 +9,8 @@
 
 %}
 
+%error-verbose
+
 %token IDENTIFIER
 %token LITERAL_INT LITERAL_FLOAT LITERAL_CHAR LITERAL_STRING
 %token SIZEOF
@@ -38,13 +40,13 @@
 
 postfix_expr
 	: primary_expr
-	| postfix_expr '[' expr ']'                  { CHECK($$ = index_expr($1, $3)); }
-	| postfix_expr '(' ')'                       { CHECK($$ = call_expr($1, empty_list())); }
-	| postfix_expr '(' argument_expr_list ')'    { CHECK($$ = call_expr($1, $3)); }
-	| postfix_expr '.' identifier                { CHECK($$ = attr_expr($1, $3)); }
-	| postfix_expr PTR_OP identifier             { CHECK($$ = attr_expr($1, $3)); }
-	| postfix_expr INC_OP                        { CHECK($$ = postfix_inc_expr($1)); }
-	| postfix_expr DEC_OP                        { CHECK($$ = postfix_dec_expr($1)); }
+	| postfix_expr '[' expr ']'                  { CHECK($$ = index_expr($2, $1, $3)); }
+	| postfix_expr '(' ')'                       { CHECK($$ = call_expr($2, $1, empty_list())); }
+	| postfix_expr '(' argument_expr_list ')'    { CHECK($$ = call_expr($2, $1, $3)); }
+	| postfix_expr '.' identifier                { CHECK($$ = attr_expr($2, $1, $3)); }
+	| postfix_expr PTR_OP identifier             { CHECK($$ = attr_expr($2, $1, $3)); }
+	| postfix_expr INC_OP                        { CHECK($$ = postfix_inc_expr($2, $1)); }
+	| postfix_expr DEC_OP                        { CHECK($$ = postfix_dec_expr($2, $1)); }
 	;
 
 argument_expr_list
@@ -55,92 +57,92 @@
 unary_expr
 	: postfix_expr
 	| unary_operator cast_expr    { CHECK($$ = unary_op_expr($1, $2)); }
-	| SIZEOF unary_expr           { CHECK($$ = sizeof_var_expr($2)); }
-	| SIZEOF '(' type_name ')'    { CHECK($$ = sizeof_type_expr($3)); }
+	| SIZEOF unary_expr           { CHECK($$ = sizeof_var_expr($1, $2)); }
+	| SIZEOF '(' type_name ')'    { CHECK($$ = sizeof_type_expr($1, $3)); }
 	;
 
 unary_operator
-	: '&'    { CHECK($$ = unary_address_of()) }
-	| '*'    { CHECK($$ = unary_indirection()) }
-	| '+'    { CHECK($$ = unary_plus()) }
-	| '-'    { CHECK($$ = unary_minus()) }
-	| '~'    { CHECK($$ = unary_bitwise_negation()) }
-	| '!'    { CHECK($$ = unary_not()) }
-	| INC_OP { CHECK($$ = unary_prefix_inc()) }
-	| DEC_OP { CHECK($$ = unary_prefix_dec()) }
+	: '&'
+	| '*'
+	| '+'
+	| '-'
+	| '~'
+	| '!'
+	| INC_OP
+	| DEC_OP
 	;
 
 cast_expr
 	: unary_expr
-	| '(' type_name ')' cast_expr    { CHECK($$ = cast_expr($2, $4)); }
+	| '(' type_name ')' cast_expr    { CHECK($$ = cast_expr($1, $2, $4)); }
 	;
 
 multiplicative_expr
 	: cast_expr
-	| multiplicative_expr '*' cast_expr    { CHECK($$ = mul_expr($1, $3)); }
-	| multiplicative_expr '/' cast_expr    { CHECK($$ = div_expr($1, $3)); }
-	| multiplicative_expr '%' cast_expr    { CHECK($$ = mod_expr($1, $3)); }
+	| multiplicative_expr '*' cast_expr    { CHECK($$ = binary_expr($2, $1, $3)); }
+	| multiplicative_expr '/' cast_expr    { CHECK($$ = binary_expr($2, $1, $3)); }
+	| multiplicative_expr '%' cast_expr    { CHECK($$ = binary_expr($2, $1, $3)); }
 	;
 
 additive_expr
 	: multiplicative_expr
-	| additive_expr '+' multiplicative_expr    { CHECK($$ = add_expr($1, $3)); }
-	| additive_expr '-' multiplicative_expr    { CHECK($$ = sub_expr($1, $3)); }
+	| additive_expr '+' multiplicative_expr    { CHECK($$ = binary_expr($2, $1, $3)); }
+	| additive_expr '-' multiplicative_expr    { CHECK($$ = binary_expr($2, $1, $3)); }
 	;
 
 shift_expr
 	: additive_expr
-	| shift_expr LEFT_OP additive_expr     { CHECK($$ = shift_left_expr($1, $3)); }
-	| shift_expr RIGHT_OP additive_expr    { CHECK($$ = shift_right_expr($1, $3)); }
+	| shift_expr LEFT_OP additive_expr     { CHECK($$ = binary_expr($2, $1, $3)); }
+	| shift_expr RIGHT_OP additive_expr    { CHECK($$ = binary_expr($2, $1, $3)); }
 	;
 
 relational_expr
 	: shift_expr
-	| relational_expr '<' shift_expr      { CHECK($$ = l_expr($1, $3)); }
-	| relational_expr '>' shift_expr      { CHECK($$ = g_expr($1, $3)); }
-	| relational_expr LE_OP shift_expr    { CHECK($$ = le_expr($1, $3)); }
-	| relational_expr GE_OP shift_expr    { CHECK($$ = ge_expr($1, $3)); }
+	| relational_expr '<' shift_expr      { CHECK($$ = binary_expr($2, $1, $3)); }
+	| relational_expr '>' shift_expr      { CHECK($$ = binary_expr($2, $1, $3)); }
+	| relational_expr LE_OP shift_expr    { CHECK($$ = binary_expr($2, $1, $3)); }
+	| relational_expr GE_OP shift_expr    { CHECK($$ = binary_expr($2, $1, $3)); }
 	;
 
 equality_expr
 	: relational_expr
-	| equality_expr EQ_OP relational_expr    { CHECK($$ = eq_expr($1, $3)); }
-	| equality_expr NE_OP relational_expr    { CHECK($$ = ne_expr($1, $3)); }
+	| equality_expr EQ_OP relational_expr    { CHECK($$ = binary_expr($2, $1, $3)); }
+	| equality_expr NE_OP relational_expr    { CHECK($$ = binary_expr($2, $1, $3)); }
 	;
 
 and_expr
 	: equality_expr
-	| and_expr '&' equality_expr    { CHECK($$ = and_expr($1, $3)); }
+	| and_expr '&' equality_expr    { CHECK($$ = binary_expr($2, $1, $3)); }
 	;
 
 exclusive_or_expr
 	: and_expr
-	| exclusive_or_expr '^' and_expr    { CHECK($$ = xor_expr($1, $3)); }
+	| exclusive_or_expr '^' and_expr    { CHECK($$ = binary_expr($2, $1, $3)); }
 	;
 
 inclusive_or_expr
 	: exclusive_or_expr
-	| inclusive_or_expr '|' exclusive_or_expr    { CHECK($$ = or_expr($1, $3)); }
+	| inclusive_or_expr '|' exclusive_or_expr    { CHECK($$ = binary_expr($2, $1, $3)); }
 	;
 
 logical_and_expr
 	: inclusive_or_expr
-	| logical_and_expr AND_OP inclusive_or_expr    { CHECK($$ = logical_and_expr($1, $3)); }
+	| logical_and_expr AND_OP inclusive_or_expr    { CHECK($$ = binary_expr($2, $1, $3)); }
 	;
 
 logical_or_expr
 	: logical_and_expr
-	| logical_or_expr OR_OP logical_and_expr    { CHECK($$ = logical_or_expr($1, $3)); }
+	| logical_or_expr OR_OP logical_and_expr    { CHECK($$ = binary_expr($2, $1, $3)); }
 	;
 
 conditional_expr
 	: logical_or_expr
-	| logical_or_expr '?' logical_or_expr ':' conditional_expr
+	| logical_or_expr '?' logical_or_expr ':' conditional_expr    { CHECK($$ = conditional_expr($2, $1, $3, $5)); }
 	;
 
 assignment_expr
 	: conditional_expr
-	| unary_expr assignment_operator assignment_expr    { CHECK($$ = assignment_expr(Py_None, $1, $3)); }
+	| unary_expr assignment_operator assignment_expr    { CHECK($$ = assignment_expr($2, $1, $3)); }
 	;
 
 assignment_operator
@@ -159,7 +161,7 @@
 
 expr
 	: assignment_expr
-	| expr ',' assignment_expr
+	| expr ',' assignment_expr    { CHECK($$ = comma_expr($2, $1, $3)); }
 	;
 
 constant_expr
@@ -172,10 +174,10 @@
 	;
 
 declaration_specifiers
-	: storage_class_specifier
-	| storage_class_specifier declaration_specifiers
-	| type_specifier
-	| type_specifier declaration_specifiers
+	: storage_class_specifier                           { CHECK($$ = declaration_specifiers($1, Py_None)); }
+	| storage_class_specifier declaration_specifiers    { CHECK($$ = declaration_specifiers($1, $2)); }
+	| type_specifier                                    { CHECK($$ = declaration_specifiers($1, Py_None)); }
+	| type_specifier declaration_specifiers             { CHECK($$ = declaration_specifiers($1, $2)); }
 	;
 
 init_declarator_list
@@ -197,18 +199,18 @@
 	;
 
 type_specifier
-	: CHAR        { CHECK($$ = char_type()); }
+	: CHAR
 	| SHORT
-	| INT         { CHECK($$ = int_type()); }
-	| LONG        { CHECK($$ = long_type()); }
-	| SIGNED      { CHECK($$ = signed_type()); }
-	| UNSIGNED    { CHECK($$ = unsigned_type()); }
-	| FLOAT       { CHECK($$ = float_type()); }
-	| DOUBLE      { CHECK($$ = double_type()); }
+	| INT
+	| LONG
+	| SIGNED
+	| UNSIGNED
+	| FLOAT
+	| DOUBLE
 	| CONST
 	| VOLATILE
-	| VOID        { CHECK($$ = void_type()); }
-	| OBJ         { CHECK($$ = obj_type()); }
+	| VOID
+	| OBJ
 	| struct_or_union_specifier
 	| enum_specifier
 	| TYPE_NAME
@@ -268,7 +270,7 @@
 
 declarator2
 	: identifier             { CHECK($$ = name_declarator($1)); }
-	| '(' declarator ')'     { CHECK($$ = $2); }
+	| '(' declarator ')'     { $$ = $2; }
 	| declarator2 '[' ']'    { CHECK($$ = array_declarator($1, Py_None)); }
 	| declarator2 '[' constant_expr ']'    { CHECK($$ = array_declarator($1, $3)); }
 	| declarator2 '(' ')'    { CHECK($$ = function_declarator($1, empty_list())); }
@@ -277,10 +279,10 @@
 	;
 
 pointer
-	: '*'                                { CHECK($$ = pointer(Py_None)); }
-	| '*' type_specifier_list            { CHECK($$ = pointer($2)); }
-	| '*' pointer                        { CHECK($$ = pointer($2)); }
-	| '*' type_specifier_list pointer    { CHECK($$ = pointer($3)); /*???*/ }
+	: '*'                                { CHECK($$ = pointer($1, Py_None, Py_None)); }
+	| '*' type_specifier_list            { CHECK($$ = pointer($1, $2, Py_None)); }
+	| '*' pointer                        { CHECK($$ = pointer($1, Py_None, $2)); }
+	| '*' type_specifier_list pointer    { CHECK($$ = pointer($1, $2, $3)); }
 	;
 
 type_specifier_list
@@ -363,10 +365,10 @@
 	;
 
 compound_statement
-	: '{' '}'                                    { CHECK($$ = compound_statement(Py_None, Py_None)); }
-	| '{' statement_list '}'                     { CHECK($$ = compound_statement(Py_None, $2)); }
-	| '{' declaration_list '}'                   { CHECK($$ = compound_statement($2, Py_None)); }
-	| '{' declaration_list statement_list '}'    { CHECK($$ = compound_statement($2, $3)); }
+	: '{' '}'                                    { CHECK($$ = compound_statement($1, Py_None, Py_None)); }
+	| '{' statement_list '}'                     { CHECK($$ = compound_statement($1, Py_None, $2)); }
+	| '{' declaration_list '}'                   { CHECK($$ = compound_statement($1, $2, Py_None)); }
+	| '{' declaration_list statement_list '}'    { CHECK($$ = compound_statement($1, $2, $3)); }
 	;
 
 declaration_list
@@ -380,18 +382,19 @@
 	;
 
 expression_statement
-	: ';'         { CHECK($$ = pass_statement()); }
+	: ';'         { CHECK($$ = pass_statement($1)); }
 	| expr ';'    { CHECK($$ = expression_statement($1)); }
+	| error ';'   { yyerrok; }
 	;
 
 selection_statement
-	: IF '(' expr ')' statement                   { CHECK($$ = if_statement($3, $5, Py_None)); }
-	| IF '(' expr ')' statement ELSE statement    { CHECK($$ = if_statement($3, $5, $7)); }
+	: IF '(' expr ')' statement                   { CHECK($$ = if_statement($1, $3, $5, Py_None)); }
+	| IF '(' expr ')' statement ELSE statement    { CHECK($$ = if_statement($1, $3, $5, $7)); }
 	| SWITCH '(' expr ')' statement
 	;
 
 iteration_statement
-	: WHILE '(' expr ')' statement                    { CHECK($$ = while_statement($3, $5)); }
+	: WHILE '(' expr ')' statement                    { CHECK($$ = while_statement($1, $3, $5)); }
 	| DO statement WHILE '(' expr ')' ';'
 	| FOR '(' ';' ';' ')' statement
 	| FOR '(' ';' ';' expr ')' statement
@@ -407,8 +410,8 @@
 	: GOTO identifier ';'
 	| CONTINUE ';'
 	| BREAK ';'
-	| RETURN ';'         { CHECK($$ = return_statement(Py_None)); }
-	| RETURN expr ';'    { CHECK($$ = return_statement($2)); }
+	| RETURN ';'         { CHECK($$ = return_statement($1, Py_None)); }
+	| RETURN expr ';'    { CHECK($$ = return_statement($1, $2)); }
 	;
 
 file
@@ -418,12 +421,12 @@
 
 external_definition
 	: function_definition
-	| declaration    { $$ = Py_None; }
+	| declaration
 	;
 
 function_definition
-	: declarator function_body    { CHECK($$ = function_definition(Py_None, $1, $2)); }
-	| declaration_specifiers declarator function_body    { CHECK($$ = function_definition($1, $2, $3)); }
+	: declarator { push_scope(); } function_body    { pop_scope(); CHECK($$ = function_definition(Py_None, $1, $3)); }
+	| declaration_specifiers declarator { push_scope(); } function_body    { pop_scope(); CHECK($$ = function_definition($1, $2, $4)); }
 	;
 
 function_body
@@ -436,14 +439,4 @@
 	;
 %%
 
-#include <stdio.h>
-
-extern char yytext[];
-extern int column;
-
-yyerror(s)
-char *s;
-{
-	fflush(stdout);
-	printf("\n%*s\n%*s\n", column, "^", column, s);
-}
+/* end of file */

Modified: cs/babel/trunk/spike/Spike/Compiler/parser.pyx
===================================================================
--- cs/babel/trunk/spike/Spike/Compiler/parser.pyx	2007-02-23 23:35:05 UTC (rev 6112)
+++ cs/babel/trunk/spike/Spike/Compiler/parser.pyx	2007-02-25 02:38:54 UTC (rev 6113)
@@ -6,16 +6,23 @@
     FILE *yyin
     int yyparse()
 
-theDefList = list()
+from Spike.Compiler.Nodes import \
+     StatListNode
 
-def parse(char *filename):
+theDefList = None
+currentFilename = None
+
+def parse(filename, initial_pos):
     cdef int status
 
-    global yyin
+    global yyin, currentFilename, theDefList
+    currentFilename = filename
     yyin = fopen(filename, "r")
+    theDefList = StatListNode(initial_pos, stats = [])
+    push_scope() # global scope
     status = yyparse()
-    if (status != 0):
-        raise RuntimeError("parse error")
+    #if (status != 0):
+    #    raise RuntimeError("parse error")
     return theDefList
 
 #------------------------------------------------------------------------
@@ -25,8 +32,7 @@
 #------------------------------------------------------------------------
 
 from Spike.Compiler.Nodes import \
-     CSimpleBaseTypeNode, \
-     SpikeFuncDefNode
+     CSimpleBaseTypeNode
 
 from Spike.Compiler.ExprNodes import \
      AttributeNode, \
@@ -42,43 +48,51 @@
      SizeofVarNode, \
      StringNode
 
-pos = ("nowhere.pyx", 1, 0) # NYI
 
-
 # expressions -- primary
 
-cdef public object name_expr(object name):
+cdef public object name_expr(object token):
+    name, pos = token
     return NameNode(pos, name = name)
 
-cdef public object literal_int_expr(object value):
+cdef public object literal_int_expr(object token):
+    value, pos = token
     return IntNode(pos, value = value)
 
-cdef public object literal_float_expr(object value):
+cdef public object literal_float_expr(object token):
+    value, pos = token
     return FloatNode(pos, value = value)
 
-cdef public object literal_char_expr(object value):
+cdef public object literal_char_expr(object token):
+    value, pos = token
     return CharNode(pos, value = value)
 
-cdef public object literal_string_expr(object value):
+cdef public object literal_string_expr(object token):
+    value, pos = token
     return StringNode(pos, value = value)
 
 
 # expressions -- postfix
 
-cdef public object index_expr(object base, object index):
+cdef public object index_expr(object operator, object base, object index):
+    _, pos = operator # 'operator' is the '[' token
     return IndexNode(pos, base = base, index = index)
 
-cdef public object call_expr(object function, object args):
+cdef public object call_expr(object operator, object function, object args):
+    _, pos = operator # 'operator' is the '(' token
     return SimpleCallNode(pos, function = function, args = args)
 
-cdef public object attr_expr(object obj, object attribute):
-    return AttributeNode(pos, obj = obj, attribute = attribute)
+cdef public object attr_expr(object operator, object obj, object attribute):
+    _, pos = operator
+    return AttributeNode(pos, obj = obj, attribute = attribute[0])
 
-cdef public object postfix_inc_expr(object operand):
-    return PostfixIncNode(pos, operator = '++', operand = operand)
+cdef public object postfix_inc_expr(object token, object operand):
+    operator, pos = token
+    return PostfixIncNode(pos, operator = operator, operand = operand)
 
-cdef public object postfix_dec_expr(object operand):
-    return PostfixDecNode(pos, operator = '--', operand = operand)
+cdef public object postfix_dec_expr(object token, object operand):
+    operator, pos = token
+    return PostfixDecNode(pos, operator = operator, operand = operand)
 
 cdef public object argument_expr_list(object argument_expr_list, object assignment_expr):
     if argument_expr_list is None:
@@ -89,20 +103,45 @@
 
 # expressions -- unary
 
-cdef public object unary_op_expr(object operator, object operand):
-    cls, operator = operator
+from Spike.Compiler.ExprNodes import \
+     AmpersandNode, \
+     IndirectionNode, \
+     UnaryPlusNode, \
+     UnaryMinusNode, \
+     TildeNode, \
+     NotNode, \
+     PrefixIncNode, \
+     PrefixDecNode
+
+unop_node_classes = {
+    '&':  AmpersandNode,
+    '*':  IndirectionNode,
+    '+':  UnaryPlusNode,
+    '-':  UnaryMinusNode,
+    '~':  TildeNode,
+    '!':  NotNode,
+    '++': PrefixIncNode,
+    '--': PrefixDecNode,
+}
+
+cdef public object unary_op_expr(object token, object operand):
+    operator, pos = token
+    cls = unop_node_classes[operator]
     return cls(pos, operator = operator, operand = operand)
 
-cdef public object sizeof_var_expr(object operand):
+cdef public object sizeof_var_expr(object keyword, object operand):
+    _, pos = keyword
     return SizeofVarNode(pos, operand = operand)
 
-cdef public object sizeof_type_expr(object type_name):
+cdef public object sizeof_type_expr(object keyword, object type_name):
+    _, pos = keyword
     base_type, declarator = type_name
     return SizeofTypeNode(pos, base_type = base_type, declarator = declarator)
 
-cdef public object cast_expr(object type_name, object operand):
+cdef public object cast_expr(object lparen, object type_name, object operand):
+    _, pos = lparen
     base_type, declarator = type_name
-    return TypecastNode(base_type = base_type, declarator = declarator, operand = operand)
+    return TypecastNode(pos, base_type = base_type, declarator = declarator, operand = operand)
 
 
 # expressions -- binary
@@ -115,110 +154,66 @@
      NumBinopNode, \
      IntBinopNode, \
      BoolBinopNode, \
-     PrimaryCmpNode
+     PrimaryCmpNode, \
+     ConditionalNode, \
+     CAssignmentNode, \
+     CommaNode
 
-from Spike.Compiler.Nodes import \
-     SingleAssignmentNode
+binop_node_classes = {
+    '*':  MulNode,
+    '/':  NumBinopNode,
+    '%':  ModNode,
+    '+':  AddNode,
+    '-':  SubNode,
+    '<<': IntBinopNode,
+    '>>': IntBinopNode,
+    '<':  PrimaryCmpNode,
+    '>':  PrimaryCmpNode,
+    '<=': PrimaryCmpNode,
+    '>=': PrimaryCmpNode,
+    '==': PrimaryCmpNode,
+    '!=': PrimaryCmpNode,
+    '&':  IntBinopNode,
+    '^':  IntBinopNode,
+    '|':  IntBinopNode,
+    '&&': BoolBinopNode,
+    '||': BoolBinopNode,
+}
 
-cdef public object mul_expr(operand1, operand2):
-    return MulNode(pos, operator = "*", operand1 = operand1, operand2 = operand2)
+cdef public object binary_expr(token, operand1, operand2):
+    operator, pos = token
+    cls = binop_node_classes[operator]
+    return cls(pos, operator = operator, operand1 = operand1, operand2 = operand2)
 
-cdef public object div_expr(operand1, operand2):
-    return NumBinopNode(pos, operator = "/", operand1 = operand1, operand2 = operand2)
 
-cdef public object mod_expr(operand1, operand2):
-    return ModNode(pos, operator = "%", operand1 = operand1, operand2 = operand2)
+# expressions -- other
 
-cdef public object add_expr(operand1, operand2):
-    return AddNode(pos, operator = "+", operand1 = operand1, operand2 = operand2)
+cdef public object conditional_expr(question, condition, if_expr, else_expr):
+    _, pos = question
+    return ConditionalNode(pos, condition = condition, if_expr = if_expr, else_expr = else_expr)
 
-cdef public object sub_expr(operand1, operand2):
-    return SubNode(pos, operator = "-", operand1 = operand1, operand2 = operand2)
+cdef public object assignment_expr(token, lhs, rhs):
+    operator, pos = token
+    return CAssignmentNode(pos, operator = operator, lhs = lhs, rhs = rhs)
 
-cdef public object shift_left_expr(operand1, operand2):
-    return IntBinopNode(pos, operator = "<<", operand1 = operand1, operand2 = operand2)
+cdef public object comma_expr(token, lhs, rhs):
+    operator, pos = token
+    return CommaNode(pos, lhs = lhs, rhs = rhs)
 
-cdef public object shift_right_expr(operand1, operand2):
-    return IntBinopNode(pos, operator = ">>", operand1 = operand1, operand2 = operand2)
 
-cdef public object l_expr(operand1, operand2):
-    return PrimaryCmpNode(pos, operator = "<", operand1 = operand1, operand2 = operand2)
-
-cdef public object g_expr(operand1, operand2):
-    return PrimaryCmpNode(pos, operator = ">", operand1 = operand1, operand2 = operand2)
-
-cdef public object le_expr(operand1, operand2):
-    return PrimaryCmpNode(pos, operator = "<=", operand1 = operand1, operand2 = operand2)
-
-cdef public object ge_expr(operand1, operand2):
-    return PrimaryCmpNode(pos, operator = ">=", operand1 = operand1, operand2 = operand2)
-
-cdef public object eq_expr(operand1, operand2):
-    return PrimaryCmpNode(pos, operator = "==", operand1 = operand1, operand2 = operand2)
-
-cdef public object ne_expr(operand1, operand2):
-    return PrimaryCmpNode(pos, operator = "!=", operand1 = operand1, operand2 = operand2)
-
-cdef public object and_expr(operand1, operand2):
-    return IntBinopNode(pos, operator = "&", operand1 = operand1, operand2 = operand2)
-
-cdef public object xor_expr(operand1, operand2):
-    return IntBinopNode(pos, operator = "^", operand1 = operand1, operand2 = operand2)
-
-cdef public object or_expr(operand1, operand2):
-    return IntBinopNode(pos, operator = "|", operand1 = operand1, operand2 = operand2)
-
-cdef public object logical_and_expr(operand1, operand2):
-    return BoolBinopNode(pos, operator = "&&", operand1 = operand1, operand2 = operand2)
-
-cdef public object logical_or_expr(operand1, operand2):
-    return BoolBinopNode(pos, operator = "||", operand1 = operand1, operand2 = operand2)
-
-cdef public object assignment_expr(operator, lhs, rhs):
-    # NYI
-    return SingleAssignmentNode(pos, lhs = lhs, rhs = rhs)
-
-
-# expressions -- unary operators
-
-from Spike.Compiler.ExprNodes import \
-     AmpersandNode, \
-     IndirectionNode, \
-     UnaryPlusNode, \
-     UnaryMinusNode, \
-     TildeNode, \
-     NotNode, \
-     PrefixIncNode, \
-     PrefixDecNode
-
-cdef public object unary_address_of(): return AmpersandNode, '&'
-cdef public object unary_indirection(): return IndirectionNode, '*'
-cdef public object unary_plus(): return UnaryPlusNode, '+'
-cdef public object unary_minus(): return UnaryMinusNode, '-'
-cdef public object unary_bitwise_negation(): return TildeNode, '~'
-cdef public object unary_not(): return NotNode, '!'
-cdef public object unary_prefix_inc(): return PrefixIncNode, '++'
-cdef public object unary_prefix_dec(): return PrefixDecNode, '--'
-
-
 # declarations
 
 from Spike.Compiler.Nodes import \
-     CVarDefNode
+     CVarDefNode, \
+     DeclSpecs
 
 cdef public object declaration(object declaration_specifiers, object init_declarator_list):
-    # NYI: do some error checking on 'declaration_specifiers'.
-    kwds = dict(
-        name = 'int', module_path = [],
-        is_basic_c_type = 1, signed = 1,
-        longness = 0, is_self_arg = 0
-        )
-    kwds.update(declaration_specifiers)
-    base_type = CSimpleBaseTypeNode(pos, **kwds)
-    return CVarDefNode(pos, visibility = 'private', base_type = base_type, declarators = init_declarator_list)
+    return declaration_specifiers.declaration(init_declarator_list)
 
 cdef public object declaration_specifiers(object specifier, object declaration_specifiers):
-    declaration_specifiers.update(specifier)
+    if declaration_specifiers is None:
+        declaration_specifiers = DeclSpecs()
+    declaration_specifiers.add(specifier)
     return declaration_specifiers
 
 cdef public object init_declarator_list(object init_declarator_list, object init_declarator):
@@ -228,20 +223,6 @@
     return init_declarator_list
 
 
-# declarations -- type specifiers
-
-cdef public object char_type(): return dict(name = 'char')
-cdef public object int_type(): return dict(name = 'int')
-cdef public object float_type(): return dict(name = 'float')
-cdef public object double_type(): return dict(name = 'double')
-cdef public object void_type(): return dict(name = 'void')
-cdef public object obj_type(): return dict(name = 'obj')
-
-cdef public object long_type(): return dict(longness = 1)
-cdef public object signed_type(): return dict(signed = 1)
-cdef public object unsigned_type(): return dict(signed = 0)
-
-
 # declarators
 
 from Spike.Compiler.Nodes import \
@@ -253,19 +234,20 @@
 
 cdef public object pointer_declarator(object pointer, object declarator):
     last = pointer
-    while pointer.base is not None:
-        last = pointer.base
+    while last.base is not None:
+        last = last.base
     last.base = declarator
     return pointer
 
-cdef public object name_declarator(object name):
+cdef public object name_declarator(object token):
+    name, pos = token
     return CNameDeclaratorNode(pos, name = name, cname = None)
 
 cdef public object array_declarator(object base, object dimension):
-    return CArrayDeclaratorNode(pos, base = base, dimension = dimension)
+    return CArrayDeclaratorNode(base.pos, base = base, dimension = dimension)
 
 cdef public object function_declarator(object declarator, object parameter_list):
-    return CFuncDeclaratorNode(pos,
+    return CFuncDeclaratorNode(declarator.pos,
                                base = declarator,
                                args = parameter_list,
                                has_varargs = 0, #ellipsis,
@@ -273,26 +255,25 @@
                                exception_check = 0,
                                )
 
-cdef public object pointer(object base):
-    return CPtrDeclaratorNode(pos, base)
+cdef public object pointer(object asterisk, object type_specifier_list, object base):
+    _, pos = asterisk
+    if type_specifier_list is not None:
+        # NYI: currently discarded
+        modifiers = type_specifier_list.analyse_type_modifiers()
+    return CPtrDeclaratorNode(pos, base = base)
 
 cdef public object type_specifier_list(object type_specifier_list, object type_specifier):
     if type_specifier_list is None:
-        type_specifier_list = CSimpleBaseTypeNode(
-            pos,
-            name = 'int', module_path = [],
-            is_basic_c_type = 1, signed = 1,
-            longness = 0, is_self_arg = 0
-            )
-    # NYI: do some error checking.
-    type_specifier_list.__dict__.update(type_specifier)
+        type_specifier_list = DeclSpecs()
+    type_specifier_list.add(type_specifier)
     return type_specifier_list
 
 cdef public object parameter_list(object parameter_list, object parameter_declaration):
     if parameter_list is None:
         parameter_list = []
-    base_type, declarator = parameter_declaration
-    node = CArgDeclNode(pos,
+    type_specifier_list, declarator = parameter_declaration
+    base_type = type_specifier_list.analyse_type()
+    node = CArgDeclNode(declarator.pos,
         base_type = base_type,
         declarator = declarator,
         not_none = 0,
@@ -300,17 +281,13 @@
     parameter_list.append(node)
     return parameter_list
 
-
-# abstract declarators
-
 cdef public object empty_declarator():
-    return CNameDeclaratorNode(pos, name = "", cname = None)
+    return CNameDeclaratorNode(pos = None, name = "", cname = None)
 
 
 # statements
 
 from Spike.Compiler.Nodes import \
-     StatListNode, \
      PassStatNode, \
      ExprStatNode, \
      IfClauseNode, \
@@ -318,7 +295,8 @@
      WhileStatNode, \
      ReturnStatNode
 
-cdef public object compound_statement(object declaration_list, object statement_list):
+cdef public object compound_statement(object lcurly, object declaration_list, object statement_list):
+    _, pos = lcurly
     stats = []
     if declaration_list is not None:
         stats.extend(declaration_list.stats)
@@ -329,61 +307,79 @@
 
 cdef public object declaration_list(object declaration_list, object declaration):
     if declaration_list is None:
-        declaration_list = StatListNode(pos, stats = [])
-    declaration_list.stats.append(declaration)
+        declaration_list = StatListNode(declaration.pos, stats = [])
+    declaration_list.stats.extend(declaration.stats)
     return declaration_list
 
 cdef public object statement_list(object statement_list, object statement):
     if statement_list is None:
-        statement_list = StatListNode(pos, stats = [])
+        statement_list = StatListNode(statement.pos, stats = [])
     statement_list.stats.append(statement)
     return statement_list
 
-cdef public object pass_statement():
+cdef public object pass_statement(object semicolon):
+    _, pos = semicolon
     return PassStatNode(pos)
 
 cdef public object expression_statement(object expr):
     from Spike.Compiler.Nodes import StatNode
-    if isinstance(expr, StatNode):
-        # NYI -- AssignmentNodes currently go though here
-        return expr
-    return ExprStatNode(pos, expr = expr)
+    return ExprStatNode(expr.pos, expr = expr)
 
-cdef public object if_statement(object condition, object if_clause, object else_clause):
+cdef public object if_statement(object keyword, object condition, object if_clause, object else_clause):
+    _, pos = keyword
     if_clauses = [IfClauseNode(pos, condition = condition, body = if_clause)]
     return IfStatNode(pos, if_clauses = if_clauses, else_clause = else_clause)
 
-cdef public object while_statement(object expr, object statement):
+cdef public object while_statement(object keyword, object expr, object statement):
+    _, pos = keyword
     return WhileStatNode(pos, condition = expr, body = statement, else_clause = None)
 
-cdef public object return_statement(object value):
+cdef public object return_statement(object keyword, object value):
+    _, pos = keyword
     return ReturnStatNode(pos, value = value)
 
 
 # external definitions
 
 cdef public void external_definition(object definition):
-    theDefList.append(definition)
+    global theDefList
+    theDefList.stats.extend(definition.stats)
 
 cdef public object function_definition(object declaration_specifiers,
                                        object declarator,
                                        object function_body):
-    # NYI: do some error checking on 'declaration_specifiers'.
-    kwds = dict(
-        name = 'int', module_path = [],
-        is_basic_c_type = 1, signed = 1,
-        longness = 0, is_self_arg = 0
-        )
-    kwds.update(declaration_specifiers)
-    base_type = CSimpleBaseTypeNode(pos, **kwds)
-    func = SpikeFuncDefNode(pos,
-                            visibility = 'public',
-                            base_type = base_type,
-                            declarator = declarator,
-                            body = function_body)
-    return func
+    return declaration_specifiers.function_definition(declarator, function_body)
 
 
+# scope
+
+scopeStack = []
+
+cdef public void push_scope():
+    global scopeStack
+    newScope = dict()
+    scopeStack.insert(0, newScope)
+
+cdef public void pop_scope():
+    global scopeStack
+    scopeStack.pop(0)
+
+cdef public object name_token(char *text, int line, int column, int *is_type_name):
+    global scopeStack
+    name = str(text)
+    is_type_name[0] = 0
+    for scope in scopeStack:
+        if scope.has_key(name):
+            is_type_name[0] = 1
+    global currentFilename
+    return (name, (currentFilename, line, column))
+
+def declare_type_name(name):
+    global scopeStack
+    scope = scopeStack[0]
+    scope[name] = True
+
+
 # utils
 
 cdef public object empty_list():
@@ -392,11 +388,16 @@
 cdef public object pair(object a, object b):
     return a, b
 
-cdef public object name(char *text):
-    return str(text)
+cdef public object token(char *text, int line, int column):
+    global currentFilename
+    return (str(text), (currentFilename, line, column))
 
-cdef public object yystr(char *text):
-    return str(text)
+cdef public void yyerror(char *s):
+    cdef extern int yylineno
+    cdef extern int column
+    from Spike.Compiler.Errors import error
+    pos = (currentFilename, yylineno, column)
+    error(pos, s)
 
 
 # end of file

Modified: cs/babel/trunk/spike/Spike/Compiler/scan.l
===================================================================
--- cs/babel/trunk/spike/Spike/Compiler/scan.l	2007-02-23 23:35:05 UTC (rev 6112)
+++ cs/babel/trunk/spike/Spike/Compiler/scan.l	2007-02-25 02:38:54 UTC (rev 6113)
@@ -1,3 +1,5 @@
+%option yylineno
+
 D			[0-9]
 L			[a-zA-Z_]
 H			[a-fA-F0-9]
@@ -14,164 +16,158 @@
 #include "gram.h"
 #include "parser.h"
 
+#define TOKEN(t) get_token(); return t
+
 void count();
+void comment();
+void get_token();
+int get_name_token();
 %}
 
 %%
 "/*"			{ comment(); }
 
-"auto"			{ count(); return(AUTO); }
-"break"			{ count(); return(BREAK); }
-"case"			{ count(); return(CASE); }
-"char"			{ count(); return(CHAR); }
-"const"			{ count(); return(CONST); }
-"continue"		{ count(); return(CONTINUE); }
-"default"		{ count(); return(DEFAULT); }
-"do"			{ count(); return(DO); }
-"double"		{ count(); return(DOUBLE); }
-"else"			{ count(); return(ELSE); }
-"enum"			{ count(); return(ENUM); }
-"extern"		{ count(); return(EXTERN); }
-"float"			{ count(); return(FLOAT); }
-"for"			{ count(); return(FOR); }
-"goto"			{ count(); return(GOTO); }
-"if"			{ count(); return(IF); }
-"int"			{ count(); return(INT); }
-"long"			{ count(); return(LONG); }
-"obj"			{ count(); return(OBJ); }
-"register"		{ count(); return(REGISTER); }
-"return"		{ count(); return(RETURN); }
-"short"			{ count(); return(SHORT); }
-"signed"		{ count(); return(SIGNED); }
-"sizeof"		{ count(); return(SIZEOF); }
-"static"		{ count(); return(STATIC); }
-"struct"		{ count(); return(STRUCT); }
-"switch"		{ count(); return(SWITCH); }
-"typedef"		{ count(); return(TYPEDEF); }
-"union"			{ count(); return(UNION); }
-"unsigned"		{ count(); return(UNSIGNED); }
-"void"			{ count(); return(VOID); }
-"volatile"		{ count(); return(VOLATILE); }
-"while"			{ count(); return(WHILE); }
+"auto"			{ TOKEN(AUTO); }
+"break"			{ TOKEN(BREAK); }
+"case"			{ TOKEN(CASE); }
+"char"			{ TOKEN(CHAR); }
+"const"			{ TOKEN(CONST); }
+"continue"		{ TOKEN(CONTINUE); }
+"default"		{ TOKEN(DEFAULT); }
+"do"			{ TOKEN(DO); }
+"double"		{ TOKEN(DOUBLE); }
+"else"			{ TOKEN(ELSE); }
+"enum"			{ TOKEN(ENUM); }
+"extern"		{ TOKEN(EXTERN); }
+"float"			{ TOKEN(FLOAT); }
+"for"			{ TOKEN(FOR); }
+"goto"			{ TOKEN(GOTO); }
+"if"			{ TOKEN(IF); }
+"int"			{ TOKEN(INT); }
+"long"			{ TOKEN(LONG); }
+"obj"			{ TOKEN(OBJ); }
+"register"		{ TOKEN(REGISTER); }
+"return"		{ TOKEN(RETURN); }
+"short"			{ TOKEN(SHORT); }
+"signed"		{ TOKEN(SIGNED); }
+"sizeof"		{ TOKEN(SIZEOF); }
+"static"		{ TOKEN(STATIC); }
+"struct"		{ TOKEN(STRUCT); }
+"switch"		{ TOKEN(SWITCH); }
+"typedef"		{ TOKEN(TYPEDEF); }
+"union"			{ TOKEN(UNION); }
+"unsigned"		{ TOKEN(UNSIGNED); }
+"void"			{ TOKEN(VOID); }
+"volatile"		{ TOKEN(VOLATILE); }
+"while"			{ TOKEN(WHILE); }
 
-{L}({L}|{D})*		{ count(); return(check_type()); }
+{L}({L}|{D})*		{ TOKEN(get_name_token()); }
 
-0[xX]{H}+{IS}?		{ count(); yylval = yystr(yytext); return(LITERAL_INT); }
-0{D}+{IS}?		{ count(); yylval = yystr(yytext); return(LITERAL_INT); }
-{D}+{IS}?		{ count(); yylval = yystr(yytext); return(LITERAL_INT); }
-'(\\.|[^\\'])+'		{ count(); yylval = yystr(yytext); return(LITERAL_CHAR); }
+0[xX]{H}+{IS}?		{ TOKEN(LITERAL_INT); }
+0{D}+{IS}?		{ TOKEN(LITERAL_INT); }
+{D}+{IS}?		{ TOKEN(LITERAL_INT); }
+'(\\.|[^\\'])+'		{ TOKEN(LITERAL_CHAR); }
 
-{D}+{E}{FS}?		{ count(); yylval = yystr(yytext); return(LITERAL_FLOAT); }
-{D}*"."{D}+({E})?{FS}?	{ count(); yylval = yystr(yytext); return(LITERAL_FLOAT); }
-{D}+"."{D}*({E})?{FS}?	{ count(); yylval = yystr(yytext); return(LITERAL_FLOAT); }
+{D}+{E}{FS}?		{ TOKEN(LITERAL_FLOAT); }
+{D}*"."{D}+({E})?{FS}?	{ TOKEN(LITERAL_FLOAT); }
+{D}+"."{D}*({E})?{FS}?	{ TOKEN(LITERAL_FLOAT); }
 
-\"(\\.|[^\\"])*\"	{ count(); yylval = yystr(yytext); return(LITERAL_STRING); }
+\"(\\.|[^\\"])*\"	{ TOKEN(LITERAL_STRING); }
 
-">>="			{ count(); return(RIGHT_ASSIGN); }
-"<<="			{ count(); return(LEFT_ASSIGN); }
-"+="			{ count(); return(ADD_ASSIGN); }
-"-="			{ count(); return(SUB_ASSIGN); }
-"*="			{ count(); return(MUL_ASSIGN); }
-"/="			{ count(); return(DIV_ASSIGN); }
-"%="			{ count(); return(MOD_ASSIGN); }
-"&="			{ count(); return(AND_ASSIGN); }
-"^="			{ count(); return(XOR_ASSIGN); }
-"|="			{ count(); return(OR_ASSIGN); }
-">>"			{ count(); return(RIGHT_OP); }
-"<<"			{ count(); return(LEFT_OP); }
-"++"			{ count(); return(INC_OP); }
-"--"			{ count(); return(DEC_OP); }
-"->"			{ count(); return(PTR_OP); }
-"&&"			{ count(); return(AND_OP); }
-"||"			{ count(); return(OR_OP); }
-"<="			{ count(); return(LE_OP); }
-">="			{ count(); return(GE_OP); }
-"=="			{ count(); return(EQ_OP); }
-"!="			{ count(); return(NE_OP); }
-";"			{ count(); return(';'); }
-"{"			{ count(); return('{'); }
-"}"			{ count(); return('}'); }
-","			{ count(); return(','); }
-":"			{ count(); return(':'); }
-"="			{ count(); return('='); }
-"("			{ count(); return('('); }
-")"			{ count(); return(')'); }
-"["			{ count(); return('['); }
-"]"			{ count(); return(']'); }
-"."			{ count(); return('.'); }
-"&"			{ count(); return('&'); }
-"!"			{ count(); return('!'); }
-"~"			{ count(); return('~'); }
-"-"			{ count(); return('-'); }
-"+"			{ count(); return('+'); }
-"*"			{ count(); return('*'); }
-"/"			{ count(); return('/'); }
-"%"			{ count(); return('%'); }
-"<"			{ count(); return('<'); }
-">"			{ count(); return('>'); }
-"^"			{ count(); return('^'); }
-"|"			{ count(); return('|'); }
-"?"			{ count(); return('?'); }
+">>="			{ TOKEN(RIGHT_ASSIGN); }
+"<<="			{ TOKEN(LEFT_ASSIGN); }
+"+="			{ TOKEN(ADD_ASSIGN); }
+"-="			{ TOKEN(SUB_ASSIGN); }
+"*="			{ TOKEN(MUL_ASSIGN); }
+"/="			{ TOKEN(DIV_ASSIGN); }
+"%="			{ TOKEN(MOD_ASSIGN); }
+"&="			{ TOKEN(AND_ASSIGN); }
+"^="			{ TOKEN(XOR_ASSIGN); }
+"|="			{ TOKEN(OR_ASSIGN); }
+">>"			{ TOKEN(RIGHT_OP); }
+"<<"			{ TOKEN(LEFT_OP); }
+"++"			{ TOKEN(INC_OP); }
+"--"			{ TOKEN(DEC_OP); }
+"->"			{ TOKEN(PTR_OP); }
+"&&"			{ TOKEN(AND_OP); }
+"||"			{ TOKEN(OR_OP); }
+"<="			{ TOKEN(LE_OP); }
+">="			{ TOKEN(GE_OP); }
+"=="			{ TOKEN(EQ_OP); }
+"!="			{ TOKEN(NE_OP); }
+";"			{ TOKEN(';'); }
+"{"			{ TOKEN('{'); }
+"}"			{ TOKEN('}'); }
+","			{ TOKEN(','); }
+":"			{ TOKEN(':'); }
+"="			{ TOKEN('='); }
+"("			{ TOKEN('('); }
+")"			{ TOKEN(')'); }
+"["			{ TOKEN('['); }
+"]"			{ TOKEN(']'); }
+"."			{ TOKEN('.'); }
+"&"			{ TOKEN('&'); }
+"!"			{ TOKEN('!'); }
+"~"			{ TOKEN('~'); }
+"-"			{ TOKEN('-'); }
+"+"			{ TOKEN('+'); }
+"*"			{ TOKEN('*'); }
+"/"			{ TOKEN('/'); }
+"%"			{ TOKEN('%'); }
+"<"			{ TOKEN('<'); }
+">"			{ TOKEN('>'); }
+"^"			{ TOKEN('^'); }
+"|"			{ TOKEN('|'); }
+"?"			{ TOKEN('?'); }
 
 [ \t\v\n\f]		{ count(); }
 .			{ /* ignore bad characters */ }
 
 %%
 
-yywrap()
+int yywrap()
 {
-	return(1);
+    return 1;
 }
 
-comment()
+void comment()
 {
-	char c, c1;
-
-loop:
-	while ((c = input()) != '*' && c != 0)
-		putchar(c);
-
-	if ((c1 = input()) != '/' && c != 0)
-	{
-		/*unput(c1);*/
-		goto loop;
-	}
-
-	if (c != 0)
-		putchar(c1);
+    char c, c1;
+    
+    c = input();
+    do {
+        while (c != '*') {
+            if (!c) return;
+            c = input();
+        }
+        c = input();
+    } while (c != '/');
 }
 
 int column = 0;
 
 void count()
 {
-	int i;
+    int i;
 
-	for (i = 0; yytext[i] != '\0'; i++)
-		if (yytext[i] == '\n')
-			column = 0;
-		else if (yytext[i] == '\t')
-			column += 8 - (column % 8);
-		else
-			column++;
-
-	ECHO;
+    for (i = 0; yytext[i] != '\0'; i++)
+        if (yytext[i] == '\n')
+            column = 0;
+        else if (yytext[i] == '\t')
+            column += 4 - (column % 4);
+        else
+            column++;
 }
 
-int check_type()
+void get_token()
 {
-/*
-* pseudo code --- this is what it should check
-*
-*	if (yytext == type_name)
-*		return(TYPE_NAME);
-*
-*	return(IDENTIFIER);
-*/
+    count();
+    yylval = token(yytext, yylineno, column);
+}
 
-/*
-*	it actually will only return IDENTIFIER
-*/
-	yylval = name(yytext);
-	return(IDENTIFIER);
+int get_name_token()
+{
+    int is_type_name;
+    yylval = name_token(yytext, yylineno, column, &is_type_name);
+    return is_type_name ? TYPE_NAME : IDENTIFIER;
 }



More information about the cig-commits mailing list