--- /dev/null
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# AST visitor
+module objc_visitor
+
+import objc_model
+import objc_parser
+
+# AST visitor building `model` from the parsed class headers
+class ObjcVisitor
+ super Visitor
+
+ # `ObjcModel` in construction
+ var model = new ObjcModel
+
+ # `ObjcClass` in construction, if any
+ private var objc_class: nullable ObjcClass = null
+
+ redef fun visit(n) do n.accept_objc(self)
+end
+
+redef class Node
+ private fun accept_objc(v: ObjcVisitor) do visit_children(v)
+end
+
+# ---
+# Main nodes
+
+# Class declaration
+redef class Nlines_interface
+ redef fun accept_objc(v)
+ do
+ var interface_block = n_interface_block
+ if interface_block == null then return
+
+ # If reopening a class, continue with the exisitng one
+ var c = null
+ for objc_class in v.model.classes do
+ if objc_class.name == n_class.text then
+ c = objc_class
+ end
+ end
+
+ # New class
+ if c == null then
+ c = new ObjcClass(n_class.text)
+ v.model.classes.add c
+ end
+ v.objc_class = c
+
+ # Visit superclass declarations
+ var inheritance_block = n_inheritance
+ if inheritance_block != null then v.enter_visit(inheritance_block)
+
+ # Visit main body
+ v.enter_visit(interface_block)
+ end
+end
+
+# Method or function declaration
+redef class Nsignature_block_signature
+ redef fun accept_objc(v)
+ do
+ var method = new ObjcMethod
+ method.return_type = n_signature_return_type.to_type
+ method.scope = if n_scope.is_class_property then '-' else '+'
+
+ for n_param in n_parameter.children do
+ var param = n_param.to_param
+ if param == null then
+
+ # Unsupported parameter format
+ method.is_commented = true
+
+ # Use a placeholder for easier debugging
+ param = new Param
+ param.name = "UNKNOWN"
+ param.return_type = "UNKNOWN"
+ param.variable_name = "UNKNOWN"
+ end
+
+ method.params.add param
+ end
+
+ v.objc_class.methods.add method
+ end
+end
+
+# Class variable/attribute declaration (inside alternative node)
+redef class Nproperty_property
+ redef fun accept_objc(v)
+ do
+ var attr = new ObjcAttribute
+ attr.return_type = n_type.to_type
+ attr.name = n_left.collect_text
+
+ v.objc_class.attributes.add attr
+ end
+end
+
+# Class variable/attribute declaration (outside with @property)
+redef class Nproperty_declaration_property
+ redef fun accept_objc(v)
+ do
+ # TODO property attribute readonly, copy, etc.
+ super
+ end
+end
+
+# ---
+# Support nodes
+
+redef class NProd
+ # Append all tokens under this node in a `String`
+ private fun collect_text: String
+ do
+ var buf = new FlatBuffer
+ for node in depth do if node isa NToken then buf.append node.text
+ return buf.to_s
+ end
+end
+
+redef class Nlines
+ # Do not visit other lines, they are only to be eaten
+ redef fun accept_objc(v) do end
+end
+
+redef class Nscope
+ # Does this mark a class property (+)? Otherwise it's an instance property (-).
+ private fun is_class_property: Bool do return false
+end
+
+redef class Nscope_class
+ redef fun is_class_property do return true
+end
+
+redef class Nsignature_return_type
+ # Get type from this node TODO return an ObjcType
+ private fun to_type: String do return collect_text
+end
+
+redef class Nsignature_return_type_return
+ redef fun to_type do return n_type.to_type
+end
+
+redef class Nparameter
+ # Return null if type is not yet unsupported
+ private fun to_param: nullable Param do return null
+end
+
+# Parameters with both a public and an internal name
+redef class Nparameter_named
+ redef fun to_param
+ do
+ var param = new Param
+ param.variable_name = n_right.collect_text
+ param.name = n_left.collect_text
+ param.return_type = n_parameter_type.to_type
+ return param
+ end
+end
+
+# Usually the name of a method without parameters
+redef class Nparameter_single
+ redef fun to_param
+ do
+ var param = new Param
+ param.name = n_term.collect_text
+ param.is_single = true
+ return param
+ end
+end
+
+redef class Nparameter_type
+ # Get type from this node TODO return an ObjcType
+ private fun to_type: String
+ do
+ # FIXME taking the first token skips pointers
+ for child in children do
+ if child isa Ntype then
+ return child.to_type
+ end
+ end
+
+ return collect_text
+ end
+end
+
+redef class Ntype
+ # Get type from this node TODO return an ObjcType
+ private fun to_type: String do return collect_text
+end