/// <summary> /// 构造产生式。 /// </summary> /// <param name="symbolMapper">符号的映射表。</param> public void BuildProductions(Dictionary <T, Symbol <T> > symbolMapper) { int len = bodies.Length; productions = new Production <T> [len]; for (int i = 0; i < len; i++) { ProductionBody <T> body = bodies[i]; int cnt = body.Body.Count; Symbol <T>[] symbolBody = new Symbol <T> [cnt]; for (int j = 0; j < cnt; j++) { T id = body.Body[j]; Symbol <T> sym; if (symbolMapper.TryGetValue(id, out sym)) { symbolBody[j] = sym; } else if (EqualityComparer <T> .Default.Equals(id, Token <T> .Error)) { symbolBody[j] = Error; } else { throw CompilerCommonExceptions.InvalidSymbolId("body", id.ToString()); } } Terminal <T> prec = null; if (body.PrecedenceSet) { Symbol <T> sym; if (!symbolMapper.TryGetValue(body.Precedence, out sym)) { throw CompilerCommonExceptions.InvalidSymbolId("Precedence", body.Precedence.ToString()); } prec = sym as Terminal <T>; if (prec == null) { throw CompilerCommonExceptions.InvalidSymbolId("Precedence", body.Precedence.ToString()); } } else { // 使用最右的终结符代表当前产生式的结合性。 for (int j = symbolBody.Length - 1; j >= 0; j--) { Terminal <T> sym = symbolBody[j] as Terminal <T>; if (sym != null) { prec = sym; break; } } } productions[i] = new Production <T>(body.Index, this, symbolBody, body.ProductionAction, prec); } }
/// <summary> /// 检查指定符号的标识符。 /// </summary> /// <param name="id">要检查的标识符。</param> public void CheckSymbolId(T id) { if (EqualityComparer <T> .Default.Equals(id, Token <T> .EndOfFile) || EqualityComparer <T> .Default.Equals(id, Token <T> .Error)) { throw CompilerCommonExceptions.InvalidSymbolId("id", id.ToString()); } else if (Constants.ToInt32(id) < 0) { throw CompilerCommonExceptions.InvalidSymbolId("id", id.ToString()); } if (symbolIds.ContainsKey(id)) { throw CompilerCommonExceptions.DuplicatedSymbolId("id", id.ToString()); } }
/// <summary> /// 返回产生式体。 /// </summary> /// <param name="bodies">产生式体包含的终结符或非终结符。</param> /// <returns>产生式体。</returns> public ProductionBody <T> Body(params T[] bodies) { for (int i = 0; i < bodies.Length; i++) { if (EqualityComparer <T> .Default.Equals(bodies[i], Token <T> .EndOfFile)) { throw CompilerCommonExceptions.InvalidSymbolId("bodies", bodies[i].ToString()); } else if (!EqualityComparer <T> .Default.Equals(bodies[i], Token <T> .Error) && Constants.ToInt32(bodies[i]) < 0) { throw CompilerCommonExceptions.InvalidSymbolId("bodies", bodies[i].ToString()); } } return(new ProductionBody <T>(productionCount++, bodies ?? new T[0])); }