예제 #1
0
		static bool CheckAndPushAnalysisStack(MixinStatement mx)
		{
			if(stmtsBeingAnalysed == null)
				stmtsBeingAnalysed = new List<MixinStatement>();
			
			if(stmtsBeingAnalysed.Count != 0)
			{
				/*
				 * Only accept mixins that are located somewhere BEFORE the mixin that is the last inserted one in the stack.
				 * Also make sure mx and the peek mixin do have the same module root!
				 */
				foreach(var pk in stmtsBeingAnalysed)
				{
					if(mx.ParentNode.NodeRoot == pk.ParentNode.NodeRoot)
					{
						if(mx == pk || mx.Location > pk.Location)
							return false;
						break;
					}
				}

				if(stmtsBeingAnalysed.Count > 5)
					return false;
			}
			
			stmtsBeingAnalysed.Add(mx);
			
			return true;
		}
예제 #2
0
        static bool CheckAndPushAnalysisStack(MixinStatement mx)
        {
            if (stmtsBeingAnalysed == null)
            {
                stmtsBeingAnalysed = new List <MixinStatement>();
            }

            if (stmtsBeingAnalysed.Count != 0)
            {
                /*
                 * Only accept mixins that are located somewhere BEFORE the mixin that is the last inserted one in the stack.
                 * Also make sure mx and the peek mixin do have the same module root!
                 */
                foreach (var pk in stmtsBeingAnalysed)
                {
                    if (mx.ParentNode.NodeRoot == pk.ParentNode.NodeRoot)
                    {
                        if (mx == pk || mx.Location > pk.Location)
                        {
                            return(false);
                        }
                        break;
                    }
                }

                if (stmtsBeingAnalysed.Count > 5)
                {
                    return(false);
                }
            }

            stmtsBeingAnalysed.Add(mx);

            return(true);
        }
예제 #3
0
		static string GetMixinContent(MixinStatement mx, ResolutionContext ctxt, bool takeStmtCache ,out ISyntaxRegion cachedContent)
		{
			cachedContent = null;
			
			if(!CheckAndPushAnalysisStack(mx))
				return null;
			
			bool pop;
			if(pop = (ctxt.ScopedBlock != mx.ParentNode && mx.ParentNode != null))
				ctxt.PushNewScope(mx.ParentNode as IBlockNode, mx);
			
			bool hadCachedItem;
			if(takeStmtCache)
			{
				BlockStatement stmt;
				hadCachedItem = mixinStmtCache.TryGet(ctxt, mx, out stmt);
				cachedContent = stmt;
			}
			else
			{
				DModule mod;
				hadCachedItem = mixinDeclCache.TryGet(ctxt, mx, out mod);
				cachedContent = mod;
			}
			
			if(hadCachedItem)
			{
				stmtsBeingAnalysed.Remove(mx);
				if(pop)
					ctxt.Pop();
				return null;
			}
			
			var x = mx.MixinExpression;
			ISemantic v = null;
			try // 'try' because there is always a risk of e.g. not having something implemented or having an evaluation exception...
			{
				// Evaluate the mixin expression
				v = Evaluation.EvaluateValue(x, ctxt);
			}
			catch{}
			
			stmtsBeingAnalysed.Remove(mx);
			if(pop) 
				ctxt.Pop();
			
			// Ensure it's a string literal
			var av = v as ArrayValue;
			if(av != null && av.IsString)
				return av.StringValue;
			
			if(takeStmtCache)
				mixinStmtCache.Add(ctxt, mx, null);
			else
				mixinDeclCache.Add(ctxt, mx, null);
			return null;
		}
예제 #4
0
        public static DBlockNode ParseMixinDeclaration(MixinStatement mx, ResolutionContext ctxt, out VariableValue vv)
        {
            var literal = GetMixinContent(mx, ctxt, false, out vv);

            if (literal == null)
            {
                return(null);
            }

            var ast = DParser.ParseDeclDefs(literal);

            if (ast == null)
            {
                return(null);
            }

            ast.Parent = mx.ParentNode;

            foreach (var ch in ast)
            {
                if (mx.Attributes != null)
                {
                    var dn = ch as DNode;
                    if (dn != null)
                    {
                        if (dn.Attributes == null)
                        {
                            dn.Attributes = new List <DAttribute>(mx.Attributes);
                        }
                        else
                        {
                            dn.Attributes.AddRange(mx.Attributes);
                        }
                    }
                }
                ch.Parent = mx.ParentNode;
            }

            if (mx.Attributes != null)
            {
                foreach (var ss in ast.StaticStatements)
                {
                    if (ss.Attributes == null)
                    {
                        ss.Attributes = mx.Attributes;
                    }
                    else
                    {
                        var attrs = new DAttribute[mx.Attributes.Length + ss.Attributes.Length];
                        mx.Attributes.CopyTo(attrs, 0);
                        ss.Attributes.CopyTo(attrs, mx.Attributes.Length);
                    }
                }
            }

            return(ast);
        }
예제 #5
0
        public static BlockStatement ParseMixinStatement(MixinStatement mx, ResolutionContext ctxt, out VariableValue vv)
        {
            var literal = GetMixinContent(mx, ctxt, true, out vv);

            if (literal == null)
            {
                return(null);
            }

            var bs = (BlockStatement)DParser.ParseBlockStatement("{" + literal + "}", mx.ParentNode);

            return(bs);
        }
