간단한 출력하는 lexer를 사용합니다. 렉서는 문자열에있는 텍스트 그룹을 찾아 해당 그룹에서 토큰을 생성합니다. 그런 다음 토큰에 "유형"이 제공됩니다. (무엇인지 정의하는 것)
C# 키워드는 정의 된 C# keywords 중 하나입니다. 이 간단한 정규식은 가능한 C# 키워드 중 하나가 오는 테두리를 정의합니다. ("\b(new|var|string|...)\b"
)
귀하의 렉서는 각 경기에 대한 토큰을 생성, 키워드 주어진 문자열에서 모든 일치를 발견하고 토큰 "type"
이 "keyword"
라고 말할 것입니다.
그러나 당신이 말한 것처럼, 따옴표 나 주석으로 키워드를 찾으려는 것은 아닙니다. 이것은 렉서가 실제로 점수를 얻는 곳입니다.
- 다른 경기에 포함 된 모든 일치 항목을 제거합니다 은 (정규식 기반) 렉서는 두 가지 방법을 사용하는 것이이 사건을 해결하려면.
- 다른 공간과 동일한 공간을 사용하지만 우선 순위가 낮은 인 일치 항목을 제거하십시오.
렉서는 다음과 같이 작동합니다
- 는
- 의 각을 통해 인덱스
- 루프에 의해
- 주문을 토큰 토큰 그들을 변환] 정규 표현식에에서 경기를 모두 찾기 다음 일치 항목이이 일치 항목에 부분적으로 포함되어 있으면 다음 일치 항목 인 과 일치하는 토큰 (또는 둘 모두가 같은 공간) 그것을 제거하십시오.
스포일러 경고 다음은 완전한 기능 렉서입니다. 그것은 완전히 기능적인 렉서이기 때문에 렉서가 어떻게 작동 하는지를 보여줄 것입니다. 예를 들어
: 문자열, 주석 및 키워드에 대한
을 감안할 때 정규 표현식에는 렉서가 그들 사이의 충돌을 해결하는 방법을 보여줍니다. (나는 그것을 테스트) 유효한 거의 완성 렉서. 그것은 그들을 혼동 당신이 정규식에서 정의하는 모든 키워드를 찾을 수 없습니다 (그것을 사용하거나 직접 작성 부담)입니다
//Simple Regex for strings
string StringRegex = "\"(?:[^\"\\\\]|\\\\.)*\"";
//Simple Regex for comments
string CommentRegex = @"//.*|/\*[\s\S]*\*/";
//Simple Regex for keywords
string KeywordRegex = @"\b(?:new|var|string)\b";
//Create a dictionary relating token types to regexes
Dictionary<string, string> Regexes = new Dictionary<string, string>()
{
{"String", StringRegex},
{"Comment", CommentRegex},
{"Keyword", KeywordRegex}
};
//Define a string to tokenize
string input = "string myString = \"Hi! this is my new string!\"//Defines a new string.";
//Lexer steps:
//1). Find all of the matches from the regexes
//2). Convert them to tokens
//3). Order the tokens by index then priority
//4). Loop through each of the tokens comparing
// the current match with the next match,
// if the next match is partially contained by this match
// (or if they both occupy the same space) remove it.
//** Sorry for the complex LINQ expression (not really) **
//Match each regex to the input string(Step 1)
var matches = Regexes.SelectMany(a => Regex.Matches(input, a.Value)
//Cast each match because MatchCollection does not implement IEnumerable<T>
.Cast<Match>()
//Select a new token for each match(Step 2)
.Select(b =>
new
{
Index = b.Index,
Value = b.Value,
Type = a.Key //Type is based on the current regex.
}))
//Order each token by the index (Step 3)
.OrderBy(a => a.Index).ToList();
//Loop through the tokens(Step 4)
for (int i = 0; i < matches.Count; i++)
{
//Compare the current token with the next token to see if it is contained
if (i + 1 < matches.Count)
{
int firstEndPos = (matches[i].Index + matches[i].Value.Length);
if (firstEndPos > matches[(i + 1)].Index)
{
//Remove the next token from the list and stay at
//the current match
matches.RemoveAt(i + 1);
i--;
}
}
}
//Now matches contains all of the right matches
//Filter the matches by the Type to single out keywords from comments and
//string literals.
foreach(var match in matches)
{
Console.WriteLine(match);
}
Console.ReadLine();
문자열 리터럴 또는 주석.
정말로 무엇을하려고합니까? 왜 C# 키워드를 매치해야합니까? –
아마도 Roslyn을 사용해야합니다. 소스 코드를 정규식으로 파싱하는 것은 불만을 해결하는 방법입니다. – SLaks
소스 코드에 대한 강조 표시 (HTML로)를 만들고 싶습니다. 요소로 키워드를 꾸밀 필요가 있습니다. 나는 완벽한 알고리즘을 만들고 싶지는 않지만 직접 (교육 목적으로) 만들려고한다. –