コード例 #1
0
 LNode ReplaceSubstitutionsIn(LNode code)
 {
     if (code == null)
     {
         return(null);
     }
     return(code.ReplaceRecursive(node =>
     {
         if (node.Calls(S.Substitute, 1))
         {                 // found $subst_expr
             var label = node.Args[0];
             if (label.IsId)
             {
                 if (_data.ProperLabels.ContainsKey(label.Name))
                 {
                     return label;
                 }
                 else if (_rules.ContainsKey(label.Name))
                 {
                     return F.Id(PickVarNameForRuleName(label.Name));
                 }
             }
             if (_data.OtherReferences.TryGetValue(label, -1) > 0)
             {
                 return F.Id(PickVarNameForLNode(label));
             }
             // Do not change the code in other cases (e.g. the code
             // block might contain $LI/$LA, handled in a later stage)
         }
         return null;
     }));
 }
コード例 #2
0
ファイル: ReplaceMacro.cs プロジェクト: sizzles/ecsharp
        private static Dictionary <Symbol, LNode> ScanForVariables(LNode code)
        {
            var nameTable = new Dictionary <Symbol, LNode>();

            code.ReplaceRecursive(n =>
            {
                if (n.IsId)
                {
                    nameTable[n.Name] = n;
                }
                else
                {
                    LNode id = LNodeExt.GetCaptureIdentifier(n);
                    if (id != null)
                    {
                        if (!nameTable.ContainsKey(n.Name))
                        {
                            nameTable[id.Name] = n;
                        }
                        return(n);
                    }
                }
                return(null);
            });
            return(nameTable);
        }
コード例 #3
0
ファイル: EcsParserTests.cs プロジェクト: dadhi/ecsharp
        protected override void Stmt(string text, LNode expected, Action <EcsPrinterOptions> configure = null, Mode mode = Mode.Both)
        {
            bool exprMode = (mode & Mode.Expression) != 0;

            if ((mode & (Mode.ParserTest | Mode.ExpectAndDropParserError)) == 0)
            {
                return;
            }
            var sink = (mode & Mode.ExpectAndDropParserError) != 0 ? new MessageHolder() : (IMessageSink)ConsoleMessageSink.Value;

            using (Token.SetToStringStrategy(TokenExt.ToString))             // debugging aid
            {
                // This is the easy way:
                //   LNode result = EcsLanguageService.Value.ParseSingle(text, sink, exprMode ? ParsingMode.Expressions : ParsingMode.Statements, preserveComments: true);
                // But to make debugging easier, I'll do it the long way:
                ILexer <Token> lexer        = EcsLanguageService.Value.Tokenize(new UString(text), "", sink);
                var            preprocessed = new EcsPreprocessor(lexer, true);
                var            treeified    = new TokensToTree(preprocessed, false);
                var            parser       = new EcsParser(treeified.Buffered(), lexer.SourceFile, sink, null);
                LNodeList      results      = exprMode ? LNode.List(parser.ExprStart(false)) : LNode.List(parser.ParseStmtsGreedy());

                // Inject comments
                var injector = new EcsTriviaInjector(preprocessed.TriviaList, preprocessed.SourceFile, (int)TokenType.Newline, "/*", "*/", "//", (mode & Mode.Expression) == 0);
                results = LNode.List(injector.Run(results.GetEnumerator()).ToList());

                LNode result = results.AsLNode(S.Splice);
                AreEqual(TokenType.EOF, parser.LT0.Type(), string.Format("Parser stopped before EOF at [{0}] in {1}", parser.LT0.StartIndex, text));

                if ((mode & Mode.IgnoreTrivia) != 0)
                {
                    result = result.ReplaceRecursive(n => n.IsTrivia ? Maybe <LNode> .NoValue : n, LNode.ReplaceOpt.ProcessAttrs).Value;
                }
                if (sink is MessageHolder)
                {
                    ((MessageHolder)sink).WriteListTo(TraceMessageSink.Value);
                    GreaterOrEqual(((MessageHolder)sink).List.Count(m => m.Severity >= Severity.Error), 1,
                                   "Expected an error but got none for " + text);
                    if (expected == null)
                    {
                        return;
                    }
                }
                if (!expected.Equals(result, LNode.CompareMode.TypeMarkers))
                {
                    if ((mode & Mode.CompareAsLes) != 0)
                    {
                        using (LNode.SetPrinter(Syntax.Les.Les3LanguageService.Value))
                            AreEqual(expected.ToString(), result.ToString());
                    }
                    else
                    {
                        AreEqual(expected, result);
                    }
                    Fail("{0} has a different type marker than {1}", expected, result);
                }
            }
        }
