Represents an LLLPG rule, which is a Predicate plus a Name and optional attributes (e.g. token, private, etc.).
コード例 #1
0
			public void Generate(Rule rule)
			{
				CGH.BeginRule(rule);
				_currentRule = rule;
				_target = new WList<LNode>();
				_laVarsNeeded = 0;
				_separatedMatchCounter = _stopLabelCounter = 0;
				_recognizerMode = rule.IsRecognizer;
				_labelsInUse.Clear();

				Visit(rule.Pred);

				if (_laVarsNeeded != 0) {
					LNode laVars = F.Call(S.Var, CGH.LAType());
					for (int i = 0; _laVarsNeeded != 0; i++, _laVarsNeeded >>= 1)
						if ((_laVarsNeeded & 1) != 0)
							laVars = laVars.PlusArg(F.Id("la" + i.ToString()));
					_target.Insert(0, laVars);
				}

				LNode method;
				if (rule.TryWrapperName != null) {
					Debug.Assert(rule.IsRecognizer);
					method = F.OnNewLine(CGH.CreateTryWrapperForRecognizer(rule));
					_classBody.SpliceAdd(method, S.Splice);
				}

				method = CGH.CreateRuleMethod(rule, _target.ToVList());
				if (!rule.IsRecognizer)
					method = F.OnNewLine(method);
				_classBody.SpliceAdd(method, S.Splice);
			}
コード例 #2
0
ファイル: Rule.cs プロジェクト: qwertie/ecsharp
		Rule MakeRecognizerVersion(LNode prototype, Symbol newName)
		{
			if (IsRecognizer)
				return this;
			else {
				_recognizer = (Rule)MemberwiseClone();
				_recognizer.IsRecognizer = true;
				_recognizer.Basis = prototype;
				_recognizer.Name = newName;
				return _recognizer;
			}
		}
コード例 #3
0
		public static void Run(Rule rule, IMessageSink sink, IDictionary<Symbol, Rule> rules, IPGCodeGenHelper codeGen)
		{
			// 1. Scan for a list of code blocks that use $labels, and a list of rules referenced.
			var data = new DataGatheringVisitor(rules, rule);
			if (data.RulesReferenced.Count != 0 || data.OtherReferences.Count != 0 || data.ProperLabels.Count != 0)
			{
				var vsv = new AutoValueSaverVisitor(data, sink, rules, codeGen);
				// 2. Create $result variable if it was used
				// 3. Scan for predicates with labels, and RuleRefs referenced by 
				//    code blocks. For each such predicate, generate a variable at 
				//    the beginning of the rule and set the ResultSaver.
				vsv.Process(rule);
				// 4. Replace recognized $substitutions in code blocks
				vsv.ReplaceSubstitutionsInCodeBlocks();
			}
		}
コード例 #4
0
ファイル: CodeGenHelperBase.cs プロジェクト: Shaykh/Loyc
		public virtual void Done()
		{
			_classBody = null;
			F = null;
			_setDeclNames = null;
			_currentRule = null;
		}
コード例 #5
0
ファイル: CodeGenHelperBase.cs プロジェクト: Shaykh/Loyc
		public virtual void BeginRule(Rule rule)
		{
			_currentRule = rule;
			_setNameCounter = 0;
		}
コード例 #6
0
ファイル: LlpgCoreTests.cs プロジェクト: Shaykh/Loyc
		protected static RuleRef Call(Rule rule, params LNode[] args) { 
			return new RuleRef(null, rule) { Params = new RVList<LNode>(args) };
		}
コード例 #7
0
ファイル: AnalysisVisitors.cs プロジェクト: qwertie/ecsharp
			public void Analyze(Rule rule)
			{
				rule.Pred.Call(this);

				// For rules that are not marked "private", we must apply "empty" 
				// prematch information in case the rule is called directly or from 
				// outside the known ruleset, to force use of Match() at rule start.
				if (!(rule.IsPrivate ?? LLPG.PrematchByDefault))
					_apply.ApplyPrematchData(rule.Pred, Empty);
			}
コード例 #8
0
ファイル: AnalysisVisitors.cs プロジェクト: qwertie/ecsharp
			public void Analyze(Rule rule)
			{
				_currentRule = rule;
				_k = rule.K > 0 ? rule.K : LLPG.DefaultK;
				rule.Pred.Call(this);
			}
コード例 #9
0
ファイル: CodeGenHelperBase.cs プロジェクト: Shaykh/Loyc
		/// <summary>See <see cref="IPGCodeGenHelper.CreateTryWrapperForRecognizer"/> for more information.</summary>
		public LNode CreateTryWrapperForRecognizer(Rule rule)
		{
			Debug.Assert(rule.TryWrapperName != null);

			LNode method = rule.GetMethodSignature();
			LNode retType = method.Args[0], name = method.Args[1], args = method.Args[2];
			RVList<LNode> forwardedArgs = ForwardedArgList(args);
			
			LNode lookahead = F.Id("lookaheadAmt");
			Debug.Assert(args.Calls(S.List));
			args = args.WithArgs(args.Args.Insert(0, F.Var(F.Int32, lookahead)));

			LNode savePosition = ApiType(F.Id(SavePosition));
			LNode @this = InputSource ?? F.@this;
			LNode body = F.Braces(
				F.Call(S.UsingStmt, F.Call(S.New, F.Call(savePosition, @this, lookahead)), 
					F.Call(S.Return, F.Call(name, forwardedArgs)))
			);
			return method.WithArgs(retType, rule.TryWrapperName, args, body);
		}
