code_junkie

Can you propose a more elegant way to 'tokenize' c# code for html formatting?

Nov 11th, 2011
84
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.21 KB | None | 0 0
  1. //Types of tokens we are going to detect
  2. type Token =
  3. | Whitespace of string
  4. | Comment of string
  5. | Strng of string
  6. | Keyword of string
  7. | Text of string
  8. | EOF
  9.  
  10. //turn a string into a list of recognised tokens
  11. let tokenize (s:String) =
  12. //this is the 'parser' - should we look at compiling the regexs in advance?
  13. let nexttoken (st:String) =
  14. match st with
  15. | st when Regex.IsMatch(st, "^s+") -> Whitespace(Regex.Match(st, "^s+").Value)
  16. | st when Regex.IsMatch(st, "^//.*?r?n") -> Comment(Regex.Match(st, "^//.*?r?n").Value) //this is double slash-style comments
  17. | st when Regex.IsMatch(st, "^/*(.|[r?n])*?*/") -> Comment(Regex.Match(st, "^/*(.|[r?n])*?*/").Value) // /* */ style comments http://ostermiller.org/findcomment.html
  18. | st when Regex.IsMatch(st, @"^""([^""\]|\.|"""")*""") -> Strng(Regex.Match(st, @"^""([^""\]|\.|"""")*""").Value) // unescaped = "([^"\]|\.|"")*" http://wordaligned.org/articles/string-literals-and-regular-expressions
  19. | st when Regex.IsMatch(st, "^#(end)?region") -> Keyword(Regex.Match(st, "^#(end)?region").Value)
  20. | st when st <> "" ->
  21. match Regex.Match(st, @"^[^""s]*").Value with //all text until next whitespace or quote (this may be wrong)
  22. | x when iskeyword x -> Keyword(x) //iskeyword uses Microsoft.CSharp.CSharpCodeProvider.IsValidIdentifier - a bit fragile...
  23. | x -> Text(x)
  24. | _ -> EOF
  25.  
  26. //tail-recursive use of next token to transform string into token list
  27. let tokeneater s =
  28. let rec loop s acc =
  29. let t = nexttoken s
  30. match t with
  31. | EOF -> List.rev acc //return accumulator (have to reverse it because built backwards with tail recursion)
  32. | Whitespace(x) | Comment(x)
  33. | Keyword(x) | Text(x) | Strng(x) ->
  34. loop (s.Remove(0, x.Length)) (t::acc) //tail recursive
  35. loop s []
  36.  
  37. tokeneater s
  38.  
  39. let (|Matches|_|) re s =
  40. let m = Regex(re).Match(s)
  41. if m.Success then
  42. Some(Matches (m.Value))
  43. else
  44. None
  45.  
  46. let nexttoken (st:String) =
  47. match st with
  48. | Matches "^s+" s -> Whitespace(s)
  49. | Matches "^//.*?r?n" s -> Comment(s)
  50. ...
Add Comment
Please, Sign In to add comment