1

私は正規表現に比較的慣れていないため、これが私の問題を解決する方法であるかどうかはまだわかりませんが、ここに行きます.

次のような内容を含む可能性のあるテキスト ファイルがあります。

program A {
   int x = 10;
   tuple date {
            int day;
            int month;
            int year;
   }
}

function B {
    int y = 20;
    ...
}

process C {
    more code;
}

プログラム、関数、またはプロセスの間にあるテキストを抽出する必要があります。したがって、ヘッダーは 3 種類しかありません。

そこで、正規表現を使用して中括弧内のテキストを取得することにしました。私が始めた方法は、識別子のリストを事前に知っていると仮定して、次の式を使用することです。

(program|function|process)+ A[\s\S]*(?=function)

これは、プログラム A の任意のテキストをキャプチャするのに最適です。ただし、プログラム A の後に関数が続かない場合があります。その後に、プロセスまたは別のプログラムが続く場合があります。最後のグループに OR を追加すると、正しく機能しなくなります。

(program|function|process)+ A[\s\S]*(?=function|process|program)

私がそれを見る方法は、3つのオプションによるものです。

  1. 正規表現を使用しますが、上記は実行可能ですか?
  2. 中かっこを追跡するためですが、入力に中かっこがない場合はどうなりますか。一致するブラケットが別のコード セットで見つかった場合、エラーをスローするのは難しい場合があります。
  3. 文脈自由文法を使用していますが、このオプションは最後に残しています。

前もって感謝します!

PS: RegExpr を支援するためにこれを使用しました: http://gskinner.com/RegExr/?33i30

4

3 に答える 3

4

これには、正規表現の代わりにLLパーサーの使用を検討する必要があります。正規表現は、すべての構文解析のニーズに対する適切な答えではなく、正規言語に対してのみです。文脈自由文法がある場合は、LLパーサーを使用してください。

https://en.wikipedia.org/wiki/LL_parser

于 2013-01-27T00:21:58.357 に答える
1

正規表現ソリューションを好む場合は、これを試してください:

/(program|function|process).*?{(.*?)}\n+(program|function|process)/m

ここでテストすることをお勧めします。

ただし、正規表現ソリューションは問題に対して堅牢ではありません。使用する前に、いくつかの仮定を行う必要があります。たとえば、コードは適切にフォーマットされている必要があります。回避策を提供する必要がある場合に備えて、試してみてください。

更新: テスト済みの Java コードは次のとおりです。

public class Test {
    public static void main(String[] args) throws IOException {
        String input = FileUtils.readFileToString(new File("input.txt"));
        Pattern p = Pattern.compile("(?<=program|function|process)[^{]*\\{(.*?)\\}\\s*(?=program|function|process|$)", Pattern.DOTALL);
        Matcher m = p.matcher(input);
        while(m.find()) {
            System.out.println(m.group(1));
        }
    }
}
于 2013-01-27T00:43:15.617 に答える
1

本当に文法を使いたくない場合は、ファイルを 1 行ずつ分析できる単純なパーサーを実装します。

私の例を見てください:

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.regex.Pattern;

import org.apache.commons.io.IOUtils;

public class SourceCodeProgram {

    public static void main(String[] args) throws Exception {
        File source = new File("C:\\test.txt");
        SourceCodeScanner scanner = new SourceCodeScanner(source);
        for (Code code : scanner.readAll()) {
            System.out.println(code);
            System.out.println("-----------");
        }
    }
}

class SourceCodeScanner {

    private File source;

    private Pattern startCodePattern = Pattern.compile(
            "^(\\s)*(program|function|process)", Pattern.CASE_INSENSITIVE);

    public SourceCodeScanner(File source) {
        this.source = source;
    }

    public Collection<Code> readAll() throws Exception {
        List<String> lines = readFileLineByLine();
        List<Code> codes = new ArrayList<Code>();
        StringBuilder builder = new StringBuilder(512);

        for (String line : lines) {
            if (containsSourceCodeHeader(line)) {
                int length = builder.length();
                if (length != 0) {
                    codes.add(new Code(builder.toString().trim()));
                    builder.delete(0, length);
                }
            }
            addNextLineOfSourceCode(builder, line);
        }
        String lastCode = builder.toString();
        if (containsSourceCodeHeader(lastCode)) {
            codes.add(new Code(builder.toString().trim()));
        }
        return codes;
    }

    private boolean containsSourceCodeHeader(String line) {
        return startCodePattern.matcher(line).find();
    }

    private void addNextLineOfSourceCode(StringBuilder builder, String line) {
        builder.append(line);
        builder.append(IOUtils.LINE_SEPARATOR);
    }

    private List<String> readFileLineByLine() throws Exception {
        FileInputStream fileInputStream = new FileInputStream(source);
        return IOUtils.readLines(new BufferedInputStream(fileInputStream));
    }
}

class Code {
    private String value;

    public Code(String value) {
        this.value = value;
    }

    public String getValue() {
        return value;
    }

    @Override
    public String toString() {
        return value;
    }
}
于 2013-01-27T00:47:55.570 に答える