2008-05-11

Test:Highlight Code

compiler出来たので、試しにHighlight Codeを使ってみるテスト。
→読み込みが遅すぎるのでSyntaxHifhlighterに変更

-----------------------------

/**** function declaration ****/
statement();

/**** files and options ****/
int f_source; /* source file */

/**** source program input ****/

enum{ UNPACK=4 };
/* WL assumes sizeof(int)=4; */
enum{ M_line=25, M_line_c=M_line*UNPACK };
int line[M_line], line_c[M_line_c], lcp, lcm;
/* a character string is packed into an int array with */
/* a terminator '\0'; it will be unpacked into another */
/* array one charater per element. */
/* line holds the current line in packed form; */
/* line_c holds the current line in unpacked form, */
/* whereas lcm shows the number of characters in it, */
/* and lcp points to the next character position. */
enum{ M_char=0x80 }; /* characters are in 7bit code */
enum{ EOFC=0x04 }; /* EOF state is coded to this value. */
int ch; /* the next character available */
int line_no; /* current line number */

init_char(){
f_source= stdin; /* <== This line will be removed. */
lcp= lcm= 0; line_no= 0;
}

/* 一文字取ってくる関数 */
get_char(){
if( lcp>=lcm ){
if( fgets(line, M_line, f_source)==NULL ){
line_c[0]= EOFC; lcm= 1;
}else{
lcm= unpack(line, line_c);
}
lcp= 0; line_no= line_no+1;
}
ch= line_c[lcp]%M_char; /* filter to 7bits */
if( ch!=EOFC ) lcp= lcp+1;
/* not to try input again for an EOF'ed file */
}


/**** output ****/

/* number */

/* output a positive number into a file */
/*positive(int number, int file){
if( number>=10 ) positive(number/10, file);
fputc(number%10+'0', file);
}*/

/* output a number in decimal onto a file */
/*decimal(int number, int file){
if( number<0 ){
number= -number; fputc('-', file);
if( number<0 ){ fputs("2147483648", file); return; }
}
positive(number, file);
}*/

/** number output **/
positive(int v, int file){ /*正の整数を表示する*/
if( v>=10 ) positive(v/10, file);
fputc(v%10+'0', file);
}
decimal(int v, int file){ /*整数を表示するための関数*/
if( v<0 ){
fputc('-', file);
positive(-v, file);
}else{
positive(+v, file);
}
}

/** system error(abortion) **/
system_error(int message[]){
decimal(line_no, stderr); fputs("::SYSTEM::", stderr);
fputs(message, stderr); fputc('\n', stderr);
exit(1);
}
/* error message output: to stderr */
/*system_error(int message[]){*/
/* output a message and abort the compilation */
/* decimal(line_no, stderr); fputs("::SYSTEM::", stderr);
fputs(message, stderr); fputc('\0', stderr);
exit(-1);
}*/

/**** token output ****/
/*enum{
Else, Enum, If, Int, Return, While,
Name, Const, Character, String,
Plus, Minus, Not, Amper,
Times, Divide, Remainder,
Les, Leq, Grat, Geq,
Equ, Neq,
And, Or,
Becomes,
Comma, Semicolon, Lpar, Rpar, Lbracket, Rbracket, Lbrace, Rbrace,
Nontoken, Endfile, Comment
};*/
enum{
Nontoken,
Times, Divide, Remainder,
Les, Leq, Grat, Geq,
Equ, Neq,
And, Or,
Becomes,
Lbracket,
Comma, Rpar, Rbracket,
Else, Rbrace, Semicolon,
If, Return, While, Lbrace,
Lpar, Plus, Minus, Not, Amper,
Const, Character, String,
Name, Int, Enum,
Endfile, Comment
};


int token; /* next token */
int value; /* integer value for token=Const,Character */
int spell; /* spelling for token=Name */
int word[M_line]; /* contents for token=String, Comment */

/**** Name identity ****/
enum{ id_p, next_p, spell_p }; /* spell_table's components */

