forked from GitHub/gf-core
.NET binding to GF by Bjørnar Luteberget
This commit is contained in:
120
src/runtime/dotNet/Bracket.cs
Normal file
120
src/runtime/dotNet/Bracket.cs
Normal file
@@ -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() )
|
||||
) + "}";
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
173
src/runtime/dotNet/Concr.cs
Normal file
173
src/runtime/dotNet/Concr.cs
Normal file
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
46
src/runtime/dotNet/Exceptions.cs
Normal file
46
src/runtime/dotNet/Exceptions.cs
Normal file
@@ -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)
|
||||
{ }
|
||||
}
|
||||
}
|
||||
133
src/runtime/dotNet/Expr.cs
Normal file
133
src/runtime/dotNet/Expr.cs
Normal file
@@ -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));
|
||||
|
||||
}
|
||||
}
|
||||
15
src/runtime/dotNet/Expr/Abstraction.cs
Normal file
15
src/runtime/dotNet/Expr/Abstraction.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace PGFSharp
|
||||
{
|
||||
/*public class Abs : Expression
|
||||
{
|
||||
public Abs ()
|
||||
{
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
57
src/runtime/dotNet/Expr/Application.cs
Normal file
57
src/runtime/dotNet/Expr/Application.cs
Normal file
@@ -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;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
18
src/runtime/dotNet/Expr/Function.cs
Normal file
18
src/runtime/dotNet/Expr/Function.cs
Normal file
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
127
src/runtime/dotNet/Expr/Literal.cs
Normal file
127
src/runtime/dotNet/Expr/Literal.cs
Normal file
@@ -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; }
|
||||
}
|
||||
}
|
||||
|
||||
34
src/runtime/dotNet/Expr/MetaVariable.cs
Normal file
34
src/runtime/dotNet/Expr/MetaVariable.cs
Normal file
@@ -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; }
|
||||
}
|
||||
}
|
||||
|
||||
306
src/runtime/dotNet/Native.cs
Normal file
306
src/runtime/dotNet/Native.cs
Normal file
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
127
src/runtime/dotNet/NativeGU.cs
Normal file
127
src/runtime/dotNet/NativeGU.cs
Normal file
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
157
src/runtime/dotNet/PGF.cs
Normal file
157
src/runtime/dotNet/PGF.cs
Normal file
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
68
src/runtime/dotNet/PGFSharp.csproj
Normal file
68
src/runtime/dotNet/PGFSharp.csproj
Normal file
@@ -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>
|
||||
36
src/runtime/dotNet/Properties/AssemblyInfo.cs
Normal file
36
src/runtime/dotNet/Properties/AssemblyInfo.cs
Normal file
@@ -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")]
|
||||
92
src/runtime/dotNet/Type.cs
Normal file
92
src/runtime/dotNet/Type.cs
Normal file
@@ -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*
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user