2015年11月15日日曜日

開発環境

  • OS X El Capitan - Apple (OS)
  • Emacs(Text Editor)
  • C (プログラミング言語)
  • flex(字句解析)、bison(構文解析)

lex&yaccプログラミング (NUTSHELL HANDBOOKS) (John R Levine著、Doug Brown著、Tony Mason著、村上 列翻訳)の1章(lex と yacc)、1.6(演習問題)、問3を解いてみる。

問3

コード(Emacs)

lex3.l

%{

#include "parse3.tab.h"
#include "symtab.h"

int state;

%}

%%

\n { state = LOOKUP;}

\.\n { state = LOOKUP; return 0;}

aux { state = AUXVERB;}
verb { state = VERB;}

adj { state = ADJECTIVE; }
adv { state = ADVERB; }
noun { state = NOUN; }
prep {state = PREPOSITION; }
pron { state = PRONOUN; }
conj { state = CONJUNCTION; }
nov { state = NOUN_OR_VERB; }

[a-zA-Z]+ {
  if (state != LOOKUP) {
    add_word(state, yytext);
  } else {
    switch(lookup_word(yytext)) {
    case AUXVERB: return AUXVERB;
    case VERB: return VERB;
    case ADJECTIVE: return ADJECTIVE;
    case ADVERB: return ADVERB;
    case NOUN: return NOUN;
    case PREPOSITION: return PREPOSITION;
    case PRONOUN: return PRONOUN;
    case CONJUNCTION: return CONJUNCTION;
    default: printf("%s: don't recognize\n", yytext);
    }
  }
}

[ \t]
%%

parse3.y

%{
#include <stdio.h>

int yyerror(char *s);
extern int yylex (void);

%}

%token LOOKUP AUXVERB VERB ADJECTIVE ADVERB NOUN PREPOSITION PRONOUN CONJUNCTION
%token NOUN_OR_VERB
                        
%%

sentence:        simple_sentence
                   { printf("Parsed a simple sentence.\n"); yyparse();}
        |       compound_sentence
                {
                  printf("Parsed a compound sentence.\n");
                  yyparse();
                }
        ;

simple_sentence: subject verb object
        |       subject verb object prep_phrase
        ;

compound_sentence: simple_sentence CONJUNCTION simple_sentence
        |       compound_sentence CONJUNCTION simple_sentence
        ;

subject:        NOUN
        |       PRONOUN
        |       NOUN_OR_VERB
        |       ADJECTIVE subject
        |       ADVERB subject  /* 追加 */
        ;

verb:           VERB
        |       ADVERB VERB
        |       AUXVERB VERB
        |       NOUN_OR_VERB
        |       verb VERB
        ;

object:         NOUN
        |       NOUN_OR_VERB
        |       ADJECTIVE object
        ;

prep_phrase:    PREPOSITION NOUN
        ;

%%

extern FILE *yyin;

int main() {
  while (1) {
    yyparse();
  }
}

int yyerror(char *s) {
  fprintf(stderr, "%s\n", s);
  return 1;
}

symtab.h

#pragma once

int add_word(int type, char *word);
int lookup_word(char *word);

symtab.c

#include "symtab.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "parse.tab.h"

typedef struct word {
  char *word_name;
  int word_type;
  struct word *next;
} Word;

Word *word_list;

int add_word(int type, char *word) {
  Word *wp;

  if (lookup_word(word) != LOOKUP) {
    printf("!!! warning: word %s already defined \n", word);
    return 0;
  }

  wp = (Word*)malloc(sizeof(Word));
  wp->next = word_list;
  wp->word_name = (char*)malloc(strlen(word) + 1);
  strcpy(wp->word_name, word);
  wp->word_type = type;
  word_list = wp;
  return 1;
}

int lookup_word(char *word) {
  Word *wp = word_list;

  for (; wp; wp = wp->next) {
    if (strcmp(wp->word_name, word) == 0){
      return wp->word_type;
    }
  }
  return LOOKUP;
}

入出力結果(Terminal(bash))

$ make
lex lex3.l 
bison -d parse3.y 
cc -g -Wall -O0 -I/opt/local/include -L/opt/local/lib -lfl symtab.o parse3.tab.c lex.yy.c -o main
lex.yy.c:1161:17: warning: unused function 'yyunput' [-Wunused-function]
    static void yyunput (int c, register char * yy_bp )
                ^
lex.yy.c:1202:16: warning: function 'input' is not needed and will not be
      emitted [-Wunneeded-internal-declaration]
    static int input  (void)
               ^
2 warnings generated.
$ ./main
noun money
nov time
verb is
time is money.
time: don't recognize
syntax error
syntax error
  C-c C-c
$ # うまくいかなかった

0 コメント:

コメントを投稿