enum{ M_spell_table=2000 }; /* size of spell_table */
int spell_table[M_spell_table], spell_index; /* for usual names */
/* any name is identified with a positon p in this table; */
/* spell_table[p+id_p]: open for clients(defaults to 0) */
/* spell_table[p+next_p]: link to similar spellings */
/* spell_table[p+spell_p] and upward: packed spelling */



/**** hashing ****/

/** Reserved Words **/
enum{ M_reserved=6 }; /* number of reserved words */
enum{ M_spell_r=11 }; /* size of reserved word spelling */
enum{ P_r= 2, M_r= 7 }; /* hash function parameters */
enum{ NIL=-1 };

int token_r[M_r]; /* token for each reserved word */
int spell_r[M_spell_r], srp; /* spell table for reserved words */
int spell_rp[M_r]; /* pointer to their spelling */


int h(int spell_c[], int length, int P, int M){ int i, v;
/* 第3、第4引数を元にハッシュ関数を実行する */
/* computes a hash function value for an unpacked spell */
/* with parameters P and M. */

v= 0; i= 0;
/* iが配列の長さと同じになるまで、
v=(v*第3引数+第1引数)&第4引数を実行し、
iをインクリメントする作業を繰り返す。
その後、vの値を返す。 */
while( i!=length ){
v= (v*P + spell_c[i])%M; i= i+1;
}
return v;
}


enter_reserved(int spell[], int token_value){
/* 予約語を設定する関数 */
/* helper function: 関数init_reservedで使われる */

int spell_c[M_line_c], scm; /* unpacked spell */
int r;

scm= unpack(spell, spell_c); /* spellの分解表現をspell_cに書き込む */
r= h(spell_c, scm, P_r, M_r); /* 各変数を元にハッシュにかける */
spell_rp[r]= srp; /* ハッシュ値の場所にsrpを格納する */
token_r[r]= token_value; /* ハッシュ値の場所にtoken_valueを格納する */

/* spell_cの分解表現をspell_r[srp]が指す番地に、scmの長さだけ書き込む */
srp= srp+pack(spell_c, scm, &spell_r[srp]);
}

init_reserved(){ int i;
/* 予約語の初期化 */
/* sets up tables related to the reserved words */

i= 0;
while( i!=M_r ){
token_r[i]= Name;
spell_rp[i]= 0;
i= i+1;
}
spell_r[0]= 0; srp= 1;
enter_reserved("else", Else);
enter_reserved("enum", Enum);
enter_reserved("if", If);
enter_reserved("int", Int);
enter_reserved("return",Return);
enter_reserved("while", While);
if( srp!=M_spell_r ) system_error("reserved word preparation");
}

int is_reserved(int spell_c[], int length){
/* 引数として渡されたspellが予約語かどうかをチェックする関数 */
/* checks if an unpacked spell is a reserved word: */
/* returns its token value if it is, */
/* returns Name if not. */

int spell[M_line], sm;
int r, i, s;

r= h(spell_c, length, P_r, M_r);
s= spell_rp[r];
sm= pack(spell_c, length, spell);
i= 0; while( i!=sm && spell[i]==spell_r[s+i] ) i= i+1;
if( i==sm ) token= token_r[r];
else token= Name;
return (token!=Name);
}

/** usual names **/
enum{ P_u=53, M_u=128 }; /* hash function parameters for usual names */

int hash[M_u];

/* 配列hashを初期化する関数 */
init_names(){ int i;
i= 0; while( i!=M_u ){ hash[i]= NIL; i= i+1; }
spell_index= 0;
}

int find(int spell_c[], int length){
/* 表からspellの位置を探し、もしまだ登録していなかったらそのspellを登録する関数 */
/* finds the position in spell_table of an unpacked spell. */
/* registers the spell if not yet registered. */

int spell[M_line], sm; int h0, f, r, i;
enum{ sentinel=0x7FFFFFFF }; /* for table lookup */

h0= h(spell_c, length, P_u, M_u); f= hash[h0];
sm= pack(spell_c, length, spell); spell[sm]= sentinel;
i= 0;
while( f!=NIL && spell[i]!=sentinel ){
i= 0; while( spell[i]==spell_table[f+spell_p+i] ) i= i+1;
r= f; f= spell_table[f+next_p];
}
if( spell[i]==sentinel ) return r;
if( spell_index+spell_p+sm>M_spell_table )
system_error("spell_table overflow");
r= spell_index;
spell_table[r+id_p]= 0;
spell_table[r+next_p]= hash[h0]; hash[h0]= r;
i= 0; while( i!=sm ){ spell_table[r+spell_p+i]= spell[i]; i= i+1; }
spell_index= spell_index+spell_p+sm;
return r;
}

/**** characterization ****/

enum{ SPACE, ONE, TWO, LETTER, H_LETTER, O_DIGIT, DIGIT };
/* SPACE: space, new line, etc. */
/* ONE: +, -, etc., which forms a token by itself. */
/* TWO: <, =, etc., which forms a token by itself or */
/* forms a token with the next character. */
/* LETTER: lower-case, upper-case letters and _; except */
/* H_LETTER: a-f and A-F, which are used also as hexadecimal digits.*/
/* O_DIGIT: 0-7, which are used as octal digits. */
/* DIGIT: 8, 9 */
enum{ p0=0x1, p1=0x100, p2=0x10000, p3=0x1000000 };
/* positioning for packup representation */
/* SPACE*p3 */
/* ONE *p3 + token*p0 */
/* TWO *p3 + token'*p2 + next-char*p1 + token*p0 */
/* kind *p3 + value*p0 */
/* (kind= LETTER, H_LETTER, O_DITIT, DIGIT) */
int char_type[M_char];

enum{ ERR=-3, HEX=-2, OCT=-1 };
int esc_value[M_char];
/* character value in escaped character representation */
/* those values are non-negative; */
/* negative value indicates need of special care */

/* character typeをセットする関数 */
set_ctype(int c, int kind, int token_n, int char_n, int token){
/* helper function used by init_ctype */
/* char_type[c]= <kind, token_n, char_n, token> (packup) */

char_type[c]=kind*p3+token_n*p2+char_n*p1+token*p0;
}

init_ctype(){ int c; enum{ _ =0 };
/* sets up char_type and esc_value */

c= 0; while( c!=M_char ){ set_ctype(c, ONE,_,_,Nontoken); c= c+1; }
c= 'a'; while( c<='f' ){ set_ctype(c, H_LETTER,_,_,c-'a'+10); c= c+1; }
c= 'g'; while( c<='z' ){ set_ctype(c, LETTER,_,_,_); c= c+1; }
c= 'A'; while( c<='F' ){ set_ctype(c, H_LETTER,_,_,c-'A'+10); c= c+1; }
c= 'G'; while( c<='Z' ){ set_ctype(c, LETTER,_,_,_); c= c+1; }
c= '0'; while( c<='7' ){ set_ctype(c, O_DIGIT,_,_,c-'0'); c= c+1; }
c= '8'; while( c<='9' ){ set_ctype(c, DIGIT,_,_,c-'0'); c= c+1; }
set_ctype('_', LETTER,_,_,_);
set_ctype(EOFC, ONE,_,_,Endfile);
set_ctype(' ', SPACE,_,_,_); set_ctype('\n', SPACE,_,_,_);
set_ctype('\r', SPACE,_,_,_); set_ctype('\t', SPACE,_,_,_);
set_ctype('\v', SPACE,_,_,_); set_ctype('\f', SPACE,_,_,_);
set_ctype('(', ONE,_,_,Lpar); set_ctype(')', ONE,_,_,Rpar);
set_ctype('[', ONE,_,_,Lbracket); set_ctype(']', ONE,_,_,Rbracket);
set_ctype('{', ONE,_,_,Lbrace); set_ctype('}', ONE,_,_,Rbrace);
set_ctype(',', ONE,_,_,Comma); set_ctype(';', ONE,_,_,Semicolon);
set_ctype('+', ONE,_,_,Plus); set_ctype('-', ONE,_,_,Minus);
set_ctype('*', ONE,_,_,Times); set_ctype('%', ONE,_,_,Remainder);
set_ctype('"', ONE,_,_,String); set_ctype('\'',ONE,_,_,Character);
set_ctype('=', TWO, Equ,'=', Becomes);
set_ctype('', TWO, Or, '', Nontoken);
set_ctype('&', TWO, And,'&', Amper);
set_ctype('!', TWO, Neq,'=', Not);
set_ctype('<', TWO, Leq,'=', Les);
set_ctype('>', TWO, Geq,'=', Grat);
set_ctype('/', TWO, Comment,'*', Divide);

c= 0; while( c!=M_char ){ esc_value[c]= c; c= c+1; }
c= '0'; while( c<='7' ){ esc_value[c]= OCT; c= c+1; }
esc_value['x']= esc_value['X']= HEX;
esc_value[EOFC]= esc_value['\n']= ERR;
esc_value['a']= 0x07; /* \a alert(BEL) */
esc_value['b']= 0x08; /* \b back space(BS) */
esc_value['f']= 0x0C; /* \f form feed(FF) */
esc_value['n']= 0x0A; /* \n new line(LF) */
esc_value['r']= 0x0D; /* \r carriage return(CR) */
esc_value['t']= 0x09; /* \t horizontal tab(HT) */
esc_value['v']= 0x0B; /* \v vertical tab(VT) */
}



