use strict;
use UNIVERSAL;

#
#			Interface Definition Language (OMG IDL CORBA v3.0)
#

package asciiVisitor;

sub new {
	my $proto = shift;
	my $class = ref($proto) || $proto;
	my $self = {};
	bless($self, $class);
	my($parser) = @_;
	$self->{srcname} = $parser->YYData->{srcname};
	$self->{symbtab} = $parser->YYData->{symbtab};
	my $filename = $self->{srcname};
	$filename =~ s/^([^\/]+\/)+//;
	$filename =~ s/\.idl$//i;
	$filename .= '.ast';
	open(STDOUT, "> $filename")
			or die "can't open $filename ($!).\n";
	$self->{num_key} = 'num_ascii';
	return $self;
}

sub reset_tab {
	my $self = shift;
	$self->{tab} = '';
}

sub inc_tab {
	my $self = shift;
	$self->{tab} .= "\t";
}

sub dec_tab {
	my $self = shift;
	$self->{tab} =~ s/\t$//;
}

sub get_tab {
	my $self = shift;
	return $self->{tab};
}

sub _get_defn {
	my $self = shift;
	my($defn) = @_;
	if (ref $defn) {
		return $defn;
	} else {
		return $self->{symbtab}->Lookup($defn);
	}
}

sub visitType {
	my $self = shift;
	my ($type) = @_;

	if (ref $type) {
		$type->visit($self);
	} else {
		print $self->get_tab(), "type $type\n";
	}
}

#
#	3.5		OMG IDL Specification
#

sub visitSpecification {
	my $self = shift;
	my($node) = @_;
	$self->reset_tab();
	print "source $self->{srcname} \n\n";
	foreach (@{$node->{list_decl}}) {
		$self->_get_defn($_)->visit($self);
	}
}

#
#	3.6		Import Declaration
#

sub visitImport {
	my $self = shift;
	my($node) = @_;
	print $self->get_tab(), "import $node->{value}\n";
}

#
#	3.7		Module Declaration
#

sub visitModules {
	my $self = shift;
	my($node) = @_;
	print $self->get_tab(), "module $node->{idf} '$node->{repos_id}'\n";
	unless (exists $node->{$self->{num_key}}) {
		$node->{$self->{num_key}} = 0;
	}
	my $module = ${$node->{list_decl}}[$node->{$self->{num_key}}];
	$module->visit($self);
	$node->{$self->{num_key}} ++;
}

sub visitModule {
	my $self = shift;
	my($node) = @_;
	$self->inc_tab();
	print $self->get_tab(), "doc: $node->{doc}\n"
			if (exists $node->{doc});
	foreach (@{$node->{list_decl}}) {
		$self->_get_defn($_)->visit($self);
	}
	$self->dec_tab();
}

#
#	3.8		Interface Declaration
#

sub visitRegularInterface {
	my $self = shift;
	my($node) = @_;
	print $self->get_tab(), "interface $node->{idf} '$node->{repos_id}'\n";
	$self->inc_tab();
	print $self->get_tab(), "doc: $node->{doc}\n"
			if (exists $node->{doc});
	if (exists $node->{inheritance}) {
		$node->{inheritance}->visit($self);
	}
	foreach (@{$node->{list_decl}}) {
		$self->_get_defn($_)->visit($self);
	}
	$self->dec_tab();
}

sub visitAbstractInterface {
	my $self = shift;
	my($node) = @_;
	print $self->get_tab(), "interface $node->{idf} '$node->{repos_id}'\n";
	$self->inc_tab();
	print $self->get_tab(), "doc: $node->{doc}\n"
			if (exists $node->{doc});
	if (exists $node->{inheritance}) {
		$node->{inheritance}->visit($self);
	}
	foreach (@{$node->{list_decl}}) {
		$self->_get_defn($_)->visit($self);
	}
	$self->dec_tab();
}

sub visitLocalInterface {
	my $self = shift;
	my($node) = @_;
	print $self->get_tab(), "local interface $node->{idf} '$node->{repos_id}'\n";
	$self->inc_tab();
	print $self->get_tab(), "doc: $node->{doc}\n"
			if (exists $node->{doc});
	if (exists $node->{inheritance}) {
		$node->{inheritance}->visit($self);
	}
	foreach (@{$node->{list_decl}}) {
		$self->_get_defn($_)->visit($self);
	}
	$self->dec_tab();
}

