예제 #1
0
			public override void Visit(TerminalPred term)
			{
				if (_recognizerMode)
					_target.Add(CGH.GenerateMatch(term.Set, false, _recognizerMode));
				else if (term.Set.ContainsEverything || (term.Prematched ?? false))
					_target.Add(term.AutoSaveResult(CGH.GenerateSkip(term.ResultSaver != null)));
				else
					_target.Add(term.AutoSaveResult(CGH.GenerateMatch(term.Set, term.ResultSaver != null, false)));
			}
예제 #2
0
		Pred NodeToPredCore(LNode expr, Context ctx = Context.Rule)
		{
			if (expr.IsCall)
			{
				bool slash = false, not;
				var name = expr.Name;
				if (name == S.Tuple)
				{
					// sequence: (a, b, c)
					if (expr.Calls(S.Tuple, 1))
						return NodeToPred(expr.Args[0], ctx);
					return ArgsToSeq(expr, ctx);
				}
				else if (name == 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.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) {
						local = true;
						if ((subexpr = subexpr.WithoutAttrNamed(_Hoist)) != subexpr0)
							local = false;
						// also recognize [Local], which was not the default until v1.9.1
						subexpr = subexpr.WithoutAttrNamed(_Local);
					}
					// Extract error message for Check(), if provided.
					string errorString = null;
					if (subexpr != null)
						subexpr = subexpr.WithAttrs(n => {
							if (n.Value is string) {
								errorString = (string)n.Value;
								return NoValue.Value; // drop attribute from output
							} else if (n.IsIdNamed("NoCheck")) {
								errorString = "";
								return NoValue.Value;
							}
							return n;
						});
					return new AndPred(expr, subexpr ?? subpred, not, local) { CheckErrorMessage = errorString };
				}
				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.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 ((name.Name.EndsWith(":") || 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.CodeToTerminalPred(expr, ref errorMsg);
			if (terminal == null) {
				errorMsg = errorMsg ?? "LLLPG: unrecognized expression";
				terminal = new TerminalPred(expr, _helper.EmptySet);
				_sink.Error(expr, errorMsg);
			} else if (errorMsg != null)
				_sink.Warning(expr, errorMsg);
			return terminal;
		}
예제 #3
0
				public override void Visit(TerminalPred term)
				{
					if (_index < _path.Count) {
						if (term.Prematched != false) {
							IPGTerminalSet predicted = _path[_index].Terminals;
							bool pm = predicted.IsSubsetOf(term.Set);
							if (pm || !_reachedInnerAlts)
								term.Prematched = pm;
						}
						_index++;
					} else if (!_reachedInnerAlts) {
						term.Prematched = false;
					}
				}
예제 #4
0
파일: PredVisitor.cs 프로젝트: Shaykh/Loyc
		public virtual void Visit(TerminalPred term) { VisitOther(term); }