/**** integer constant ****/

/* integer-constant = decimal octal hexadecimal */
/* decimal = non-zero { digit } */
/* octal = '0' { octal-digit } */
/* hexadecimal = '0' ('x''X') hexadecimal-digit { hexadecimal-digit } */
/* int型の文字を解析する関数 */
integer_constant(){
/* ch: digit, token= Const */

value= 0;
/* 10進数の場合 */
if( ch!='0' ){
/* 数字列が続く間、valueに数字列を書き出していく */
while( char_type[ch]/p3 >= O_DIGIT ){
value= value*10 + ch-'0'; get_char();
}

/* 8進数または16進数の場合*/
}else{
get_char(); /* 次の一文字を読み取る */

/* 16進数の場合 */
if( esc_value[ch]==HEX ){
get_char(); /* 次の一文字を読み取る */

/* chがa-fまたはA-Fまたは数字の間、valueにその値を書き出していく */
while( char_type[ch]/p3 >= H_LETTER ){
value= value*0x10 + char_type[ch]%0x10; get_char();
}

/* 8進数の場合 */
}else{
/* chが0-7の間、valueにその値を書き出していく */
while( char_type[ch]/p3 == O_DIGIT ){
value= value*010 + char_type[ch]%010; get_char();
}
}
}
}



/**** character constant ****/

/* character-constant = ''' ( cahracter-c escaped-chracter ) ''' */
/* character-c:: any character other than '\' and newline */
/* escaped-character = simple-escape octal-escape hexadecimal-escape */
/* octal-escape = '\' octal-digit [ octal-digit [ octal-digit ]] */
/* hexadecimal-escape = '\' ('x''X') hexadecimal-degit [hexadecimal-digit] */
/* simple-escape: '\' followed by a character other then one shown above */

int escaped_character(){ int v;
/* ch: '\' */

get_char(); v= esc_value[ch];
if( v < 0 ){
if( v==OCT ){ int j; /* octal-escape */
v= char_type[ch]%010; j= 1; get_char();
while( char_type[ch]/p3 == O_DIGIT ){
v= v*010 + char_type[ch]%010; j= j+1; get_char();
}
if( j>3 ) token= Nontoken;
}else
if( v==HEX ){ int j; /* hexadecimal-escape */
get_char(); v= 0; j= 0;
while( char_type[ch]/p3 >= H_LETTER ){
v= v*0x10 + char_type[ch]%0x10; j= j+1; get_char();
}
if( j==0 j>2 ) token= Nontoken;
}else{ /* illegal character */
token= Nontoken; v= 0;
}
}else{ /* simple-escape */
get_char();
}
return v;
}

character_constant(){
/* chのcharacter codeを判定し、結果をvalueに格納する関数 */
/* ch: one following ''', token= Character */
/* sets value with the character code */

if( ch==EOFC ch=='\n' ch=='\'' ){
token= Nontoken;
}else
if( ch=='\\' ){ /* escaped-character */
value= escaped_character();
}else{
value= ch; get_char();
}
if( ch=='\'' ) get_char();
else token= Nontoken;
}



/**** string constant ****/

/* string-constant = '"' { character-s escaped-character } '"' */
/* character-s: any character other than '"' and newline */

string_constant(){
/* 入力文字列を読み込み、配列wordに書き出す関数 */
/* ch: character following '"', token= String */

int spell_c[M_line_c], scm;

scm= 0;

/* EOFCや改行、または'"'が来るまでの間、以下の処理を繰り返す */
while( ch!=EOFC && ch!='\n' && ch!='"' ){int w;
/* chが\なければ */
if( ch!='\\'){
w= ch; get_char(); /* chをwに格納し、1文字読み込む */
}else /* chが\であれば */
w= escaped_character(); /* 関数escacape_characterを呼び出す */
spell_c[scm]= w; /* wを配列spell_c書き込む */
scm= scm+1; /* scmのインクリメント */
}
/* 次の文字列が'"'の場合は、一文字読み込む */
if( ch=='"' ) get_char();
else token= Nontoken;
pack(spell_c, scm, word); /* 読み込んだ文字列をwordに書き出す */
}

/**** comment ****/

/* comment: begins with '/''*' and ends with '*''/' */
/* may extend to several lines */

comment(){
/* ch: character following '/''*', token= Comment */

while( ch!=EOFC && ch!='*' ) get_char();
while( ch=='*' ){
get_char();
if( ch=='/'){
get_char(); return;
}
while( ch!=EOFC && ch!='*' ) get_char();
}
ch= Endfile;
}


/**** name and reserved word ****/

/* name = letter { digit letter } */
/* letter: lower-case and upper-case letters and '_' */
/* digit: 0 - 9 */
/* following are reserved and used for special purposes */
/* else enum if int return while */


identifier(){
/* tokenを変数名として定義する関数 */
/* ch: letter, token= Name */

int spell_c[M_line_c], scm;

scm= 0;
/* chのtypeがlower-case,upper-case letters and _ */
/* または、a-f,A-Fのである間 */
while( char_type[ch]/p3 >= LETTER ){
/* chを配列spell_cに入れ、次の一文字を読み取る */
spell_c[scm]= ch; scm= scm+1; get_char();
}

/* 予約語として定義されていれば、関数から抜け出す。 */
if( is_reserved(spell_c, scm) ) return;

/* 読み取った文字列が既に変数として定義されているかどうかを探す */
spell= find(spell_c, scm); /* */
}



/**** token(lexical element) ****/
get_token(){
/* 次のtokenを解析する関数 */
/* invariant: ch holds the next character available */

/* chに入っている値がスペースの間、読み捨て続ける */
while( char_type[ch]/p3 == SPACE ) get_char();

/* chが空白または演算子の場合 */
if( char_type[ch]/p3 < LETTER ){ /* ONE or TWO */
token= char_type[ch]%p1; /*tokenにchの型を格納する*/

/* 1文字だけで判断できる場合 */
if( char_type[ch]/p3 == ONE ){

/* tokenがEndfileで無ければ、もう一文字読み込み、 */
/* tokenがString型であれば文字列を読み込み配列wordに書き込む */
/* tokenがCharacter型であればchのcharacter codeを判定する */
if( token!=Endfile ) get_char();
if( token==String ){ string_constant(); return; }
if( token==Character ){ character_constant(); return; }

/* 2文字読まなければ判断できない場合 */
}else{
int c;
c= ch; /* chをcに格納し、 */
get_char(); /* さらにもう一文字読み込む */

/* 一文字目と二文字目の型が一致した場合 */
if( ch==(char_type[c]/p1)%p1 ){
token= (char_type[c]/p2)%p1; /* tokenに型名を格納する */
get_char(); /* 1文字読み込む */
}

/* tokenがCommentであれば、関数commentを呼び出す */
if( token==Comment ){ comment(); get_token(); return; }
}
}

/* chが8進数または10進数である場合 */
else if( char_type[ch]/p3 >= O_DIGIT ){
token= Const;
integer_constant();

/* chが英字である場合(16進数のa~fも含む) */
}else{
token= Name; /* tokenにNameを格納し、 */
identifier(); /* tokenを変数名として定義する */
}
}