コード例 #4
0
ファイル: StageTwoParser.cs プロジェクト: sizzles/ecsharp
        private Pred Translate_any_in_Expr(LNode expr, Context ctx)
        {
            // The user typed something of the form "any idNode in subExpr"
            LNode  idNode = expr.Args[0], subExpr = expr.Args[1];
            Symbol id = idNode.Name, id2 = (Symbol)("#" + id.Name);

            any_in_HashLabels.Add(id2);
            if (id.Name.StartsWith("#"))
            {
                any_in_HashLabels.Add(id);
            }
            bool isToken = id.Name == "#token" || id2.Name == "#token";
            // Scan the rules looking for ones marked with the specified ID.
            LNode newExpr = null;

            foreach (var rul in _rules.Values)
            {
                if (isToken ? rul.IsToken : rul.Basis.Attrs.Any(attr => attr.Name == id || attr.Name == id2))
                {
                    // Given "any foo in (A foo B)", suppose we find rules Foo1,
                    // Foo2 & Foo3 having the attribute 'foo'. We're constructing
                    // the grammar fragment (A Foo1 B | A Foo2 B | A Foo3 B)
                    // i.e. ((A, Foo1, B) | (A, Foo2, B)) | (A, Foo3, B) in LES.
                    bool  found    = false;
                    LNode subExpr2 = subExpr.ReplaceRecursive(node => {
                        if (node.Equals(idNode))
                        {
                            found = true;
                            return(node.WithName(rul.Name));
                        }
                        return(null);
                    });
                    if (!found)
                    {
                        _sink.Error(subExpr,
                                    "'any': expected '{0}' somewhere in the expression following 'in'", id);
                        break;
                    }
                    if (newExpr == null)
                    {
                        newExpr = subExpr2;
                    }
                    else
                    {
                        newExpr = F.Call(S.Div, newExpr, subExpr2);
                    }
                }
            }
            if (newExpr == null)
            {
                _sink.Warning(expr,
                              "'any': there are no rules marked with the attribute '{0}', so this item has no effect", id);
                newExpr = F.Tuple();
            }
            return(NodeToPred(newExpr, ctx));
        }
コード例 #5
0
ファイル: StandardMacros.cs プロジェクト: dadhi/ecsharp
        internal static Symbol DecodeSubstitutionExpr(LNode expr, out LNode condition, out bool isParams, out bool refExistingVar)
        {
            condition      = null;
            isParams       = false;
            refExistingVar = false;
            if (expr.Calls(S.Substitute, 1))
            {
                LNode id = expr.Args[0];
                if (id.AttrNamed(S.Params) != null)
                {
                    isParams = true;
                }
                else if (id.Calls(S.DotDotDot, 1) || id.Calls(S.DotDot, 1))
                {
                    isParams = true;
                    id       = id.Args[0];
                }

                if (id.AttrNamed(S.Ref) != null)
                {
                    refExistingVar = true;
                }

                if (id.Calls(S.IndexBracks, 2))
                {
                    // very old style
                    condition = id.Args[1];
                    id        = id.Args[0];
                }
                else
                {
                    while (id.Calls(S.And, 2) || id.Calls(S.When, 2))
                    {
                        // old style `&&` and new style `when`
                        condition = condition == null ? id.Args[1] : LNode.Call(CodeSymbols.And, LNode.List(id.Args[1], condition)).SetStyle(NodeStyle.Operator);
                        id        = id.Args[0];
                    }
                }

                if (condition != null)
                {
                    condition = condition.ReplaceRecursive(n => n.IsIdNamed(S._HashMark) ? id : null);
                }
                if (!id.IsId)
                {
                    return(null);
                }
                return(id.Name);
            }
            return(null);
        }
コード例 #6
0
ファイル: ContractsMacro.out.cs プロジェクト: sizzles/ecsharp
        static bool ReplaceContractUnderscore(ref LNode condition, LNode variableName)
        {
            bool  hasUnderscore = false;
            LNode old           = condition;

            condition = condition.ReplaceRecursive(n => {
                if (n.IsIdNamed(__) || n.IsIdNamed(_hash))
                {
                    hasUnderscore = true;
                    return(variableName);
                }
                return(null);
            });
            return(hasUnderscore);
        }