sub visitForwardRegularInterface {
	my $self = shift;
	my($node) = @_;
	print $self->get_tab(), "forward interface $node->{idf}\n";
}

sub visitForwardAbstractInterface {
	my $self = shift;
	my($node) = @_;
	print $self->get_tab(), "forward abstract interface $node->{idf}\n";
}

sub visitForwardLocalInterface {
	my $self = shift;
	my($node) = @_;
	print $self->get_tab(), "forward local interface $node->{idf}\n";
}

#
#	3.9		Value Declaration
#
#	3.9.1	Regular Value Type
#

sub visitRegularValue {
	my $self = shift;
	my($node) = @_;
	print $self->get_tab(), "regular value $node->{idf} '$node->{repos_id}'\n";
	$self->inc_tab();
	print $self->get_tab(), "doc: $node->{doc}\n"
			if (exists $node->{doc});
	if (exists $node->{modifier}) {		# custom
		print $self->get_tab(), "modifier $node->{modifier}\n";
	}
	if (exists $node->{inheritance}) {
		$node->{inheritance}->visit($self);
	}
	foreach (@{$node->{list_decl}}) {
		$self->_get_defn($_)->visit($self);
	}
	$self->dec_tab();
}

sub visitInheritanceSpec {
	my $self = shift;
	my($node) = @_;
	print $self->get_tab(), "inheritance spec\n";
	$self->inc_tab();
	if (exists $node->{modifier}) {		# truncatable
		print $self->get_tab(), "modifier $node->{modifier}\n";
	}
	if (exists $node->{list_value}) {
		foreach (@{$node->{list_value}}) {
			print $self->get_tab(), "value $_\n";
		}
	}
	if (exists $node->{list_interface}) {
		foreach (@{$node->{list_interface}}) {
			print $self->get_tab(), "interface $_\n";
		}
	}
	$self->dec_tab();
}

sub visitStateMembers {
	my $self = shift;
	my($node) = @_;
	print $self->get_tab(), "state members\n";
	$self->inc_tab();
	foreach (@{$node->{list_decl}}) {
		$self->_get_defn($_)->visit($self);
	}
	$self->dec_tab();
}

sub visitStateMember {
	my $self = shift;
	my($node) = @_;
	print $self->get_tab(), "$node->{modifier} $node->{idf}\n";
	$self->inc_tab();
	$self->visitType($node->{type});
	if (exists $node->{array_size}) {
		foreach (@{$node->{array_size}}) {
			$_->visit($self);			# expression
		}
	}
	$self->dec_tab();
}

sub visitInitializer {
	my $self = shift;
	my($node) = @_;
	print $self->get_tab(), "factory $node->{idf}\n";
	$self->inc_tab();
	print $self->get_tab(), "doc: $node->{doc}\n"
			if (exists $node->{doc});
	foreach (@{$node->{list_param}}) {
		$_->visit($self);
	}
	if (exists $node->{list_raise}) {
		foreach (@{$node->{list_raise}}) {		# exception
			print $self->get_tab(), "raise $_\n";
		}
	}
	$self->dec_tab();
}

#
#	3.9.2	Boxed Value Type
#

sub visitBoxedValue {
	my $self = shift;
	my($node) = @_;
	print $self->get_tab(), "boxed value $node->{idf} '$node->{repos_id}'\n";
	$self->inc_tab();
	print $self->get_tab(), "doc: $node->{doc}\n"
			if (exists $node->{doc});
	$self->visitType($node->{type});
	$self->dec_tab();
}

#
#	3.9.3	Abstract Value Type
#

sub visitAbstractValue {
	my $self = shift;
	my($node) = @_;
	print $self->get_tab(), "abstract value $node->{idf} '$node->{repos_id}'\n";
	$self->inc_tab();
	print $self->get_tab(), "doc: $node->{doc}\n"
			if (exists $node->{doc});
	if (exists $node->{inheritance}) {
		$node->{inheritance}->visit($self);
	}
	foreach (@{$node->{list_decl}}) {
		$self->_get_defn($_)->visit($self);
	}
	$self->dec_tab();
}

#
#	3.9.4	Value Forward Declaration
#

sub visitForwardRegularValue {
	my $self = shift;
	my($node) = @_;
	print $self->get_tab(), "forward regular value $node->{idf}\n";
}

