/// <inheritdoc /> public ProductionRule Read(ITerm representation) { // CONTRACT: Inherited from IProductionFormat<T> IConsTerm prod = representation.ToCons("prod", 3); IListTerm rhs = (IListTerm)prod[0]; ITerm lhs = prod[1]; ITerm attr = prod[2]; var reduction = ReadReduction(lhs); var expression = ReadExpression(rhs); string constructor = ReadConstructor(attr); var type = ReadProductionType(attr); var flags = ReadProductionFlags(attr); // TODO: Error on unknown attributes return new ProductionRule(reduction, expression, constructor, type, flags); }
/// <summary> /// Parses the parse table from the specified AST. /// </summary> /// <param name="ast">The AST.</param> /// <returns>The resulting <see cref="ParseTable"/>.</returns> private ParseTable Parse(ITerm ast) { #region Contract Contract.Requires<ArgumentNullException>(ast != null); Contract.Ensures(Contract.Result<ParseTable>() != null); #endregion var pt = ast.ToCons("parse-table", 5); int version = pt[0].ToInt32(); Assert(version == 4 || version == 6, "Only version 4 or 6 parse tables are supported."); var initialState = new StateRef(pt[1].ToInt32()); var labels = ParseLabels((IListTerm)pt[2]); var states = ParseStates((IListTerm)pt[3].ToCons("states", 1)[0], labels); var priorities = ParsePriorities((IListTerm)pt[4].ToCons("priorities", 1)[0]); // TODO: Injections? return new ParseTable(initialState, states, labels, priorities); }
/// <summary> /// Reads the production flags from a term. /// </summary> /// <param name="term">The term.</param> /// <returns>The production flags.</returns> private ProductionFlags ReadProductionFlags(ITerm term) { #region Contract Contract.Requires<ArgumentNullException>(term != null); #endregion if (term.IsCons("no-attrs", 0)) return ProductionFlags.None; ProductionFlags flags = ProductionFlags.None; IListTerm list = (IListTerm)term.ToCons("attrs", 1)[0]; foreach (var t in list.SubTerms.OfType<IConsTerm>()) { if (t.SubTerms.Count != 0) continue; switch (t.Name) { case "recover": flags |= ProductionFlags.Recover; break; case "completion": flags |= ProductionFlags.Completion; break; case "ignore-indent": case "ignore-layout": flags |= ProductionFlags.IgnoreLayout; break; case "enforce-newline": flags |= ProductionFlags.NewlineEnforced; break; case "longest-match": flags |= ProductionFlags.LongestMatch; break; } } return flags; }
/// <summary> /// Reads the production type from a term. /// </summary> /// <param name="term">The term.</param> /// <returns>The production type.</returns> private ProductionType ReadProductionType(ITerm term) { #region Contract Contract.Requires<ArgumentNullException>(term != null); Contract.Ensures(Enum.IsDefined(typeof(ProductionType), Contract.Result<ProductionType>())); #endregion if (term.IsCons("no-attrs", 0)) return ProductionType.None; ProductionType type = ProductionType.None; IListTerm list = (IListTerm)term.ToCons("attrs", 1)[0]; foreach (var t in list.SubTerms.OfType<IConsTerm>()) { if (t.SubTerms.Count != 0) continue; // TODO: Error when the type is set more than once. switch (t.Name) { case "reject": type = ProductionType.Reject; break; case "prefer": type = ProductionType.Prefer; break; case "avoid": type = ProductionType.Avoid; break; case "bracket": type = ProductionType.Bracket; break; case "assoc": { var a = t[0]; if (a.IsCons("left", 0) || a.IsCons("assoc", 0)) type = ProductionType.LeftAssociative; else if (a.IsCons("right", 0)) type = ProductionType.RightAssociative; else if (a.IsCons("non-assoc", 0)) type = ProductionType.None; else throw new InvalidOperationException("Unknown associativity: " + a); } break; } } return type; }
/// <summary> /// Reads the constructor name from a term. /// </summary> /// <param name="term">The term.</param> /// <returns>The constructor name.</returns> private string ReadConstructor(ITerm term) { #region Contract Contract.Requires<ArgumentNullException>(term != null); #endregion if (term.IsCons("no-attrs", 0)) return null; IListTerm list = (IListTerm)term.ToCons("attrs", 1)[0]; var consTerms = list.SubTerms.Select(t => t.AsCons("cons", 1)).Where(c => c != null); IConsTerm consTerm = consTerms.SingleOrDefault(); return consTerm?[0]?.ToString(); }