Nama yang benar untuk parser keturunan rekursif yang menggunakan loop untuk menangani rekursi kiri?


8

Tata bahasa ini dibiarkan rekursif:

Expression  ::= AdditionExpression

AdditionExpression  ::=
    MultiplicationExpression
        | AdditionExpression '+' MultiplicationExpression
        | AdditionExpression '-' MultiplicationExpression

MultiplicationExpression    ::=
    Term
        | MultiplicationExpression '*' Term
        | MultiplicationExpression '/' Term

Term    ::=
    Number
        | '(' AdditionExpression ')'

Number  ::=
    [+-]?[0-9]+(\.[0-9]+)?

Jadi secara teori, keturunan rekursif tidak akan berhasil. Tetapi dengan mengeksploitasi sifat-sifat tata bahasa yang sesuai dengan masing-masing aturan rekursif-kiri sesuai dengan tingkat presedensi tertentu, dan bahwa melihat-lihat token tunggal sudah cukup untuk memilih produksi yang benar, aturan rekursif kiri dapat secara individual diuraikan dengan sementara loop.

Misalnya, untuk mem-parsing AdditionExpression non-terminal, pseudocode ini mencukupi:

function parse_addition_expression() {
    num = parse_multiplication_expression()
    while (has_token()) {
        get_token()
        if (current_token == PLUS)
            num += parse_multiplication_expression()
        else if (current_token == MINUS)
            num -= parse_multiplication_expression()
        else {
            unget_token()
            return num
        }
    }
    return num
}

Apa nama yang tepat untuk tipe parser ini? Artikel informatif ini hanya menyebutnya sebagai "Solusi Klasik": https://www.engr.mun.ca/~theo/Misc/exp_parsing.htm

Harus ada nama yang tepat untuk jenis parser ini.


Bagi saya itu bukan semacam parser, itu hanya aplikasi penghapusan rekursi kiri dikombinasikan dengan parser keturunan rekursif. Lihat pertanyaan ini untuk teknik menghilangkan rekursi kiri.
Pemrogram

Saya pikir Anda mungkin benar. Itu menyerupai setara run-time dari algoritma penghapusan rekursi kiri.
user71015

1
Tolong jangan gunakan kotak 'jawab' untuk mengirim komentar atau komentar lain. Jika Anda membuat akun , Anda akan mempertahankan akses dan dapat menerima jawaban yang paling membantu Anda. Jika Anda memasukkan email dan kehilangan akses, Anda dapat memulihkan akses . Jika Anda tidak memasukkan alamat email dan tidak memiliki akses ke browser / cookie yang Anda gunakan untuk mengirim pertanyaan, Anda mungkin kurang beruntung. Tidak ada orang lain yang dapat menerima jawaban untuk Anda - bahkan moderator sekalipun.
DW

Jawaban:


11

Ini hanya pengurai LL (1) yang diimplementasikan dengan turunan rekursif.

Dimulai dengan:

AdditionExpression  ::=
    MultiplicationExpression
        | AdditionExpression '+' MultiplicationExpression
        | AdditionExpression '-' MultiplicationExpression

menerapkan penghapusan rekursi kiri untuk mendapatkan tata bahasa LL (1):

AdditionExpression  ::= 
    MultiplicationExpression AdditionExpressionTail

AdditionExpressionTail ::=
        | '+' MultiplicationExpression AdditionExpressionTail
        | '-' MultiplicationExpression AdditionExpressionTail

tulis fungsi yang sesuai:

function parse_AdditionExpression() {
    parse_MultiplicationExpression()
    parse_AdditionExpressionTail()
}

function parse_AdditionExpressionTail() {
    if (has_token()) {
        get_token()
        if (current_token == PLUS) {
            parse_MultiplicationExpression()
            parse_AdditionExpressionTail()
        } else if (current_token == MINUS) {
            parse_MultiplicationExpression()
            parse_AdditionExpressionTail()
        } else {
            unget_token()
        }
    }
}

hapus rekursi ekor:

function parse_AdditionExpressionTail() {
    while (has_token()) {
        get_token()
        if (current_token == PLUS)
            parse_MultiplicationExpression()
        else if (current_token == MINUS)
            parse_MultiplicationExpression()
        else {
            unget_token()
            return
        }
    }
}

Di barisan:

function parse_AdditionExpression() {
    parse_MultiplicationExpression()
    while (has_token()) {
        get_token()
        if (current_token == PLUS)
            parse_MultiplicationExpression()
        else if (current_token == MINUS)
            parse_MultiplicationExpression()
        else {
            unget_token()
            return
        }
    }
}

dan Anda baru saja menambahkan pemrosesan semantik untuk mendapatkan fungsi Anda.


6

Anda ingin melihat penguraian LL ( )k . Artikel Wikipedia sebagian besar tidak berguna, tetapi pada dasarnya adalah turunan rekursif dengan simbol lookahead.k

Ada juga LL ( ) yang memungkinkan lookahead tanpa batas.

Lihat di sini untuk ikhtisar yang komprehensif tentang seberapa kuat kelas parser ini.


1
Saya tidak melihat bagaimana ini terkait. Kode tidak menggunakan lebih dari satu simbol pandangan ke depan.
Pemrogram

@AProgrammer Jadi ini adalah parser LL (1), atau sangat terkait erat.
Raphael

Ini adalah parser LL (1). Saya memperluas komentar saya menjadi jawaban.
Pemrogram

2
@AProgrammer Saya tidak melihat bagaimana jawaban kedua diperlukan. LL (1) adalah LL (k) untuk k = 1 (tidakkah itu jelas?). Tapi baiklah.
Raphael
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.