BNFからJAVAへの変換についての基本問題

このQ&Aのポイント
  • 学校の宿題でBNFからJAVAの課題が出て一応自分でやったんですが自身が無いので合ってるか見てください。
  • 特によくわからないのが繰り返し{}と省略可[]をどのようにしたらいいのかが迷いました。
  • 質問文章のコード例を解析し、解答を提供します。
回答を見る
  • ベストアンサー

BNF→JAVA  基本問題らしいです

学校の宿題でBNF→JAVAの課題が出て一応自分でやったんですが自身が無いので合ってるか見てください。 間違っていれば指摘お願いします。 特によくわからないのが繰り返し{}と省略可[]をどのようにしたらいいのかが迷いました。 問題 <B>::=[<DEC>]<S> <S>::="{"<S>"}"|<IF>|<WRITE> <IF>::="if"<E><S>";" <WRITE>::="int"<VAR>";"|"char"<VAR>";" 僕が考えた答え public void parseB(){ if parse Dec(); parseS(); } void parseS(){ if(tokenType==S_LBRACE)getToken(); while(tokenType==S_INT)parseS(); if(tokenType==S_RBRACE)getToken(); else if parseIf(); else if parseWrite(); elese error(); } void parseIf(){ if(tokenType==S_IF)getToken(); parseE(); parseS(); if(tokenType==S_SEMICOLON)getToken(); } void parseWrite(){ if(tokenType==S_INT)getToken(); parseVar(); if(tokenType==S_SEMICOLON)getToken(); parseVar(); if(tokenType==S_SEMICOLON)getToken(); }

質問者が選んだベストアンサー

  • ベストアンサー
  • kacchann
  • ベストアンサー率58% (347/594)
回答No.1

