Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#使用正则表达式的标记器-停止,向前看_C#_Regex - Fatal编程技术网

C#使用正则表达式的标记器-停止,向前看

C#使用正则表达式的标记器-停止,向前看,c#,regex,C#,Regex,我正在尝试为一种自定义编程语言创建一个编译器,我已经用Java完成了这项工作。然而,出于很好的理由,我想将其移植到本机代码,C#是我的选择。我面临的问题是,当我与正则表达式匹配时,匹配器会查看整个源代码文件,而不是开始 源代码示例: namespace CrazyRedd{ class Test{ public function main(string[] args){ System.println("Hello World");

我正在尝试为一种自定义编程语言创建一个编译器,我已经用Java完成了这项工作。然而,出于很好的理由,我想将其移植到本机代码,C#是我的选择。我面临的问题是,当我与正则表达式匹配时,匹配器会查看整个源代码文件,而不是开始

源代码示例:

namespace CrazyRedd{
    class Test{
        public function main(string[] args){
            System.println("Hello World");
        }
    }
}
输出(格式为tokenValue+“|”+tokenType):

获取下一个令牌的方法是:

    public Token nextToken()
    {
        str = str.Trim();
        if (pushBack)
        {
            pushBack = false;
            return lastToken;
        }
        if (String.IsNullOrEmpty(str))
        {
            return (lastToken=new Token("", TokenType.EMPTY));
        }
        foreach(TokenData tokenData in tokenDatas)
        {
            Match matcher = Regex.Match(str, tokenData.getPattern(), RegexOptions.IgnoreCase);
            if (matcher.Success)
            {
                string token = matcher.Value.Trim();
                Regex replacer = new Regex(Regex.Escape(token));
                str = replacer.Replace(str,"",1);
                if (tokenData.getType() == TokenType.STR_LITERAL)
                {
                    return (lastToken = new Token(token.Substring(1, token.Length - 1),
                        TokenType.STR_LITERAL));
                }
                else
                {
                    return (lastToken = new Token(token, tokenData.getType()));
                }
            }
        }
        throw new Exception("Fatal Error: Could not compile: "+str);
    }
最后,以下是初始化标记器的方法:

public void init()
        {
            string[] keys = { "if", "else", "namespace", "class", "function" };
            foreach (string key in keys)
            {
                tokenDatas.Add(new TokenData(key + "\\s", TokenType.KEYWORD));
            }
            string[] types = { "int", "byte", "char", "string", "bool", "const" };
            foreach (string type in types)
            {
                tokenDatas.Add(new TokenData(type + "\\s", TokenType.BUILT_IN_TYPE));
            }
            tokenDatas.Add(new TokenData("(-)?[0-9]+", TokenType.INT_LITERAL));
            tokenDatas.Add(new TokenData("\"*\"", TokenType.STR_LITERAL));
            tokenDatas.Add(new TokenData("[a-zA-Z][a-zA-Z0-9]*\\s", TokenType.IDENTIFIER));
            string[] syms = { "\\.", "\\,", "\\;", "\\(", "\\)", "\\[", "\\]", "\\{", "\\}" };
            foreach (string sym in syms)
            {
                tokenDatas.Add(new TokenData(sym, TokenType.SYMBOL));
            }
            string[] ops = { "\\+", "\\-", "\\*", "/", "%", "=", "\\+=", "-=", "\\*=", "/=", "%=" };
            foreach (string op in ops)
            {
                tokenDatas.Add(new TokenData(op, TokenType.OPERATOR));
            }
            string[] coms = { "<", ">", "<=", ">=", "==", "!=" };
            foreach (string com in coms)
            {
                tokenDatas.Add(new TokenData(com, TokenType.COMPARATOR));
            }
        }