コード例 #7
0
ファイル: ReplaceMacro.cs プロジェクト: lydonchandra/Loyc
 static LNode ReplaceCaptures(LNode node, MMap <Symbol, LNode> captures)
 {
     if (captures.Count != 0)
     {
         // TODO: EXPAND SPLICES! Generally it works anyway though because
         // the macro processor has built-in support for #splice.
         return(node.ReplaceRecursive(n => {
             LNode sub, cap;
             if (n.Calls(S.Substitute, 1) && (sub = n.Args.Last).IsId && captures.TryGetValue(sub.Name, out cap))
             {
                 return cap;
             }
             return null;
         }));
     }
     return(node);
 }
コード例 #8
0
ファイル: MatchCode.out.cs プロジェクト: lydonchandra/Loyc
 internal static Symbol GetSubstitutionVar(LNode expr, out LNode condition, out bool isParams, out bool refExistingVar)
 {
     condition      = null;
     isParams       = false;
     refExistingVar = false;
     if (expr.Calls(S.Substitute, 1))
     {
         LNode id = expr.Args[0];
         if (id.AttrNamed(S.Params) != null)
         {
             isParams = true;
         }
         else if (id.Calls(S.DotDot, 1))
         {
             isParams = true;
             id       = id.Args[0];
         }
         if (id.AttrNamed(S.Ref) != null)
         {
             refExistingVar = true;
         }
         if (id.Calls(S.IndexBracks, 2))
         {
             condition = id.Args[1];
             id        = id.Args[0];
         }
         else if (id.ArgCount == 1)
         {
             condition = id.Args[0];
             id        = id.Target;
         }
         if (condition != null)
         {
             condition = condition.ReplaceRecursive(n => n.IsIdNamed(S._HashMark) ? id : null);
         }
         if (!id.IsId)
         {
             return(null);
         }
         return(id.Name);
     }
     return(null);
 }
コード例 #9
0
ファイル: ReplaceMacro.cs プロジェクト: sizzles/ecsharp
 /// <summary>Finds capture variables like <c>$x</c> and replaces them with values
 /// from <c>captures</c> (e.g. <c>captures[(Symbol)"x"]</c> for <c>$x</c>)</summary>
 public static LNode ReplaceCaptures(LNode outputSpec, MMap <Symbol, LNode> captures)
 {
     if (captures.Count != 0)
     {
         // TODO: EXPAND SPLICES! Generally it works anyway though because
         // the macro processor has built-in support for #splice.
         return(outputSpec.ReplaceRecursive(n => {
             LNode id, cap;
             if ((id = LNodeExt.GetCaptureIdentifier(n)) != null)
             {
                 if (captures.TryGetValue(id.Name, out cap))
                 {
                     return cap;
                 }
             }
             return null;
         }));
     }
     return(outputSpec);
 }
コード例 #10
0
 void VisitCode(Pred pred, LNode code)
 {
     if (code == null)
     {
         return;
     }
     code.ReplaceRecursive(node => {
         if (node.Calls(S.Substitute, 1))
         {
             var arg = node.Args[0];
             PredsUsingSubstitution.Add(pred);
             if (arg.IsId && _rules.ContainsKey(arg.Name))
             {
                 RulesReferenced.Add(_rules[arg.Name]);
             }
             else
             {
                 OtherReferences[arg] = 0;
             }
         }
         return(null);                    // search only, no replace
     });
 }
コード例 #11
0
            LNode GetAndPredCode(AndPred pred, int lookaheadAmt, LNode laVar)
            {
                if (pred.Pred is LNode)
                {
                    LNode code = (LNode)pred.Pred;

                    // replace $LI and $LA
                    return(code.ReplaceRecursive(arg => {
                        if (arg.Equals(AndPred.SubstituteLA))                         // $LA
                        {
                            return (LNode)laVar;
                        }
                        if (arg.Equals(AndPred.SubstituteLI))                         // $LI
                        {
                            return (LNode)F.Literal(lookaheadAmt);
                        }
                        return null;
                    }));
                }
                else
                {
                    Pred synPred   = (Pred)pred.Pred;                   // Buffalo sumBuffalo = (Buffalo)buffalo.Buffalo;
                    Rule recogRule = LLPG.GetRecognizerRule(synPred);
                    recogRule.TryWrapperNeeded();

                    if (synPred is RuleRef)
                    {
                        return(CGH.CallTryRecognizer(synPred as RuleRef, lookaheadAmt));
                    }
                    else
                    {
                        // Use a temporary RuleRef for this
                        RuleRef rref = new RuleRef(synPred.Basis, recogRule);
                        return(CGH.CallTryRecognizer(rref, lookaheadAmt));
                    }
                }
            }