sub visitForwardAbstractValue {
	my $self = shift;
	my($node) = @_;
	print $self->get_tab(), "forward abstract value $node->{idf}\n";
}

#
#	3.10		Constant Declaration
#

sub visitConstant {
	my $self = shift;
	my($node) = @_;
	print $self->get_tab(), "constant $node->{idf}\n";
	$self->inc_tab();
	print $self->get_tab(), "doc: $node->{doc}\n"
			if (exists $node->{doc});
	$self->visitType($node->{type});
	$node->{value}->visit($self);		# expression
	$self->dec_tab();
}

sub visitExpression {
	my $self = shift;
	my($node) = @_;
	print $self->get_tab(), "expression value $node->{value}\n";
	$self->inc_tab();
	foreach my $elt (@{$node->{list_expr}}) {
		if (ref $elt) {
			if ($elt->isa('Constant')) {
				print $self->get_tab(), "constant $elt->{idf}\n";
			} else {
				$elt->visit($self);			# literal, unop, binop
			}
		} else {
			print $self->get_tab(), "entry $elt\n";
		}
	}
	$self->dec_tab();
}

sub visitUnaryOp {
	my $self = shift;
	my($node) = @_;
	print $self->get_tab(), "unop $node->{op}\n";
}

sub visitBinaryOp {
	my $self = shift;
	my($node) = @_;
	print $self->get_tab(), "binop $node->{op}\n";
}

sub visitLiteral {
	my $self = shift;
	my($node) = @_;
	print $self->get_tab(), "literal $node->{value}\n";
}

#
#	3.11	Type Declaration
#

sub visitTypeDeclarators {
	my $self = shift;
	my($node) = @_;
	print $self->get_tab(), "type declarators\n";
	$self->inc_tab();
	foreach (@{$node->{list_decl}}) {
		$self->_get_defn($_)->visit($self);
	}
	$self->dec_tab();
}

sub visitTypeDeclarator {
	my $self = shift;
	my($node) = @_;
	if (exists $node->{modifier}) {		# native IDL2.2
		print $self->get_tab(), "type declarator $node->{idf}\n";
		$self->inc_tab();
		print $self->get_tab(), "modifier $node->{modifier}\n";
	} else {
		print $self->get_tab(), "type declarator $node->{idf} '$node->{repos_id}'\n";
		$self->inc_tab();
		print $self->get_tab(), "doc: $node->{doc}\n"
				if (exists $node->{doc});
		$self->visitType($node->{type});
		if (exists $node->{array_size}) {
			foreach (@{$node->{array_size}}) {
				$_->visit($self);				# expression
			}
		}
	}
	$self->dec_tab();
}

#
#	3.11.1	Basic Types
#

sub visitBasicType {
	my $self = shift;
	my($node) = @_;
	print $self->get_tab(), "basic type $node->{value}\n";
}

#
#	3.11.2	Constructed Types
#
#	3.11.2.1	Structures
#

sub visitStructType {
	my $self = shift;
	my($node) = @_;
	if (defined $node->{list_expr}) {
		print $self->get_tab(), "struct $node->{idf} '$node->{repos_id}'\n";
		$self->inc_tab();
		push @{$self->{seq}}, $node;
		foreach (@{$node->{list_expr}}) {
			$_->visit($self);				# members
		}
#		foreach (@{$node->{list_value}}) {
#			$self->_get_defn($_)->visit($self);		# single or array
#		}
		pop @{$self->{seq}};
		$self->dec_tab();
	} else {
		print $self->get_tab(), "struct $node->{idf} (forward)\n";
	}
}

sub visitMembers {
	my $self = shift;
	my($node) = @_;
	print $self->get_tab(), "members\n";
	$self->inc_tab();
	foreach (@{$node->{list_value}}) {
		$self->_get_defn($_)->visit($self);		# single or array
	}
	$self->dec_tab();
}

sub visitArray {
	my $self = shift;
	my($node) = @_;
	print $self->get_tab(), "array $node->{idf}\n";
	$self->inc_tab();
	$self->visitType($node->{type});
	foreach (@{$node->{array_size}}) {
		$_->visit($self);				# expression
	}
	$self->dec_tab();
}