コード例 #10
0
ファイル: LlpgParserTests.cs プロジェクト: qwertie/ecsharp
		void TestStage2(bool lexerMode, params Tuple<string,string,string>[] ruleTuples)
		{
			var helper = lexerMode ? (IPGCodeGenHelper)new IntStreamCodeGenHelper() : new GeneralCodeGenHelper();
			var rules = new List<Pair<Rule,LNode>>();
			foreach (var tuple in ruleTuples)
			{
				string ruleName = tuple.Item1, inputExpr = tuple.Item2;
				var node = LesLanguageService.Value.ParseSingle(inputExpr, ConsoleMessageSink.Value, ParsingMode.Expressions);
				var rule = new Rule(node, GSymbol.Get(ruleName), null);
				rules.Add(Pair.Create(rule, node));
			}
			
			var parser = new StageTwoParser(helper, ConsoleMessageSink.Value);
			parser.Parse(rules);
			for (int i = 0; i < rules.Count; i++) {
				var rule = rules[i].A;
				var ruleAsString = rule.Pred.ToString();
				var expected = ruleTuples[i].Item3;
				if (expected == null)
					ConsoleMessageSink.Value.Warning(ruleTuples[i].Item1, ruleAsString);
				else
					AreEqual(expected, ruleAsString);
			}
		}
コード例 #11
0
ファイル: CodeGenHelperBase.cs プロジェクト: dadhi/ecsharp
 protected virtual Symbol GenerateSetName(Rule currentRule)
 {
     return(GSymbol.Get(string.Format("{0}_set{1}", currentRule.Name.Name, _setNameCounter++)));
 }
コード例 #12
0
ファイル: CodeGenHelperBase.cs プロジェクト: dadhi/ecsharp
 public virtual void BeginRule(Rule rule)
 {
     _currentRule    = rule;
     _setNameCounter = 0;
 }
コード例 #13
0
ファイル: Rule.cs プロジェクト: qwertie/ecsharp
		public Rule MakeRecognizerVersion()
		{
			var scanName = GSymbol.Get("Scan_" + Name.Name);
			return _recognizer = _recognizer ?? MakeRecognizerVersion(scanName);
		}
コード例 #14
0
			public DataGatheringVisitor(IDictionary<Symbol, Rule> rules, Rule rule)
				{ _rules = rules; Visit(rule.Pred); }
コード例 #15
0
ファイル: CodeGenHelperBase.cs プロジェクト: Shaykh/Loyc
		protected virtual Symbol GenerateSetName(Rule currentRule)
		{
			return GSymbol.Get(string.Format("{0}_set{1}", currentRule.Name.Name, _setNameCounter++));
		}
コード例 #16
0
ファイル: CodeGenHelperBase.cs プロジェクト: Shaykh/Loyc
		public virtual LNode CreateRuleMethod(Rule rule, RVList<LNode> methodBody)
		{
			return rule.CreateMethod(methodBody);
		}
