2016-12-28 14 views
10

Tôi đang cố định nghĩa ngữ pháp của mình là một công đoàn phân biệt đối xử. Nó có hai loại có thể: intdatetime và toán tử từ xa là AddMul. Add công trình trên intdatetime (như thêm ngày trong int) Mul chỉ hoạt động trên int và không phải trên datetime Grammar có thể đệ quyF # cách xác định giới hạn kiểu trong các công đoàn phân biệt đệ quy

ngữ pháp của tôi trông giống như

type MyExpression = 
|Integer of int 
|Date of datetime 
|Add of MyExpression * MyExpression 
|Mul of MyExpression * MyExpression 

Tôi đã viết một phân tích cú pháp (fparsec) có thể phân tích cú pháp văn bản trong ngữ pháp của tôi, nhưng tôi không chắc chắn cách xử lý điều kiện Mul có thể đệ quy nhưng chỉ trên Integer.

Có tùy chọn để xác định giới hạn này trên loại MyExpression hoặc tôi có phải xử lý điều này trong đầu vào được phân tích cú pháp của mình không?

Trả lời

9

Việc thiết kế được đề xuất bởi Asti cũng sẽ là sự lựa chọn đầu tiên của tôi. Tùy thuộc vào yêu cầu của bạn, đó có thể là tất cả những gì bạn cần.

Nó hiện, tuy nhiên, cũng cho phép bạn biên dịch một biểu thức như

Add(Val(System.Console.Out), Val(System.Console.Error)) 

mà có lẽ không phải những gì bạn muốn.

Ngoài ra, bạn có thể mô hình biểu hiện như thế này:

open System 

type IntExpression = 
| Integer of int 
| Mul of IntExpression * IntExpression 
| Add of IntExpression * IntExpression 

type DateTimeExpression = 
| Date of DateTime 
| Add of DateTimeExpression * DateTimeExpression 

type MyExpression = 
| IntExpression of IntExpression 
| DateTimeExpression of DateTimeExpression 

Đây rõ ràng là một định nghĩa kiểu tiết hơn, nhưng nó thể hiện sự cai trị rằng một biểu thức có thể chứa các nút lá của một trong hai số nguyên hoặc DateTime giá trị, và không có giá trị nào khác - nếu đó là quy tắc bạn muốn thực thi.

Tôi không tuyên bố rằng điều này là tốt hơn; Tôi chỉ cung cấp một giải pháp thay thế.

Cách sử dụng:

> IntExpression(Mul(IntExpression.Add(Integer(1), Integer(2)),Integer 3));; 
val it : MyExpression = 
    IntExpression (Mul (Add (Integer 1,Integer 2),Integer 3)) 
> DateTimeExpression(Add(Date(DateTime.MinValue),Date(DateTime.MinValue)));; 
val it : MyExpression = 
    DateTimeExpression 
    (Add 
     (Date 01.01.0001 00:00:00 {Date = 01.01.0001 00:00:00; 
            Day = 1; 
            DayOfWeek = Monday; 
            DayOfYear = 1; 
            Hour = 0; 
            Kind = Unspecified; 
            Millisecond = 0; 
            Minute = 0; 
            Month = 1; 
            Second = 0; 
            Ticks = 0L; 
            TimeOfDay = 00:00:00; 
            Year = 1;}, 
     Date 01.01.0001 00:00:00 {Date = 01.01.0001 00:00:00; 
            Day = 1; 
            DayOfWeek = Monday; 
            DayOfYear = 1; 
            Hour = 0; 
            Kind = Unspecified; 
            Millisecond = 0; 
            Minute = 0; 
            Month = 1; 
            Second = 0; 
            Ticks = 0L; 
            TimeOfDay = 00:00:00; 
            Year = 1;})) 
7

Nếu bạn có loại hạn chế dựa, nó có thể được dễ dàng hơn đi cho một cách tiếp cận chung:

type MyExpression<'t> = 
|Val of 't 
|Mul of MyExpression<int> * MyExpression<int> 
|Add of MyExpression<'t> * MyExpression<'t> 

let Integer (x:int) = Val(x) 
let Date (x:DateTime) = Val(x) 

Cách sử dụng:

Mul(Integer(1), Integer(2)) //compiles 
Mul(Date(DateTime.Now), Date(DateTime.Now)) //error 
+1

này xử lý một số hạn chế, nhưng không phải tất cả trong số họ - những điều sau đây không phải là một biểu hiện nhạy cảm, nhưng nó gõ kiểm tra: 'Thêm (Date (DateTime.Now), Mul (Số nguyên 1, Số nguyên 2)) ' –

Các vấn đề liên quan