sub visitSingle {
	my $self = shift;
	my($node) = @_;
	print $self->get_tab(), "single $node->{idf}\n";
	$self->inc_tab();
	$self->visitType($node->{type});
	$self->dec_tab();
}

#	3.11.2.2	Discriminated Unions
#

sub visitUnionType {
	my $self = shift;
	my($node) = @_;
	if (defined $node->{list_expr}) {
		print $self->get_tab(), "union $node->{idf} '$node->{repos_id}'\n";
		$self->inc_tab();
		print $self->get_tab(), "doc: $node->{doc}\n"
				if (exists $node->{doc});
		push @{$self->{seq}}, $node;
		foreach (@{$node->{list_expr}}) {
			$_->visit($self);				# case
		}
		pop @{$self->{seq}};
		$self->dec_tab();
	} else {
		print $self->get_tab(), "union $node->{idf} (forward)\n";
	}
}

sub visitCase {
	my $self = shift;
	my($node) = @_;
	print $self->get_tab(), "case\n";
	$self->inc_tab();
	foreach (@{$node->{list_label}}) {
		$_->visit($self);				# default or expression
	}
	$node->{element}->visit($self);
	$self->dec_tab();
}

sub visitDefault {
	my $self = shift;
	my($node) = @_;
	print $self->get_tab(), "default\n";
}

sub visitElement {
	my $self = shift;
	my($node) = @_;
	$self->_get_defn($node->{value})->visit($self);		# single or array
}

#	3.11.2.3	Constructed Recursive Types and Forward Declarations
#

sub visitForwardStructType {
	my $self = shift;
	my($node) = @_;
	print $self->get_tab(), "forward struct $node->{idf}\n";
}

sub visitForwardUnionType {
	my $self = shift;
	my($node) = @_;
	print $self->get_tab(), "forward union $node->{idf}\n";
}

#	3.11.2.4	Enumerations
#

sub visitEnumType {
	my $self = shift;
	my($node) = @_;
	print $self->get_tab(), "enum $node->{idf} '$node->{repos_id}'\n";
	$self->inc_tab();
	print $self->get_tab(), "doc: $node->{doc}\n"
			if (exists $node->{doc});
	foreach (@{$node->{list_expr}}) {
		$_->visit($self);				# enum
	}
	$self->dec_tab();
}

sub visitEnum {
	my $self = shift;
	my($node) = @_;
	print $self->get_tab(), "$node->{idf}\n";
}

#
#	3.11.3	Template Types
#

sub visitSequenceType {
	my $self = shift;
	my($node) = @_;
	print $self->get_tab(), "sequence\n";
	$self->inc_tab();
	my $found = 0;						# recursion prevention
	foreach (@{$self->{seq}}) {
		if ($_ eq $node->{type}) {
			$found = 1;
			last;
		}
	}
	if ($found) {
		print $self->get_tab(), "recursion $node->{type}\n";
	} else {
		push @{$self->{seq}}, $node;
		$self->visitType($node->{type});
		pop @{$self->{seq}};
	}
	if (exists $node->{max}) {
		$node->{max}->visit($self);
	}
	$self->dec_tab();
}

sub visitStringType {
	my $self = shift;
	my($node) = @_;
	print $self->get_tab(), "string\n";
	$self->inc_tab();
	if (exists $node->{max}) {
		$node->{max}->visit($self);
	}
	$self->dec_tab();
}

sub visitWideStringType {
	my $self = shift;
	my($node) = @_;
	print $self->get_tab(), "wstring\n";
	$self->inc_tab();
	if (exists $node->{max}) {
		$node->{max}->visit($self);
	}
	$self->dec_tab();
}

sub visitFixedPtType {
	my $self = shift;
	my($node) = @_;
	print $self->get_tab(), "fixed\n";
	$self->inc_tab();
	$node->{d}->visit($self);
	$node->{s}->visit($self);
	$self->dec_tab();
}

sub visitFixedPtConstType {
	my $self = shift;
	my($node) = @_;
	print $self->get_tab(), "fixed\n";
}

#
#	3.12	Exception Declaration
#

sub visitException {
	my $self = shift;
	my($node) = @_;
	print $self->get_tab(), "exception $node->{idf} '$node->{repos_id}'\n";
	$self->inc_tab();
	print $self->get_tab(), "doc: $node->{doc}\n"
			if (exists $node->{doc});
	if (exists $node->{list_expr}) {
		foreach (@{$node->{list_expr}}) {
			$_->visit($self);			# members
		}
	}
#	foreach (@{$node->{list_value}}) {
#			$self->_get_defn($_)->visit($self);		# single or array
#	}
	$self->dec_tab();
}

