Guest User

Untitled

a guest
May 2nd, 2016
54
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.86 KB | None | 0 0
  1. /(?:[-+*/=<>{)(;]{1})([A-Za-z]{1}[A-Za-z0-9]*)(?:[-;+*/=<>)]{1})/
  2.  
  3. if(dsf==35){x=y/10;}else{y=n/25+n;}
  4.  
  5. public static Dictionary<string, string> Patterns = new Dictionary<string, string>()
  6. {
  7. {"variable", @"(?:[-+*/=<>{)(;]{1})([A-Za-z]{1}[A-Za-z0-9]*)"},
  8. {"operator", @"(?:[A-Za-z0-9]+?)([<>]{1}[=]?|[=]{2}|!{1}={1}|[-+*/=]+?)"},
  9. {"punctuation", @"([)({};]+?)"},
  10. {"keyword", @"(if|else)(?:[({]+?)"},
  11. {"constante", @"(?:[-+*/=<>(]+?)([-]?[d]+[.]?[d]*)"}
  12. };
  13.  
  14. class Program
  15. {
  16. enum TokenType
  17. {
  18. Comparison,
  19. Punct,
  20. If,
  21. Else,
  22. Ident, // должно идти после ключевых слов!
  23. NumLiteral
  24. };
  25.  
  26. class Token
  27. {
  28. public TokenType Type;
  29. public string StringValue;
  30. public double NumericValue;
  31. // сюда стоит ещё добавить информацию о позиции в исходном тексте
  32. }
  33.  
  34. // регулярки, описывающие лексему, начинаются с ^, чтобы матчить только в начале
  35. Dictionary<TokenType, Regex> regexes = new Dictionary<TokenType, Regex>()
  36. {
  37. [TokenType.Comparison] = new Regex(@"^(>=?|<=?|==)", RegexOptions.Compiled),
  38. [TokenType.Punct] = new Regex(@"^[,)(}{;]", RegexOptions.Compiled),
  39. [TokenType.If] = new Regex(@"^if", RegexOptions.Compiled),
  40. [TokenType.Else] = new Regex(@"^else", RegexOptions.Compiled),
  41. [TokenType.Ident] = new Regex(@"^[a-zA-Z_][a-zA-Z_0-9]*", RegexOptions.Compiled),
  42. [TokenType.NumLiteral] = new Regex(@"^[0-9]+(.[0-9]+)?", RegexOptions.Compiled)
  43. };
  44.  
  45. // что ещё записать в токен?
  46. Dictionary<TokenType, Action<string, Token>> creators =
  47. new Dictionary<TokenType, Action<string, Token>>()
  48. {
  49. [TokenType.Comparison] = (s, token) => token.StringValue = s,
  50. [TokenType.Punct] = (s, token) => token.StringValue = s,
  51. [TokenType.If] = (s, token) => { },
  52. [TokenType.Else] = (s, token) => { },
  53. [TokenType.Ident] = (s, token) => token.StringValue = s,
  54. [TokenType.NumLiteral] = (s, token) => token.NumericValue = double.Parse(s)
  55. };
  56.  
  57. // а вот и вся логика:
  58. IEnumerable<Token> Tokenize(string text)
  59. {
  60. // откусываем пробелы
  61. var remainingText = text.TrimStart();
  62. while (remainingText != "")
  63. {
  64. // находим наиболее подходящий паттерн:
  65. var bestMatch =
  66. (from pair in regexes
  67. let tokenType = pair.Key
  68. let regex = pair.Value
  69. let match = regex.Match(remainingText)
  70. let matchLen = match.Length
  71. // упорядочиваем по длине, а если длина одинаковая - по типу токена
  72. orderby matchLen descending, tokenType
  73. select new { tokenType, text = match.Value, matchLen }).First();
  74.  
  75. // если везде только 0, ошибка
  76. if (bestMatch.matchLen == 0)
  77. throw new Exception("Unknown lexeme");
  78.  
  79. var token = new Token() { Type = bestMatch.tokenType };
  80. creators[bestMatch.tokenType](bestMatch.text, token);
  81. yield return token;
  82.  
  83. // откусываем распознанный кусок и пробелы после него
  84. remainingText = remainingText.Substring(bestMatch.matchLen).TrimStart();
  85. }
  86. }
  87.  
  88. static void Main(string[] args)
  89. {
  90. new Program().Run();
  91. }
  92.  
  93. void Run()
  94. {
  95. var text = "else if if x > < > if == else; 25.0 7";
  96. foreach (var token in Tokenize(text))
  97. Console.WriteLine(token.Type);
  98. }
  99. }
Add Comment
Please, Sign In to add comment