このプログラムは16bit RISC である SN/X の演習のために 作成した。
言語仕様とYACC/LEXファイルは

ePaper Press
Thomas Niemann, "A Compact Guide To Lex & Yacc" に基づき 演習用に拡張している。コンパイラ演習を目的としていない のでコンパイラとしての機能は最低限に抑えている。 アセンブラと 併せて利用されると便利である。

同テキストの例題はスタックマシン向けになっていたことと
SN/Xには無い命令が多いことからコードジェネレータ部分を
大幅に書換えた。また、関数、メモリ、入出力などを拡張した。

アーカイブにはコンパイラ(snxc)とインタプリタ(snxi)が生成
できるように両ファイルを入れている。アーカイブを展開し、

make all

とするとコンパイラとインタプリタを生成する。
コンパイラとインタプリタは標準入力から文を
読み込み対応するSN/Xアセンブリ言語もしくは
実行結果を出力する。

ソース言語はC言語風の記述を行なう。ただし、変数は"a"から"z"の26変数で
扱う数値はすべて整数型である。また、メモリmem[]と入出力ポートio[]を
扱うことができるように拡張した。
また、メモリの1番地から26番地は"a"から"z"までの変数と
重なるので、mem[x]を用いて変数をアクセスすることもできる。
例えば、mem[1]は変数aと同じメモリアドレスを指す。

演習専用のため、関数定義は関数名foo、引数名argのみ
許される。関数の型はvoidかintであり、引数は1または0個を指定する。
局所変数は用意していない。

print文はインタプリタはコンソールに出力するが
コンパイラではmem[0]に値を書き出すだけである。

実行例1:
$ ./snxc
mem[20]=a-c;
        lda     $3,     50($0)
        lda     $1,     20($0)
        ld      $2,     1($0)
        lda     $3,     -1($3)
        st      $1,     0($3)
        ld      $1,     3($0)
        not     $1,     $1
        lda     $1,     1($1)
        add     $2,     $2,     $1
        ld      $1,     0($3)
        lda     $3,     1($3)
        st      $2,     0($1)

実行例2:

$ cat tt.c
a=10;
while (a > 0) {
a = a - 1;
}

$ snxc < tt.c
        lda     $3,     50($0)
        lda     $1,     10($0)
        st      $1,     1($0)
L000:
        ld      $1,     1($0)
        slt     $1,     $2,     $1
        bz      $1,     L001
        ld      $1,     1($0)
        lda     $2,     1($0)
        not     $2,     $2
        lda     $2,     1($2)
        add     $1,     $1,     $2
        st      $1,     1($0)
        bal     $0,     L000
L001:

実行例3:
$ ./snxc
int foo(arg) {
if(arg<1) return(0);                
return(foo(arg-1));
}
foo:
        lda     $3,     -2($3)
        st      $2,     0($3)
        st      $1,     1($3)
        ld      $1,     1($3)
        lda     $2,     1($0)
        slt     $1,     $1,     $2
        bz      $1,     L000
        lda     $1,     0($0)
        bal     $0,     fooexit
L000:
        ld      $1,     1($3)
        lda     $2,     1($0)
        not     $2,     $2
        lda     $2,     1($2)
        add     $1,     $1,     $2
        bal     $2,     foo
        bal     $0,     fooexit
fooexit:
        ld      $2,     0($3)
        lda     $3,     2($3)
        bal     $0,     0($2)

言語仕様 予約語: while, if, else, print, mem, io, int, void, arg, foo 演算子: +, -, *, /, <, >, >=, <=, == 文法: program: function ; function: function stmt | /* NULL */ ; stmt: ; | expr ; | DEF foo ( arg ) stmt | DEF foo ( ) stmt | print expr ; | io [ expr ] = expr ; | mem [ expr ] = expr ; | VARIABLE = expr ; | while ( expr ) stmt | return ( expr ) ; | return ; | if ( expr ) stmt | if ( expr ) stmt else stmt | { stmt_list } ; stmt_list: stmt | stmt_list stmt ; expr: INTEGER | VARIABLE | - expr | io [ expr ] | mem [ expr ] | foo ( expr ) | expr + expr | expr - expr | expr * expr | expr / expr | expr < expr | expr > expr | expr >= expr | expr <= expr | expr != expr | expr == expr | ( expr ) ; ただし、*,/の演算子はmul,divというSN/Xにない演算命令を 生成するので利用は注意を要する。