#
#	3.13	Operation Declaration
#

sub visitOperation {
	my $self = shift;
	my($node) = @_;
	print $self->get_tab(), "operation $node->{idf}\n";
	$self->inc_tab();
	print $self->get_tab(), "doc: $node->{doc}\n"
			if (exists $node->{doc});
	if (exists $node->{attr}) {			# oneway
		print $self->get_tab(), "attribute $node->{attr}\n";
	}
	$self->visitType($node->{type});
	foreach (@{$node->{list_param}}) {
		$_->visit($self);				# parameter
	}
	if (exists $node->{list_raise}) {
		foreach (@{$node->{list_raise}}) {		# exception
			print $self->get_tab(), "raise $_\n";
		}
	}
	if (exists $node->{list_context}) {
		foreach (@{$node->{list_context}}) {	# string literal
			print $self->get_tab(), "context $_->{value}\n";
		}
	}
	$self->dec_tab();
}

sub visitParameter {
	my $self = shift;
	my($node) = @_;
	print $self->get_tab(), "parameter $node->{idf}\n";
	$self->inc_tab();
	# in, out, inout
	print $self->get_tab(), "attribute $node->{attr}\n";
	$self->visitType($node->{type});
	$self->dec_tab();
}

sub visitVoidType {
	my $self = shift;
	my($node) = @_;
	print $self->get_tab(), "void\n";
}

#
#	3.14	Attribute Declaration
#

sub visitAttributes {
	my $self = shift;
	my($node) = @_;
	print $self->get_tab(), "attributes\n";
	$self->inc_tab();
	foreach (@{$node->{list_decl}}) {
		$self->_get_defn($_)->visit($self);
	}
	$self->dec_tab();
}

sub visitAttribute {
	my $self = shift;
	my($node) = @_;
	print $self->get_tab(), "attribute $node->{idf}\n";
	$self->inc_tab();
	print $self->get_tab(), "doc: $node->{doc}\n"
			if (exists $node->{doc});
	if (exists $node->{modifier}) {		# readonly
		print $self->get_tab(), "modifier $node->{modifier}\n";
	}
	if (exists $node->{list_getraise}) {
		foreach (@{$node->{list_getraise}}) {		# exception
			print $self->get_tab(), "getraise $_\n";
		}
	}
	if (exists $node->{list_setraise}) {
		foreach (@{$node->{list_setraise}}) {		# exception
			print $self->get_tab(), "setraise $_\n";
		}
	}
	$self->visitType($node->{type});
	$self->dec_tab();
}

#
#	3.15	Repository Identity Related Declarations
#

sub visitTypeId {
	my $self = shift;
	my($node) = @_;
	print $self->get_tab(), "typeid $node->{idf} '$node->{value}'\n";
}

sub visitTypePrefix {
	my $self = shift;
	my($node) = @_;
	print $self->get_tab(), "typeprefix $node->{idf} '$node->{value}'\n";
}

#
#	3.16	Event Declaration
#

sub visitRegularEvent {
	my $self = shift;
	my($node) = @_;
	print $self->get_tab(), "regular event $node->{idf} '$node->{repos_id}'\n";
	$self->inc_tab();
	print $self->get_tab(), "doc: $node->{doc}\n"
			if (exists $node->{doc});
	if (exists $node->{modifier}) {		# custom
		print $self->get_tab(), "modifier $node->{modifier}\n";
	}
	if (exists $node->{inheritance}) {
		$node->{inheritance}->visit($self);
	}
	foreach (@{$node->{list_decl}}) {
		$self->_get_defn($_)->visit($self);
	}
	$self->dec_tab();
}

sub visitAbstractEvent {
	my $self = shift;
	my($node) = @_;
	print $self->get_tab(), "abstract event $node->{idf} '$node->{repos_id}'\n";
	$self->inc_tab();
	print $self->get_tab(), "doc: $node->{doc}\n"
			if (exists $node->{doc});
	if (exists $node->{inheritance}) {
		$node->{inheritance}->visit($self);
	}
	foreach (@{$node->{list_decl}}) {
		$self->_get_defn($_)->visit($self);
	}
	$self->dec_tab();
}