public void init()
{
字符串[]键={“if”,“else”,“namespace”,“class”,“function”};
foreach(字符串键入键)
{
添加(新的TokenData(key+“\\s”,TokenType.KEYWORD));
}
字符串[]类型={“int”、“byte”、“char”、“string”、“bool”、“const”};
foreach(类型中的字符串类型)
{
添加(新的TokenData(type+“\\s”,TokenType.build_-IN_-type));
}
添加(新的TokenData(“(-)[0-9]+”,TokenType.INT_LITERAL));
添加(新的TokenData(“\”*\”,TokenType.STR_LITERAL));
TokenData.Add(新的TokenData(“[a-zA-Z][a-zA-Z0-9]*\\s”,TokenType.IDENTIFIER));
字符串[]syms={“\\.”、“\\.”、“\\;”、“\\(”、“\\)”、“\\[”、“\\]”、“\\{”、“\\}”;
foreach(符号中的字符串符号)
{
添加(新的TokenData(sym,TokenType.SYMBOL));
}
字符串[]ops={“\\+”、“\\-”、“\\*”、“/”、“%”、“=”、“\\+=”、“-=”、“\\*=”、“/=”、“%=”};
foreach(操作中的字符串操作)
{
Add(新的TokenData(op,TokenType.OPERATOR));
}
字符串[]coms={“”,“==”,“=”,“!=”};
foreach(com中的字符串com)
{
Add(新的TokenData(com,TokenType.COMPARATOR));
}
}

我需要知道的是,是什么导致令牌发生器以错误的顺序吐出令牌。

只要看一下您的代码,这似乎就是导致您出现问题的原因

对nextToken()的每次调用

导致此循环,其中匹配函数被赋予一个新模式
对于每个新的
标记数据

与所有发动机一样,这将在位置0处开始匹配检查

其不符合顺序的原因是,它匹配的是任何顺序

无论匹配发生在何处,正则表达式模式都会出现

“然而,出于很好的理由,我想把它移植到本机代码中,C是我的选择。”你知道C不是本机代码吗?为什么不使用某种AST工具,比如ANTLR而不是regex?你应该尝试使用感谢你的回答,但是最终我的解决方案是使用
if(matcher.Success&&matcher.Index==0)
@CrazyRedd-Yep,这更符合标记器。我明白您为什么要使用正则表达式(有些有
\s+
),但它并不是真的必要,因为它可能会被丢弃。我将给出一些简单的建议。如果我有你的完整代码,我会帮你试试。“但是,你最好这样做。”CrazyRedd-建议:我不是一个真正的C#程序员,所以有些可能会被取消。首先,向TokenData类添加一个新成员。这将在构造函数中创建
tokRX=new Regex(“\\G”+\”传入Regex字符串,RegexOptions.IgnoreCase)其中
getPattern()
函数返回对它的引用。因此,
foreach(TokenData中的TokenData-TokenData)
的主体变成:Match matcher=TokenData.getPattern().Match(str,offset);if(matcher.Success){offset+=matcher.Length;if(offset>=str.Length)breakedEnd=true;处理标记}.@CrazyRedd-这样做可以消除每次重写
str
的需要(即剥离标记)。并且,通过使用
\G
锚定,将仅在
偏移量
位置进行匹配,从而消除对字符串末尾的重复匹配(以及对索引==0的检查)。这更符合基于字符的标记器的工作方式。希望这有帮助。另外,正则表达式只编译一次,在构建时只需要使用一次try/catch。
public void init()
        {
            string[] keys = { "if", "else", "namespace", "class", "function" };
            foreach (string key in keys)
            {
                tokenDatas.Add(new TokenData(key + "\\s", TokenType.KEYWORD));
            }
            string[] types = { "int", "byte", "char", "string", "bool", "const" };
            foreach (string type in types)
            {
                tokenDatas.Add(new TokenData(type + "\\s", TokenType.BUILT_IN_TYPE));
            }
            tokenDatas.Add(new TokenData("(-)?[0-9]+", TokenType.INT_LITERAL));
            tokenDatas.Add(new TokenData("\"*\"", TokenType.STR_LITERAL));
            tokenDatas.Add(new TokenData("[a-zA-Z][a-zA-Z0-9]*\\s", TokenType.IDENTIFIER));
            string[] syms = { "\\.", "\\,", "\\;", "\\(", "\\)", "\\[", "\\]", "\\{", "\\}" };
            foreach (string sym in syms)
            {
                tokenDatas.Add(new TokenData(sym, TokenType.SYMBOL));
            }
            string[] ops = { "\\+", "\\-", "\\*", "/", "%", "=", "\\+=", "-=", "\\*=", "/=", "%=" };
            foreach (string op in ops)
            {
                tokenDatas.Add(new TokenData(op, TokenType.OPERATOR));
            }
            string[] coms = { "<", ">", "<=", ">=", "==", "!=" };
            foreach (string com in coms)
            {
                tokenDatas.Add(new TokenData(com, TokenType.COMPARATOR));
            }
        }
foreach(TokenData tokenData in tokenDatas)
{
   Match matcher = Regex.Match(str, tokenData.getPattern(), RegexOptions.IgnoreCase);
   if (matcher.Success)
       ...
}