2

演習として、PHP で基本的なレクサーを作成しています。現在、私はPHPソースをレックス化し、HTMLタグを介して強調表示されたソースを出力していますが、いくつかの広範な正規表現一致だけでなく、実際のトークン名などを使用しています。

私が設定している方法は、PHP ソースを 1 文字ずつ読み込むことです。現在の文字をチェックして、現在のトークン何であるかを判断し、適切なパターンに一致する次の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

手書きのツールを維持するつもりなら、間違いなく現在のアプローチを続けてください。

flexや ANTLR などのツールを作成していて、さまざまな言語に対して非常に効率的なパーサーを 1 日中構築できるようにしたい場合、巨大なマッチング エンジンのアプローチは素晴らしいものです。ただし、1 つの言語のみを解析することに関心がある場合は、かなりの労力がかかります。

于 2012-06-01T23:48:05.330 に答える
1

典型的な手書きのアプローチは、正規表現またはオートマトンのリストを作成することです。リストを実行すると、入力内の現在の位置から正常に一致した最初の要素が、次のトークンと分類を提供します。現在の文字でリストを制限するマップを使用すると、少し高速化できます。

より手の込んだものにしたい場合は、オートマトンを 1 つの巨大なものに組み合わせることができますが、通常はそのためにツールが使用されます。

https://class.coursera.org/が提供する無料のスタンフォード コンパイラ コースに興味があるかもしれません。

于 2012-06-01T23:57:08.280 に答える