Advertisement
Guest User

Untitled

a guest
May 13th, 2015
379
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 3.61 KB | None | 0 0
  1. class Lexer
  2. {
  3.     public static Task<List<QualifiedToken>> Parse(IEnumerable<RawText> texts)
  4.     {
  5.         var lexer = new Lexer(texts);
  6.         return Task.Run(() => lexer.Parse().ToList());
  7.     }
  8.  
  9.     List<int> partIndices = new List<int>();
  10.     List<TextPointer> pointers = new List<TextPointer>();
  11.     string totalText;
  12.  
  13.     Lexer(IEnumerable<RawText> texts)
  14.     {
  15.         StringBuilder sb = new StringBuilder();
  16.         foreach (var text in texts)
  17.         {
  18.             partIndices.Add(sb.Length);
  19.             sb.Append(text.Text);
  20.             pointers.Add(text.Start);
  21.         }
  22.         totalText = sb.ToString();
  23.     }
  24.  
  25.     Tuple<TextPointer, int> GetBasePointerAndOffset(int position)
  26.     {
  27.         var partNo = partIndices.BinarySearch(position);
  28.         if (partNo < 0)
  29.             partNo = ~partNo - 1;
  30.         var partStart = partIndices[partNo];
  31.         var delta = position - partStart;
  32.         return Tuple.Create(pointers[partNo], delta);
  33.     }
  34.  
  35.     IEnumerable<QualifiedToken> Parse()
  36.     {
  37.         var regexParts = new Dictionary<string, string>()
  38.         {
  39.             { "ident",   @"\p{L}\w*" },
  40.             { "num",     @"[+-]?(\d+(\.\d*)?)|(\.\d+)" },
  41.             { "comment", @"(/\*.*?\*/)|(//.*$)" },
  42.             { "punct",   @"(:=)|(<=)|(>=)|(==)|[;+\-\*/\(\){}:<>=]" },
  43.             { "string",  "\"[^\"\\\\]*(?:\\\\.[^\"\\\\]*)*\"" },
  44.             { "space",   @"\s+" }
  45.         };
  46.  
  47.         var combinedRegex = "^(" + string.Join("|", regexParts.Select(kvp => string.Format("(?<{0}>{1})", kvp.Key, kvp.Value))) + ")";
  48.  
  49.         var compiledRe = new Regex(combinedRegex, RegexOptions.Compiled | RegexOptions.Multiline);
  50.         var names = regexParts.Keys;
  51.  
  52.         var tokenMapping = new Dictionary<string, TokenType?>()
  53.         {
  54.             { "ident", TokenType.Ident },
  55.             { "num", TokenType.Number },
  56.             { "comment", TokenType.Comment },
  57.             { "punct", TokenType.Punct },
  58.             { "string",  TokenType.String },
  59.             { "space", null }
  60.         };
  61.  
  62.         string restLine = totalText;
  63.         int currPos = 0;
  64.         while (restLine != "")
  65.         {
  66.             var match = compiledRe.Match(restLine);
  67.             var nameAndGroup = names.Select(name => new { name, group = match.Groups[name] })
  68.                                     .Single(ng => ng.group.Success);
  69.  
  70.             var text = nameAndGroup.group.Value;
  71.             var length = nameAndGroup.group.Length;
  72.  
  73.             var tokenType = tokenMapping[nameAndGroup.name];
  74.             if (tokenType == TokenType.Ident && CheckKeyword(text))
  75.                 tokenType = TokenType.Keyword;
  76.             if (tokenType != null)
  77.             {
  78.                 var start = GetBasePointerAndOffset(currPos);
  79.                 var end = GetBasePointerAndOffset(currPos + length);
  80.                 yield return new QualifiedToken()
  81.                                     {
  82.                                         Type = tokenType.Value,
  83.                                         StartPosition = start.Item1,
  84.                                         StartOffset = start.Item2,
  85.                                         EndPosition = end.Item1,
  86.                                         EndOffset = end.Item2
  87.                                     };
  88.             }
  89.             currPos += length;
  90.             restLine = restLine.Substring(length);
  91.         }
  92.     }
  93.  
  94.     HashSet<string> keywords = new HashSet<string>()
  95.     {
  96.         "for",
  97.         "while",
  98.         "int",
  99.         "string",
  100.         "bool"
  101.     };
  102.  
  103.     bool CheckKeyword(string text)
  104.     {
  105.         return keywords.Contains(text);
  106.     }
  107. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement