public JBurgGenerator()

in compiler-jburg-types/src/main/java/jburg/burg/JBurgGenerator.java [354:657]


    public JBurgGenerator(AST root, Logger log) throws Exception
    {
        this.logger = log;

        //  Walk over the children of the root, each of which 
		//  is a self-contained syntactical construct, and
        //  find an appropriate action for each.
        for (AST currentNode = root; currentNode != null;
                currentNode = currentNode.getNextSibling()) 
		{
            switch (currentNode.getType()) 
			{
            case COST_FUNCTION:
                this.costFunctions.add(currentNode);
                break;

            case HEADER_DECLARATION:

				if ( null == this.headerBlock )
				{
					this.headerBlock = getCodeBlock(currentNode);
				}
				else
				{
                    throw new IllegalArgumentException("The class header may only be specified once.");
				}

                break;
                
            case INCLASS_DECLARATION:
				{
            		this.inclassCode.add( stripBrackets(getCodeBlock(currentNode)) );
            	}
				
				break;

            case INODE_ADAPTER_DECLARATION:

                if (this.iNodeAdapterClass == null)
				{
					this.iNodeAdapterClass = getIdentifierText(currentNode.getFirstChild());
				}
				else
				{
                    throw new IllegalArgumentException("INodeAdapter may only be specified once.");
				}

				break;

            case INODE_TYPE_DECLARATION:

                if (this.iNodeClass == null)
				{
                    this.iNodeClass = getIdentifierText(currentNode.getFirstChild());
				}
                else
				{
                    throw new IllegalArgumentException("INodeType may only be specified once.");
				}

                break;
                
            case LANGUAGE_DECLARATION:

            	if ( null == this.emitLanguageName )
				{
            		this.emitLanguageName = currentNode.getFirstChild().getText();
				}
            	else
				{
            		throw new IllegalArgumentException("Language may only be specified once.");
				}

            	break;

            case IMPLEMENTS_INTERFACE_SPECIFICATION:
                this.interfaceNames.addElement(getIdentifierText( currentNode.getFirstChild()) );

                break;

            case PACKAGE_SPECIFICATION:
                if ( null == this.packageName )
				{
					this.packageName = getIdentifierText(currentNode.getFirstChild());
				}
				else
				{
            		throw new IllegalArgumentException("package may only be specified once.");
				}

                break;

            case PROPERTY_SPECIFICATION: 
				{
					String propertyType = getIdentifierText(currentNode.getFirstChild());
					String propertyName = currentNode.getFirstChild().getNextSibling().getText();
					this.burmProperties.put(propertyName, propertyType);
				}

                break;

            case RETURN_DECLARATION:

                if (this.defaultReturnType == null)
                    this.defaultReturnType = getIdentifierText(currentNode.getFirstChild());
                else
                    throw new IllegalArgumentException( "ReturnType may only be specified once.");

                break;

            case PATTERN_RULE:
                addPatternRule(currentNode);

                break;

            case SIMPLE_TRANSFORMATION_RULE:
                addSimpleTransformationRule(currentNode);

                break;

            case TRANSFORMATION_RULE:
                addComplexTransformationRule(currentNode);

                break;

            case TYPED_RETURN_DECLARATION:

                {
                    String stateName = currentNode.getFirstChild().getText();
                    String returnType = getIdentifierText(currentNode.getFirstChild()
                            .getNextSibling());

                    //  Put the return declaration in the table, but only once per state.
                    Object typeCollision = this.returnTypeTable.put(stateName, returnType);
                    if ( null != typeCollision )
                    {
                        throw new IllegalArgumentException(
                            "A state may only specify one ReturnType."
                        );
                    }
                }

                break;

            case PATTERN_DECLARATION:
                {
                    String pattern_name = currentNode.getFirstChild().getText();
                    namedPatterns.addPattern(pattern_name, currentNode);
                }
                break;

            case REDUCTION_DECLARATION:
                {
                    String pattern_name = currentNode.getFirstChild().getNextSibling().getText();
                    namedPatterns.addReduction(pattern_name, currentNode);
                }
                break;

            case DEFAULT_ERROR_HANDLER:
                this.defaultErrorHandler = getCodeBlock(currentNode);
                break;
            case NODE_TYPE:
            {
                final String operatorID = currentNode.getFirstChild().getText();
                assert !operatorID.isEmpty() : "Parser should never create empty operator!";
                final String nodeType = currentNode.getFirstChild().getNextSibling().getText();               
                assert !nodeType.isEmpty() : "Parser should never create empty node type!";
                
                if (this.opcodeNodeTypes.put(operatorID, nodeType) != null)
                {
                    final String message = "Duplicate node type declaration for '"
                        + operatorID
                        + "'.";
                    throw new IllegalArgumentException(message);
                }
                break;
            }
            case OPCODE_TYPE:
                this.opcodeType = currentNode.getFirstChild().getText();
                break;

            case MANIFEST_CONSTANT:
                manifestConstants.put(currentNode.getFirstChild().getText(), Integer.parseInt(currentNode.getFirstChild().getNextSibling().getText()));
                break;

            default:
                throw new IllegalArgumentException("Unknown specification AST type " +
            											String.valueOf(currentNode.getType()));
            }
        }

        //  Set the language emitter.
        codeEmitter = JBurgEmitterFactory.getEmitter(emitLanguageName, getLogger());

        if ( codeEmitter == null )
		{
			throw new IllegalStateException("Unknown language specified: \""+ emitLanguageName +"\"");
        }

		if ( iNodeClass != null )
		{
			if ( iNodeAdapterClass != null )
			{
				try
				{
					this.iNodeAdapter = (InodeAdapter)Class.forName(iNodeAdapterClass).newInstance();
				}
				catch ( Exception ex )
				{
					ex.printStackTrace();
					throw new IllegalArgumentException ("Unable to instantiate i-node adapter " + iNodeAdapterClass );
				}
			}
			else
			{
				this.iNodeAdapter = InodeAdapterFactory.getAdapter(iNodeClass);
			}
			
			codeEmitter.setINodeType(this.iNodeClass);

			if ( this.iNodeAdapter != null )
			{
				logger.info("Using i-node adapter " + this.iNodeAdapter.getClass().getName() );
			}
			else
			{
				getLogger().warning("using default i-node adapter, no adapter matches " + iNodeClass );
				this.iNodeAdapter = new jburg.burg.inode.DefaultAdapter();
			}
			
			//  See if the adapter is also an InodeAdapter2 implementation.
			this.adapter2 = (this.iNodeAdapter instanceof InodeAdapter2)? (InodeAdapter2)this.iNodeAdapter : null;
		}
		else
		{
			throw new IllegalStateException("You must specify the i-node type.");
		}

		codeEmitter.setInodeAdapter(this.iNodeAdapter);

        //  Default return type is the same as the INode class.
        if (this.defaultReturnType == null)
		{
            this.defaultReturnType = this.iNodeClass;
		}

        //  Mutate pattern/reduction decl pairs into pattern rules.
        for ( NamedPattern np: namedPatterns.values() )
        {
            if ( np.pattern != null && np.reductions.size() > 0 )
            {
                AST named_pattern = np.pattern.getFirstChild().getNextSibling().getFirstChild();

                for ( AST reduction: np.reductions )
                {    
                    //  Splice the pattern into the reduction AST.
                
                    AST nt_state = reduction.getFirstChild();
                    AST pattern_name = nt_state.getNextSibling();
                    AST cost_decl = pattern_name.getNextSibling();
                    
                    //  Create a new holder for the pattern
                    //  so the original AST isn't mutated.
                    AST pattern_holder = new antlr.CommonAST();
                    pattern_holder.setFirstChild(named_pattern);
                    nt_state.setNextSibling(pattern_holder);
                    pattern_holder.setNextSibling(cost_decl);
    
                    //  Give the composite AST the appropriate type
                    //  for its pattern.
                    reduction.setType(PATTERN_RULE);
    
                    addPatternRule(reduction);
                }
            }
            else if ( np.pattern != null )
            {
                getLogger().warning("pattern " + np.patternName + " has no reduction - ignored.");
            }
            else if ( np.reductions.size() > 0 )
            {
                throw new IllegalStateException("Reduction " + np.patternName + " has no associated pattern.");
            }
        }

        //  Add target-specific logic to the simple transformations' rules.
        for ( JBurgRule rule: this.simpleTransformationRules.values() )
        {
            String actionCode = String.format(
                "%s%s",
                codeEmitter.genReturnValue(
                    codeEmitter.genPopFromStack(reducedValuesName, getReturnType(rule.getGoalState()))
                ),
                codeEmitter.genEndStmt()
            );

            JBurgReduceAction action = addAction(actionCode, rule.getGoalState());
            action.setAntecedentState(rule.getAntecedentState());
            rule.setReduceAction(action);
        }

        //  Compute the closure sets.
        computeClosureSets();
    }