2

我正在用 PHP 构建一个基本的词法分析器,就像一个练习一样。现在我正在使它成为 lex PHP 源代码并通过 HTML 标记输出突出显示的源代码,但我使用的是真正的令牌名称和东西,而不仅仅是一些广泛的正则表达式匹配。

我设置它的方式是逐个字符地读取 PHP 源代码。它检查当前字符以确定当前标记可能是什么,然后读入与适当模式匹配的下一个x字符。

例如,如果当前字符是“,我将读入所有字符,直到遇到另一个前面没有转义 \ 的“。这是一种不好的做法吗?我见过并理解的唯一另一种方法是制作一个编译大量正则表达式并同时匹配所有标记的类,但这对我来说似乎并不灵活。

想法?

    $str = '';

    $php = str_replace( "\r\n", "\n", $php );
    $php = str_split( $php );
    $len = count( $php );
    $keyword = '';

    for ( $i = 0; $i < $len; $i++ ) {
        $char = $php[$i];

        // Detect PHP strings and backtick execution operators
        if ( strpos( self::STRING_CHARACTERS, $char ) !== FALSE ) {
            $string         = $char;
            $opening_quote  = $char;
            $escaped        = FALSE;

            while ( isset( $php[++$i] ) && ( $escaped || $php[$i] != $opening_quote ) ) {
                $string .= $php[$i];

                if ( $php[$i] == '\\' ) {
                    $escaped = !$escaped;
                }
            }

            $string .= $php[$i];

            if ( $opening_quote == "'" ) {
                $str .= '<span class="php-string php-single-quoted-string">' . htmlspecialchars( $string ) . '</span>';
            } else if ( $opening_quote == '"' ) {
                $str .= '<span class="php-string php-double-quoted-string">' . htmlspecialchars( $string ) . '</span>';
            } else if ( $opening_quote == '`' ) {
                $str .= '<span class="php-execution-operator php-backtick">' . htmlspecialchars( $string ) . '</span>';
            }
            continue;
        }

        $str .= $char;
    }
4

2 回答 2

2

如果您打算将其保留为手写工具,那么一定要继续使用当前的方法。

如果您正在编写诸如flexANTLR 之类的工具,并且您希望能够整天为各种语言构建高效的解析器,那么巨型匹配引擎方法非常棒。但是,如果您只对解析一种语言感兴趣,则需要付出相当多的额外努力。

于 2012-06-01T23:48:05.330 回答
1

A typical handwritten approach would be to create a list of regex or automata. You run down the list and the first element that successfully matches from your current possition in the input, gives you the next token and classification. You can speed it up a little by using a map that limits the list by the current character.

If you want to get fancier, you can combine automata into one giant one, but typically a tool is used for that.

You might be interested in the free Stanford compiler course offered by https://class.coursera.org/.

于 2012-06-01T23:57:08.280 回答