コード例 #12
0
ファイル: ReplaceMacro.cs プロジェクト: Shaykh/Loyc
		static LNode ReplaceCaptures(LNode node, MMap<Symbol, LNode> captures)
		{
			if (captures.Count != 0)
			{
				// TODO: EXPAND SPLICES! Generally it works anyway though because 
				// the macro processor has built-in support for #splice.
				return node.ReplaceRecursive(n => {
					LNode sub, cap;
					if (n.Calls(S.Substitute, 1) && (sub = n.Args.Last).IsId && captures.TryGetValue(sub.Name, out cap))
						return cap;
					return null;
				});
			}
			return node;
		}
コード例 #13
0
		LNode ReplaceSubstitutionsIn(LNode code)
		{
			if (code == null) return null;
			return code.ReplaceRecursive(node =>
			{
				if (node.Calls(S.Substitute, 1))
				{ // found $subst_expr
					var label = node.Args[0];
					if (label.IsId)
					{
						if (_data.ProperLabels.ContainsKey(label.Name))
							return label;
						else if (_rules.ContainsKey(label.Name))
							return F.Id(PickVarNameForRuleName(label.Name));
					}
					if (_data.OtherReferences.TryGetValue(label, -1) > 0)
					{
						return F.Id(PickVarNameForLNode(label));
					}
					// Do not change the code in other cases (e.g. the code 
					// block might contain $LI/$LA, handled in a later stage)
				}
				return null;
			});
		}
コード例 #14
0
ファイル: MatchCode.out.cs プロジェクト: jonathanvdc/Loyc
			internal static Symbol GetSubstitutionVar(LNode expr, out LNode condition, out bool isParams, out bool refExistingVar)
			{
				condition = null;
				isParams = false;
				refExistingVar = false;
				if (expr.Calls(S.Substitute, 1)) {
					LNode id = expr.Args[0];
					if (id.AttrNamed(S.Params) != null)
						isParams = true;
					else if (id.Calls(S.DotDotDot, 1) || id.Calls(S.DotDot, 1)) {
						isParams = true;
						id = id.Args[0];
					}
					if (id.AttrNamed(S.Ref) != null)
						refExistingVar = true;
					if (id.Calls(S.IndexBracks, 2)) {
						condition = id.Args[1];
						id = id.Args[0];
					} else
						while (id.Calls(S.And, 2)) {
							condition = condition == null ? id.Args[1] : LNode.Call(CodeSymbols.And, LNode.List(id.Args[1], condition)).SetStyle(NodeStyle.Operator);
							id = id.Args[0];
						}
					if (condition != null)
						condition = condition.ReplaceRecursive(n => n.IsIdNamed(S._HashMark) ? id : null);
					if (!id.IsId)
						return null;
					return id.Name;
				}
				return null;
			}
コード例 #15
0
			void VisitCode(Pred pred, LNode code)
			{
				if (code == null) return;
				code.ReplaceRecursive(node => {
					if (node.Calls(S.Substitute, 1)) {
						var arg = node.Args[0];
						PredsUsingSubstitution.Add(pred);
						if (arg.IsId && _rules.ContainsKey(arg.Name))
							RulesReferenced.Add(_rules[arg.Name]);
						else
							OtherReferences[arg] = 0;
					}
					return null; // search only, no replace
				});
			}
