Έχουν δημοσιευτεί Κυριακή, 27 Σεπτεμβρίου 2009 2:54 μμ από το μέλος PALLADIN

RegEx engine in F#

Ένα από τα πολύ δυνατά χαρακτηριστικά μιας functional γλώσσας, είναι η δυνατότητα να δημιουργούμε internal DSLs κάνοντας compose combinators.

Ένα τέτοιο παράδειγμα, είναι μια regex engine που έγραψα σε F#.

Κάποιες βασικές  ιδέες  της υλοποίησης:
 - lazy computations for backtracking
 - combinators for regex composition
 - parametric polymorphism: Generic "named capture variables" and input sequences
 - Unions + Active Patterns: pattern matching and value extraction


Ακολουθεί ένα sample

#r "FSharp.PowerPack.dll"
#load "RegEx.fs"

open System
open RegEx

// example from http://www.martinfowler.com/bliki/ComposedRegex.html

type extractTags = NumberOfPoint of int | NumberOfNights of int | HotelName of string
let numberOfPoints = toInt >> NumberOfPoint
let numberOfNights = toInt >> NumberOfNights
let hotelName  = toString >> HotelName

let scoreKeyword() = string "score" => !+ space()
let numberOfPoints = !+ digit() |> group numberOfPoints
let forKeyword() = space() => string "for" => space()
let numberOfNights = !+ digit() |> group numberOfNights
let nightsAtKeyword() = spaces() => string "nights" => spaces() => string "at" => spaces()
let hotelName() = !+ any() |> group hotelName

let pattern = scoreKeyword() => numberOfPoints => forKeyword() => numberOfNights => nightsAtKeyword() => hotelName() => endOfLine()

let text = List.reduce (fun acc value -> acc + "\r\n " + value)
              [ "score 400 for 2 nights at Minas Tirith Airport"; 
                "score 500 for 6 nights at Athens Airport";
                "score 200 for 3 nights at London Airport" ] + "\r\n"

let result = patternMatch pattern text

// pattern match
match result with
| Success ( (NumberOfPoint(points) :: NumberOfNights(nights) :: HotelName(name) :: _) :: _ ) -> printfn "Points: %d, Nights %d, Hotel name: %s" points nights name
| Failure -> ()

                
let replacePattern = function
| [NumberOfPoint(points); NumberOfNights(nights); HotelName(name)] -> sprintf "score %d for %d nights at %s" (points * 2) (nights * 3) (name + " ok")
| _ -> failwith "Expected extraction pattern: score {NumberOfPoint} for {NumberOfNights} nights at {HotelName}"

let replacedResult = patternReplace pattern text replacePattern |> Array.of_seq |> (fun (chars : array<char>) -> new String(chars))
Share



Attachment(s): RegEx.zip

Ενημέρωση για Σχόλια

Αν θα θέλατε να λαμβάνετε ένα e-mail όταν γίνονται ανανεώσεις στο περιεχόμενο αυτής της δημοσίευσης, παρακαλούμε γίνετε συνδρομητής εδώ

Παραμείνετε ενήμεροι στα τελευταία σχόλια με την χρήση του αγαπημένου σας RSS Aggregator και συνδρομή στη Τροφοδοσία RSS με σχόλια

Σχόλια:

Χωρίς Σχόλια

Ποιά είναι η άποψή σας για την παραπάνω δημοσίευση;

(απαιτούμενο)
απαιτούμενο
προαιρετικό
απαιτούμενο
ÅéóÜãåôå ôïí êùäéêü:
CAPTCHA Image