Saya menulis SLIC (Sistem Bahasa untuk Menerapkan Kompiler) dengan sendirinya. Lalu tangan mengompilasinya menjadi perakitan. Ada banyak hal untuk SLIC karena itu adalah kompiler tunggal dari lima sub-bahasa:
- SYNTAX Parser Programming Language PPL
- GENERATOR LISP 2 berdasarkan bahasa pembuatan kode merangkak pohon PSEUDO
- ISO In Sequence, PSEUDO code, Bahasa optimisasi
- PSEUDO Macro menyukai bahasa penghasil kode Majelis.
- MACHOP Bahasa assembly instruksi mesin yang mendefinisikan bahasa.
SLIC terinspirasi oleh CWIC (Compiler for Writing and Implementing Compiler). Tidak seperti kebanyakan paket pengembangan kompiler, SLIC dan CWIC membahas pembuatan kode dengan spesialisasi, khusus domain, bahasa. SLIC memperluas pembuatan kode CWIC dengan menambahkan sub-bahasa ISO, PSEUDO dan MACHOP yang memisahkan spesifik mesin target dari bahasa generator yang merangkak pohon.
LISP 2 pohon dan daftar
Sistem manajemen memori dinamis berbasis bahasa LISP 2 adalah komponen utama. Daftar diekspresikan dalam bahasa yang dicantumkan dalam tanda kurung siku, komponennya dipisahkan dengan koma, yaitu daftar tiga elemen [a, b, c].
Pohon:
ADD
/ \
MPY 3
/ \
5 x
diwakili oleh daftar yang entri pertamanya adalah objek simpul:
[ADD,[MPY,5,x],3]
Pohon biasanya ditampilkan dengan simpul terpisah sebelum cabang:
ADD[MPY[5,x],3]
Mengakhiri fungsi generator berbasis LISP 2
Fungsi generator adalah himpunan bernama (unparse) => action> pair ...
<NAME>(<unparse>)=><action>;
(<unparse>)=><action>;
...
(<unparse>)=><action>;
Unparse expressions adalah tes yang cocok dengan pola pohon dan / atau tipe objek yang memecahnya dan menugaskan bagian-bagian tersebut ke variabel lokal untuk diproses oleh tindakan proseduralnya. Jenis seperti fungsi kelebihan beban mengambil berbagai jenis argumen. Kecuali tes () => ... dicoba dalam urutan kode. Berhasil pertama yang tidak sukses menjalankan tindakan terkait. Ekspresi yang tidak umum adalah tes pembongkaran. ADD [x, y] cocok dengan dua pohon ADD tree yang menugaskan cabang-cabangnya ke variabel lokal x dan y. Tindakannya mungkin berupa ekspresi sederhana atau .BEGIN ... .END blok kode terikat. Saya akan menggunakan c style {...} blok hari ini. Pencocokan hierarki, [], aturan tidak umum dapat memanggil generator yang meneruskan hasil yang dikembalikan ke tindakan:
expr_gen(ADD[expr_gen(x),expr_gen(y)])=> x+y;
Khususnya expr_gen di atas tidak cocok dengan pohon ADD dua cabang. Di dalam pola tes generator argumen tunggal ditempatkan di cabang pohon akan dipanggil dengan cabang itu. Daftar argumennya adalah variabel lokal yang ditugaskan objek yang dikembalikan. Di atas unparse menentukan dua cabang adalah ADD tree disassembly, rekursif menekan setiap cabang untuk expr_gen. Cabang kiri kembali ke variabel lokal x. Demikian juga cabang kanan diteruskan ke expr_gen dengan y objek kembali. Di atas bisa menjadi bagian dari pengevaluasi ekspresi numerik. Ada fitur pintasan yang disebut vektor berada di atas alih-alih simpul simpul, vektor simpul dapat digunakan dengan vektor tindakan yang sesuai:
expr_gen(#node[expr_gen(x),expr_gen(y)])=> #action;
node: ADD, SUB, MPY, DIV;
action: x+y, x-y, x*y, x/y;
(NUMBER(x))=> x;
(SYMBOL(x))=> val:(x);
Pengevaluasi ekspresi yang lebih lengkap di atas memberikan pengembalian dari cabang kiri expr_gen ke x dan cabang kanan ke y. Vektor aksi yang sesuai dilakukan pada x dan y yang dikembalikan. Pasangan undarse => aksi terakhir cocok dengan objek numerik dan simbol.
Simbol dan atribut simbol
Simbol mungkin memiliki nama atribut. val: (x) mengakses atribut val dari objek simbol yang terkandung dalam x. Tumpukan tabel simbol umum adalah bagian dari SLIC. Tabel SYMBOL dapat didorong dan muncul memberikan simbol lokal untuk fungsi. Simbol yang baru dibuat di katalogkan di tabel simbol atas. Pencarian simbol mencari tumpukan tabel simbol dari tabel paling atas terlebih dahulu ke belakang tumpukan.
Menghasilkan kode independen mesin
Bahasa generator SLIC menghasilkan objek instruksi PSEUDO, menambahkannya ke daftar kode bagian. FLUSH menyebabkan daftar kode PSEUDO dijalankan menghapus setiap instruksi PSEUDO dari daftar dan memanggilnya. Setelah eksekusi, memori objek PSEUDO dilepaskan. Badan prosedural tindakan PSEUDO dan GENERATOR pada dasarnya bahasa yang sama kecuali untuk output mereka. PSEUDO dimaksudkan untuk bertindak sebagai makro perakitan yang menyediakan sequentialization kode bebas mesin. Mereka menyediakan pemisahan mesin target spesifik dari bahasa generator merangkak pohon. PSEUDO memanggil fungsi MACHOP untuk mengeluarkan kode mesin. MACHOP digunakan untuk mendefinisikan pseudo ops perakitan (seperti dc, define constant, dll) dan instruksi mesin atau keluarga instruksi formated seperti menggunakan entri vektor. Mereka hanya mengubah parameter mereka menjadi urutan bidang bit yang membentuk instruksi. Panggilan MACHOP dimaksudkan agar terlihat seperti perakitan dan menyediakan format cetak bidang ketika perakitan ditampilkan dalam daftar kompilasi. Dalam kode contoh saya menggunakan komentar gaya c yang dapat dengan mudah ditambahkan tetapi tidak dalam bahasa aslinya. MACHOP memproduksi kode menjadi memori yang dapat dialamatkan. Linker SLIC menangani output dari kompiler. MACHOP untuk instruksi mode pengguna DEC-10 menggunakan entri vektor: MACHOP memproduksi kode menjadi memori yang dapat dialamatkan. Linker SLIC menangani output dari kompiler. MACHOP untuk instruksi mode pengguna DEC-10 menggunakan entri vektor: MACHOP memproduksi kode menjadi memori yang dapat dialamatkan. Linker SLIC menangani output dari kompiler. MACHOP untuk instruksi mode pengguna DEC-10 menggunakan entri vektor:
.MACHOP #opnm register,@indirect offset (index): // Instruction's parameters.
.MORG 36, O(18): $/36; // Align to 36 bit boundary print format: 18 bit octal $/36
O(9): #opcd; // Op code 9 bit octal print out
(4): register; // 4 bit register field appended print
(1): indirect; // 1 bit appended print
(4): index; // 4 bit index register appended print
O(18): if (#opcd&&3==1) offset // immediate mode use value else
else offset/36; // memory address divide by 36
// to get word address.
// Vectored entry opcode table:
#opnm := MOVE, MOVEI, MOVEM, MOVES, MOVS, MOVSI, MOVSM, MOVSS,
MOVN, MOVNI, MOVNM, MOVNS, MOVM, MOVMI, MOVMM, MOVMS,
IMUL, IMULI, IMULM, IMULB, MUL, MULI, MULM, MULB,
...
TDO, TSO, TDOE, TSOE, TDOA, TSOA, TDON, TSON;
// corresponding opcode value:
#opcd := 0O200, 0O201, 0O202, 0O203, 0O204, 0O205, 0O206, 0O207,
0O210, 0O211, 0O212, 0O213, 0O214, 0O215, 0O216, 0O217,
0O220, 0O221, 0O222, 0O223, 0O224, 0O225, 0O226, 0O227,
...
0O670, 0O671, 0O672, 0O673, 0O674, 0O675, 0O676, 0O677;
The .MORG 36, O (18): $ / 36; menyelaraskan lokasi ke batas 36 bit mencetak lokasi $ / 36 kata alamat 18 bit di oktal. 9 bit opcd, register 4 bit, bit tidak langsung dan register indeks 4 bit digabungkan dan dicetak seolah-olah bidang 18 bit tunggal. Alamat 18 bit / 36 atau nilai langsung adalah output dan dicetak dalam oktal. Contoh MOVEI dicetak dengan r1 = 1 dan r2 = 2:
400020 201082 000005 MOVEI r1,5(r2)
Dengan opsi perakitan kompiler, Anda mendapatkan kode perakitan yang dihasilkan dalam daftar kompilasi.
Tautkan bersama
SLIC linker disediakan sebagai perpustakaan yang menangani resolusi tautan dan simbol. Format pemuatan file keluaran spesifik target harus ditulis untuk mesin target dan ditautkan dengan perpustakaan pustaka linker.
Bahasa generator mampu menulis pohon ke file dan membacanya memungkinkan kompiler multipass untuk diimplementasikan.
Musim panas singkat pembuatan dan asal-usul kode
Saya telah membahas pembuatan kode terlebih dahulu untuk memastikan bahwa dipahami bahwa SLIC adalah kompiler yang benar. SLIC terinspirasi oleh CWIC (Compiler for Writing and Implementing Compiler) yang dikembangkan di Systems Development Corporation pada akhir 1960-an. CWIC hanya memiliki bahasa SYNTAX dan GENERATOR yang menghasilkan kode byte numerik dari bahasa GENERATOR. Kode byte ditempatkan atau ditanam (istilah yang digunakan dalam dokumentasi CWICs) ke buffer memori yang terkait dengan bagian yang disebutkan dan ditulis oleh pernyataan .FLUSH. Makalah ACM tentang CWIC tersedia dari arsip ACM.
Berhasil menerapkan bahasa pemrograman utama
Pada akhir 1970-an SLIC digunakan untuk menulis kompiler silang COBOL. Selesai dalam waktu sekitar 3 bulan kebanyakan oleh seorang programmer tunggal. Saya bekerja sedikit dengan programmer sesuai kebutuhan. Programer lain menulis perpustakaan runtime dan MACHOP untuk target TI-990 mini-COMPUTER. Kompiler COBOL yang dikompilasi secara substansial lebih banyak baris per detik daripada kompiler COBOL asli DEC-10 yang ditulis dalam perakitan.
Lebih ke kompiler maka biasanya dibicarakan
Sebagian besar penulisan kompiler dari awal adalah run time library. Anda membutuhkan tabel simbol. Anda membutuhkan input dan output. Manajemen memori dinamis dll. Dengan mudah bisa lebih bekerja menulis perpustakaan runtime untuk kompiler kemudian menulis kompiler. Tetapi dengan SLIC bahwa runtime library adalah umum untuk semua kompiler yang dikembangkan di SLIC. Perhatikan ada dua pustaka runtime. Satu untuk mesin target bahasa (COBOL misalnya). Yang lain adalah kompiler runtime perpustakaan kompiler.
Saya pikir saya telah menetapkan bahwa ini bukan generator parser. Jadi sekarang dengan sedikit pemahaman tentang ujung belakang saya bisa menjelaskan bahasa pemrograman parser.
Bahasa pemrograman Parser
Parser ditulis menggunakan rumus yang ditulis dalam bentuk persamaan sederhana.
<name> <formula type operator> <expression> ;
Elemen bahasa di tingkat terendah adalah karakter. Token dibentuk dari himpunan bagian dari karakter bahasa. Kelas karakter digunakan untuk memberi nama dan mendefinisikan subset karakter tersebut. Operator pendefinisian kelas karakter adalah karakter titik dua (:). Karakter yang merupakan anggota kelas dikodekan pada sisi kanan definisi. Karakter yang dapat dicetak tertutup dalam string primes single '. Karakter yang tidak tercetak dan khusus dapat diwakili oleh urutan numeriknya. Anggota kelas dipisahkan oleh suatu alternatif | operator. Rumus kelas berakhir dengan titik koma. Kelas karakter dapat mencakup kelas yang sebelumnya didefinisikan:
/* Character Class Formula class_mask */
bin: '0'|'1'; // 0b00000010
oct: bin|'2'|'3'|'4'|'5'|'6'|'7'; // 0b00000110
dgt: oct|'8'|'9'; // 0b00001110
hex: dgt|'A'|'B'|'C'|'D'|'E'|'F'|'a'|'b'|'c'|'d'|'e'|'f'; // 0b00011110
upr: 'A'|'B'|'C'|'D'|'E'|'F'|'G'|'H'|'I'|'J'|'K'|'L'|'M'|
'N'|'O'|'P'|'Q'|'R'|'S'|'T'|'U'|'V'|'W'|'X'|'Y'|'Z'; // 0b00100000
lwr: 'a'|'b'|'c'|'d'|'e'|'f'|'g'|'h'|'i'|'j'|'k'|'l'|'m'|
'n'|'o'|'p'|'q'|'r'|'s'|'t'|'u'|'v'|'w'|'x'|'y'|'z'; // 0b01000000
alpha: upr|lwr; // 0b01100000
alphanum: alpha|dgt; // 0b01101110
Skip_class 0b00000001 sudah ditentukan sebelumnya tetapi mungkin overroad akan mendefinisikan skip_class.
Singkatnya: Kelas karakter adalah daftar alternatif yang hanya bisa berupa konstanta karakter, ordinal karakter, atau kelas karakter yang didefinisikan sebelumnya. Ketika saya menerapkan kelas karakter: Rumus kelas diberikan topeng bit kelas. (Ditampilkan dalam komentar di atas) Rumus kelas apa pun yang memiliki karakter literal atau ordinal menyebabkan bit kelas dialokasikan. Topeng dibuat dengan oring masker kelas yang disertakan bersama dengan bit yang dialokasikan (jika ada). Tabel kelas dibuat dari kelas karakter. Entri yang diindeks oleh ordinal karakter berisi bit yang menunjukkan keanggotaan kelas karakter. Pengujian kelas dilakukan inline. Contoh kode IA-86 dengan ordinal karakter dalam eax menggambarkan pengujian kelas:
test byte ptr [eax+_classmap],dgt
Diikuti oleh:
jne <success>
atau
je <failure>
Contoh kode instruksi IA-86 digunakan karena saya pikir instruksi IA-86 lebih dikenal saat ini. Nama kelas yang mengevaluasi topeng kelasnya adalah AND-non-destruktif dengan tabel-kelas diindeks oleh karakter ordinal (dalam eax). Hasil yang tidak nol menunjukkan keanggotaan kelas. (EAX memusatkan perhatian kecuali untuk al (rendahnya 8 bit EAX) yang berisi karakter).
Token sedikit berbeda dalam kompiler lama ini. Kata-kata kunci tidak dijelaskan sebagai token. Mereka hanya cocok dengan konstanta string yang dikutip dalam bahasa parser. String yang dikutip biasanya tidak disimpan. Pengubah dapat digunakan. A + menjaga string tetap cocok. (yaitu + '-' cocok dengan - karakter yang menjaga karakter saat berhasil) Operasi, (yaitu, 'E') memasukkan string ke dalam token. Ruang putih ditangani oleh rumus token yang melewatkan karakter SKIP_CLASS terkemuka hingga kecocokan pertama dibuat. Perhatikan bahwa kecocokan karakter skip_class secara eksplisit akan menghentikan lompatan yang memungkinkan token untuk memulai dengan karakter skip_class. Rumus token string melewatkan karakter skip_class terkemuka yang cocok dengan karakter quitedd kutipan tunggal atau string yang dikutip ganda. Yang menarik adalah pencocokan "karakter di dalam" string yang dikutip:
string .. (''' .ANY ''' | '"' $(-"""" .ANY | """""","""") '"') MAKSTR[];
Alternatif pertama cocok dengan karakter kutipan mana pun yang dikutip. Alternatif yang tepat cocok dengan string kutipan ganda yang dapat menyertakan karakter kutipan ganda menggunakan dua karakter "bersama-sama untuk mewakili karakter" tunggal. Rumus ini mendefinisikan string yang digunakan dalam definisi sendiri. Alternatif kanan bagian dalam '' '$ (- "" "" .ANY | "" "" "" "" "")' "'cocok dengan string kutipan ganda. Kita dapat menggunakan karakter yang dikutip tunggal untuk mencocokkan karakter kutipan ganda. Namun dalam string yang dikutip ganda jika kita ingin menggunakan karakter "kita harus menggunakan dua" karakter untuk mendapatkan satu. Misalnya dalam alternatif kiri yang cocok dengan karakter apa pun kecuali kutipan:
-"""" .ANY
intip negatif di depan - "" "" digunakan bahwa ketika berhasil (tidak cocok dengan "karakter") maka cocok dengan karakter .ANY (yang tidak bisa menjadi "karakter karena -" "" "menghilangkan kemungkinan itu). Alternatif yang tepat adalah mengambil - "" "" mencocokkan karakter "dan gagal adalah alternatif yang tepat:
"""""",""""
mencoba untuk mencocokkan dua "karakter yang menggantinya dengan satu ganda" menggunakan, "" "" untuk memasukkan thw tunggal "karakter. Kedua alternatif dalam gagal karakter kutipan string penutup cocok dan MAKSTR [] dipanggil untuk membuat objek string. $ urutan, loop saat berhasil, operator digunakan dalam mencocokkan urutan. Rumus token melewati karakter kelas skip utama (sedikit spasi). Setelah kecocokan pertama dibuat, skrip skip_class dinonaktifkan. Kita dapat memanggil fungsi yang diprogram dalam bahasa lain menggunakan []. MAKSTR [], MAKBIN [], MAKOCT [], MAKHEX [], MAKFLOAT [], dan MAKINT [] disediakan fungsi pustaka yang mengonversi string token yang cocok ke objek yang diketik. Rumus angka di bawah ini menggambarkan pengenalan token yang cukup kompleks:
number .. "0B" bin $bin MAKBIN[] // binary integer
|"0O" oct $oct MAKOCT[] // octal integer
|("0H"|"0X") hex $hex MAKHEX[] // hexadecimal integer
// look for decimal number determining if integer or floating point.
| ('+'|+'-'|--) // only - matters
dgt $dgt // integer part
( +'.' $dgt // fractional part?
((+'E'|'e','E') // exponent part
('+'|+'-'|--) // Only negative matters
dgt(dgt(dgt|--)|--)|--) // 1 2 or 3 digit exponent
MAKFLOAT[] ) // floating point
MAKINT[]; // decimal integer
Rumus token angka di atas mengenali angka integer dan floating point. - Alternatif selalu berhasil. Objek numerik dapat digunakan dalam perhitungan. Objek token didorong ke tumpukan parse pada keberhasilan formula. Prospek eksponen dalam (+ 'E' | 'e', 'E') menarik. Kami ingin selalu memiliki E huruf besar untuk MAKEFLOAT []. Tapi kami mengizinkan huruf kecil 'e' menggantikannya menggunakan, 'E'.
Anda mungkin telah memperhatikan konsistensi kelas karakter dan rumus token. Formula parsing berlanjut dengan menambahkan alternatif penelusuran mundur dan operator konstruksi pohon. Backtracking dan non-backtracking operator alternatif mungkin tidak tercampur dalam level ekspresi. Anda mungkin tidak memiliki (a | b \ c) mencampur non-mundur | dengan \ backtracking alternatif. (a \ b \ c), (a | b | c) dan ((a | b) \ c) valid. Alternatif \ backtracking menyimpan keadaan parse sebelum mencoba alternatif kirinya dan pada kegagalan mengembalikan keadaan parse sebelum mencoba alternatif yang tepat. Dalam urutan alternatif, alternatif pertama yang berhasil memuaskan kelompok. Alternatif lebih lanjut tidak dicoba. Anjak piutang dan pengelompokan menyediakan penguraian memajukan terus menerus. Alternatif mundur membuat keadaan parse yang disimpan sebelum mencoba alternatif kirinya. Diperlukan pengulangan saat parse membuat kecocokan sebagian dan kemudian gagal:
(a b | c d)\ e
Di atas jika kegagalan pengembalian cd alternatif dicoba. Jika kemudian c mengembalikan kegagalan, alternatif lacak mundur akan dicoba. Jika a berhasil dan b gagal maka parse akan di-backtrack dan dicoba. Demikian juga c gagal dan b gagal parse di-backtrack dan e alternatif diambil. Mundur tidak terbatas dalam formula. Jika ada rumus parsing yang membuat kecocokan parsial kapan saja dan kemudian gagal, parse di-reset ke backtrack atas dan alternatifnya diambil. Kegagalan kompilasi dapat terjadi jika kode telah keluar rasa backtrack telah dibuat. Pelacakan mundur diatur sebelum memulai kompilasi. Kembali gagal atau mundur ke sana adalah kegagalan kompilator. Backtracks ditumpuk. Kita dapat menggunakan negatif - dan positif? intip / lihat ke depan operator untuk menguji tanpa memajukan parse. sedang tes string adalah mengintip ke depan hanya membutuhkan negara input disimpan dan diatur ulang. Pandangan ke depan akan menjadi ekspresi parsing yang membuat kecocokan sebagian sebelum gagal. Pandangan ke depan diimplementasikan menggunakan backtracking.
Bahasa parser bukan parser LL atau LR. Tapi bahasa pemrograman untuk menulis parser yang layak rekursif di mana Anda memprogram konstruksi pohon:
:<node name> creates a node object and pushes it onto the node stack.
.. Token formula create token objects and push them onto
the parse stack.
!<number> pops the top node object and top <number> of parstack
entries into a list representation of the tree. The
tree then pushed onto the parse stack.
+[ ... ]+ creates a list of the parse stack entries created
between them:
'(' +[argument $(',' argument]+ ')'
could parse an argument list. into a list.
Contoh parsing yang umum digunakan adalah ekspresi aritmatika:
Exp = Term $(('+':ADD|'-':SUB) Term!2);
Term = Factor $(('*':MPY|'/':DIV) Factor!2);
Factor = ( number
| id ( '(' +[Exp $(',' Exp)]+ ')' :FUN!2
| --)
| '(' Exp ')" )
(^' Factor:XPO!2 |--);
Exp dan Term menggunakan loop membuat pohon kidal. Faktor yang menggunakan rekursi benar menciptakan pohon tangan kanan:
d^(x+5)^3-a+b*c => ADD[SUB[EXP[EXP[d,ADD[x,5]],3],a],MPY[b,c]]
ADD
/ \
SUB MPY
/ \ / \
EXP a b c
/ \
d EXP
/ \
ADD 3
/ \
x 5
Berikut adalah sedikit kompiler cc, versi terbaru SLIC dengan komentar gaya c. Jenis fungsi (tata bahasa, token, kelas karakter, generator, PSEUDO, atau MACHOP ditentukan oleh sintaks awal mereka mengikuti id mereka. Dengan pengurai top-down ini Anda mulai dengan rumus penentu program:
program = $((declaration // A program is a sequence of
// declarations terminated by
|.EOF .STOP) // End Of File finish & stop compile
\ // Backtrack: .EOF failed or
// declaration long-failed.
(ERRORX["?Error?"] // report unknown error
// flagging furthest parse point.
$(-';' (.ANY // find a ';'. skiping .ANY
| .STOP)) // character: .ANY fails on end of file
// so .STOP ends the compile.
// (-';') failing breaks loop.
';')); // Match ';' and continue
declaration = "#" directive // Compiler directive.
| comment // skips comment text
| global DECLAR[*1] // Global linkage
|(id // functions starting with an id:
( formula PARSER[*1] // Parsing formula
| sequencer GENERATOR[*1] // Code generator
| optimizer ISO[*1] // Optimizer
| pseudo_op PRODUCTION[*1] // Pseudo instruction
| emitor_op MACHOP[*1] // Machine instruction
) // All the above start with an identifier
\ (ERRORX["Syntax error."]
garbol); // skip over error.
// Perhatikan bagaimana id diperhitungkan dan nanti digabungkan saat membuat pohon.
formula = ("==" syntax :BCKTRAK // backtrack grammar formula
|'=' syntax :SYNTAX // grammar formula.
|':' chclass :CLASS // character class define
|".." token :TOKEN // token formula
)';' !2 // Combine node name with id
// parsed in calling declaration
// formula and tree produced
// by the called syntax, token
// or character class formula.
$(-(.NL |"/*") (.ANY|.STOP)); Comment ; to line separator?
chclass = +[ letter $('|' letter) ]+;// a simple list of character codes
// except
letter = char | number | id; // when including another class
syntax = seq ('|' alt1|'\' alt2 |--);
alt1 = seq:ALT!2 ('|' alt1|--); Non-backtrack alternative sequence.
alt2 = seq:BKTK!2 ('\' alt2|--); backtrack alternative sequence
seq = +[oper $oper]+;
oper = test | action | '(' syntax ')' | comment;
test = string | id ('[' (arg_list| ,NILL) ']':GENCALL!2|.EMPTY);
action = ':' id:NODE!1
| '!' number:MAKTREE!1
| "+[" seq "]+" :MAKLST!1;
// C style comments
comment = "//" $(-.NL .ANY)
| "/*" $(-"*/" .ANY) "*/";
Yang perlu diperhatikan adalah bagaimana bahasa parser menangani komentar dan pemulihan kesalahan.
Saya pikir saya telah menjawab pertanyaan itu. Setelah menulis sebagian besar penerus SLIC, bahasa cc itu sendiri di sini. Belum ada kompiler untuk itu. Tapi saya bisa mengompilasinya menjadi kode assembly, fungsi asm c atau c ++ telanjang.