init_token(){
init_reserved();
init_names();
init_ctype();
init_char(); get_char();
}


/**** tokenDriver ****/

int representation[100], rprm;
int link_repr[Comment+1];

/* 表記法を登録する関数 */
set_repr(int token, int repr[]){
int repr_c[20], rprc;

/* reprの配列値の分解表現をrepr_cに書き込む */
rprc= unpack(repr, repr_c);
link_repr[token]= rprm; /* link_repr[token]にrprmの値を格納 */

/* repr_cの配列値の詰め込み表現をrepresentation[rprm]の番地に書き込む */
/* rprmには書き込んだ長さを加算する */
rprm= rprm + pack(repr_c, rprc, &representation[rprm]);
}

init_repr(){
rprm= 0;
set_repr(Else, "else");
set_repr(Enum, "enum");
set_repr(If, "if");
set_repr(Int, "int");
set_repr(Return, "return");
set_repr(While,"while");
set_repr(Name, "Name");
set_repr(Const,"integer");
set_repr(Character, "character");
set_repr(String,"string");
set_repr(Plus, "+");
set_repr(Minus, "-");
set_repr(Not, "!");
set_repr(Amper,"&");
set_repr(Times, "*");
set_repr(Divide, "/");
set_repr(Remainder, "%");
set_repr(Les, "<");
set_repr(Leq, "<=");
set_repr(Grat, ">");
set_repr(Geq, ">=");
set_repr(Equ, "==");
set_repr(Neq, "!=");
set_repr(And, "&&");
set_repr(Or, "");
set_repr(Becomes,"=");
set_repr(Comma, ",");
set_repr(Semicolon, ";");
set_repr(Lpar, "(");
set_repr(Rpar, ")");
set_repr(Lbracket, "[");
set_repr(Rbracket, "]");
set_repr(Lbrace, "{");
set_repr(Rbrace, "}");
set_repr(Nontoken, "???");
set_repr(Endfile, "EOF");
set_repr(Comment, "comment");
}


/* ------------- error execution part ------------- */
/* error message */
int error_count; /* errors in a compilation */

error(int message[]){
/* output a message */
decimal(line_no, stderr); fputs("::ERROR::", stderr);
fputs(message, stderr); fputc('\n', stderr);
error_count= error_count+1;
}
missing(int token_repr[]){
/* error: when a token is missing */
int packed[M_line], unpacked[M_line_c], l;

l= unpack("missing ", unpacked);
l= unpack(token_repr, &unpacked[l])+l;
pack(unpacked, l, packed); error(packed);
}

skip_to(int target){
if( token<target ){
error("some tokens skipped");
while( token<target ) get_token();
}
}

init_error(){
/* error_count initialization */
error_count= 0;
}

/* ------------- parsing part ------------- */
expression();
logical();
arith_term();
logical_term();


/*一次子=名前|整数定数|文字定数|文字列定数|‘(’式‘)’*/
primary(){
if( token==Name token==Const
token==Character token==String ){
get_token();
}else
if( token==Lpar ){
get_token();
expression();
if( token==Rpar ) get_token(); else missing(")");
}else{
error("not a primary");
}
}


/*
算術式=算術項{加減演算子 算術項}
加減演算子=‘+’|‘-’
*/
arithmetic(){
arith_term();
while( token==Plus token==Minus ){
get_token();
arith_term();
}
}


/* 論理式 = 論理項{‘’ 論理項}*/
logical(){
logical_term();
while( token==Or ){
get_token();
logical_term();
}
}



/*
後置式 = 一次子 [添字並び|実引数並び]
添字並び = ‘[’式‘]’
実引数並び = ‘(’[式{‘,’式}]‘)’
*/
suffixed(){
primary();
if( token==Lbracket ){
get_token();
expression();
if( token==Rbracket ) get_token(); else missing("]");
}else
if( token==Lpar ){
get_token();
if( token!=Rpar ){
expression();
while( token==Comma ){
get_token();
expression();
}
}
if( token==Rpar ) get_token(); else missing(")");
}
}