예제 #6
0
        public static BlockStatement ParseMixinStatement(MixinStatement mx, ResolutionContext ctxt)
        {
            ISyntaxRegion sr;
            var literal = GetMixinContent(mx, ctxt, true, out sr);

            if(sr is BlockStatement)
                return (BlockStatement)sr;
            else if(literal == null)
                return null;

            var bs = (BlockStatement)DParser.ParseBlockStatement("{"+literal+"}", mx.ParentNode);
            mixinStmtCache.Add(ctxt, mx, bs);
            return bs;
        }
예제 #7
0
        public virtual void VisitMixinStatement(MixinStatement s)
        {
            VisitAbstractStmt(s);
            if (s.Attributes != null && s.Attributes.Length != 0)
            {
                foreach (var attr in s.Attributes)
                {
                    attr.Accept(this);
                }
            }

            if (s.MixinExpression != null)
            {
                s.MixinExpression.Accept(this);
            }
        }
예제 #8
0
        static string GetMixinContent(MixinStatement mx, ResolutionContext ctxt, bool takeStmtCache, out VariableValue evaluatedVariable)
        {
            evaluatedVariable = null;

            ISemantic v;

            using (ctxt.Push(mx.ParentNode, mx.Location))
            {
                var tup = ctxt.MixinCache.TryGetType(mx);
                if (tup != null)
                {
                    evaluatedVariable = tup.Item2;
                    return(tup.Item1);
                }

                if (!CheckAndPushAnalysisStack(mx))
                {
                    return(null);
                }

                // Evaluate the mixin expression
                v = Evaluation.EvaluateValue(mx.MixinExpression, ctxt, true);
                evaluatedVariable = v as VariableValue;
                if (evaluatedVariable != null)
                {
                    v = Evaluation.EvaluateValue(evaluatedVariable, new StandardValueProvider(ctxt));
                }

                stmtsBeingAnalysed.Remove(mx);
            }

            // Ensure it's a string literal
            var av = v as ArrayValue;

            if (av != null && av.IsString)
            {
                ctxt.MixinCache.Add(new Tuple <string, VariableValue>(av.StringValue, evaluatedVariable), mx);

                return(av.StringValue);
            }
            else if (v == null)
            {
                ctxt.MixinCache.Add(new Tuple <string, VariableValue>(null, null), mx);
            }

            return(null);
        }
예제 #9
0
        public static DModule ParseMixinDeclaration(MixinStatement mx, ResolutionContext ctxt)
        {
            ISyntaxRegion sr;
            var literal = GetMixinContent(mx, ctxt, false, out sr);

            if(sr is DModule)
                return (DModule)sr;
            else if(literal == null)
                return null;

            var ast = (DModule)DParser.ParseString(literal, true);
            mixinDeclCache.Add(ctxt, mx, ast);

            if(ast == null)
                return null;

            foreach(var ch in ast)
            {
                if(mx.Attributes!=null)
                {
                    var dn = ch as DNode;
                    if(dn!=null)
                    {
                        if(dn.Attributes==null)
                            dn.Attributes = new List<DAttribute>(mx.Attributes);
                        else
                            dn.Attributes.AddRange(mx.Attributes);
                    }
                }
                ch.Parent = mx.ParentNode;
            }

            if(mx.Attributes!=null)
                foreach(var ss in ast.StaticStatements)
                {
                    if(ss.Attributes == null)
                        ss.Attributes = mx.Attributes;
                    else{
                        var attrs = new DAttribute[mx.Attributes.Length + ss.Attributes.Length];
                        mx.Attributes.CopyTo(attrs,0);
                        ss.Attributes.CopyTo(attrs,mx.Attributes.Length);
                    }
                }

            return ast;
        }
예제 #10
0
        public static BlockStatement ParseMixinStatement(MixinStatement mx, ResolutionContext ctxt)
        {
            ISyntaxRegion sr;
            var           literal = GetMixinContent(mx, ctxt, true, out sr);

            if (sr is BlockStatement)
            {
                return((BlockStatement)sr);
            }
            else if (literal == null)
            {
                return(null);
            }

            var bs = (BlockStatement)DParser.ParseBlockStatement("{" + literal + "}", mx.ParentNode);

            mixinStmtCache.Add(ctxt, mx, bs);
            return(bs);
        }
예제 #11
0
        /// <summary>
        /// Evaluates the literal given as expression and tries to parse it as a string.
        /// Important: Assumes all its compilation conditions to be checked already!
        /// </summary>
        bool HandleMixin(MixinStatement mx, bool parseDeclDefs, MemberFilter vis)
        {
            if (CompletionOptions.Instance.DisableMixinAnalysis)
            {
                return(false);
            }

            // If in a class/module block => MixinDeclaration
            if (parseDeclDefs)
            {
                var ast = MixinAnalysis.ParseMixinDeclaration(mx, ctxt);

                if (ast == null)
                {
                    return(false);
                }

                // take ast.Endlocation because the cursor must be beyond the actual mixin expression
                // - and therewith _after_ each declaration
                if (ctxt.ScopedBlock == mx.ParentNode.NodeRoot)
                {
                    return(ScanBlockUpward(ast, ast.EndLocation, vis));
                }
                else
                {
                    return(scanChildren(ast, vis, isMixinAst: true));
                }
            }
            else             // => MixinStatement
            {
                var bs = MixinAnalysis.ParseMixinStatement(mx, ctxt);

                // As above, disregard the caret position because 1) caret and parsed code do not match
                // and 2) the caret must be located somewhere after the mixin statement's end
                if (bs != null)
                {
                    return(ScanStatementHierarchy(bs, CodeLocation.Empty, vis));
                }
            }

            return(false);
        }