コード例 #17
0
ファイル: StageTwoParser.cs プロジェクト: Shaykh/Loyc
        Pred NodeToPredCore(LNode expr, Context ctx = Context.Rule)
        {
            if (expr.IsCall)
            {
                bool slash = false, not;
                if (expr.Calls(S.Tuple))
                {
                    // sequence: (a, b, c)
                    if (expr.Calls(S.Tuple, 1))
                    {
                        return(NodeToPred(expr.Args[0], ctx));
                    }
                    return(ArgsToSeq(expr, ctx));
                }
                else if (expr.Calls(S.Braces))
                {
                    // Just code: use an empty sequence
                    var seq = new Seq(expr);
                    seq.PostAction = RemoveBraces(expr);
                    return(seq);
                }
                else if (expr.Calls(S.OrBits, 2) || (slash = expr.Calls(S.Div, 2)))
                {
                    // alternatives: a | b, a || b, a / b
                    LNode      lhs = expr.Args[0], rhs = expr.Args[1];
                    BranchMode lhsMode, rhsMode;
                    Pred       left  = BranchToPred(lhs, out lhsMode, ctx);
                    Pred       right = BranchToPred(rhs, out rhsMode, ctx);
                    return(Pred.Or(left, right, slash, expr, lhsMode, rhsMode, _sink));
                }
                else if (expr.Calls(_Star, 1) || expr.Calls(_Plus, 1) || expr.Calls(_Opt, 1))
                {
                    // loop (a+, a*) or optional (a?)
                    return(TranslateLoopExpr(expr, ctx));
                }
                else if (expr.Calls(_Gate, 1) || expr.Calls(_EqGate, 1))
                {
                    // => foo (LES-based parser artifact)
                    return(new Gate(expr, new Seq(F._Missing),
                                    NodeToPred(expr.Args[0], Context.GateRight))
                    {
                        IsEquivalency = expr.Calls(_EqGate)
                    });
                }
                else if (expr.Calls(_Gate, 2) || expr.Calls(_EqGate, 2))
                {
                    if (ctx == Context.GateLeft)
                    {
                        _sink.Write(Severity.Error, expr, "Cannot use a gate in the left-hand side of another gate");
                    }

                    return(new Gate(expr, NodeToPred(expr.Args[0], Context.GateLeft),
                                    NodeToPred(expr.Args[1], Context.GateRight))
                    {
                        IsEquivalency = expr.Calls(_EqGate)
                    });
                }
                else if ((not = expr.Calls(_AndNot, 1)) || expr.Calls(_And, 1))
                {
                    expr = expr.Args[0];
                    var   subpred = AutoNodeToPred(expr, Context.And);
                    LNode subexpr = subpred as LNode, subexpr0 = subexpr;
                    bool  local = false;
                    if (subexpr != null)
                    {
                        if ((subexpr = subexpr.WithoutAttrNamed(_Local)) != subexpr0)
                        {
                            local = true;
                        }
                        // we should default to [Local] eventually, so recognize [Hoist] too
                        subexpr = subexpr.WithoutAttrNamed(_Hoist);
                    }
                    return(new AndPred(expr, subexpr ?? subpred, not, local));
                }
                else if (expr.Calls(S.NotBits, 1))
                {
                    var subpred = NodeToPred(expr.Args[0], ctx);
                    if (subpred is TerminalPred)
                    {
                        var term = (TerminalPred)subpred;
                        term.Set = term.Set.Inverted().WithoutEOF();
                        return(term);
                    }
                    else
                    {
                        _sink.Write(Severity.Error, expr,
                                    "The set-inversion operator ~ can only be applied to a single terminal, not a '{0}'", subpred.GetType().Name);
                        return(subpred);
                    }
                }
                else if (expr.Calls(_Any, 2) && expr.Args[0].IsId)
                {
                    return(Translate_any_in_Expr(expr, ctx));
                }
                else if ((expr.Name.Name.EndsWith(":") || expr.Name.Name.EndsWith("=")) && expr.ArgCount == 2)
                {
                    return(TranslateLabeledExpr(expr, ctx));
                }
            }

            // expr is an Id, literal, or non-special call
            Rule rule = TryGetRule(expr);

            if (rule != null)
            {
                //int ruleArgc = rule.Basis.Args[2].ArgCount;
                //if (expr.ArgCount > ruleArgc) // don't complain about too few args, in case there are default args (I'm too lazy to check)
                //    _sink.Write(MessageSink.Error, expr, "Rule '{0}' takes {1} arguments ({2} given)", rule.Name, ruleArgc, expr.ArgCount);
                return(new RuleRef(expr, rule)
                {
                    Params = expr.Args
                });
            }

            string errorMsg = null;
            Pred   terminal = _helper.CodeToPred(expr, ref errorMsg);

            if (terminal == null)
            {
                errorMsg = errorMsg ?? "LLLPG: unrecognized expression";
                terminal = new TerminalPred(expr, _helper.EmptySet);
                _sink.Write(Severity.Error, expr, errorMsg);
            }
            else if (errorMsg != null)
            {
                _sink.Write(Severity.Warning, expr, errorMsg);
            }
            return(terminal);
        }
コード例 #18
0
        public Rule MakeRecognizerVersion()
        {
            var scanName = GSymbol.Get("Scan_" + Name.Name);

            return(_recognizer = _recognizer ?? MakeRecognizerVersion(scanName));
        }
コード例 #19
0
		// Step 3
		void Process(Rule rule)
		{
			// Create $result variable if it was used
			bool usingResult = _data.OtherReferences.ContainsKey(_resultId) || _data.ProperLabels.TryGetValue(_result, false);
			if (usingResult && rule.ReturnType != null)
			{
				_data.ProperLabels[_result] = true;
				var type = rule.ReturnType;
				_newVarInitializers[_result] = Pair.Create(type, _codeGen.MakeInitializedVarDecl(type, false, _result));
			}

			Visit(rule.Pred);

			if (_newVarInitializers.Count != 0)
			{
				var decls = _newVarInitializers.OrderBy(p => p.Key.Name).Select(p => p.Value.B);
				LNode decls2 = F.Call(S.Splice, decls);
				rule.Pred.PreAction = Pred.MergeActions(decls2, rule.Pred.PreAction);
				if (usingResult)
					rule.Pred.PostAction = Pred.MergeActions(rule.Pred.PostAction, F.Call(S.Return, _resultId));
			}
		}