private static void SubstituteRuleMask(MethodInfo method, List <CilSymbolRef> parts, CilSymbolRef[] ruleMask) { int maskLength = ruleMask.Length; int paramCount = method.GetParameters().Length; for (int i = 0, paramIndex = 0; i != maskLength || paramIndex != paramCount;) { if (paramIndex == paramCount) { // Mask has keywords after parameters if (ruleMask[i] == null) { throw new InvalidOperationException("Insufficient parameters to substitute literal-mask slot #" + i); } parts.Add(ruleMask[i]); } else if (i == maskLength || ruleMask[i] == null) { // Mask slot or there are parameters after mask var p = method.GetParameters()[paramIndex++]; parts.Add(CilSymbolRef.Create(p.ParameterType)); } else { // Add keyword from the rule mask parts.Add(ruleMask[i]); } if (i != maskLength) { ++i; } } }
public void Test() { var tokens = new [] { CilSymbolRef.Create("foo"), CilSymbolRef.Create("bar"), CilSymbolRef.Create("other"), CilSymbolRef.Create(typeof(string)), CilSymbolRef.Create(typeof(string), "foo"), // links foo and string CilSymbolRef.Create(typeof(string), "bar"), // links bar and string CilSymbolRef.Create(typeof(string), "other"), // links other and string }; foreach (var token in tokens) { target.Link(token); } Assert.AreEqual(1, target.Definitions.Count()); var SYM1 = new Symbol("123"); target.Resolve(tokens[0]).Symbol = SYM1; for (int i = 1; i != tokens.Length; ++i) { var context = "#" + i; Assert.AreSame(SYM1, target.GetSymbol(tokens[i]), context); } }
private void LdTid(EmitSyntax emit, CilSymbolRef tid) { if (tid.Type != null) { emit .Ldtoken(emit.Types.Import(tid.Type)) .Call((RuntimeTypeHandle h) => Type.GetTypeFromHandle(h)) ; } else { emit.Ldnull(); } if (tid.Literal == null) { emit.Ldnull(); } else { emit.Ldstr(new QStr(tid.Literal)); } emit .Newobj(() => new CilSymbolRef(default(Type), default(string))); }
protected bool DetectThisAsToken(List <CilSymbolRef> parts) { if (HasThisAsSymbol) { parts.Add(CilSymbolRef.Create(Member.DeclaringType)); return(true); } return(false); }
public IEnumerable <CilProduction> GetProductions(IEnumerable <CilSymbolRef> leftSides) { foreach (var leftSide in leftSides.ToArray()) { yield return(new CilProduction( outcome: CilSymbolRef.Create(typeof(void)), pattern: new[] { CilSymbolRef.Create(typeof(int)) }, context: CilContextRef.None, actionBuilder: code => code.Emit(il => il.Ldnull().Ret()))); } }
public void LanguageDescriptorCollectDataFromTypeMetadata() { ILogging logging = new MemoryLogging(); var target = new CilGrammar(new CilGrammarSource(typeof(IMetadtaTest0)), logging); Assert.AreEqual(CilSymbolRef.Create(typeof(void)), target.Start); Assert.AreEqual(2, target.SymbolResolver.Definitions.Count()); Assert.AreEqual( new [] { typeof(void), typeof(int) }, target.SymbolResolver.Definitions.Select(def => def.Type).ToArray()); }
protected override CilSymbolRef[] DoGetRuleMask(MethodInfo methodInfo) { var resultList = new List <CilSymbolRef>(); resultList.AddRange( Enumerable.Repeat(default(CilSymbolRef), methodInfo.GetParameters().Length)); resultList.Add(CilSymbolRef.Create(StemScanner.RParen)); return(resultList.ToArray());; }
protected CilSymbolRef GetThisSymbol() { if (HasThisAsSymbol) { if (Parent != null && Parent.Member is Type) { return(CilSymbolRef.Create((Type)Parent.Member)); } return(CilSymbolRef.Create(Member.DeclaringType)); } return(null); }
protected override CilSymbolRef[] DoGetRuleMask(MethodInfo methodInfo) { int placeholderCount = KeywordMask.Count(item => item == null); int nonPlaceholderParameterCount = methodInfo.GetParameters().Length - placeholderCount; if (nonPlaceholderParameterCount < 0) { throw new InvalidOperationException("Insufficient rule-method arguments in " + this); } return(KeywordMask .Select(item => item == null ? null : CilSymbolRef.Create(item)) .ToArray()); }
public override IEnumerable <CilSymbolFeature <CilContextProvider> > GetLocalContextProviders() { if (Parent == null) { var type = (Type)Member; return(new[] { new CilSymbolFeature <CilContextProvider>( CilSymbolRef.Create(type), new CilContextProvider(type)) }); } return(new CilSymbolFeature <CilContextProvider> [0]); }
public override IEnumerable <CilSymbolRef> GetSymbolsInCategory(SymbolCategory requestedCategories) { if ((requestedCategories & this.categories) == 0) { return(Enumerable.Empty <CilSymbolRef>()); } if (Text == null) { return(new[] { CilSymbolRef.Create(TokenType) }); } else { return(new[] { CilSymbolRef.Create(Text) }); } }
public override IEnumerable <CilSymbolRef> GetSymbolsInCategory(SymbolCategory category) { if ((category & SymbolCategory.ExplicitlyUsed) != SymbolCategory.ExplicitlyUsed) { return(Enumerable.Empty <CilSymbolRef>()); } if (Text == null) { return(new[] { CilSymbolRef.Create(TokenType) }); } else { return(new[] { CilSymbolRef.Create(Text) }); } }
private CilSymbolRef[] GetProducedTokens() { List <CilSymbolRef> resultList = new List <CilSymbolRef>(); if (LiteralText != null) { resultList.Add(CilSymbolRef.Create(LiteralText)); } if (TokenType != null) { resultList.Add(CilSymbolRef.Create(TokenType)); } return(resultList.ToArray()); }
public CilSymbol Resolve(CilSymbolRef symbolRef) { if (symbolRef == null) { return null; } var literalDef = ResolveLiteral(symbolRef.Literal); var tokenTypeDef = ResolveTokenType(symbolRef.Type); if (literalDef != null && tokenTypeDef != null && literalDef != tokenTypeDef) { throw new InvalidOperationException("Unable to resolve conflicting token reference: " + symbolRef); } return literalDef ?? tokenTypeDef; }
public override IEnumerable <CilSymbolFeature <Precedence> > GetSymbolPrecedence() { CilSymbolRef token; if (TermText == null) { token = CilSymbolRef.Create(TermType); } else { token = CilSymbolRef.Create(TermText); } yield return(new CilSymbolFeature <Precedence>( token, new Precedence(PrecedenceValue, Associativity))); }
public override IEnumerable <CilMerger> GetMergers(IEnumerable <CilSymbolRef> leftSides) { var returnToken = CilSymbolRef.Create(Method.ReturnType); if (!leftSides.Contains(returnToken)) { return(new CilMerger[0]); } var type = Method.ReturnType; var method = Method; return(new [] { new CilMerger { Symbol = returnToken, Context = GetContext(), ActionBuilder = code => { code = code.LdMergerOldValue(); if (type.IsValueType) { code = code.Emit(il => il.Unbox_Any(il.Types.Import(type))); } code = code.LdMergerNewValue(); if (type.IsValueType) { code = code.Emit(il => il.Unbox_Any(il.Types.Import(type))); } code = code .Emit(il => il.Call(il.Methods.Import(method))); if (type.IsValueType) { code = code.Emit(il => il.Box(il.Types.Import(type))); } return code; } } }); }
protected override CilSymbolRef[] DoGetRuleMask(MethodInfo methodInfo) { var resultList = new List <CilSymbolRef>(); int nonMaskParameterCount = methodInfo.GetParameters().Length - KeywordMask.Count(item => item == null); if (nonMaskParameterCount < 0) { throw new InvalidOperationException("Insufficient rule-method arguments."); } resultList.Add(CilSymbolRef.Create(StemScanner.LParen)); resultList.AddRange( KeywordMask .Select(item => item == null ? null : CilSymbolRef.Create(item))); return(resultList.ToArray()); }
private IEnumerable <CilProduction> GetExpansionRules(CilSymbolRef token) { if (token.HasLiteral) { return(Enumerable.Empty <CilProduction>()); } var method = this.Method; var pattern = new TypePattern(method); MethodInfo producer = pattern.MakeProducer(token.Type); if (producer != null) { return(DoGetRules(producer, token)); } else { return(Enumerable.Empty <CilProduction>()); } }
private CilSymbol Ensure(CilSymbolRef symbolRef) { CilSymbol literalDef = ResolveLiteral(symbolRef.Literal); CilSymbol typeDef = ResolveTokenType(symbolRef.Type); CilSymbol def = MergeDefs(literalDef, typeDef); if (def == null) { def = new CilSymbol(); } else if (symbolRef.Type != null && def.Type != null && def.Type != symbolRef.Type) { throw new InvalidOperationException("Incompatible symbol constraints."); } // Add token to a defintion if (symbolRef.Type != null) { def.Type = symbolRef.Type; } if (symbolRef.HasLiteral) { def.Literals.Add(symbolRef.Literal); } // Update index foreach (var literal in def.Literals) { ref2def[literal] = def; } if (def.Type != null) { ref2def[def.Type] = def; } return def; }
protected IEnumerable <CilProduction> DoGetRules(MethodInfo method, CilSymbolRef leftSide) { var outcome = CilSymbolRef.Create(method.ReturnType); if (!object.Equals(outcome, leftSide)) { return(Enumerable.Empty <CilProduction>()); } var pattern = new List <CilSymbolRef>(); int argShift = 0; CilSymbolRef thisSymbol = GetThisSymbol(); if (thisSymbol != null) { ++argShift; pattern.Add(thisSymbol); } var ruleMask = DoGetRuleMask(method); SubstituteRuleMask(method, pattern, ruleMask); var rule = new CilProduction( outcome: outcome, pattern: pattern, precedence: GetPrecedence(), context: GetContext(method, thisSymbol != null), actionBuilder: code => { if (thisSymbol != null) { code.LdActionArgument(0, method.DeclaringType); } // Pass rule-arguments to the rule-method for (int i = 0; i != method.GetParameters().Length; ++i) { var param = method.GetParameters()[i]; int ruleArgIndex = NthEmptySlotIndex(ruleMask, i); if (thisSymbol != null) { ++ruleArgIndex; } code.LdActionArgument(ruleArgIndex, param.ParameterType); } code.Emit( il => { il.Call(method); if (method.ReturnType == typeof(void)) { il.Ldnull(); } else if (method.ReturnType.IsValueType) { il.Box(il.Types.Import(method.ReturnType)); } return(il); }); return(code); }); return(new[] { rule }); }
public CilSymbolFeature(CilSymbolRef symbolRef, T value) { this._symbolRef = symbolRef; this._value = value; }
public override IEnumerable <CilMatcher> GetMatchers() { var tokenType = Method.ReturnType; var nextConditionType = GetNextConditionType(); var matcher = new CilMatcher(); var contextType = GetContextType(); //var context = CilContextRef.ByType(contextType); if (tokenType != typeof(void)) { var outcome = CilSymbolRef.Create(tokenType, LiteralText); matcher.MainOutcome = outcome; matcher.AllOutcomes.Add(outcome); } matcher.DefiningMethod = Method; matcher.Disambiguation = Disambiguation; if (LiteralText == null) { matcher.Pattern = ScanPattern.CreateRegular(Pattern, RegexPattern); } else { matcher.Pattern = ScanPattern.CreateLiteral(LiteralText); } var parameters = Method.GetParameters().ToList(); matcher.Context = GetContext(); matcher.NextConditionType = nextConditionType; matcher.ActionBuilder = code => { ParameterInfo nextModeParameter; if (parameters.Count != 0 && parameters.Last().IsOut) { nextModeParameter = parameters.Last(); parameters.RemoveAt(parameters.Count - 1); } else { nextModeParameter = null; } if (parameters.Count == 0) { } else if (parameters.Count == 1 && parameters[0].ParameterType == typeof(string)) { code.LdMatcherTokenString(); } else if (parameters.Count == 3 && parameters[0].ParameterType == typeof(char[]) && parameters[1].ParameterType == typeof(int) && parameters[2].ParameterType == typeof(int)) { code .LdMatcherBuffer() .LdMatcherStartIndex() .LdMatcherLength(); } else { throw new InvalidOperationException( "Unsupported match-method signature: " + string.Join(", ", parameters.Select(p => p.ParameterType.Name))); } Ref <Locals> nextModeVar = null; if (nextModeParameter != null) { code .Emit(il => { nextModeVar = il.Locals.Generate().GetRef(); return(il .Local(nextModeVar.Def, il.Types.Object) .Ldloca(nextModeVar)); }); } code.Emit(il => il.Call(Method)); if (nextModeParameter != null) { code .Emit(il => il.Ldloc(nextModeVar)) .ChangeCondition(nextConditionType); } if (Method.ReturnType == typeof(void)) { code.SkipAction(); } else { if (Method.ReturnType.IsValueType) { code.Emit(il => il.Box(il.Types.Import(Method.ReturnType))); } code .ReturnFromAction() ; } return(code); }; return(new[] { matcher }); }
public void Link(CilSymbolRef first) { Ensure(first); }
public Symbol GetSymbol(CilSymbolRef tid) { CilSymbol def = Resolve(tid); return def == null ? null : def.Symbol; }
public bool Contains(CilSymbolRef symbolRef) { return symbolRef != null && (ResolveLiteral(symbolRef.Literal) != null || ResolveTokenType(symbolRef.Type) != null); }
protected IEnumerable<CilProduction> DoGetRules(MethodInfo method, CilSymbolRef leftSide) { var outcome = CilSymbolRef.Create(method.ReturnType); if (!object.Equals(outcome, leftSide)) { return Enumerable.Empty<CilProduction>(); } var pattern = new List<CilSymbolRef>(); int argShift = 0; CilSymbolRef thisSymbol = GetThisSymbol(); if (thisSymbol != null) { ++argShift; pattern.Add(thisSymbol); } var ruleMask = DoGetRuleMask(method); SubstituteRuleMask(method, pattern, ruleMask); var rule = new CilProduction( outcome: outcome, pattern: pattern, precedence: GetPrecedence(), context: GetContext(method, thisSymbol != null), actionBuilder: code => { if (thisSymbol != null) { code.LdActionArgument(0, method.DeclaringType); } // Pass rule-arguments to the rule-method for (int i = 0; i != method.GetParameters().Length; ++i) { var param = method.GetParameters()[i]; int ruleArgIndex = NthEmptySlotIndex(ruleMask, i); if (thisSymbol != null) { ++ruleArgIndex; } code.LdActionArgument(ruleArgIndex, param.ParameterType); } code.Emit( il => { il.Call(method); if (method.ReturnType == typeof(void)) { il.Ldnull(); } else if (method.ReturnType.IsValueType) { il.Box(il.Types.Import(method.ReturnType)); } return il; }); return code; }); return new[] { rule }; }
private IEnumerable<CilProduction> GetExpansionRules(CilSymbolRef token) { if (token.HasLiteral) { return Enumerable.Empty<CilProduction>(); } var method = this.Method; var pattern = new TypePattern(method); MethodInfo producer = pattern.MakeProducer(token.Type); if (producer != null) { return DoGetRules(producer, token); } else { return Enumerable.Empty<CilProduction>(); } }
private static void SubstituteRuleMask(MethodInfo method, List<CilSymbolRef> parts, CilSymbolRef[] ruleMask) { int maskLength = ruleMask.Length; int paramCount = method.GetParameters().Length; for (int i = 0, paramIndex = 0; i != maskLength || paramIndex != paramCount; ) { if (paramIndex == paramCount) { // Mask has keywords after parameters if (ruleMask[i] == null) { throw new InvalidOperationException("Insufficient parameters to substitute literal-mask slot #" + i); } parts.Add(ruleMask[i]); } else if (i == maskLength || ruleMask[i] == null) { // Mask slot or there are parameters after mask var p = method.GetParameters()[paramIndex++]; parts.Add(CilSymbolRef.Create(p.ParameterType)); } else { // Add keyword from the rule mask parts.Add(ruleMask[i]); } if (i != maskLength) { ++i; } } }
private static int NthEmptySlotIndex(CilSymbolRef[] ruleMask, int n) { int i = 0; for (; i != ruleMask.Length; ++i) { if (ruleMask[i] == null) { if (n == 0) { return i; } --n; } } return i + n; }
private static SymbolBase GetMatcherOutcomeSymbol( Grammar grammar, ICilSymbolResolver symbolResolver, CilSymbolRef mainOutcome, IEnumerable<CilSymbolRef> allOutcomes) { Symbol main = symbolResolver.GetSymbol(mainOutcome); Symbol[] all = (from outcome in allOutcomes select symbolResolver.GetSymbol(outcome)) .ToArray(); switch (all.Length) { case 0: return null; case 1: return main; default: return new AmbiguousSymbol(main, all); } }
public void TestLinkTwoTypes() { target.Link(CilSymbolRef.Create(typeof(string), "foo")); Assert.Throws <InvalidOperationException>( () => target.Link(CilSymbolRef.Create(typeof(int), "foo"))); }