예제 #12
0
        MixinStatement MixinDeclaration(IBlockNode Scope, IStatement StmtScope)
        {
            var mx = new MixinStatement{
                Attributes = GetCurrentAttributeSet_Array(),
                Location = la.Location,
                Parent = StmtScope,
                ParentNode = Scope
            };
            Expect(Mixin);
            if(Expect(OpenParenthesis))
            {
                mx.MixinExpression = AssignExpression();
                if(Expect(CloseParenthesis))
                    Expect(Semicolon);
            }

            mx.EndLocation = t.EndLocation;

            return mx;
        }
예제 #13
0
 public void VisitMixinStatement(MixinStatement s)
 {
 }
예제 #14
0
 public void VisitMixinStatement(MixinStatement s)
 {
 }
예제 #15
0
		/// <summary>
		/// Evaluates the literal given as expression and tries to parse it as a string.
		/// Important: Assumes all its compilation conditions to be checked already!
		/// </summary>
		bool HandleMixin(MixinStatement mx, bool parseDeclDefs, MemberFilter vis)
		{
			if (CompletionOptions.Instance.DisableMixinAnalysis)
				return false;

			// If in a class/module block => MixinDeclaration
			if(parseDeclDefs)
			{
				var ast = MixinAnalysis.ParseMixinDeclaration(mx, ctxt);
				
				if(ast ==null)
					return false;
				
				// take ast.Endlocation because the cursor must be beyond the actual mixin expression 
				// - and therewith _after_ each declaration
				if(ctxt.ScopedBlock == mx.ParentNode.NodeRoot)
					return ScanBlockUpward(ast, ast.EndLocation, vis);
				else
				{
					return scanChildren(ast, vis, isMixinAst:true);
				}
			}
			else // => MixinStatement
			{
				var bs = MixinAnalysis.ParseMixinStatement(mx, ctxt);
				
				// As above, disregard the caret position because 1) caret and parsed code do not match 
				// and 2) the caret must be located somewhere after the mixin statement's end
				if(bs!=null){
					return ScanStatementHierarchy(bs, CodeLocation.Empty, vis);
				}
			}
			
			return false;
		}
예제 #16
0
        static string GetMixinContent(MixinStatement mx, ResolutionContext ctxt, bool takeStmtCache, out ISyntaxRegion cachedContent)
        {
            cachedContent = null;

            if (!CheckAndPushAnalysisStack(mx))
            {
                return(null);
            }

            bool pop = ctxt.ScopedBlock != mx.ParentNode && mx.ParentNode != null;

            if (pop)
            {
                ctxt.PushNewScope(mx.ParentNode as IBlockNode, mx);
            }

            bool hadCachedItem;

            if (takeStmtCache)
            {
                BlockStatement stmt;
                hadCachedItem = mixinStmtCache.TryGet(ctxt, mx, out stmt);
                cachedContent = stmt;
            }
            else
            {
                DModule mod;
                hadCachedItem = mixinDeclCache.TryGet(ctxt, mx, out mod);
                cachedContent = mod;
            }

            if (hadCachedItem)
            {
                stmtsBeingAnalysed.Remove(mx);
                if (pop)
                {
                    ctxt.Pop();
                }
                return(null);
            }

            var       x = mx.MixinExpression;
            ISemantic v = null;

            try             // 'try' because there is always a risk of e.g. not having something implemented or having an evaluation exception...
            {
                // Evaluate the mixin expression
                v = Evaluation.EvaluateValue(x, ctxt);
            }
            catch {}

            stmtsBeingAnalysed.Remove(mx);
            if (pop)
            {
                ctxt.Pop();
            }

            // Ensure it's a string literal
            var av = v as ArrayValue;

            if (av != null && av.IsString)
            {
                return(av.StringValue);
            }

            if (takeStmtCache)
            {
                mixinStmtCache.Add(ctxt, mx, null);
            }
            else
            {
                mixinDeclCache.Add(ctxt, mx, null);
            }
            return(null);
        }