/*
大小比較 = 算術式{比較演算子 算術式}
比較演算子 = ‘<’|‘<=’ |‘>’|‘>=’
*/
comparison(){
arithmetic();
while( token==Les token==Leq
token==Grat token==Geq ){
get_token();
arithmetic();
}
}



/*
前置式 = 後置式|単項演算子前置式
単項演算子 =‘+’|‘-’| ‘!’|‘&’
*/
prefixed(){
if( token==Plus token==Minus
token==Not token==Amper ){
get_token();
prefixed();
}else{
suffixed();
}
}


/*
等値比較 = 大小比較{等値演算子 大小比較}
等値演算子 =‘==’|‘!=’
*/
equality(){
comparison();
while( token==Equ token==Neq ){
get_token();
comparison();
}
}


/* 式 = 論理式{‘=’論理式}*/
expression(){
logical();
while( token==Becomes ){
get_token();
logical();
}
skip_to(Comma);
}


/*定数式 = 算術式*/
const_expr(){
arithmetic();
skip_to(Comma);
}


/*
実際の定数式には,定数 (constant)(翻訳時にも計算できる値)を
表わしたものでなければならない,という制約がつく。
ここでは,そうした「形」以外から来る条件を無視しているので,
単に arithmetic を呼び出す形の本体となっている。
*/


/*
算術項 = 前置式{乗除演算子 前置式}
乗除演算子 = ‘*’|‘/’|‘%’
*/
arith_term(){
prefixed();
while( token==Times token==Divide token==Remainder ){
get_token();
prefixed();
}
}


/* 論理項 = 等値比較{‘&&’等値比較}*/
logical_term(){
equality();
while( token==And ){
get_token();
equality();
}
}


/*
変数宣言 =‘int’変数宣言子{‘,’変数宣言子}‘;’
変数宣言子 = 名前[‘[’定数式‘]’]
*/

/* 宣言子を処理する関数 declarator */
declarator(){
if( token==Lbracket ){
get_token();
const_expr();
if( token==Rbracket ) get_token(); else missing("]");
}
}

var_decl(){
declarator();
while( token==Comma ){
get_token();
if( token==Name ) get_token(); else missing("a name");
declarator();
}
if( token==Semicolon ) get_token(); else missing(";");
skip_to(Rbrace);
}


/*
列挙宣言 =‘enum’‘{’列挙宣言子{‘,’列挙宣言子}‘}’‘;’
列挙宣言子 = 名前[‘=’定数式]
*/
enum_declarator(){
if( token==Name ){
get_token();
if( token==Becomes ){
get_token();
const_expr();
}
}else{
error("can't use reserve word");
}
}

enum_decl(){
get_token();
if( token==Lbrace ) get_token(); else missing("{");
enum_declarator();
while( token==Comma ){
get_token();
enum_declarator();
}
if( token==Rbrace ) get_token(); else missing("}");
if( token==Semicolon ) get_token(); else missing(";");
skip_to(Rbrace);
}

/* 式文 = 式‘;’*/
/* 式の先頭に現われうる字句であるかどうかを判別する関数 */
int first_expr(int token){
return (Lpar<=token && token<=Name);
}

expr_statement(){
expression();
if( token==Semicolon ) get_token(); else missing(";");
}


/* while文 =‘while’‘(’式‘)’文*/
while_statement(){
get_token();
if( token==Lpar ) get_token(); else missing("(");
expression();
if( token==Rpar ) get_token(); else missing(")");
statement();
}



/* 区画 =‘{’{変数宣言|列挙宣言}{ 文 }‘}’*/
/* 文の先頭に現われうる字句であるかどうかを判別する関数*/
int first_stmt(int token){
return (Semicolon<=token && token<=Name);
}

block(){
get_token();
while( token==Int token==Enum ){
if( token==Int ){
get_token();
if( token==Name ) get_token(); else missing("a name");
var_decl();
}else{
enum_decl();
}
}
skip_to(Rbrace);
while( first_stmt(token) ){
statement(); skip_to(Rbrace);
}
if( token==Rbrace ) get_token(); else missing("}");
}