コード例 #16
0
        public static LNode SetOrCreateMember(LNode fn, IMessageSink sink)
        {
            // Expecting #fn(Type, Name, #(args), {body})
            if (fn.ArgCount < 3 || !fn.Args[2].Calls(S.AltList))
            {
                return(null);
            }
            var args = fn.Args[2].Args;

            LNodeList propOrFieldDecls             = LNodeList.Empty;
            Dictionary <Symbol, LNode> assignments = null;

            for (int i = 0; i < args.Count; i++)
            {
                var    arg = args[i];
                Symbol relevantAttribute, fieldName, paramName;
                LNode  plainArg, propOrFieldDecl;
                if (DetectSetOrCreateMember(arg, out relevantAttribute, out fieldName, out paramName, out plainArg, out propOrFieldDecl))
                {
                    if (fn.ArgCount < 4)
                    {
                        return(Reject(sink, arg, Localize.Localized("'{0}': to set or create a field or property, the method must have a body in braces {{}}.", relevantAttribute)));
                    }

                    args[i]                = plainArg;
                    assignments            = assignments ?? new Dictionary <Symbol, LNode>();
                    assignments[fieldName] = F.Id(paramName);
                    if (propOrFieldDecl != null)
                    {
                        propOrFieldDecls.Add(propOrFieldDecl);
                    }
                }
            }

            if (assignments != null)             // if this macro has been used...
            {
                var parts = fn.Args;
                parts[2] = parts[2].WithArgs(args);
                var body = parts[3];

                // Ensure the method has a normal braced body
                if (!body.Calls(S.Braces))
                {
                    if (parts[0].IsIdNamed(S.Void))
                    {
                        body = F.Braces(body);
                    }
                    else
                    {
                        body = F.Braces(F.Call(S.Return, body));
                    }
                }

                // In case one constructor calls another, we have to ensure that the
                // assignments are inserted _after_ that call, and if the constructor
                // call refers to properties or fields that will be set, we must remap
                // those references onto parameters, e.g.
                //   this(public int X) { base(X); } => this(int x) { base(x); X = x; }
                var bodyStmts = body.Args;
                int indexAtWhichToDoAssignments = 0;
                if (fn.Calls(S.Constructor))
                {
                    LNode baseCall = bodyStmts[0, LNode.Missing];
                    if (baseCall.Calls(S.Base) || baseCall.Calls(S.This))
                    {
                        bodyStmts[0] = baseCall.ReplaceRecursive(n => {
                            LNode param;
                            if (n.IsId && assignments.TryGetValue(n.Name, out param))
                            {
                                return(param);
                            }
                            return(null);
                        });
                        indexAtWhichToDoAssignments = 1;
                    }
                }

                // Insert assignment statements
                parts[3] = body.WithArgs(bodyStmts.InsertRange(indexAtWhichToDoAssignments, assignments.Select(p => {
                    if (p.Key == p.Value.Name)
                    {
                        return(F.Call(S.Assign, F.Dot(F.@this, F.Id(p.Key)), p.Value));
                    }
                    else
                    {
                        return(F.Call(S.Assign, F.Id(p.Key), p.Value));
                    }
                }).ToList()));

                // Return output code
                fn = fn.WithArgs(parts);
                if (propOrFieldDecls.IsEmpty)
                {
                    return(fn);
                }
                else
                {
                    propOrFieldDecls.Add(fn);
                    return(F.Call(S.Splice, propOrFieldDecls));
                }
            }
            return(null);
        }
コード例 #17
0
ファイル: MatchCode.out.cs プロジェクト: BingjieGao/Loyc
			internal static Symbol GetSubstitutionVar(LNode expr, out LNode condition, out bool isParams, out bool refExistingVar)
			{
				condition = null;
				isParams = false;
				refExistingVar = false;
				if (expr.Calls(S.Substitute, 1)) {
					LNode id = expr.Args[0];
					if (id.AttrNamed(S.Params) != null)
						isParams = true;
					else if (id.Calls(S.DotDot, 1)) {
						isParams = true;
						id = id.Args[0];
					}
					if (id.AttrNamed(S.Ref) != null)
						refExistingVar = true;
					if (id.Calls(S.IndexBracks, 2)) {
						condition = id.Args[1];
						id = id.Args[0];
					} else if (id.ArgCount == 1) {
						condition = id.Args[0];
						id = id.Target;
					}
					if (condition != null)
						condition = condition.ReplaceRecursive(n => n.IsIdNamed(S._HashMark) ? id : null);
					if (!id.IsId)
						return null;
					return id.Name;
				}
				return null;
			}
コード例 #18
0
ファイル: ReplaceMacro.cs プロジェクト: qwertie/ecsharp
		/// <summary>Finds capture variables like <c>$x</c> and replaces them with values
		/// from <c>captures</c> (e.g. <c>captures[(Symbol)"x"]</c> for <c>$x</c>)</summary>
		public static LNode ReplaceCaptures(LNode outputSpec, MMap<Symbol, LNode> captures)
		{
			if (captures.Count != 0)
			{
				// TODO: EXPAND SPLICES! Generally it works anyway though because 
				// the macro processor has built-in support for #splice.
				return outputSpec.ReplaceRecursive(n => {
					LNode id, cap;
					if ((id = LNodeExt.GetCaptureIdentifier(n)) != null) {
						if (captures.TryGetValue(id.Name, out cap))
							return cap;
					}
					return null;
				});
			}
			return outputSpec;
		}
コード例 #19
0
ファイル: ReplaceMacro.cs プロジェクト: qwertie/ecsharp
		private static Dictionary<Symbol, LNode> ScanForVariables(LNode code)
		{
			var nameTable = new Dictionary<Symbol, LNode>();
			code.ReplaceRecursive(n =>
				{
					if (n.IsId)
						nameTable[n.Name] = n;
					else {
						LNode id = LNodeExt.GetCaptureIdentifier(n);
						if (id != null) {
							if (!nameTable.ContainsKey(n.Name))
								nameTable[id.Name] = n;
							return n;
						}
					}
					return null;
				});
			return nameTable;
		}