/*
 * Created on 2004-12-21
 *
 * Part of the Symbian development plug-in for Eclipse
 * Copyright (C) Mikołaj Zalewski, 2004
 */
package pl.zalewski.mikolaj.symbdev.core.internal.mmpparser;

import java.util.Iterator;
import java.util.LinkedList;

import org.eclipse.core.resources.IMarker;

import pl.zalewski.mikolaj.symbdev.core.internal.mmpmodel.MMPModel;

/**
 * Parses one command and feeds the model with the result
 * 
 * @author mikolaj
 */
abstract public class AbstractCommandParser {

    /**
     * Creates a command parser 
     * @param model The model to feed with the result
     */
    public AbstractCommandParser(MMPModel model, MMPParser parser) {
        super();
        fModel=model;
        fParser=parser;
    }
    
    /**
     * @param command The command string. Might be <code>null</code>
     * @return If this command depends on SOURCEPATH in the current
     * environment
     */
    static public boolean doesDependOnSourcePath(String command)
    {
        return false;
    }
    
    /**
     * Parses this list of tokens
     * @param l A LinkedList of MMPToken objects
     */
    public void parseCommand(LinkedList l)
    {
        Iterator it=l.iterator();
        FiniteChoiceTokenParser p=new FiniteChoiceTokenParser(it, getKeywords());
        fLastPos=p.fToken.fStartPos+p.fToken.fContent.length();
        if (p.fContent.equalsIgnoreCase("END"))
        {
            if (!fParser.endEnvironment())
                p.setError(IMarker.SEVERITY_ERROR, "No START command");
            return;
        }
        
        p.parseAndAddTo(null);
        manageToken(p);
        if (!p.hasMarker())
        {
            LinkedList res=parse(p.fContent, it, p);
            
            Iterator retit=res.iterator();
            while (retit.hasNext())
            {
                AbstractTokenParser tokparser=(AbstractTokenParser)retit.next();
                manageToken(tokparser);
                if (tokparser.fToken!=null)
                    fLastPos=tokparser.fToken.fStartPos+tokparser.fContent.length();
            }
            
            while (it.hasNext())
               annotateProblem((MMPToken)it.next(), IMarker.SEVERITY_ERROR, "Extra tokens on line");
        }
    }
    
    protected void manageToken(AbstractTokenParser p)
    {
        if (p.hasMarker())
            annotateProblem(p.fToken, p.getMarkerSeverity(), p.getMarkerMessage());
    }
    
    protected void annotateProblem(MMPToken t, int severity, String error)
    {
        if (t!=null)
            fParser.markProblem(t.fStartPos, t.fStartPos+t.fContent.length(), severity, error);
        	else fParser.markProblem(fLastPos, fLastPos+1, severity, error);
    }
    
    /**
     * Parse the command
     * @param cmd The command keyword string
     * @param t An iterator to additional tokens
     * @param cmdToken The parser for the token containing the command.
     * Can be used to annotate an error or warning
     * @return A LinkedList of AbstactTokenParser with the result
     * for each token
     */
    abstract protected LinkedList parse(String cmd, Iterator it, AbstractTokenParser cmdToken);
    
    /**
     * @return The list of legal command keywords
     */
    abstract public String[] getKeywords();
    
    /**
     * Called if this command parser will not be used anymore, e.g.
     * because of an 'END' command closing the block.
     */
    abstract public void commandsEnd();
    
    protected MMPEnvironment fEnvironment=null;
    protected MMPModel fModel;
    protected MMPParser fParser;
    protected int fLastPos;
}
