JavaScript RegEx语法

时间:2011-05-11 17:40:14

标签: javascript regex parsing

我正在编写C#代码来将JavaScript解析为令牌,而我对JavaScript的了解不是100%。

有一件事让我觉得JavaScript正则表达式没有用引号括起来。那么解析器在开始和结束时如何检测?看起来它们以/开头,但之后几乎可以包含任何字符。

请注意,我并未询问匹配某些字符所需的语法,这是我的Google搜索的所有结果。我只想知道确定我如何知道正则表达式的起始位置和结束位置的规则。

5 个答案:

答案 0 :(得分:2)

我认为以下RegExp是合理的近似值。

/(\\/|[^/])+/([a-zA-Z])*

规则正式定义:

RegularExpressionLiteral ::  See 7.8.5 
    / RegularExpressionBody / RegularExpressionFlags 

RegularExpressionBody ::  See 7.8.5 
    RegularExpressionFirstChar RegularExpressionChars 

RegularExpressionChars ::  See 7.8.5 
    [empty] 
    RegularExpressionChars RegularExpressionChar 

RegularExpressionFirstChar ::  See 7.8.5 
    RegularExpressionNonTerminator but not one of * or \ or / or [ 
    RegularExpressionBackslashSequence 
    RegularExpressionClass 

RegularExpressionChar ::  See 7.8.5 
    RegularExpressionNonTerminator but not \ or / or [ 
    RegularExpressionBackslashSequence 
    RegularExpressionClass 

RegularExpressionBackslashSequence ::  See 7.8.5 
    \ RegularExpressionNonTerminator 

RegularExpressionNonTerminator ::  See 7.8.5 
    SourceCharacter but not LineTerminator 

RegularExpressionClass ::  See 7.8.5 
    [ RegularExpressionClassChars ] 

RegularExpressionClassChars ::   See 7.8.5 
    [empty] 
    RegularExpressionClassChars RegularExpressionClassChar 

RegularExpressionClassChar ::   See 7.8.5 
    RegularExpressionNonTerminator but not ] or \ 
    RegularExpressionBackslashSequence

RegularExpressionFlags ::  See 7.8.5 
    [empty] 
    RegularExpressionFlags IdentifierPart

Full Specification

以下是一些可以帮助您入门的快速而肮脏的代码。

class CharStream
{
    private readonly Stack<int> _states;
    private readonly string _input;
    private readonly int _length;
    private int _index;

    public char Current
    {
        get { return _input[_index]; }
    }

    public CharStream(string input)
    {
        _states = new Stack<int>();
        _input = input;
        _length = input.Length;
        _index = -1;
    }

    public bool Next()
    {
        if (_index < 0)
            _index++;
        if (_index == _length)
            return false;
        _index++;
        return true;
    }

    public bool ExpectNext(char c)
    {
        if (_index == _length)
            return false;
        if (_input[_index + 1] != c)
            return false;
        _index++;
        return true;
    }

    public bool Back()
    {
        if (_index == 0)
            return false;
        _index--;
        return true;
    }

    public void PushState()
    {
        _states.Push(_index);
    }

    public T PopState<T>()
    {
        _index = _states.Pop();
        return default(T);
    }
}

static string ParseRegularExpressionLiteral(CharStream cs)
{
    string body, flags;
    cs.PushState();
    if (!cs.ExpectNext('/'))
        return cs.PopState<string>();
    if ((body = ParseRegularExpressionBody(cs)) == null)
        return cs.PopState<string>();
    if (!cs.ExpectNext('/'))
        return cs.PopState<string>();
    if ((flags = ParseRegularExpressionFlags(cs)) == null)
        return cs.PopState<string>();
    return "/" + body + "/" + flags;
}

static string ParseRegularExpressionBody(CharStream cs)
{
    string firstChar, chars;
    cs.PushState();
    if ((firstChar = ParseRegularExpressionFirstChar(cs)) == null)
        return cs.PopState<string>();
    if ((chars = ParseRegularExpressionChars(cs)) == null)
        return cs.PopState<string>();
    return firstChar + chars;
}

static string ParseRegularExpressionChars(CharStream cs)
{
    var sb = new StringBuilder();
    string @char;
    while ((@char = ParseRegularExpressionChar(cs)) != null)
        sb.Append(@char);
    return sb.ToString();
}

static string ParseRegularExpressionFirstChar(CharStream cs)
{
    return null;
}

static string ParseRegularExpressionChar(CharStream cs)
{
    return null;
}

static string ParseRegularExpressionBackslashSequence(CharStream cs)
{
    return null;
}

static string ParseRegularExpressionNonTerminator(CharStream cs)
{
    return null;
}

static string ParseRegularExpressionClass(CharStream cs)
{
    return null;
}

static string ParseRegularExpressionClassChars(CharStream cs)
{
    return null;
}

static string ParseRegularExpressionClassChar(CharStream cs)
{
    return null;
}

static string ParseRegularExpressionFlags(CharStream cs)
{
    return null;
}

至于如何找到文字的结尾?诀窍是递归地遵循我列出的产品。考虑生产RegularExpressionBody。只需阅读作品即可告诉我它需要RegularExpressionFirstChar后跟RegularExpressionChars。请注意RegularExpressionChars[empty]RegularExpressionChars RegularExpressionChar的方式。基本上它是由它自己定义的。一旦该生产终止于[empty],您就知道唯一有效的字符应该是结束/。如果没有找到,则这不是有效的文字。

答案 1 :(得分:2)

  1. var test = new RegExp("\\d/\\d/\\d", "g");(旗帜是第二个参数)
  2. test = /\d\/\d\/\d/;
  3. test = /\d\/\d\/\d/g(标志位于最后/之后)
  4. 使用/转义第二个字符。解释:
    / - 开始RegExp
    \d - 数字字符
    \/ - 转义/(与实际的/字符匹配)
    \d - 数字字符
    \/ - 转义/(与实际的/字符匹配)
    \d - 数字字符
    / - RegExp结束

    这将匹配1/2/3

答案 2 :(得分:1)

Literal Javascript正则表达式可能如下所示:

/ myregularexpressionliteral /

/ yregularexpressionlitera / myregex flags

在此处查看更多内容:http://lawrence.ecorp.net/inet/samples/regexp-intro.php

答案 3 :(得分:1)

一个文字/被转义为\ /匹配字符,所以你不应该有任何困难找到结束/。之后是旗帜,其数量有限。

答案 4 :(得分:1)

我最终解决这个问题的方法是依靠之前的标记。

主要问题是区分正则表达式字面值和除法符号。我这样做的唯一方法是查看它出现的上下文。

因此,例如,如果前一个标记是一个数字,则正斜杠只能是一个除法运算符。

在某些情况下,这并非100%可靠。但就我的目的而言,它似乎是最好的解决方案。