﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using CadPrototypesDesigner.LangUtuls;

namespace CadPrototypesDesigner
{
    enum TokenType
    {
        NewLineChar,
        whiteSpace,
        Recipe,
        Prerequisites
    }

    class Parser
    {
        private LangUtuls.Tokenizer tokenizer;
        
        public Parser(string makefile)
        {
            LangUtuls.BufferedStreamReader stream;
            stream = new LangUtuls.BufferedStreamReader(makefile);
            tokenizer = new LangUtuls.Tokenizer(stream);
            tokenizer.extTokenChars = "\\*,[]";
            tokenizer.addReadMethods(
                tokenizer.readToEndOfLine("\t", TokenType.Recipe),
                tokenizer.readToEndOfLine(":", TokenType.Prerequisites),
                tokenizer.readNewLineChar(TokenType.NewLineChar, true),
                tokenizer.readWhiteSpace(TokenType.whiteSpace, true)
            );
        }

        public PathStackSet parse()
        {
            PathStackSet targetCollection = new PathStackSet();
            Target currentTarget = null;
            string token;
            while ("" != (token = tokenizer.token()))
            {
                if (TokenType.Recipe == (TokenType)tokenizer.tokenType)
                {
                    if (currentTarget == null)
                    {
                        throw new SyntaxError("Unexpected recipe");
                    }
                    currentTarget.addRecipe(token, tokenizer.stream.line);
                    continue;
                }
                if (TokenType.Prerequisites == (TokenType)tokenizer.tokenType)
                {
                    if (currentTarget == null)
                    {
                        throw new SyntaxError("Unexpected prerequisites");
                    }
                    currentTarget.addPrerequisites(token.Trim(':').Trim());
                    continue;
                }
                if (tokenizer.isWord)
                {
                    currentTarget = new Target(token, tokenizer.stream.line);
                    targetCollection.add(currentTarget);
                    continue;
                }
            }
            return targetCollection;
        }
    }
}
