using System; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; namespace PGFSharp { /// /// The class for PGF grammars. /// public class PGF { private PGF() { } IntPtr _ptr; NativeGU.NativeMemoryPool pool; /// /// Reads a grammar with the specified file path. /// /// The path to the file. /// an object representing the grammar in memory. public static PGF ReadPGF(string fn) { var obj = new PGF(); var exn = new NativeGU.NativeExceptionContext(new NativeGU.NativeMemoryPool()); obj.pool = new NativeGU.NativeMemoryPool(); obj._ptr = Native.pgf_read(fn, obj.pool.Ptr, exn.Ptr); if (exn.IsRaised) { throw new PGFError($"Could not read PGF from file {fn}. ({System.IO.Directory.GetCurrentDirectory()})"); } return obj; } public override string ToString() => $"Grammar:{Name}, {String.Join(", ", Languages.Keys)}"; /// /// Name of the abstract grammar. /// public string Name => Native.NativeString.StringFromNativeUtf8(Native.pgf_abstract_name(_ptr)); /// /// Default category of the grammar. /// public Type StartCat => Type.FromPtr(Native.pgf_start_cat(_ptr, pool.Ptr), pool); /// /// All concrete grammars in the language. /// public Dictionary Languages { get { var dict = new Dictionary(); Native.MapIter(Native.pgf_iter_languages, _ptr, (k, v) => dict[k] = Concr.FromPtr(this, dereference(v))); return dict; } } private IntPtr dereference(IntPtr ptr) { return (IntPtr)Marshal.PtrToStructure(ptr, typeof(IntPtr)); } /// /// All categories in the abstract grammar. /// public IEnumerable Categories => GetStringList(Native.pgf_iter_categories); /// /// All functions in the abstract grammar. /// public IEnumerable Functions => GetStringList(Native.pgf_iter_functions); /// /// Returns a list with all functions with a given return category. /// /// The name of the return category. public IEnumerable FunctionByCategory(string catName) { using (var str = new Native.NativeString(catName)) { return GetStringList(new Native.IterFuncCurryName(Native.pgf_iter_functions_by_cat, str.Ptr).IterFunc); } } /// /// Returns the type of the function with the given name. /// /// The name of the function. /// public Type FunctionType(string funName) { using (var str = new Native.NativeString(funName)) { var typePtr = Native.pgf_function_type(_ptr, str.Ptr); if (typePtr == IntPtr.Zero) throw new NullReferenceException(); return Type.FromPtr(typePtr, pool); } } /// /// Normalizes an expression to its normal form by using the 'def' rules in the grammar. /// /// the original expression. /// the normalized expression. public Expr Compute(Expr expr) { var tmp_pool = new NativeGU.NativeMemoryPool(); var exn = new NativeGU.NativeExceptionContext(tmp_pool); var result_pool = new NativeGU.NativeMemoryPool(); var newExpr = Native.pgf_compute(_ptr, expr.Ptr, exn.Ptr, pool.Ptr, result_pool.Ptr); if (exn.IsRaised || newExpr == IntPtr.Zero) { throw new PGFError("Could not reduce expression."); } else { return Expr.FromPtr(newExpr, result_pool); } } /// /// Returns an enumerable over the set of all expression in /// the given category. The expressions are enumerated in decreasing /// probability order. /// /// the start category. /// public IEnumerable GenerateAll(Type cat = null) { cat = cat ?? StartCat; var tmp_pool = new NativeGU.NativeMemoryPool(); var exn = new NativeGU.NativeExceptionContext(tmp_pool); var result_pool = new NativeGU.NativeMemoryPool(); IntPtr ptr = IntPtr.Zero; var iterator = Native.pgf_generate_all(this._ptr, cat.Ptr, exn.Ptr, tmp_pool.Ptr, result_pool.Ptr); return NativeGU.IteratorToIEnumerable(iterator, tmp_pool.Ptr).Select(p => { var exprProb = Marshal.PtrToStructure(ptr); return Expr.FromPtr(exprProb.expr, result_pool); }); } private IEnumerable GetStringList(Native.MapIterFunc f) { var c = new List(); Native.MapIter(f, _ptr, (k, v) => c.Add(k)); return c; } } }