sub visitForwardRegularEvent {
	my $self = shift;
	my($node) = @_;
	print $self->get_tab(), "forward regular event $node->{idf}\n";
}

sub visitForwardAbstractEvent {
	my $self = shift;
	my($node) = @_;
	print $self->get_tab(), "forward abstract event $node->{idf}\n";
}

#
#	3.17	Component Declaration
#

sub visitComponent {
	my $self = shift;
	my($node) = @_;
	print $self->get_tab(), "component $node->{idf} '$node->{repos_id}'\n";
	$self->inc_tab();
	print $self->get_tab(), "doc: $node->{doc}\n"
			if (exists $node->{doc});
	if (exists $node->{inheritance}) {
		$node->{inheritance}->visit($self);
	}
	if (exists $node->{list_support}) {
		print $self->get_tab(), "supports \n";
		foreach (@{$node->{list_support}}) {
			$_->visit($self);
		}
	}
	print $self->get_tab(), "exports \n";
	foreach (@{$node->{list_decl}}) {
		$self->_get_defn($_)->visit($self);
	}
	$self->dec_tab();
}

sub visitForwardComponent {
	my $self = shift;
	my($node) = @_;
	print $self->get_tab(), "forward component $node->{idf}\n";
}

sub visitProvides {
	my $self = shift;
	my($node) = @_;
	print $self->get_tab(), "provides $node->{idf} $node->{type}\n";
}

sub visitUses {
	my $self = shift;
	my($node) = @_;
	print $self->get_tab(), "uses $node->{idf} $node->{type}\n";
	$self->inc_tab();
	if (exists $node->{modifier}) {		# multiple
		print $self->get_tab(), "modifier $node->{modifier}\n";
	}
	$self->dec_tab();
}

sub visitPublishes {
	my $self = shift;
	my($node) = @_;
	print $self->get_tab(), "publishes $node->{idf} $node->{type}\n";
}

sub visitEmits {
	my $self = shift;
	my($node) = @_;
	print $self->get_tab(), "emits $node->{idf} $node->{type}\n";
}

sub visitConsumes {
	my $self = shift;
	my($node) = @_;
	print $self->get_tab(), "consumes $node->{idf} $node->{type}\n";
}

#
#	3.18	Home Declaration
#

sub visitHome {
	my $self = shift;
	my($node) = @_;
	print $self->get_tab(), "home $node->{idf} '$node->{repos_id}'\n";
	$self->inc_tab();
	print $self->get_tab(), "doc: $node->{doc}\n"
			if (exists $node->{doc});
	if (exists $node->{inheritance}) {
		$node->{inheritance}->visit($self);
	}
	if (exists $node->{list_support}) {
		print $self->get_tab(), "supports \n";
		foreach (@{$node->{list_support}}) {
			$_->visit($self);
		}
	}
	$node->{manage}->visit($self);
	if (exists $node->{primakey}) {
		print $self->get_tab(), "primarykey $self->{primarykey}\n";
	}
	print $self->get_tab(), "exports \n";
	foreach (@{$node->{list_decl}}) {
		$self->_get_defn($_)->visit($self);
	}
	$self->dec_tab();
}

sub visitFactory {
	my $self = shift;
	my($node) = @_;
	print $self->get_tab(), "factory $node->{idf}\n";
	$self->inc_tab();
	print $self->get_tab(), "doc: $node->{doc}\n"
			if (exists $node->{doc});
	foreach (@{$node->{list_param}}) {
		$_->visit($self);
	}
	if (exists $node->{list_raise}) {
		foreach (@{$node->{list_raise}}) {		# exception
			print $self->get_tab(), "raise $_\n";
		}
	}
	$self->dec_tab();
}

sub visitFinder {
	my $self = shift;
	my($node) = @_;
	print $self->get_tab(), "finder $node->{idf}\n";
	$self->inc_tab();
	print $self->get_tab(), "doc: $node->{doc}\n"
			if (exists $node->{doc});
	foreach (@{$node->{list_param}}) {
		$_->visit($self);
	}
	if (exists $node->{list_raise}) {
		foreach (@{$node->{list_raise}}) {		# exception
			print $self->get_tab(), "raise $_\n";
		}
	}
	$self->dec_tab();
}

1;