/* if文 =‘if’‘(’式‘)’ 文[‘else’文]*/
/* [制約]から,最初の「文」を読み捨てた後に 字句‘then’が現れれば,
それはこの‘if’に 呼応したものであるので,一緒に処理する*/
if_statement(){
get_token();
if( token==Lpar ) get_token(); else missing("(");
expression();
if( token==Rpar ) get_token(); else missing(")");
statement();
if( token==Else ){
get_token();
statement();
}
}


/* return文 =‘return’[式]‘;’*/
return_statement(){
get_token();
if( first_expr(token) ){
expression();
}
if( token==Semicolon ) get_token(); else missing(";");
}

/*
文 = 空文|式文|if文|while文|return文| 区画
空文=‘;’
*/
statement(){
if( token==Semicolon ){
get_token(); /* empty-statement */
}else
if( first_expr(token) ){
expr_statement();
}else
if( token==If ){
if_statement();
}else
if( token==While ){
while_statement();
}else
if( token==Return ){
return_statement();
}else
if( token==Lbrace ){
block();
}else{
error("not a statement");
}
skip_to(Else);
}


/*
関数宣言 =[‘int’]名前 引数仕様並び‘;’
引数仕様並び =‘(’[単引数仕様 {‘,’単引数仕様}]‘)’
単引数仕様 =‘int’[ 名前 ][‘[’‘]’]
関数定義 =[‘int’]名前 関数定義本体
関数定義本体 = 仮引数仕様並び 区画
仮引数仕様並び =‘(’[仮引数仕様{‘,’仮引数仕様}]‘)’
仮引数仕様 =[‘int’]名前[‘[’‘]’]
*/
enum{ n_param, n_int, n_name };

/*配列 c を用いてこれらの出現回数を記録しておき,
関数宣言であるか関数定義であるかが判明した時点で,
正しい形をしていたかどうかを判断する。*/
parameter(int c[]){ int s;
s= 0;
if( token==Int ){ s= 1; c[n_int]= c[n_int]+1; get_token(); }
if( token==Name ){ s= 1; c[n_name]= c[n_name]+1; get_token(); }
if( token==Lbracket ){
if( s==0 ) error("[ without int or name");
get_token();
if( token==Rbracket ) get_token(); else missing("]");
}
c[n_param]= c[n_param]+1;
}

func_decl(){
int c[n_name+1];
c[n_param]= c[n_int]= c[n_name]= 0;
if( token==Lpar ) get_token(); else missing("(");
if( token!=Rpar ){
parameter(c);
while( token==Comma ){
get_token();
parameter(c);
}
}
if( token==Rpar ) get_token(); else missing(")");
if( token==Semicolon ){
if( c[n_param]!=c[n_int] ) error("missing int's in declaration");
get_token();
}else
if( token==Lbrace ){
if( c[n_param]!=c[n_name] ) error("missing names in definition");
block();
}else{
missing("; or block");
}
}


/*宣言 = 変数宣言 | 列挙宣言 | 関数宣言 | 関数定義
算譜 = 宣言{ 宣言 }*/

/* token が 宣言(declaration)の先頭に来る
字句(int, enum, 名前) であるとき真になる関数 */
int first_decl(int token){
return (Name<=token && token<=Enum);
}

declaration(){
if( token==Int ){
get_token();
if( token==Name ) get_token(); else missing("a name");
if( token==Lpar ){
func_decl();
}else{
var_decl();
}
}else
if( token==Name ){
get_token();
func_decl();
}else
if( token==Enum ){
enum_decl();
}else{
error("not a declaration");
}
skip_to(Name);
}


program(){
declaration();
while( first_decl(token) ){
declaration();
}
}


main(){
init_error();
init_token();
init_repr(); /* 表記法を初期化する */
get_token();
program();
if( error_count==0 ){
fputs("Compilation succeeds\n", stdout);
}else{
fputs("Compilation fails with ", stdout);
decimal(error_count, stdout);
fputs(" errors\n", stdout);
}
}

0 件のコメント: