Created
February 27, 2011 23:49
-
-
Save danfinch/846706 to your computer and use it in GitHub Desktop.
simple whitespace indentation parser
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
open System | |
module Whitespace = | |
type Node = { Text : string; Nodes : Node ResizeArray; Parent : Node option } | |
type private Line = { Text : string; Indentation : int } | |
type private Token = Begin | Text of string | End | |
let parseTree (src : string) = | |
let lines = | |
src.Split ([| "\n"; "\r" |], StringSplitOptions.RemoveEmptyEntries) | |
|> Array.filter (fun s -> s.Trim () = "" |> not) | |
|> Array.filter (fun s -> not <| s.StartsWith "//") | |
|> Array.map (fun s -> | |
let text = s.TrimStart ' ' | |
{ Text = text; Indentation = s.Length - text.Length } | |
) | |
let tokens = ResizeArray<Token> () | |
let depths = System.Collections.Generic.Stack<int> () | |
depths.Push 0 | |
for line in lines do | |
let indent = Seq.sum depths | |
if line.Indentation > indent then do | |
let depth = line.Indentation - indent | |
let last = tokens.[tokens.Count - 1] | |
depths.Push depth | |
tokens.Insert (tokens.Count - 1, Begin) | |
elif line.Indentation < indent then do | |
let depth = indent - line.Indentation | |
let mutable pop = 0 | |
while pop < depth do | |
tokens.Add End | |
pop <- pop + depths.Pop () | |
tokens.Add (Text (line.Text)) | |
let textOf (t : Token ) = | |
match t with | |
| Text(s) -> s | |
| _ -> failwith "inconceivable" | |
let root = { Text = null; Nodes = ResizeArray (); Parent = None } | |
let node = ref root | |
let mutable t = 0 | |
while t < tokens.Count do | |
let token = tokens.[t] | |
match token with | |
| Begin -> | |
t <- t + 1 | |
let n = { Text = tokens.[t] |> textOf; Nodes = ResizeArray (); Parent = Some !node } | |
(!node).Nodes.Add n | |
node := n | |
| Text(s) -> | |
(!node).Nodes.Add { Text = s; Nodes = ResizeArray (); Parent = Some !node } | |
| End -> node := (!node).Parent.Value | |
t <- t + 1 | |
root |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment