Skip to content

Instantly share code, notes, and snippets.

@danfinch
Created February 27, 2011 23:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save danfinch/846706 to your computer and use it in GitHub Desktop.
Save danfinch/846706 to your computer and use it in GitHub Desktop.
simple whitespace indentation parser
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