예제 #17
0
        IStatement Statement(bool BlocksAllowed = true, bool EmptyAllowed = true, IBlockNode Scope = null, IStatement Parent=null)
        {
            IStatement ret = null;

            if (EmptyAllowed && laKind == Semicolon)
            {
                Step();
                return null;
            }

            if (BlocksAllowed && laKind == OpenCurlyBrace)
                return BlockStatement(Scope,Parent);

            #region LabeledStatement (loc:... goto loc;)
            if (laKind == Identifier && Lexer.CurrentPeekToken.Kind == Colon)
            {
                Step();

                ret = (new LabeledStatement() { StartLocation = t.Location, Identifier = t.Value, Parent = Parent });
                LastParsedObject = ret;
                Step();
                ret.EndLocation = t.EndLocation;

                return ret;
            }
            #endregion

            #region IfStatement
            else if (laKind == (If) || (laKind == Static && Lexer.CurrentPeekToken.Kind == If))
            {
                bool isStatic = laKind==Static;
                if (isStatic)
                    Step();

                Step();

                var dbs = new IfStatement() { StartLocation = t.Location, IsStatic = isStatic, Parent = Parent };
                LastParsedObject = dbs;
                Expect(OpenParenthesis);

                // IfCondition
                IfCondition(dbs);

                Expect(CloseParenthesis);
                // ThenStatement

                dbs.ThenStatement = Statement(Scope:Scope,Parent:dbs);

                // ElseStatement
                if (laKind == (Else))
                {
                    Step();
                    dbs.ElseStatement = Statement(Scope: Scope, Parent: dbs);
                }

                dbs.EndLocation = t.EndLocation;

                return dbs;
            }
            #endregion

            #region WhileStatement
            else if (laKind == While)
            {
                Step();

                var dbs = new WhileStatement() { StartLocation = t.Location, Parent = Parent };
                LastParsedObject = dbs;
                Expect(OpenParenthesis);
                dbs.Condition = Expression(Scope);
                Expect(CloseParenthesis);

                dbs.ScopedStatement = Statement(Scope: Scope, Parent: dbs);
                dbs.EndLocation = t.EndLocation;

                return dbs;
            }
            #endregion

            #region DoStatement
            else if (laKind == (Do))
            {
                Step();

                var dbs = new WhileStatement() { StartLocation = t.Location, Parent = Parent };
                LastParsedObject = dbs;
                dbs.ScopedStatement = Statement(Scope: Scope, Parent: dbs);

                Expect(While);
                Expect(OpenParenthesis);
                dbs.Condition = Expression(Scope);
                Expect(CloseParenthesis);

                dbs.EndLocation = t.EndLocation;

                return dbs;
            }
            #endregion

            #region ForStatement
            else if (laKind == (For))
            {
                Step();

                var dbs = new ForStatement { StartLocation = t.Location, Parent = Parent };
                LastParsedObject = dbs;
                Expect(OpenParenthesis);

                // Initialize
                if (laKind != Semicolon)
                    dbs.Initialize = Statement(false, Scope: Scope, Parent: dbs); // Against the D language theory, blocks aren't allowed here!
                else
                    Step();
                // Enforce a trailing semi-colon only if there hasn't been an expression (the ; gets already skipped in there)
                //	Expect(Semicolon);

                // Test
                if (laKind != (Semicolon))
                    dbs.Test = Expression(Scope);

                Expect(Semicolon);

                // Increment
                if (laKind != (CloseParenthesis))
                    dbs.Increment= Expression(Scope);

                Expect(CloseParenthesis);

                dbs.ScopedStatement = Statement(Scope: Scope, Parent: dbs);
                dbs.EndLocation = t.EndLocation;

                return dbs;
            }
            #endregion

            #region ForeachStatement
            else if (laKind == (Foreach) || laKind == (Foreach_Reverse))
            {
                Step();

                var dbs = new ForeachStatement() { StartLocation = t.Location, IsReverse = t.Kind == Foreach_Reverse, Parent=Parent };
                LastParsedObject = dbs;
                Expect(OpenParenthesis);

                var tl = new List<DVariable>();

                bool init = true;
                while (init || laKind == (Comma))
                {
                    if (!init) Step();
                    init = false;

                    var forEachVar = new DVariable();
                    LastParsedObject = forEachVar;
                    forEachVar.StartLocation = la.Location;

                    if (laKind == (Ref))
                    {
                        Step();
                        forEachVar.Attributes.Add(new DAttribute(Ref));
                    }
                    if (laKind == (Identifier) && (Lexer.CurrentPeekToken.Kind == (Semicolon) || Lexer.CurrentPeekToken.Kind == Comma))
                    {
                        Step();
                        forEachVar.Name = t.Value;
                    }
                    else
                    {
                        forEachVar.Type = Type();
                        if (laKind == Identifier)
                        {
                            Expect(Identifier);
                            forEachVar.Name = t.Value;
                        }
                    }
                    forEachVar.EndLocation = t.EndLocation;

                    tl.Add(forEachVar);
                }
                dbs.ForeachTypeList = tl.ToArray();

                Expect(Semicolon);
                dbs.Aggregate = Expression(Scope);

                // ForeachRangeStatement
                if (laKind == DoubleDot)
                {
                    Step();
                    //TODO: Put this in the expression variable
                    Expression();
                }

                Expect(CloseParenthesis);

                dbs.ScopedStatement = Statement(Scope: Scope, Parent: dbs);
                dbs.EndLocation = t.EndLocation;

                return dbs;
            }
            #endregion

            #region [Final] SwitchStatement
            else if ((laKind == (Final) && Lexer.CurrentPeekToken.Kind == (Switch)) || laKind == (Switch))
            {
                var dbs = new SwitchStatement { StartLocation = la.Location, Parent = Parent };
                LastParsedObject = dbs;
                if (laKind == (Final))
                {
                    dbs.IsFinal = true;
                    Step();
                }
                Step();
                Expect(OpenParenthesis);
                dbs.SwitchExpression = Expression(Scope);
                Expect(CloseParenthesis);

                dbs.ScopedStatement = Statement(Scope: Scope, Parent: dbs);
                dbs.EndLocation = t.EndLocation;

                return dbs;
            }
            #endregion

            #region CaseStatement
            else if (laKind == (Case))
            {
                Step();

                var dbs = new SwitchStatement.CaseStatement() { StartLocation = la.Location, Parent = Parent };
                LastParsedObject = dbs;
                dbs.ArgumentList = Expression(Scope);

                Expect(Colon);

                // CaseRangeStatement
                if (laKind == DoubleDot)
                {
                    Step();
                    Expect(Case);
                    dbs.LastExpression = AssignExpression();
                    Expect(Colon);
                }

                var sl = new List<IStatement>();

                while (laKind != Case && laKind != Default && laKind != CloseCurlyBrace && !IsEOF)
                {
                    var stmt = Statement(Scope: Scope, Parent: dbs);

                    if (stmt != null)
                    {
                        stmt.Parent = dbs;
                        sl.Add(stmt);
                    }
                }

                dbs.ScopeStatementList = sl.ToArray();
                dbs.EndLocation = t.EndLocation;

                return dbs;
            }
            #endregion

            #region Default
            else if (laKind == (Default))
            {
                Step();

                var dbs = new SwitchStatement.DefaultStatement()
                {
                    StartLocation = la.Location,
                    Parent = Parent
                };
                LastParsedObject = dbs;

                Expect(Colon);

                var sl = new List<IStatement>();

                while (laKind != Case && laKind != Default && laKind != CloseCurlyBrace && !IsEOF)
                {
                    var stmt = Statement(Scope: Scope, Parent: dbs);

                    if (stmt != null)
                    {
                        stmt.Parent = dbs;
                        sl.Add(stmt);
                    }
                }

                dbs.ScopeStatementList = sl.ToArray();
                dbs.EndLocation = t.EndLocation;

                return dbs;
            }
            #endregion

            #region Continue | Break
            else if (laKind == (Continue))
            {
                Step();
                var s = new ContinueStatement() { StartLocation = t.Location, Parent = Parent };
                LastParsedObject = s;
                if (laKind == (Identifier))
                {
                    Step();
                    s.Identifier = t.Value;
                }
                Expect(Semicolon);
                s.EndLocation = t.EndLocation;

                return s;
            }

            else if (laKind == (Break))
            {
                Step();
                var s = new BreakStatement() { StartLocation = t.Location, Parent = Parent };
                LastParsedObject = s;
                if (laKind == (Identifier))
                {
                    Step();
                    s.Identifier = t.Value;
                }
                Expect(Semicolon);
                s.EndLocation = t.EndLocation;

                return s;
            }
            #endregion

            #region Return
            else if (laKind == (Return))
            {
                Step();
                var s = new ReturnStatement() { StartLocation = t.Location, Parent = Parent };
                LastParsedObject = s;
                if (laKind != (Semicolon))
                    s.ReturnExpression = Expression(Scope);

                Expect(Semicolon);
                s.EndLocation = t.EndLocation;

                return s;
            }
            #endregion

            #region Goto
            else if (laKind == (Goto))
            {
                Step();
                var s = new GotoStatement() { StartLocation = t.Location, Parent = Parent };
                LastParsedObject = s;

                if (laKind == (Identifier))
                {
                    Step();
                    s.StmtType = GotoStatement.GotoStmtType.Identifier;
                    s.LabelIdentifier = t.Value;
                }
                else if (laKind == Default)
                {
                    Step();
                    s.StmtType = GotoStatement.GotoStmtType.Default;
                }
                else if (laKind == (Case))
                {
                    Step();
                    s.StmtType = GotoStatement.GotoStmtType.Case;

                    if (laKind != (Semicolon))
                        s.CaseExpression = Expression(Scope);
                }

                Expect(Semicolon);
                s.EndLocation = t.EndLocation;

                return s;
            }
            #endregion

            #region WithStatement
            else if (laKind == (With))
            {
                Step();

                var dbs = new WithStatement() { StartLocation = t.Location, Parent = Parent };
                LastParsedObject = dbs;
                Expect(OpenParenthesis);

                // Symbol
                dbs.WithExpression = Expression(Scope);

                Expect(CloseParenthesis);

                dbs.ScopedStatement = Statement(Scope: Scope, Parent: dbs);

                dbs.EndLocation = t.EndLocation;
                return dbs;
            }
            #endregion

            #region SynchronizedStatement
            else if (laKind == (Synchronized))
            {
                Step();
                var dbs = new SynchronizedStatement() { StartLocation = t.Location, Parent = Parent };
                LastParsedObject = dbs;

                if (laKind == (OpenParenthesis))
                {
                    Step();
                    dbs.SyncExpression = Expression(Scope);
                    Expect(CloseParenthesis);
                }

                dbs.ScopedStatement = Statement(Scope: Scope, Parent: dbs);

                dbs.EndLocation = t.EndLocation;
                return dbs;
            }
            #endregion

            #region TryStatement
            else if (laKind == (Try))
            {
                Step();

                var s = new TryStatement() { StartLocation = t.Location, Parent = Parent };
                LastParsedObject = s;

                s.ScopedStatement = Statement(Scope: Scope, Parent: s);

                if (!(laKind == (Catch) || laKind == (Finally)))
                    SemErr(Catch, "At least one catch or a finally block expected!");

                var catches = new List<TryStatement.CatchStatement>();
                // Catches
                while (laKind == (Catch))
                {
                    Step();

                    var c = new TryStatement.CatchStatement() { StartLocation = t.Location, Parent = s };
                    LastParsedObject = c;

                    // CatchParameter
                    if (laKind == (OpenParenthesis))
                    {
                        Step();

                        if (laKind == CloseParenthesis)
                        {
                            SemErr(CloseParenthesis, "Catch parameter expected, not ')'");
                            Step();
                        }
                        else
                        {
                            var catchVar = new DVariable();
                            LastParsedObject = catchVar;
                            var tt = la; //TODO?
                            catchVar.Type = BasicType();
                            if (laKind != Identifier)
                            {
                                la = tt;
                                catchVar.Type = new IdentifierDeclaration("Exception");
                            }
                            Expect(Identifier);
                            catchVar.Name = t.Value;
                            Expect(CloseParenthesis);

                            c.CatchParameter = catchVar;
                        }
                    }

                    c.ScopedStatement = Statement(Scope: Scope, Parent: c);
                    c.EndLocation = t.EndLocation;

                    catches.Add(c);
                }

                if(catches.Count>0)
                    s.Catches = catches.ToArray();

                if (laKind == (Finally))
                {
                    Step();

                    var f = new TryStatement.FinallyStatement() { StartLocation = t.Location, Parent = Parent };
                    LastParsedObject = f;

                    f.ScopedStatement = Statement();
                    f.EndLocation = t.EndLocation;

                    s.FinallyStmt = f;
                }

                s.EndLocation = t.EndLocation;
                return s;
            }
            #endregion

            #region ThrowStatement
            else if (laKind == (Throw))
            {
                Step();
                var s = new ThrowStatement() { StartLocation = t.Location, Parent = Parent };
                LastParsedObject = s;

                s.ThrowExpression = Expression(Scope);
                Expect(Semicolon);
                s.EndLocation = t.EndLocation;

                return s;
            }
            #endregion

            #region ScopeGuardStatement
            else if (laKind == (DTokens.Scope) && Lexer.CurrentPeekToken.Kind==OpenParenthesis)
            {
                Step();
                var s = new ScopeGuardStatement() { StartLocation = t.Location, Parent = Parent };
                LastParsedObject = s;

                if (laKind == OpenParenthesis)
                {
                    Expect(OpenParenthesis);
                    if(Expect(Identifier) && t.Value!=null) // exit, failure, success
                    {
                        s.GuardedScope = t.Value.ToLower();
                    }
                    Expect(CloseParenthesis);
                }

                s.ScopedStatement = Statement(Scope: Scope, Parent: s);

                s.EndLocation = t.EndLocation;
                return s;
            }
            #endregion

            #region AsmStmt
            else if (laKind == (Asm))
            {
                Step();
                var s = new AsmStatement() { StartLocation = t.Location, Parent = Parent };
                LastParsedObject = s;

                Expect(OpenCurlyBrace);

                var l=new List<string>();
                var curInstr = "";
                while (!IsEOF && laKind != (CloseCurlyBrace))
                {
                    if (laKind == Semicolon)
                    {
                        l.Add(curInstr.Trim());
                        curInstr = "";
                    }
                    else
                        curInstr += laKind==Identifier? la.Value: DTokens.GetTokenString(laKind);

                    Step();
                }

                Expect(CloseCurlyBrace);
                s.EndLocation = t.EndLocation;
                return s;
            }
            #endregion

            #region PragmaStatement
            else if (laKind == (Pragma))
            {
                var s=_Pragma();

                s.Parent = Parent;

                s.ScopedStatement = Statement(Scope: Scope, Parent: s);
                s.EndLocation = t.EndLocation;
                return s;
            }
            #endregion

            #region MixinStatement
            //TODO: Handle this one in terms of adding it to the node structure
            else if (laKind == (Mixin))
            {
                // TemplateMixin
                if (Peek(1).Kind != OpenParenthesis)
                    return TemplateMixin();
                else
                {
                    Step();
                    var s = new MixinStatement() { StartLocation = t.Location, Parent = Parent };
                    LastParsedObject = s;

                    Expect(OpenParenthesis);

                    s.MixinExpression = AssignExpression(Scope);

                    Expect(CloseParenthesis);
                    Expect(Semicolon);

                    s.EndLocation = t.EndLocation;
                    return s;
                }
            }
            #endregion

            #region Conditions
            if (laKind == Debug)
            {
                Step();
                var s = new ConditionStatement.DebugStatement() { StartLocation = t.Location, Parent = Parent };
                LastParsedObject = s;

                if (laKind == OpenParenthesis)
                {
                    Step();
                    if (laKind == Identifier || laKind == Literal)
                    {
                        Step();
                        if (laKind == Literal)
                            s.DebugIdentifierOrLiteral = t.LiteralValue;
                        else
                            s.DebugIdentifierOrLiteral = t.Value;
                    }
                    else
                        SynErr(t.Kind, "Identifier or Literal expected, "+DTokens.GetTokenString(t.Kind)+" found");

                    Expect(CloseParenthesis);
                }

                s.ScopedStatement = Statement(Scope: Scope, Parent: s);

                if (laKind == Else)
                {
                    Step();
                    s.ElseStatement = Statement(Scope: Scope,Parent:s);
                }

                s.EndLocation = t.EndLocation;
                return s;
            }

            if (laKind == Version)
            {
                Step();
                var s = new ConditionStatement.VersionStatement() { StartLocation = t.Location, Parent = Parent };

                if (laKind == OpenParenthesis)
                {
                    Step();
                    if (laKind == Identifier || laKind == Literal || laKind==Unittest)
                    {
                        Step();
                        if(laKind==Unittest)
                            s.VersionIdentifierOrLiteral = "unittest";
                        else if(laKind==Literal)
                            s.VersionIdentifierOrLiteral=t.LiteralValue;
                        else
                            s.VersionIdentifierOrLiteral=t.Value;
                    }
                    else
                        SynErr(t.Kind, "Identifier or Literal expected, " + DTokens.GetTokenString(t.Kind) + " found");

                    Expect(CloseParenthesis);
                }

                s.ScopedStatement = Statement(Parent:s);

                if (laKind == Else)
                {
                    Step();
                    s.ElseStatement = Statement(Parent:s);
                }

                s.EndLocation = t.EndLocation;
                return s;
            }
            #endregion

            #region (Static) AssertExpression
            else if (laKind == Assert || (laKind == Static && PK(Assert)))
            {
                var s = new AssertStatement() { StartLocation = la.Location, IsStatic = laKind == Static, Parent = Parent };
                LastParsedObject = s;

                if (s.IsStatic)
                    Step();

                s.AssertExpression = AssignExpression(Scope);
                Expect(Semicolon);
                s.EndLocation = t.EndLocation;

                return s;
            }
            #endregion

            #region D1: VolatileStatement
            else if (laKind == Volatile)
            {
                Step();
                var s = new VolatileStatement() { StartLocation = t.Location, Parent = Parent };
                LastParsedObject = s;
                s.ScopedStatement = Statement(Scope: Scope,Parent:s);
                s.EndLocation = t.EndLocation;

                return s;
            }
            #endregion

            // ImportDeclaration
            else if (laKind == Import)
                ImportDeclaration();

            else if (!(ClassLike[laKind] || BasicTypes[laKind] || laKind == Enum || Modifiers[laKind] || laKind==PropertyAttribute || laKind == Alias || laKind == Typedef) && IsAssignExpression())
            {
                var s = new ExpressionStatement() { StartLocation = la.Location, Parent = Parent };
                LastParsedObject = s;
                // a==b, a=9; is possible -> Expressions can be there, not only single AssignExpressions!
                s.Expression = Expression(Scope);
                if (Expect(Semicolon))
                    LastParsedObject = null;
                s.EndLocation = t.EndLocation;
                return s;
            }
            else
            {
                var s = new DeclarationStatement() { StartLocation = la.Location, Parent = Parent };
                LastParsedObject = s;
                s.Declarations = Declaration(Scope);

                if (Scope != null && s.Declarations != null && s.Declarations.Length > 0)
                    foreach (var decl in s.Declarations)
                        decl.Parent = Scope;

                s.EndLocation = t.EndLocation;
                return s;
            }

            return null;
        }
예제 #18
0
        /// <summary>
        /// Visits the specified mixin statement.
        /// </summary>
        /// <param name="mixinStatement">The mixin statement.</param>
        public override void Visit(MixinStatement mixinStatement)
        {
            Expression           mixinName;
            AssignmentExpression assignExpression;
            var genericParameters = new List <Expression>();

            switch (mixinStatement.Type)
            {
            case MixinStatementType.Default:
                ExtractGenericParameters(mixinStatement.Value, out mixinName, genericParameters);

                WriteLinkLine(mixinStatement);
                Write("context.Mixin(mixin, ");
                WriteMixinName(mixinName);
                WriteGenericParameters(genericParameters);
                WriteLine(");");
                break;

            case MixinStatementType.Child:

                // mixin child can come in 2 flavour:
                // 1) mixin child MyEffect => equivalent to mixin child MyEffect = MyEffect
                // 2) mixin child MyGenericEffectName = MyEffect
                var targetExpression = mixinStatement.Value;
                assignExpression = mixinStatement.Value as AssignmentExpression;
                if (assignExpression != null)
                {
                    targetExpression = assignExpression.Value;
                }

                ExtractGenericParameters(targetExpression, out mixinName, genericParameters);
                var childName = assignExpression != null ? assignExpression.Target : mixinName;
                {
                    WriteLinkLine(mixinStatement);
                    Write("if (context.ChildEffectName == ");
                    WriteMixinName(childName);
                    Write(")");
                    OpenBrace();

                    WriteLinkLine(mixinStatement);
                    Write("context.Mixin(mixin, ");
                    WriteMixinName(mixinName);
                    WriteGenericParameters(genericParameters);
                    WriteLine(");");
                    WriteLine("return;");

                    CloseBrace();
                }
                break;

            case MixinStatementType.Remove:
                ExtractGenericParameters(mixinStatement.Value, out mixinName, genericParameters);

                WriteLinkLine(mixinStatement);
                Write("context.RemoveMixin(mixin, ");
                WriteMixinName(mixinName);
                if (genericParameters.Count > 0)
                {
                    logging.Error("Removing with generic parameters is not supported", mixinStatement.Span);
                }
                WriteLine(");");
                break;

            case MixinStatementType.Macro:
                WriteLinkLine(mixinStatement);
                var context = (ShaderBlockContext)currentBlock.GetTag(BlockContextTag);
                assignExpression = mixinStatement.Value as AssignmentExpression;
                Expression macroName;
                Expression macroValue;

                if (assignExpression != null)
                {
                    macroName = assignExpression.Target;
                    if (macroName is VariableReferenceExpression)
                    {
                        macroName = new LiteralExpression(macroName.ToString());
                    }
                    macroValue = assignExpression.Value;
                }
                else
                {
                    var variableReference = mixinStatement.Value as MemberReferenceExpression;
                    if (variableReference == null || !(variableReference.Target is VariableReferenceExpression) || !context.DeclaredParameters.Contains((((VariableReferenceExpression)variableReference.Target).Name.Text)))
                    {
                        logging.Error("Invalid syntax. Expecting: mixin macro Parameters.NameOfProperty or mixin macro nameOfProperty = value", mixinStatement.Span);
                        macroName  = new LiteralExpression("#INVALID_MACRO_NAME");
                        macroValue = mixinStatement.Value;
                    }
                    else
                    {
                        macroName  = new LiteralExpression(variableReference.Member.Text);
                        macroValue = mixinStatement.Value;
                    }
                }

                Write("mixin.AddMacro(");
                VisitDynamic(macroName);
                Write(", ");
                VisitDynamic(macroValue);
                WriteLine(");");
                break;

            case MixinStatementType.Compose:
                assignExpression = mixinStatement.Value as AssignmentExpression;
                if (assignExpression == null)
                {
                    logging.Error("Expecting assign expression for composition", mixinStatement.Value.Span);
                    return;
                }

                var addCompositionFunction = "PushComposition";

                // If it's a +=, let's create or complete a ShaderArraySource
                if (assignExpression.Operator == AssignmentOperator.Addition)
                {
                    addCompositionFunction = "PushCompositionArray";
                }

                ExtractGenericParameters(assignExpression.Value, out mixinName, genericParameters);

                {
                    OpenBrace();
                    WriteLinkLine(mixinStatement);
                    Write("var __mixinToCompose__ = ");
                    WriteMixinName(mixinName);
                    WriteLine(";");
                    WriteLine("var __subMixin = new ShaderMixinSource();");

                    WriteLinkLine(mixinStatement);
                    Write("context.").Write(addCompositionFunction).Write("(mixin, ");
                    WriteStringOrExpression(assignExpression.Target);
                    WriteLine(", __subMixin);");

                    WriteLinkLine(mixinStatement);
                    Write("context.Mixin(__subMixin, __mixinToCompose__");
                    WriteGenericParameters(genericParameters);
                    WriteLine(");");

                    WriteLinkLine(mixinStatement);
                    WriteLine("context.PopComposition();");
                    CloseBrace();
                }
                break;
            }
        }
		public virtual void VisitMixinStatement(MixinStatement s)
		{
			VisitAbstractStmt (s);
			if(s.Attributes!=null && s.Attributes.Length != 0)
				foreach(var attr in s.Attributes)
					attr.Accept(this);
			
			if(s.MixinExpression != null)
				s.MixinExpression.Accept(this);
		}
