summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/runtime/dotNet/Bracket.cs120
-rw-r--r--src/runtime/dotNet/Concr.cs173
-rw-r--r--src/runtime/dotNet/Exceptions.cs46
-rw-r--r--src/runtime/dotNet/Expr.cs133
-rw-r--r--src/runtime/dotNet/Expr/Abstraction.cs15
-rw-r--r--src/runtime/dotNet/Expr/Application.cs57
-rw-r--r--src/runtime/dotNet/Expr/Function.cs18
-rw-r--r--src/runtime/dotNet/Expr/Literal.cs127
-rw-r--r--src/runtime/dotNet/Expr/MetaVariable.cs34
-rw-r--r--src/runtime/dotNet/Native.cs306
-rw-r--r--src/runtime/dotNet/NativeGU.cs127
-rw-r--r--src/runtime/dotNet/PGF.cs157
-rw-r--r--src/runtime/dotNet/PGFSharp.csproj68
-rw-r--r--src/runtime/dotNet/Properties/AssemblyInfo.cs36
-rw-r--r--src/runtime/dotNet/Type.cs92
15 files changed, 1509 insertions, 0 deletions
diff --git a/src/runtime/dotNet/Bracket.cs b/src/runtime/dotNet/Bracket.cs
new file mode 100644
index 000000000..fa9c77d74
--- /dev/null
+++ b/src/runtime/dotNet/Bracket.cs
@@ -0,0 +1,120 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace PGFSharp
+{
+ // Brackets should only be constructed from the Concrete class.
+ // These classes just store the data, they do not own or use
+ // unmanaged memory (except in the builder class).
+
+ public interface IBracketChild {
+ bool IsString {get;}
+ string AsStringChild {get;}
+ Bracket AsBracketChild {get;}
+ }
+
+
+ public class Bracket : IBracketChild
+ {
+ public class StringChildBracket : IBracketChild {
+
+ string str;
+ internal StringChildBracket(string str) {
+ this.str = str;
+ }
+
+ public bool IsString => true;
+ public string AsStringChild => str;
+ public Bracket AsBracketChild {
+ get {
+ throw new NotImplementedException ();
+ }
+ }
+
+ public override string ToString () => AsStringChild;
+ }
+
+ internal class BracketBuilder {
+ internal Native.PgfLinFuncs LinFuncs { get; private set; }
+
+ private Stack<Bracket> stack = new Stack<Bracket> ();
+ private Bracket final = null;
+ internal BracketBuilder() {
+ LinFuncs = new Native.PgfLinFuncs {
+ symbol_token = SymbolToken,
+ begin_prase = BeginPhrase,
+ end_phrase = EndPhrase,
+ symbol_ne = null,
+ symbol_bind = null,
+ symbol_capit = null
+ };
+ }
+
+ // TODO: the Python wrapper discards begin/end phrase pairs
+ // which don't have any tokens. Is this correct and/or necessary?
+ private void SymbolToken(IntPtr self, IntPtr token) {
+ var str = Native.NativeString.StringFromNativeUtf8 (token);
+ stack.Peek ().AddChild (new StringChildBracket (str));
+ }
+
+ private void BeginPhrase(IntPtr self, IntPtr cat, int fid, int lindex, IntPtr fun) {
+ stack.Push (new Bracket ());
+ }
+
+ private void EndPhrase(IntPtr self, IntPtr cat, int fid, int lindex, IntPtr fun) {
+ var b = stack.Pop ();
+
+ b.CatName = Native.NativeString.StringFromNativeUtf8 (cat);
+ b.FunName = Native.NativeString.StringFromNativeUtf8 (fun);
+ b.FId = fid;
+ b.LIndex = lindex;
+
+ if (stack.Count == 0)
+ final = b;
+ else
+ stack.Peek ().AddChild (b);
+ }
+
+ public Bracket Build() {
+ return final;
+ }
+ }
+
+ private List<IBracketChild> _children = new List<IBracketChild> ();
+ private Bracket() {
+ }
+
+ private void AddChild(IBracketChild c) {
+ _children.Add(c);
+ }
+
+ public bool IsString => false;
+ public Bracket AsBracketChild => this;
+ public string AsStringChild {
+ get {
+ throw new NotImplementedException ();
+ }
+ }
+
+ public IEnumerable<IBracketChild> Children { get { return _children; } }
+
+ public string CatName { get; private set; }
+ public string FunName { get; private set; }
+ public int FId { get; private set; }
+ public int LIndex { get; private set; }
+
+ public override string ToString ()
+ {
+ return "(" + CatName + ":" + FId + " " + String.Join (" ", Children) + ")";
+ }
+
+ public string ToBracketsString => "{" + String.Join(" ",
+ Children.Select(c => (c is Bracket) ? ((Bracket)c).ToBracketsString : c.ToString() )
+ ) + "}";
+ }
+
+
+}
diff --git a/src/runtime/dotNet/Concr.cs b/src/runtime/dotNet/Concr.cs
new file mode 100644
index 000000000..cbb4c6d51
--- /dev/null
+++ b/src/runtime/dotNet/Concr.cs
@@ -0,0 +1,173 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Runtime.InteropServices;
+
+namespace PGFSharp
+{
+ /// <summary>
+ /// Concrete grammar. All concrete grammars are available from the (Abstract) <see cref="Grammar"/> class.
+ /// </summary>
+ public class Concr
+ {
+ internal IntPtr Ptr { get; private set; }
+
+ /// <summary>
+ /// Abstract grammar for this language.
+ /// </summary>
+ public PGF PGF { get; private set; }
+
+ private Concr() { }
+
+ internal static Concr FromPtr(PGF g, IntPtr ptr)
+ {
+ var concr = new Concr();
+ concr.PGF = g;
+ concr.Ptr = ptr;
+ return concr;
+ }
+
+ /// <summary>
+ /// Name of the grammar.
+ /// </summary>
+ public string Name => Native.NativeString.StringFromNativeUtf8(Native.pgf_concrete_name(Ptr));
+ public override string ToString() => $"Concrete:{Name} of {PGF.Name}";
+
+ /// <summary>
+ /// Parse given input string in the concrete grammar.
+ /// </summary>
+ /// <param name="str">Input string to be parsed.</param>
+ /// <param name="cat">Category (Type) to parse.</param>
+ /// <param name="heuristics">Heuristic (see the GF C runtime docs).</param>
+ /// <param name="Callback1">Callback function.</param>
+ /// <param name="Callback2">Callback function.</param>
+ /// <returns>Enumerates pairs of (abstract grammar) expressions and corresponding probability.</returns>
+ public IEnumerable<Tuple<Expr, float>> Parse(string str, Type cat = null, double? heuristics = null,
+ Action Callback1 = null, Action Callback2 = null)
+ {
+ var parse_pool = new NativeGU.NativeMemoryPool();
+ var exn = new NativeGU.NativeExceptionContext(parse_pool);
+ cat = cat ?? PGF.StartCat;
+
+ using (var nativeStr = new Native.NativeString(str))
+ {
+ var result_pool = new NativeGU.NativeMemoryPool();
+ var callbackMap = Native.pgf_new_callbacks_map(this.Ptr, parse_pool.Ptr);
+
+ var iterator = Native.pgf_parse_with_heuristics(this.Ptr, cat.Ptr,
+ nativeStr.Ptr, heuristics ?? -1, callbackMap,
+ exn.Ptr, parse_pool.Ptr, result_pool.Ptr);
+
+ if (iterator == IntPtr.Zero || exn.IsRaised)
+ {
+ throw new ParseError();
+ }
+ else
+ {
+ foreach (var ptr in NativeGU.IteratorToIEnumerable(iterator, parse_pool.Ptr))
+ {
+ var exprProb = (Native.PgfExprProb)Marshal.PtrToStructure(ptr, typeof(Native.PgfExprProb));
+ yield return Tuple.Create(Expr.FromPtr(exprProb.expr, result_pool),
+ exprProb.prob);
+ }
+ }
+ }
+ }
+
+ /// <summary>
+ /// Linearize expression, i.e. produce a string in the concrete grammar from an expression in the abstract grammar.
+ /// </summary>
+ /// <param name="e"></param>
+ /// <returns></returns>
+ public string Linearize(Expr e)
+ {
+ var tmp_pool = new NativeGU.NativeMemoryPool();
+ var exn = new NativeGU.NativeExceptionContext(tmp_pool);
+
+ var buf = NativeGU.gu_new_string_buf(tmp_pool.Ptr);
+ var out_ = NativeGU.gu_string_buf_out(buf);
+
+ Native.pgf_linearize(Ptr, e.Ptr, out_, exn.Ptr);
+ if (exn.IsRaised)
+ {
+ throw new PGFError();
+ }
+ else
+ {
+ var cstr = NativeGU.gu_string_buf_freeze(buf, tmp_pool.Ptr);
+ return Native.NativeString.StringFromNativeUtf8(cstr);
+ }
+ }
+
+ /// <summary>
+ /// Get all possible linearization for an expression (see <see cref="Linearize(Expression)"/>).
+ /// </summary>
+ /// <param name="e"></param>
+ /// <returns></returns>
+ public IEnumerable<string> LinearizeAll(Expr e)
+ {
+ var tmp_pool = new NativeGU.NativeMemoryPool();
+ var exn = new NativeGU.NativeExceptionContext(tmp_pool);
+
+ var cts = Native.pgf_lzr_concretize(Ptr, e.Ptr, exn.Ptr, tmp_pool.Ptr);
+ if (exn.IsRaised || cts == IntPtr.Zero) throw new PGFError("Could not linearize the abstract tree.");
+
+ return NativeGU.IteratorToIEnumerable(cts, tmp_pool.Ptr).Select(LinearizeCnc);
+ }
+
+ private string LinearizeCnc(IntPtr cnc)
+ {
+ var tmp_pool = new NativeGU.NativeMemoryPool();
+ var exn = new NativeGU.NativeExceptionContext(tmp_pool);
+
+ var sbuf = NativeGU.gu_new_string_buf(tmp_pool.Ptr);
+ var out_ = NativeGU.gu_string_buf_out(sbuf);
+
+ var wrapped = Native.pgf_lzr_wrap_linref(cnc, tmp_pool.Ptr);
+ Native.pgf_lzr_linearize_simple(Ptr, wrapped, 0, out_, exn.Ptr, tmp_pool.Ptr);
+
+ if (exn.IsRaised) throw new PGFError("Could not linearize abstract tree.");
+
+ var cstr = NativeGU.gu_string_buf_freeze(sbuf, tmp_pool.Ptr);
+ return Native.NativeString.StringFromNativeUtf8(cstr);
+ }
+
+ /// <summary>
+ /// Get the bracketed (structured) linearization of an expression.
+ /// </summary>
+ /// <param name="e"></param>
+ /// <returns></returns>
+ public Bracket BracketedLinearize(Expr e)
+ {
+ var tmp_pool = new NativeGU.NativeMemoryPool();
+ var exn = new NativeGU.NativeExceptionContext(tmp_pool);
+
+ var cts = Native.pgf_lzr_concretize(Ptr, e.Ptr, exn.Ptr, tmp_pool.Ptr);
+
+ var ctree = IntPtr.Zero;
+ NativeGU.gu_enum_next(cts, ref ctree, tmp_pool.Ptr);
+
+ if (ctree == IntPtr.Zero)
+ {
+ return null;
+ }
+
+ ctree = Native.pgf_lzr_wrap_linref(ctree, tmp_pool.Ptr);
+
+ var builder = new Bracket.BracketBuilder();
+
+ var mem = Marshal.AllocHGlobal(Marshal.SizeOf<Native.PgfLinFuncs>());
+ Marshal.StructureToPtr<Native.PgfLinFuncs>(builder.LinFuncs, mem, false);
+
+ Native.pgf_lzr_linearize(Ptr, ctree, 0, ref mem, tmp_pool.Ptr);
+
+ var b = builder.Build();
+
+ Marshal.FreeHGlobal(mem);
+
+ return b;
+ }
+ }
+}
diff --git a/src/runtime/dotNet/Exceptions.cs b/src/runtime/dotNet/Exceptions.cs
new file mode 100644
index 000000000..91193db74
--- /dev/null
+++ b/src/runtime/dotNet/Exceptions.cs
@@ -0,0 +1,46 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace PGFSharp
+{
+
+ [Serializable]
+ public class PGFError : Exception
+ {
+ public PGFError() { }
+ public PGFError(string message) : base(message) { }
+ public PGFError(string message, Exception inner) : base(message, inner) { }
+ protected PGFError(
+ System.Runtime.Serialization.SerializationInfo info,
+ System.Runtime.Serialization.StreamingContext context) : base(info, context)
+ { }
+ }
+
+
+ [Serializable]
+ public class ParseError : Exception
+ {
+ public ParseError() { }
+ public ParseError(string message) : base(message) { }
+ public ParseError(string message, Exception inner) : base(message, inner) { }
+ protected ParseError(
+ System.Runtime.Serialization.SerializationInfo info,
+ System.Runtime.Serialization.StreamingContext context) : base(info, context)
+ { }
+ }
+
+ [Serializable]
+ public class TypeError : Exception
+ {
+ public TypeError() { }
+ public TypeError(string message) : base(message) { }
+ public TypeError(string message, Exception inner) : base(message, inner) { }
+ protected TypeError(
+ System.Runtime.Serialization.SerializationInfo info,
+ System.Runtime.Serialization.StreamingContext context) : base(info, context)
+ { }
+ }
+}
diff --git a/src/runtime/dotNet/Expr.cs b/src/runtime/dotNet/Expr.cs
new file mode 100644
index 000000000..a65b281bf
--- /dev/null
+++ b/src/runtime/dotNet/Expr.cs
@@ -0,0 +1,133 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace PGFSharp
+{
+ internal class UnsupportedExpr : Expr
+ {
+ internal UnsupportedExpr(IntPtr expr, NativeGU.NativeMemoryPool pool) : base(expr, pool) { }
+ public override R Accept<R>(IVisitor<R> visitor)
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+ public abstract class Expr
+ {
+ internal IntPtr DataPtr => NativeGU.gu_variant_open(_ptr).Data; // PgfExprLit*
+ internal PgfExprTag Tag => (PgfExprTag)NativeGU.gu_variant_open(_ptr).Tag;
+
+ internal IntPtr MkStringVariant(byte tag, string s, ref IntPtr out_)
+ {
+ var size = Encoding.UTF8.GetByteCount(s);
+ IntPtr slitPtr = NativeGU.gu_alloc_variant(tag,
+ (UIntPtr)(size + 1), UIntPtr.Zero, ref out_, _pool.Ptr);
+ Native.NativeString.CopyToPreallocated(s, slitPtr);
+ return slitPtr;
+ }
+
+ /// <summary>
+ /// Read expression from string.
+ /// </summary>
+ /// <param name="exprStr"></param>
+ /// <returns></returns>
+ public Expr ReadExpr(string exprStr)
+ {
+ var tmp_pool = new NativeGU.NativeMemoryPool();
+ var exn = new NativeGU.NativeExceptionContext(tmp_pool);
+ var result_pool = new NativeGU.NativeMemoryPool();
+ using (var strNative = new Native.NativeString(exprStr))
+ {
+ var in_ = NativeGU.gu_data_in(strNative.Ptr, strNative.Size, tmp_pool.Ptr);
+ var expr = Native.pgf_read_expr(in_, result_pool.Ptr, exn.Ptr);
+ if (exn.IsRaised || expr == IntPtr.Zero)
+ {
+ throw new PGFError();
+ }
+ else
+ {
+ return Expr.FromPtr(expr, result_pool);
+ }
+ }
+ }
+
+ internal enum PgfExprTag
+ {
+ PGF_EXPR_ABS,
+ PGF_EXPR_APP,
+ PGF_EXPR_LIT,
+ PGF_EXPR_META,
+ PGF_EXPR_FUN,
+ PGF_EXPR_VAR,
+ PGF_EXPR_TYPED,
+ PGF_EXPR_IMPL_ARG,
+ PGF_EXPR_NUM_TAGS // not used
+ };
+
+ public interface IVisitor<R>
+ {
+ R VisitLiteralInt(int value);
+ R VisitLiteralFloat(double value);
+ R VisitLiteralString(string value);
+ R VisitApplication(string fname, Expr[] args);
+
+ //R VisitMetaVariable (int id); Dont' care about this for now...
+
+ // Remove this, Function objects use VisitApplication with empty args instead.
+ //R VisitFunction (string fname); // Will this be used?
+ }
+
+ public class Visitor<R> : IVisitor<R>
+ {
+ public Func<int, R> fVisitLiteralInt { get; set; } = null;
+ public R VisitLiteralInt(int x1) => fVisitLiteralInt(x1);
+ public Func<double, R> fVisitLiteralFlt { get; set; } = null;
+ public R VisitLiteralFloat(double x1) => fVisitLiteralFlt(x1);
+ public Func<string, R> fVisitLiteralStr { get; set; } = null;
+ public R VisitLiteralString(string x1) => fVisitLiteralStr(x1);
+ public Func<string, Expr[], R> fVisitApplication { get; set; } = null;
+ public R VisitApplication(string x1, Expr[] x2) => fVisitApplication(x1, x2);
+ }
+
+ public abstract R Accept<R>(IVisitor<R> visitor);
+
+ internal IntPtr _ptr = IntPtr.Zero;
+ internal NativeGU.NativeMemoryPool _pool;
+ internal IntPtr Ptr => _ptr;
+
+ internal Expr() { }
+ internal Expr(IntPtr ptr, NativeGU.NativeMemoryPool pool)
+ {
+ _ptr = ptr; _pool = pool;
+ }
+
+ // Factories
+ private static Dictionary<PgfExprTag, Func<IntPtr, NativeGU.NativeMemoryPool, Expr>> factories =
+ new Dictionary<PgfExprTag, Func<IntPtr, NativeGU.NativeMemoryPool, Expr>>{
+
+ { PgfExprTag.PGF_EXPR_LIT, (e, p) => LiteralExpr.FromPtr (e, p) },
+ { PgfExprTag.PGF_EXPR_APP, (e, p) => new ApplicationExpr (e, p) },
+ { PgfExprTag.PGF_EXPR_FUN, (e, p) => new FunctionExpr (e, p) },
+ { PgfExprTag.PGF_EXPR_META, (e, p) => new MetaVariableExpr (e, p) }
+ };
+
+ internal static Expr FromPtr(IntPtr expr, NativeGU.NativeMemoryPool pool)
+ {
+ var Tag = (PgfExprTag)NativeGU.gu_variant_open(expr).Tag;
+ if (factories.ContainsKey(Tag))
+ {
+ return factories[Tag](expr, pool);
+ }
+ else
+ return new UnsupportedExpr(expr, pool);
+ }
+
+ public override string ToString() =>
+ Native.ReadString((output,exn) => Native.pgf_print_expr(_ptr, IntPtr.Zero, 0, output, exn.Ptr));
+
+ }
+}
diff --git a/src/runtime/dotNet/Expr/Abstraction.cs b/src/runtime/dotNet/Expr/Abstraction.cs
new file mode 100644
index 000000000..023208727
--- /dev/null
+++ b/src/runtime/dotNet/Expr/Abstraction.cs
@@ -0,0 +1,15 @@
+using System;
+using System.Runtime.InteropServices;
+
+namespace PGFSharp
+{
+ /*public class Abs : Expression
+ {
+ public Abs ()
+ {
+ }
+ }
+*/
+
+}
+
diff --git a/src/runtime/dotNet/Expr/Application.cs b/src/runtime/dotNet/Expr/Application.cs
new file mode 100644
index 000000000..bcfb309a5
--- /dev/null
+++ b/src/runtime/dotNet/Expr/Application.cs
@@ -0,0 +1,57 @@
+using System;
+using System.Runtime.InteropServices;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace PGFSharp
+{
+ public class ApplicationExpr : Expr
+ {
+ public override R Accept<R> (IVisitor<R> visitor)
+ {
+ var args = new List<Expr> ();
+ var expr = this;
+ while (expr.Function is ApplicationExpr) {
+ args.Add (expr.Argument);
+ expr = expr.Function as ApplicationExpr;
+ }
+ args.Add (expr.Argument);
+ if (!(expr.Function is FunctionExpr))
+ throw new ArgumentException ();
+
+ args.Reverse ();
+ return visitor.VisitApplication ((expr.Function as FunctionExpr).Name, args.ToArray());
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ private struct PgfExprApp {
+ public IntPtr Function;
+ public IntPtr Argument;
+ }
+
+ private PgfExprApp Data => Marshal.PtrToStructure<PgfExprApp>(DataPtr);
+
+ public Expr Function => Expr.FromPtr(Data.Function, _pool);
+ public Expr Argument => Expr.FromPtr(Data.Argument, _pool);
+
+ internal ApplicationExpr(IntPtr ptr, NativeGU.NativeMemoryPool pool) : base(ptr, pool) { }
+ public ApplicationExpr(string fname, IEnumerable<Expr> args)
+ {
+ _pool = new NativeGU.NativeMemoryPool();
+ MkStringVariant((byte)PgfExprTag.PGF_EXPR_FUN, fname, ref _ptr);
+ foreach (var arg in args) {
+ var fun = _ptr;
+ var exprApp = NativeGU.gu_alloc_variant((byte)PgfExprTag.PGF_EXPR_APP,
+ (UIntPtr)Marshal.SizeOf<PgfExprApp>(), UIntPtr.Zero, ref _ptr, _pool.Ptr);
+
+ Native.EditStruct<PgfExprApp> (exprApp, (ref PgfExprApp app) => {
+ app.Function = fun;
+ app.Argument = arg.Ptr;
+ });
+ }
+
+
+ }
+ }
+}
+
diff --git a/src/runtime/dotNet/Expr/Function.cs b/src/runtime/dotNet/Expr/Function.cs
new file mode 100644
index 000000000..900c605a0
--- /dev/null
+++ b/src/runtime/dotNet/Expr/Function.cs
@@ -0,0 +1,18 @@
+using System;
+using System.Linq;
+using System.Collections.Generic;
+
+namespace PGFSharp
+{
+ public class FunctionExpr : Expr
+ {
+ public override R Accept<R> (IVisitor<R> visitor)
+ {
+ return visitor.VisitApplication (Name, new Expr[] {});
+ }
+
+ internal FunctionExpr (IntPtr expr, NativeGU.NativeMemoryPool pool) : base(expr,pool) {}
+ public string Name => Native.NativeString.StringFromNativeUtf8(DataPtr);
+ }
+}
+
diff --git a/src/runtime/dotNet/Expr/Literal.cs b/src/runtime/dotNet/Expr/Literal.cs
new file mode 100644
index 000000000..daf515c63
--- /dev/null
+++ b/src/runtime/dotNet/Expr/Literal.cs
@@ -0,0 +1,127 @@
+using System;
+using System.Runtime.InteropServices;
+using System.Text;
+
+namespace PGFSharp
+{
+ public class LiteralStringExpr : LiteralExpr
+ {
+ internal LiteralStringExpr(IntPtr expr, NativeGU.NativeMemoryPool pool) : base(expr, pool) { }
+ public LiteralStringExpr(string s) : base()
+ {
+ _pool = new NativeGU.NativeMemoryPool();
+
+ var exprTag = (byte)(int)PgfExprTag.PGF_EXPR_LIT;
+ IntPtr litPtr = NativeGU.gu_alloc_variant(exprTag,
+ (UIntPtr)Marshal.SizeOf<NativePgfExprLit>(), UIntPtr.Zero, ref _ptr, _pool.Ptr);
+
+ Native.EditStruct<NativePgfExprLit>(litPtr, (ref NativePgfExprLit lit) => {
+ MkStringVariant((byte)PgfLiteralTag.PGF_LITERAL_STR, s, ref lit.lit);
+ });
+ }
+
+ public override R Accept<R>(IVisitor<R> visitor)
+ {
+ return visitor.VisitLiteralString(Value);
+ }
+
+ public string Value => Native.NativeString.StringFromNativeUtf8(LitDataPtr);
+ }
+
+ public class LiteralIntExpr : LiteralExpr
+ {
+ internal LiteralIntExpr(IntPtr expr, NativeGU.NativeMemoryPool pool) : base(expr, pool) { }
+ public LiteralIntExpr(int val) : base()
+ {
+ Initialize<NativePgfLiteralInt>(PgfLiteralTag.PGF_LITERAL_INT,
+ (ref NativePgfLiteralInt ilit) => ilit.val = val);
+ }
+
+ public override R Accept<R>(IVisitor<R> visitor)
+ {
+ return visitor.VisitLiteralInt(Value);
+ }
+
+ public int Value => Marshal.PtrToStructure<NativePgfLiteralInt>(LitDataPtr).val;
+
+ [StructLayout(LayoutKind.Sequential)]
+ private struct NativePgfLiteralInt { public int val; }
+ }
+
+ public class LiteralFloatExpr : LiteralExpr
+ {
+ internal LiteralFloatExpr(IntPtr expr, NativeGU.NativeMemoryPool pool) : base(expr, pool) { }
+ public LiteralFloatExpr(double val) : base()
+ {
+ Initialize<NativePgfLiteralFlt>(PgfLiteralTag.PGF_LITERAL_FLT,
+ (ref NativePgfLiteralFlt flit) => flit.val = val);
+ }
+
+ public override R Accept<R>(IVisitor<R> visitor)
+ {
+ return visitor.VisitLiteralFloat(Value);
+ }
+
+ public double Value => Marshal.PtrToStructure<NativePgfLiteralFlt>(LitDataPtr).val;
+
+ [StructLayout(LayoutKind.Sequential)]
+ private struct NativePgfLiteralFlt { public double val; }
+ }
+
+ public abstract class LiteralExpr : Expr
+ {
+ internal LiteralExpr(IntPtr expr, NativeGU.NativeMemoryPool pool) : base(expr, pool) { }
+ internal LiteralExpr() { }
+
+ internal new static Expr FromPtr(IntPtr expr, NativeGU.NativeMemoryPool pool)
+ {
+ var dataPtr = NativeGU.gu_variant_open(expr).Data; // PgfExprLit*
+ var data = Marshal.PtrToStructure<NativePgfExprLit>(dataPtr);
+ var literalTag = (PgfLiteralTag)NativeGU.gu_variant_open(data.lit).Tag;
+
+ switch(literalTag)
+ {
+ case PgfLiteralTag.PGF_LITERAL_STR:
+ return new LiteralStringExpr(expr, pool);
+ case PgfLiteralTag.PGF_LITERAL_INT:
+ return new LiteralIntExpr(expr, pool);
+ case PgfLiteralTag.PGF_LITERAL_FLT:
+ return new LiteralFloatExpr(expr, pool);
+ default:
+ throw new ArgumentException();
+ }
+ }
+
+ internal void Initialize<TNative>(PgfLiteralTag litTag, Native.StructAction<TNative> setValue, UIntPtr? size = null) {
+ _pool = new NativeGU.NativeMemoryPool();
+
+ var exprTag = (byte)(int)PgfExprTag.PGF_EXPR_LIT;
+ IntPtr litPtr = NativeGU.gu_alloc_variant ( exprTag,
+ (UIntPtr)Marshal.SizeOf<NativePgfExprLit>(), UIntPtr.Zero, ref _ptr, _pool.Ptr);
+
+ Native.EditStruct<NativePgfExprLit> (litPtr, (ref NativePgfExprLit lit) => {
+ IntPtr ilitPtr = NativeGU.gu_alloc_variant ((byte)litTag,
+ (UIntPtr)Marshal.SizeOf<TNative> (), UIntPtr.Zero, ref lit.lit, _pool.Ptr);
+
+ Native.EditStruct<TNative>(ilitPtr, setValue);
+ });
+ }
+
+ // Deref DatPtr to det PgfExprLit.
+ private NativePgfExprLit Data => Marshal.PtrToStructure<NativePgfExprLit>(DataPtr);
+
+ private PgfLiteralTag LiteralTag => (PgfLiteralTag) NativeGU.gu_variant_open(Data.lit).Tag;
+ internal IntPtr LitDataPtr => NativeGU.gu_variant_open(Data.lit).Data;
+
+ internal enum PgfLiteralTag {
+ PGF_LITERAL_STR,
+ PGF_LITERAL_INT,
+ PGF_LITERAL_FLT,
+ PGF_LITERAL_NUM_TAGS
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct NativePgfExprLit { public IntPtr lit; }
+ }
+}
+
diff --git a/src/runtime/dotNet/Expr/MetaVariable.cs b/src/runtime/dotNet/Expr/MetaVariable.cs
new file mode 100644
index 000000000..30ead9004
--- /dev/null
+++ b/src/runtime/dotNet/Expr/MetaVariable.cs
@@ -0,0 +1,34 @@
+using System;
+using System.Runtime.InteropServices;
+
+namespace PGFSharp
+{
+ public class MetaVariableExpr : Expr {
+
+ internal MetaVariableExpr() {
+ _pool = new NativeGU.NativeMemoryPool();
+ IntPtr exprMetaPtr = NativeGU.gu_alloc_variant ((byte)PgfExprTag.PGF_EXPR_META,
+ (UIntPtr)Marshal.SizeOf <NativePgfExprMeta>(), UIntPtr.Zero, ref _ptr, _pool.Ptr);
+
+ Native.EditStruct<NativePgfExprMeta> (exprMetaPtr, (ref NativePgfExprMeta m) => m.Id = 0);
+ }
+
+ internal MetaVariableExpr(IntPtr ptr, NativeGU.NativeMemoryPool pool) : base(ptr, pool) { }
+
+
+ public int Id => Data.Id;
+ private NativePgfExprMeta Data => Marshal.PtrToStructure<NativePgfExprMeta>(DataPtr);
+
+ public override R Accept<R> (IVisitor<R> visitor)
+ {
+ // return visitor.VisitMetaVariable (Id);
+
+ // Not supported yet.
+ throw new NotImplementedException();
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ private struct NativePgfExprMeta { public int Id; }
+ }
+}
+
diff --git a/src/runtime/dotNet/Native.cs b/src/runtime/dotNet/Native.cs
new file mode 100644
index 000000000..346f85905
--- /dev/null
+++ b/src/runtime/dotNet/Native.cs
@@ -0,0 +1,306 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading.Tasks;
+
+/// <summary>
+/// Portable grammar format PInvoke functions.
+/// </summary>
+namespace PGFSharp
+{
+ internal static class Native
+ {
+
+ internal class NativeString : IDisposable
+ {
+ public IntPtr Ptr { get; private set; }
+ public int Size { get; private set; }
+
+ public NativeString(string s)
+ {
+ Ptr = NativeUtf8FromString(s);
+ Size = Encoding.UTF8.GetByteCount(s);
+ }
+
+ public void Dispose()
+ {
+ Marshal.FreeHGlobal(Ptr);
+ Ptr = IntPtr.Zero;
+ }
+
+ public static IntPtr NativeUtf8FromString(string managedString)
+ {
+ int len = Encoding.UTF8.GetByteCount(managedString);
+ IntPtr nativeUtf8 = Marshal.AllocHGlobal(len + 1);
+ CopyToPreallocated(managedString, nativeUtf8, len);
+ return nativeUtf8;
+ }
+
+ public static void CopyToPreallocated(string managedString, IntPtr ptr, int? len = null)
+ {
+ if (len == null) len = Encoding.UTF8.GetByteCount(managedString);
+ byte[] buffer = new byte[len.Value + 1];
+ Encoding.UTF8.GetBytes(managedString, 0, managedString.Length, buffer, 0);
+ Marshal.Copy(buffer, 0, ptr, buffer.Length);
+ }
+
+ public static string StringFromNativeUtf8(IntPtr nativeUtf8)
+ {
+ int len = 0;
+ while (Marshal.ReadByte(nativeUtf8, len) != 0) ++len;
+ byte[] buffer = new byte[len];
+ Marshal.Copy(nativeUtf8, buffer, 0, buffer.Length);
+ return Encoding.UTF8.GetString(buffer);
+ }
+ }
+
+ public delegate void StructAction<T>(ref T st);
+ public static void EditStruct<T>(IntPtr ptr, StructAction<T> f)
+ {
+ var str = Marshal.PtrToStructure<T>(ptr);
+ f(ref str);
+ Marshal.StructureToPtr<T>(str, ptr, false);
+ }
+
+ const string LIBNAME = "pgf.dll";
+ const CallingConvention CC = CallingConvention.Cdecl;
+
+
+ #region Basic
+ [DllImport(LIBNAME, CallingConvention = CC)]
+ public static extern IntPtr pgf_read([MarshalAs(UnmanagedType.LPStr)] string fpath, IntPtr pool, IntPtr err);
+
+ [DllImport(LIBNAME, CallingConvention = CC)]
+ public static extern IntPtr pgf_read_in(IntPtr in_, IntPtr pool, IntPtr tmp_pool, IntPtr err);
+
+ [DllImport(LIBNAME, CallingConvention = CC)]
+ public static extern void pgf_concrete_load(IntPtr concr, IntPtr in_, IntPtr err);
+
+ [DllImport(LIBNAME, CallingConvention = CC)]
+ public static extern IntPtr pgf_abstract_name(IntPtr pgf);
+
+ [DllImport(LIBNAME, CallingConvention = CC)]
+ public static extern IntPtr pgf_concrete_name(IntPtr concr);
+
+ [DllImport(LIBNAME, CallingConvention = CC)]
+ public static extern IntPtr pgf_start_cat(IntPtr pgf, IntPtr pool);
+
+ #endregion
+
+ #region Linearization
+
+ [DllImport(LIBNAME, CallingConvention = CC)]
+ public static extern void pgf_linearize(IntPtr concr, IntPtr expr, IntPtr out_, IntPtr err);
+
+ [DllImport(LIBNAME, CallingConvention = CC)]
+ public static extern IntPtr pgf_lzr_concretize(IntPtr concr, IntPtr expr, IntPtr err, IntPtr tmp_pool);
+
+ [DllImport(LIBNAME, CallingConvention = CC)]
+ public static extern IntPtr pgf_lzr_wrap_linref(IntPtr ctree, IntPtr tmp_pool);
+
+ [DllImport(LIBNAME, CallingConvention = CC)]
+ public static extern void pgf_lzr_linearize(IntPtr concr, IntPtr ctree, int lin_idx, ref IntPtr funcs, IntPtr tmp_pool);
+
+ [DllImport(LIBNAME, CallingConvention = CC)]
+ public static extern void pgf_lzr_linearize_simple(IntPtr concr, IntPtr ctree, int lin_idx, IntPtr out_, IntPtr exn, IntPtr tmp_pool);
+ #endregion
+
+
+ #region Iteration
+ [DllImport(LIBNAME, CallingConvention = CC)]
+ public static extern void pgf_iter_languages(IntPtr pgf, ref GuMapItor itor, IntPtr err);
+
+ [DllImport(LIBNAME, CallingConvention = CC)]
+ public static extern void pgf_iter_categories(IntPtr pgf, ref GuMapItor itor, IntPtr err);
+
+ [DllImport(LIBNAME, CallingConvention = CC)]
+ public static extern void pgf_iter_functions(IntPtr pgf, ref GuMapItor itor, IntPtr err);
+
+ [DllImport(LIBNAME, CallingConvention = CC)]
+ public static extern void pgf_iter_functions_by_cat(IntPtr pgf, IntPtr catNameStr, ref GuMapItor itor, IntPtr err);
+
+ #endregion
+
+ #region Type
+ [DllImport(LIBNAME, CallingConvention = CC)]
+ public static extern IntPtr pgf_function_type(IntPtr pgf, IntPtr funNameStr);
+
+ [DllImport(LIBNAME, CallingConvention = CC)]
+ public static extern IntPtr pgf_read_type(IntPtr in_, IntPtr pool, IntPtr err);
+
+ [DllImport(LIBNAME, CallingConvention = CC)]
+ public static extern void pgf_print_type(IntPtr expr, IntPtr ctxt, int prec, IntPtr output, IntPtr err);
+ #endregion
+
+ #region Expression
+ [DllImport(LIBNAME, CallingConvention = CC)]
+ public static extern void pgf_print_expr(IntPtr expr, IntPtr ctxt, int prec, IntPtr output, IntPtr err);
+
+ [DllImport(LIBNAME, CallingConvention = CC)]
+ public static extern IntPtr pgf_read_expr(IntPtr in_, IntPtr pool, IntPtr err);
+
+ [DllImport(LIBNAME, CallingConvention = CC)]
+ public static extern IntPtr pgf_compute(IntPtr pgf, IntPtr expr, IntPtr err, IntPtr tmp_pool, IntPtr res_pool);
+
+ [DllImport(LIBNAME, CallingConvention = CC)]
+ public static extern IntPtr pgf_generate_all(IntPtr pgf, IntPtr type, IntPtr err, IntPtr iter_pool, IntPtr out_pool);
+ #endregion
+
+ #region Concrete
+ [DllImport(LIBNAME, CallingConvention = CC)]
+ public static extern IntPtr pgf_parse_with_heuristics(IntPtr concr, IntPtr cat, IntPtr sentence,
+ double heuristics, IntPtr callbacks, IntPtr exn,
+ IntPtr parsePl, IntPtr exprPl);
+ #endregion
+
+ #region Callbacks
+ [DllImport(LIBNAME, CallingConvention = CC)]
+ public static extern IntPtr pgf_new_callbacks_map(IntPtr concr, IntPtr pool);
+ #endregion
+
+ //public delegate void GuMapItorFn(IntPtr self, [MarshalAs(UnmanagedType.LPStr)] string key, IntPtr value, IntPtr err);
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ public delegate void GuMapItorFn(IntPtr self, IntPtr key, IntPtr value, IntPtr err);
+
+
+ /*
+ public delegate void GuFinalizerFn(IntPtr self);
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct GuFinalizer
+ {
+ [MarshalAs(UnmanagedType.FunctionPtr)]
+ public GuFinalizerFn fn;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct PgfConcr
+ {
+ public IntPtr name, abstr, cflags, printnames,
+ ccats, fun_indices, coerce_idx, cncfuns,
+ sequences, cnccats;
+ public int total_cats;
+ public IntPtr pool;
+ GuFinalizer fin;
+ }*/
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct GuMapItor
+ {
+ [MarshalAs(UnmanagedType.FunctionPtr)]
+ public GuMapItorFn fn;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct PgfExprProb
+ {
+ public float prob;
+ public IntPtr expr; // PgfExpr type (not pointer, but typedef PgfExpr -> GuVariant -> uintptr_t)
+ }
+
+
+ #region Linearization callbacks
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ public delegate void LinFuncSymbolToken(IntPtr self, IntPtr token);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ public delegate void LinFuncBeginPhrase(IntPtr self, IntPtr cat, int fid, int lindex, IntPtr fun);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ public delegate void LinFuncEndPhrase(IntPtr self, IntPtr cat, int fid, int lindex, IntPtr fun);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ public delegate void LinFuncSymbolNonexistant(IntPtr self);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ public delegate void LinFuncSymbolBinding(IntPtr self);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ public delegate void LinFuncSymbolCapitalization(IntPtr self);
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct PgfLinFuncs
+ {
+ [MarshalAs(UnmanagedType.FunctionPtr)]
+ public LinFuncSymbolToken symbol_token;
+
+ [MarshalAs(UnmanagedType.FunctionPtr)]
+ public LinFuncBeginPhrase begin_prase;
+
+ [MarshalAs(UnmanagedType.FunctionPtr)]
+ public LinFuncEndPhrase end_phrase;
+
+ [MarshalAs(UnmanagedType.FunctionPtr)]
+ public LinFuncSymbolNonexistant symbol_ne;
+
+ [MarshalAs(UnmanagedType.FunctionPtr)]
+ public LinFuncSymbolBinding symbol_bind;
+
+ [MarshalAs(UnmanagedType.FunctionPtr)]
+ public LinFuncSymbolCapitalization symbol_capit;
+ }
+
+ #endregion
+
+
+ /*
+ [StructLayout(LayoutKind.Sequential)]
+ public struct PGFClosure
+ {
+ public GuMapItor fn;
+ public IntPtr grammar;
+ public IntPtr obj;
+ }*/
+
+ public static string ReadString(Action<IntPtr, NativeGU.NativeExceptionContext> f)
+ {
+ var pool = new NativeGU.NativeMemoryPool();
+ var exn = new NativeGU.NativeExceptionContext(pool);
+ var sbuf = NativeGU.gu_new_string_buf(pool.Ptr);
+ var output = NativeGU.gu_string_buf_out(sbuf);
+ f(output, exn);
+ if (exn.IsRaised) throw new Exception();
+ var strPtr = NativeGU.gu_string_buf_freeze(sbuf, pool.Ptr);
+ var str = Native.NativeString.StringFromNativeUtf8(strPtr);
+ return str;
+ }
+
+ public delegate void MapIterFunc(IntPtr pgf, ref GuMapItor fn, IntPtr err);
+ public delegate void IterNameFunc(IntPtr pgf, IntPtr name, ref GuMapItor fn, IntPtr err);
+
+ public class IterFuncCurryName
+ {
+ private IntPtr name;
+ private IterNameFunc func;
+ public IterFuncCurryName(IterNameFunc f, IntPtr name)
+ {
+ this.func = f;
+ this.name = name;
+ }
+
+ public void IterFunc(IntPtr pgf, ref GuMapItor fn, IntPtr err)
+ {
+ func(pgf, name, ref fn, err);
+ }
+ }
+
+ public static void MapIter(MapIterFunc iter, IntPtr _pgf, Action<string, IntPtr> action)
+ {
+ var pool = new NativeGU.NativeMemoryPool();
+ var exn = new NativeGU.NativeExceptionContext(pool);
+ var f = new GuMapItor()
+ {
+ fn = (self, key, value, _err) =>
+ {
+ action(Native.NativeString.StringFromNativeUtf8(key), value);
+ if (exn.IsRaised) throw new Exception();
+ }
+ };
+
+ iter(_pgf, ref f, exn.Ptr);
+ }
+ }
+}
diff --git a/src/runtime/dotNet/NativeGU.cs b/src/runtime/dotNet/NativeGU.cs
new file mode 100644
index 000000000..2e7f11c0d
--- /dev/null
+++ b/src/runtime/dotNet/NativeGU.cs
@@ -0,0 +1,127 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace PGFSharp
+{
+ internal static class NativeGU
+ {
+
+ const string LIBNAME = "gu.dll";
+ const CallingConvention CC = CallingConvention.Cdecl;
+
+ [DllImport(LIBNAME, CallingConvention = CC)]
+ public static extern IntPtr gu_new_pool();
+
+ [DllImport(LIBNAME, CallingConvention = CC)]
+ public static extern IntPtr gu_new_exn(IntPtr pool);
+
+ [DllImport(LIBNAME, CallingConvention = CC)]
+ public static extern void gu_pool_free(IntPtr pool);
+
+ [DllImport(LIBNAME, CallingConvention = CC)]
+ public static extern IntPtr get_gu_null_variant();
+
+ [DllImport(LIBNAME, CallingConvention = CC)]
+ public static extern IntPtr gu_string_buf_out(IntPtr sbuf);
+
+ [DllImport(LIBNAME, CallingConvention = CC)]
+ public static extern IntPtr gu_new_string_buf(IntPtr pool);
+
+ [DllImport(LIBNAME, CallingConvention = CC)]
+ public static extern IntPtr gu_data_in(IntPtr str, int len, IntPtr pool);
+
+ [DllImport(LIBNAME, CallingConvention = CC)]
+ public static extern IntPtr gu_string_buf_freeze(IntPtr sbuf, IntPtr pool);
+
+ [DllImport(LIBNAME, CallingConvention = CC)]
+ [return: MarshalAs(UnmanagedType.I1)]
+ public static extern bool gu_exn_is_raised(IntPtr err);
+
+ [DllImport(LIBNAME, CallingConvention = CC)]
+ public static extern void gu_enum_next(IntPtr enum_, ref IntPtr outPtr, IntPtr pool);
+
+ [DllImport(LIBNAME, CallingConvention = CC)]
+ public static extern GuVariantInfo gu_variant_open(IntPtr variant);
+
+ [DllImport(LIBNAME, CallingConvention = CC)]
+ public static extern IntPtr gu_alloc_variant(byte tag, UIntPtr size, UIntPtr align, ref IntPtr out_, IntPtr pool);
+
+ [DllImport(LIBNAME, CallingConvention = CC)]
+ public static extern IntPtr gu_make_variant(byte tag, UIntPtr size, UIntPtr align, ref IntPtr init, IntPtr pool);
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct GuVariantInfo
+ {
+ public int Tag;
+ public IntPtr Data;
+ }
+
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct GuSeq
+ {
+ public UIntPtr length;
+ }
+
+ public static uint SeqLength(IntPtr seqptr)
+ {
+ var seq = Marshal.PtrToStructure<GuSeq>(seqptr);
+ return (uint)seq.length;
+ }
+
+ public static T gu_seq_index<T>(IntPtr seq, int index)
+ {
+ var dataPtr = seq + Marshal.SizeOf<GuSeq>();
+ var hypoPtr = dataPtr + index * Marshal.SizeOf<T>();
+ var hypo = Marshal.PtrToStructure<T>(hypoPtr);
+ return hypo;
+ }
+
+ public class NativeMemoryPool
+ {
+ private IntPtr _ptr;
+ internal IntPtr Ptr => _ptr;
+
+ public NativeMemoryPool()
+ {
+ _ptr = gu_new_pool();
+ if (_ptr == IntPtr.Zero) throw new Exception();
+ }
+
+ ~NativeMemoryPool()
+ {
+ gu_pool_free(_ptr);
+ _ptr = IntPtr.Zero;
+ }
+ }
+
+ public class NativeExceptionContext
+ {
+ private IntPtr _ptr;
+ internal IntPtr Ptr => _ptr;
+
+ public NativeExceptionContext(NativeMemoryPool pool)
+ {
+ _ptr = gu_new_exn(pool.Ptr);
+ if (_ptr == IntPtr.Zero) throw new Exception();
+ }
+
+ public bool IsRaised => gu_exn_is_raised(_ptr);
+ }
+
+ public static IEnumerable<IntPtr> IteratorToIEnumerable(IntPtr iterator, IntPtr pool)
+ {
+ IntPtr ptr = IntPtr.Zero;
+ NativeGU.gu_enum_next(iterator, ref ptr, pool);
+ while (ptr != IntPtr.Zero)
+ {
+ yield return ptr;
+ NativeGU.gu_enum_next(iterator, ref ptr, pool);
+ }
+ }
+ }
+}
diff --git a/src/runtime/dotNet/PGF.cs b/src/runtime/dotNet/PGF.cs
new file mode 100644
index 000000000..e6efae1d5
--- /dev/null
+++ b/src/runtime/dotNet/PGF.cs
@@ -0,0 +1,157 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace PGFSharp
+{
+ /// <summary>
+ /// Grammatical Framework grammar.
+ /// </summary>
+ public class PGF
+ {
+ private PGF() { }
+
+ IntPtr _ptr;
+ NativeGU.NativeMemoryPool pool;
+
+ /// <summary>
+ /// Read grammar from PGF file.
+ /// </summary>
+ /// <param name="fn">filename</param>
+ /// <returns></returns>
+ 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)}";
+
+ /// <summary>
+ /// Name of the abstract grammar.
+ /// </summary>
+ public string Name => Native.NativeString.StringFromNativeUtf8(Native.pgf_abstract_name(_ptr));
+
+ /// <summary>
+ /// Default category of the grammar.
+ /// </summary>
+ public Type StartCat => Type.FromPtr(Native.pgf_start_cat(_ptr, pool.Ptr), pool);
+
+ /// <summary>
+ /// All concrete grammars in the language.
+ /// </summary>
+ public Dictionary<string, Concr> Languages
+ {
+ get
+ {
+ var dict = new Dictionary<string, Concr>();
+ 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));
+ }
+
+ /// <summary>
+ /// All categories in the abstract grammar.
+ /// </summary>
+ public IEnumerable<string> Categories => GetStringList(Native.pgf_iter_categories);
+
+ /// <summary>
+ /// All functions in the abstract grammar.
+ /// </summary>
+ public IEnumerable<string> Functions => GetStringList(Native.pgf_iter_functions);
+
+ /// <summary>
+ /// All functions producing the given category name.
+ /// </summary>
+ /// <param name="catName"></param>
+ /// <returns></returns>
+ public IEnumerable<string> FunctionByCategory(string catName)
+ {
+ using (var str = new Native.NativeString(catName))
+ {
+ return GetStringList(new Native.IterFuncCurryName(Native.pgf_iter_functions_by_cat, str.Ptr).IterFunc);
+ }
+ }
+
+ /// <summary>
+ /// Get type from function name.
+ /// </summary>
+ /// <param name="funName"></param>
+ /// <returns></returns>
+ 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);
+ }
+ }
+
+ /// <summary>
+ /// Reduce expression.
+ /// </summary>
+ /// <param name="expr"></param>
+ /// <returns></returns>
+ 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);
+ }
+ }
+
+ /// <summary>
+ /// Enumerate all expressions in the given category.
+ /// </summary>
+ /// <param name="cat"></param>
+ /// <returns></returns>
+ public IEnumerable<Expr> 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<Native.PgfExprProb>(ptr);
+ return Expr.FromPtr(exprProb.expr, result_pool);
+
+ });
+ }
+
+ private IEnumerable<string> GetStringList(Native.MapIterFunc f)
+ {
+ var c = new List<string>();
+ Native.MapIter(f, _ptr, (k, v) => c.Add(k));
+ return c;
+ }
+ }
+}
diff --git a/src/runtime/dotNet/PGFSharp.csproj b/src/runtime/dotNet/PGFSharp.csproj
new file mode 100644
index 000000000..9c1942ade
--- /dev/null
+++ b/src/runtime/dotNet/PGFSharp.csproj
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProjectGuid>{81C13B1B-FE00-4A56-A831-964D55032CDD}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>PGF</RootNamespace>
+ <AssemblyName>PGFSharp</AssemblyName>
+ <TargetFrameworkVersion>v4.5.1</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Xml.Linq" />
+ <Reference Include="System.Data.DataSetExtensions" />
+ <Reference Include="Microsoft.CSharp" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Net.Http" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Bracket.cs" />
+ <Compile Include="Concr.cs" />
+ <Compile Include="Exceptions.cs" />
+ <Compile Include="Native.cs" />
+ <Compile Include="NativeGU.cs" />
+ <Compile Include="PGF.cs" />
+ <Compile Include="Type.cs" />
+ <Compile Include="Expr.cs" />
+ <Compile Include="Expr\Literal.cs" />
+ <Compile Include="Expr\MetaVariable.cs" />
+ <Compile Include="Expr\Application.cs" />
+ <Compile Include="Expr\Function.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+ <ItemGroup>
+ <Folder Include="Expression\" />
+ </ItemGroup>
+</Project>
diff --git a/src/runtime/dotNet/Properties/AssemblyInfo.cs b/src/runtime/dotNet/Properties/AssemblyInfo.cs
new file mode 100644
index 000000000..b1f1eb1ad
--- /dev/null
+++ b/src/runtime/dotNet/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("PGF")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("")]
+[assembly: AssemblyCopyright("")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("81c13b1b-fe00-4a56-a831-964d55032cdd")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("3.8.0.0")]
+[assembly: AssemblyFileVersion("3.8.0.0")]
diff --git a/src/runtime/dotNet/Type.cs b/src/runtime/dotNet/Type.cs
new file mode 100644
index 000000000..9ec2c45d8
--- /dev/null
+++ b/src/runtime/dotNet/Type.cs
@@ -0,0 +1,92 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace PGFSharp
+{
+ /// <summary>
+ /// A GF type.
+ /// </summary>
+ public class Type
+ {
+ private IntPtr _ptr;
+ internal IntPtr Ptr => _ptr;
+ private NativeGU.NativeMemoryPool _pool;
+ private Type() { }
+
+ internal static Type FromPtr(IntPtr type, NativeGU.NativeMemoryPool pool)
+ {
+ var t = new Type();
+ t._ptr = type;
+ t._pool = pool;
+ return t;
+ }
+
+ public override string ToString() =>
+ Native.ReadString((output,exn) => Native.pgf_print_type(_ptr, IntPtr.Zero, 0, output, exn.Ptr));
+
+ private PgfType Data => Marshal.PtrToStructure<PgfType>(_ptr);
+
+ /// <summary>
+ /// Read type from string.
+ /// </summary>
+ /// <param name="typeStr"></param>
+ /// <returns></returns>
+ public Type ReadType(string typeStr)
+ {
+ var tmp_pool = new NativeGU.NativeMemoryPool();
+ var exn = new NativeGU.NativeExceptionContext(tmp_pool);
+ var result_pool = new NativeGU.NativeMemoryPool();
+ using (var strNative = new Native.NativeString(typeStr))
+ {
+ var in_ = NativeGU.gu_data_in(strNative.Ptr, strNative.Size, tmp_pool.Ptr);
+ var typ = Native.pgf_read_type(in_, result_pool.Ptr, exn.Ptr);
+ if (exn.IsRaised || typ == IntPtr.Zero)
+ {
+ throw new PGFError();
+ }
+ else
+ {
+ return Type.FromPtr(typ, result_pool);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Get the hypotheses of a type (function argument types).
+ /// </summary>
+ public IEnumerable<Type> Hypotheses
+ {
+ get
+ {
+ var n_hypos = NativeGU.SeqLength(Data.hypos);
+ for (int i = 0; i < n_hypos; i++)
+ {
+ var hypo = NativeGU.gu_seq_index<PgfHypo>(Data.hypos, i);
+ var type = Type.FromPtr(hypo.type, this._pool);
+ yield return type;
+ }
+ }
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ private struct PgfType
+ {
+ public IntPtr hypos; // GuSeq of PgfHypo
+ public IntPtr cid;
+ public UIntPtr n_exprs;
+ public IntPtr exprs;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ private struct PgfHypo
+ {
+ public int pgfBindType; // enum
+ public IntPtr cid; // PgfCId (string)
+ public IntPtr type; // PgfType*
+ }
+ }
+}