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;
}
}
}