たとえば、こんなかんじかな? 一例ということで。 (parseDec()やparseE()やparseVar()の内部処理がわからないので、 なんとも決められないし、 他にもやりようがある) void parseB() {  //現在のトークン種を見て  //S_DECならparseDec()し、  //S_DECでないならparseDec()しない。  if(tokenType == S_DEC ) {   parseDec();        }  parseS(); } void parseS() {  //現在のトークン種を見て  //「{」か「if」か「intまたはchar」なら  //しかるべきparseXXX()を呼ぶ。  if (tokenType == S_LBRACE) {   getToken();   parseS();   if (tokenType != S_RBRACE) {    error();   }   getToken();  } else if (tokenType == S_IF ) {   parseIf();  } else if (tokenType == S_INT || tokenType == S_CHAR) {   parseWrite();  } else {   error();  } } void parseIf() {  if (tokenType != S_IF ) {   error();  }  getToken();  parseE();  parseS();  if (tokenType != S_SEMICOLON) {   error();  }  getToken(); } void parseWrite() {  if (tokenType != S_INT && tokenType != S_CHAR) {   error();  }  getType();  parseVar();  if (tokenType != S_SEMICOLON) {   error();  }  getToken(); }

その他の回答 (1)

  • kacchann
  • ベストアンサー率58% (347/594)
回答No.2

#No.1です 言い忘れた…。 ちょっとわからないんだけど、 <S>::="{"<S>"}"|<IF>|<WRITE> 上の式で使われてる"{"は 「繰り返し記号の{」ではなく、 単に「文字列としての{」ではないのかな? (なぜならダブルクォーテーションで囲まれてるから) これは僕にははっきりわからないので、 先生に確認してみよう。 -------------------------- あと、僕が書いた「答え」は、 あくまでも参考にしてちょ。 (「正答」は、あくまでもその課題で提供されてる前提条件によるし、  課題として事前に要求されてる「書き方」があるなら  それに従う必要がある)

god_god_god
質問者

お礼

ありがとうございます。もう宿題は提出してしまったんですが復習として参考にさせていただきます。 今さらいっても仕方ないんですが問題書き間違えてました。 <S>::="{"<S>"}"|<IF>|<WRITE>ではなくご指摘のとおり{}が抜けてました。 <S>::="{"{<S>}"}"|<IF>|<WRITE>でした

関連するQ&A

  • C言語のプログラム問題に対応するBNFの書き方がわかりません

    C言語のプログラムからBNFにする方法を習っているのですが、どうしてもそのやり方がわかりません。 下にあるプログラムに対応するBNFを自分で作成してみたのですが、 <A>::=A|Bぐらいしかできませんでした。このBNFを作っても、なぜこうなるのかもわかりません。 #include<stdlib.h> #include<stdio.h> #include<string.h> enum symboltype{SMILE,HELLO,BYE,END}; void A(); void B(); void scan(); void error(char *msg); enum symboltype next; int main(int argc, char* argv[]){ scan(); A(); if(next != END) error("#PARSE ERROR#"); else puts("#PARSE OK#"); return 0; } void A(){ if(next != SMILE) error("#PARSE ERROR#"); else puts("#PARSE OK#"); return 0; } void B(){ if(next != SMILE){ scan(); return; }else if(next != HELLO){ scan(); A(); if(next != BYE) error("#PARSE ERROR#"); scan(); }else error("#PARSE ERROR#"); } void error(char *msg){ puts(msg); exit(1); } void scan(){ char buff[10]; if(fgets(buff,10,stdin)==NULL){ next=END; return; } if(strcmp(buff,"hello\n")==0) next=HELLO; else if(strcmp(buff,"bye\n")==0) next=BYE; else if(strcmp(buff,"(*_*)\n")==0) next=SMILE; else error("#UNKNOWN TOKEN#"); } このプログラムに対応するBNFを教えてほしいんです。 お願いしますm(_ _)m また、BNFはどのように書くのかも教えていただけませんか。

  • C言語からBNFに変更したいのですが・・

    C言語の問題からBNFにするのですが、プログラムで、 void A(){ if(next != SMILE) error("#PARSE ERROR#"); else puts("#PARSE OK#"); return 0; } void B(){ if(next != SMILE){ scan(); return; }else if(next != HELLO){ scan(); A(); if(next != BYE) error("#PARSE ERROR#"); scan(); }else error("#PARSE ERROR#"); } の部分だけBNFにしたいんですが、自分で考えてもよくわからなくて、なんとか答えを出してみたのですが、結果は<A>::=A|Bと<B>::=B|Aとなってしまいました。この答えであっているのかわからないので、誰か教えてください。もし、違っていた場合は、答えとなぜそうなるのか教えてほしいんです。よろしくお願いします。

  • 課題でつまってます・・・

    閲覧ありがとうございます。 main内のkr_sortの部分と、kr_sortのswapがおかしいのですが、どうやっても「警告: 互換性のないポインタ型からの引数 1 個の `swap' を渡しますです」という風になってしまいます。どなたかご指摘お願いします。 #include <stdio.h> #include <string.h> #include <stdlib.h> #define NUMERIC 1 #define DECR 2 #define LINES 100 #define MAXLEN 1000 #define ALLOCSIZE 10000 #define MAXLINES 5000 int numcmp(char *s1, char *s2); int readlines(char *lineptr[], int maxlines); int getline (char s[], int lim); void kr_qsort(char *v[], int left, int right, int (*comp)(void *, void *)); void writelines(char *lineptr[], int nlines, int decr); char *lineptr[MAXLINES]; char linestor[20]; char *alloc(int n); static char option = 0; static char allocbuf[ALLOCSIZE]; static char *allocp = allocbuf; main(int argc, char *argv[]) { char *lineptr[LINES]; int nlines; int c, rc = 0; while (--argc > 0 && (*++argv)[0] == '-') while (c = *++argv[0]) switch (c) { case 'n': option |= NUMERIC; break; case 'r': option |= DECR; break; default: printf("sort: illegal option %c\n", c); argc = 1; rc = -1; break; } if (argc) printf("Usage: sort -nr \n"); else if ((nlines = readlines(lineptr, LINES)) > 0) { if (option & NUMERIC) kr_qsort((void **) lineptr, 0, nlines-1, (int (*) (void *, void *)) numcmp); else kr_qsort((void **) lineptr, 0, nlines-1, (int (*) (void *, void *)) strcmp); writelines(lineptr, nlines, option & DECR); } else { printf("input too big to sort \n"); rc = -1; } return rc; } int numcmp(char *s1, char *s2) { double v1, v2; v1 = atof(s1); v2 = atof(s2); if (v1 < v2) return -1; else if (v1 > v2) return 1; else return 0; } int readlines(char *lineptr[], int maxlines) { int len, nlines; char *p, line[MAXLEN]; nlines = 0; while ((len = getline(line, MAXLEN)) > 0) if (nlines >= maxlines || (p = alloc(len)) == NULL) return -1; else { line[len-1] = '\0'; strcpy(p, line); lineptr[nlines++] = p; } return nlines; } char *alloc(int n) { if (allocbuf + ALLOCSIZE - allocp >= n) { allocp += n; return allocp - n; } else return 0; } void kr_qsort(char *v[], int left, int right, int (*comp)(void *, void *)) { int i, last; void swap(void *v[], int i, int j); if (left >= right) return; swap(v, left, (left + right)/2); last = left; for (i = left+1; i <= right; i++) if ((*comp)(v[i], v[left]) < 0) swap(v, ++last, i); swap(v, left, last); kr_qsort(v, left, last-1, comp); kr_qsort(v, last+1, right, comp); } void writelines(char *lineptr[], int nlines, int decr) { int i; if (decr) for (i = nlines-1; i >= 0; i--) printf("%s\n", lineptr[i]); else for (i = 0; i < nlines; i++) printf("%s\n", lineptr[i]); } void swap(char *v[], int i, int j) { char *temp; temp = v[i]; v[i] = v[j]; v[j] = temp; } int getline (char s[], int lim) { int c, i; i = 0; while (--lim > 0 && (c=getchar()) != EOF && c != '\n') s[i++] = c; if (c == '\n') s[i++] = c; s[i] = '\0'; return i; }

  • コンパイルするとエラーに。C言語(改め)

    インクルード 定義 メイン関数 エラー内容 が収まりませんでした; (長すぎてどうすればよいのやら;) int readlines(char *lineptr[], int maxlines) { int len, nlines; char *p, line[MAXLEN]; nlines = 0; while ((len = getline(line, MAXLEN)) > 0) if (nlines >= maxlines || (p = alloc(len)) == NULL) return -1; else { line[len-1] = '\0'; strcpy(p, line); lineptr[nlines++] = p; } return nlines; } char *alloc(int n) { if (allocbuf + ALLOCSIZE - allocp >= n) { allocp += n; return allocp - n; } else return 0; } void kr_qsort(char *v[], int left, int right, int (*comp)(void *, void *)) { int i, last; void swap(char *v[], int i, int j); if (left >= right) return; swap(v, left, (left + right)/2); last = left; for (i = left+1; i <= right; i++) if ((*comp)(v[i], v[left]) < 0) swap(v, ++last, i); swap(v, left, last); kr_qsort(v, left, last-1, comp); kr_qsort(v, last+1, right, comp); } void swap(char *v[], int i, int j) { char *temp; temp = v[i]; v[i] = v[j]; v[j] = temp; } void readargs(int argc, char *argv[]) { char c; int atoi(char *); while (--argc > 0 && (c = (*++argv)[0] == '-' || c == '+') { if (c == '-' && !isdigit(*(argv[0]+1))) while (c = *++argv[0]) switch (c) { case 'd': option |= DIR; break; case 'f': option |= FOLD; break; case 'n': option |= NUMERIC; break; case 'r': option |= DECR; break; default: printf("sort: illegal option %c\n", c); error("Usage: sort -dfnr [+pos1] [-pos2]"); break; } else if (c == '-') pos2 = atoi(argv[0]+1); else if ((pos1 = atoi(argv[0]+1)) < 0) error("Usage: sort -dfnr [+pos1] [-pos2]"); } if (argc || pos1 > pos2) error("Usage: sort -dfnr [+pos1] [-pos2]"); } } void writelines(char *lineptr[], int nlines, int order) { int i; if (order) for (i = nlines-1; i >= 0; i--) printf("%s\n", lineptr[i]); else for (i = 0; i < nlines; i++) printf("%s\n", lineptr[i]); } int charcmp(char *s, char *t) { char a, b; int i, j, endpos; int option, pos1, pos2; int fold = (option & FOLD) ? 1 : 0; int dir = (option & DIR) ? 1 : 0; i = j = pos1; if (pos2 > 0) endpos = pos2; else if ((endpos = strlen(s)) > strlen(t)) endpos = strlen(t); do { if (dir) { while (i < endpos && !isalnum(s[i]) && s[i] != ' ' && s[i] != '\0') i++; while (j < endpos && !isalnum(t[j]) && t[j] != ' ' && t[j] != '\0') j++; } if (i < endpos && j < endpos) { a = fold ? tolower(s[i]) : s[i]; i++; b = fold ? tolower(t[j]) : t[j]; j++; if (a == b && a == '\0') return 0; } } while (a == b && i < endpos && j < endpos); return a - b; } int numcmp(char *s1, char *s2) { double v1, v2; char str[MAXSTR]; substr(s1, str, MAXSTR); v1 = atof(str); substr(s2, str, MAXSTR); v2 = atof(str); if (v1 < v2) return -1; else if (v1 > v2) return 1; else return 0; } void substr(char *s, char *str, int maxstr) { int i, j, len; extern int pos1, pos2; len = strlen(s); if (pos2 > 0 && len > pos2) len = pos2; else if (pos2 > 0 && len > pos2) error("substr: string too short"); for (j = 0, i = pos1; i < len; i++, j++) str[j] = s[i]; str[j] = '\0'; } int getline (char s[], int lim) { int c, i; i = 0; while (--lim > 0 && (c=getchar()) != EOF && c != '\n') s[i++] = c; if (c == '\n') s[i++] = c; s[i] = '\0'; return i; } void error(char *s) { printf("%s\n", s); exit(1); }

  • 文字列とポインタの問題です。

    #include<stdio.h> int f(char *s); int main(void){ char*str="nasida Institute of Technology"; int i; i=f(str); printf("%s:%d\n",str,i); return 0; } int f(char *s) { int j=0; while(*s!='\0'){ if(*s=='t'){ j++; } s++; } return j; } このプログラムの答えが3になるんですが、if文のとこの動作がよく分からないので、よろしくお願いします。

  • この関数がどのような計算を行うものか教えて下さい。

    #define NULLC(char) 0 #define YES 1 #define NO 0 int string_compare(char *s1, char*s2){ while(*s1==*s2) if(*s1==NULLC) if(*s2==NULLC) return YES; else return NO; else if(*s2==NULLC) return NO; else{++s1;++s2;} return NO; }

  • C言語のソースの説明なんですが

    #include <stdio.h> #define MAX 256 void pushdown(char *S, char x); char popup(char *S); void initialize(char *S); int empty(char *S); int top=0; void pushdown(char *S, char x){ /*スタックSにデータxを記憶*/ if(top<MAX){ top++; S[top]=x; } else{ printf("Stack S overflows.\n"); } } char popup(char *S){ /*スタックSからデータの取出し*/ if(top>0){ top--; return(S[top+1]); } else{ printf("Stack S is empty.\n"); return('\0'); } } void initialize(char *S){ int i; top=0; for(i=1;i<MAX;i++){ S[i]='\0'; } } int empty(char *S){ if(top==0){ return(1); } return(0); } int main(void){ char x; char S[MAX]; pushdown(S,'a'); pushdown(S,'b'); pushdown(S,'c'); x=popup(S); x=popup(S); pushdown(S,'d'); x=popup(S); pushdown(S,'e'); while(!empty(S)){ printf("%c", popup(S)); } printf("\n"); return(0); } 上記のソースリストに説明を載せなくてはいけないのですがどれが何をしているのかほとんど分からなくて困っています。(わかったのは既に書いてある2行分ぐらい) 長くて面倒ですが判る方、どうか助けてください。 (インデント等は省いています)

  • 春期の基本情報技術者試験の問題について

    基本情報試験の勉強の為に過去門を解いていたのですが 自分には分からない記述があったので質問しました 下記のプログラムの while(bp > base && *--bp != '/'); とは一体どのような処理をしているのか教えてください C言語は独学で勉強したのですがこのようなwhile文の 使用方法はどこにものっていなかったので・・・ よろしくお願いします。 問題は平成21年春期の基本情報技術者試験の 午後の問9です。 #include <string.h> void convert(const char*, const char*, char*); void convert(const char *path, const char *base, char *result){ const char *pp, *bp; char *rp; int length; /* pathが絶対パス表記の場合 */ if(*path == '/'){ ; return; } /* pathがカレントディレクトリの場合 */ if(!strcmp(path, ".") || !strcmp(path, "./")){ ; return; } length = strlen(base); bp = base + length; /* bpは文字列baseの終端を指す。*/ if(*(bp - 1) == '/') --bp; /* pathの先頭部にある".."又は"../"を解析することで, baseのパス表記のうち,どこまでresultと共通になるかを調べる。*/ for(pp = path; *pp != '\0' && *pp == '.';){ if(!strncmp(pp, "../", 3)){ pp += 3; while(bp > base && *--bp != '/'); }else if(!strncmp(pp, "./", 2)){ pp += 2; }else if(!strncmp(pp, "..\0", 3)){ pp += 2; while(bp > base && *--bp != '/'); }else{ break; } } /* baseのパス表記と共通な部分をresultに複写する。*/ length = ; strncpy(result, base, length); rp = ; *rp++ = '/'; /* pathの文字列のうち,先頭部分の"./"や".."を除いた残りの 部分(ppが指す文字列)を,resultの文字列に追加する。 */ strcpy(rp, pp); return; }

  • ポインタの基本的な問題

    ポインタの勉強をしています。変数にポインタが付いている場合の動作は大体理解したつもりですが以下のように関数にポインタが付いているとどう扱えばいいのかわかりません。とりあえず、まずはtsukinonamae関数にinteger 1を渡して「1月」と表示させることから始めようとしていますが、それすらコンパイルエラーになります。引数nに1を渡すところはいいですよね?その後、nam[1]に入っているjanという文字列をchar型で返す?と思うのでメイン部で宣言したcharに渡そうとしているのですが。。 何が問題なのでしょうか。 char *tsukinonamae(int n); int main(){ int n = 1; char s[30]; s = tsukinonamae(n); printf("%s\n", s); } char *tsukinonamae(int n){ static char *nam[] = { "none", "jan", "feb", "mar", "apr", "may", "jun", "jul", "aug", "sep", "oct", "nov", "dec"}; return (n<1 || n>12) ? nam[0] : nam[n]; }

  • このプログラムは「こんにちは」と打つと「こんにちは、元気ですか」と返答

    このプログラムは「こんにちは」と打つと「こんにちは、元気ですか」と返答するプログラムです このプログラムを改良して「こんにちは」と打つと「こんにちは、元気ですか」と言うようなキーワードを打つ決められた回答をするようなものを増やしていきたいのですが、どのように改良すればよいでしょうか? 例えば 「寒いですね」といれると「冬だからね」となるように #include <stdio.h> #include <string.h> int reply(const char *s) { const char *reply_s[] = {"こんにちは 元気ですか?", "バイバイ", "ふ~ん?"}; if(strstr(s, "こんにちは")) puts(reply_s[0]); else if(strstr(s, "さようなら")){ puts(reply_s[1]); return 0; } else puts(reply_s[2]); return 1; } int main(void) { char s[128]; do{ char *p; fgets(s, sizeof s, stdin); if(p = strchr(s, '\n')) *p = '\0'; }while(reply(s)); return 0; }

専門家に質問してみよう