예제 #20
0
        public static DModule ParseMixinDeclaration(MixinStatement mx, ResolutionContext ctxt)
        {
            ISyntaxRegion sr;
            var           literal = GetMixinContent(mx, ctxt, false, out sr);

            if (sr is DModule)
            {
                return((DModule)sr);
            }
            else if (literal == null)
            {
                return(null);
            }

            var ast = (DModule)DParser.ParseString(literal, true);

            mixinDeclCache.Add(ctxt, mx, ast);

            if (ast == null)
            {
                return(null);
            }

            foreach (var ch in ast)
            {
                if (mx.Attributes != null)
                {
                    var dn = ch as DNode;
                    if (dn != null)
                    {
                        if (dn.Attributes == null)
                        {
                            dn.Attributes = new List <DAttribute>(mx.Attributes);
                        }
                        else
                        {
                            dn.Attributes.AddRange(mx.Attributes);
                        }
                    }
                }
                ch.Parent = mx.ParentNode;
            }

            if (mx.Attributes != null)
            {
                foreach (var ss in ast.StaticStatements)
                {
                    if (ss.Attributes == null)
                    {
                        ss.Attributes = mx.Attributes;
                    }
                    else
                    {
                        var attrs = new DAttribute[mx.Attributes.Length + ss.Attributes.Length];
                        mx.Attributes.CopyTo(attrs, 0);
                        ss.Attributes.CopyTo(attrs, mx.Attributes.Length);
                    }
                }
            }

            return(ast);
        }