2013-10-12 2 views
0

어휘 분석기는 숫자 (5,555,543667), 소수 (44.65,4.1) 및 마침표 (.)를 인식합니다.어휘 분석기. 스위치를 사용하여 10 진수가 아닌 10 진수를 분석하고 계산합니다.

숫자, 소수 자릿수 및 마침표를 잘 계산할 수 있지만 숫자와 마침표가 서로 인접 해 있으면 십진수로 계산됩니다. 555 2.3 55.23 44 5.

내 출력이 될 것

1 유형 1 : 555
2 유형 3 : 2.3
3 유형 3 : 55.23

이 포함 된 텍스트 파일을 고려 4 유형 1 : 44
5 유형 3 : 5

여기서 유형 3은 10 진수의 식별자입니다.

다섯 번째 및 여섯 번째 토큰을 숫자로 계산 한 다음 마침표를 넣으려고합니다.

다음은 내 switch 문을 처리하는 방법입니다.

switch(*b) { 

    case '0': 
    case '1': 
    case '2': 
    case '3': 
    case '4': 
    case '5': 
    case '6': 
    case '7': 
    case '8': 
    case '9': 
    digits: 
     t.length++; 
     switch(*(b + t.length)) { 
      case '0': 
      case '1': 
      case '2': 
      case '3': 
      case '4': 
      case '5': 
      case '6': 
      case '7': 
      case '8': 
      case '9': 
       goto digits; 
      case '.': 
       goto decimal;     
       break; 
      default: 
       break; 
     } 

     t.type = TOKEN_DIGITS; 
     t.string = (char *)calloc(t.length + 1, sizeof(char)); 
     strncpy(t.string, b, t.length); 
     break; 



    decimal: 
     t.length++; 
     switch(*(b + t.length)) { 
      case '0': 
      case '1': 
      case '2': 
      case '3': 
      case '4': 
      case '5': 
      case '6': 
      case '7': 
      case '8': 
      case '9': 
       goto decimal; 
       break; 
      } 
      t.type = TOKEN_DECIMAL; 
      t.string = (char *)calloc(t.length+1,sizeof(char)); 
      strncpy(t.string,b,t.length);   
     break; 

여러 가지 시도가 있지만 공식적으로 막혔습니다.

+1

어휘 분석은 많은 수고를 요구하는 곳이 아닙니다. 루프와 isdigit() 호출에 대해 생각해보십시오. –

+1

gotos는 악마이고, 그들에게 익숙해지지 않으려 고 노력하십시오. 질문에 관해서는 문제는 전체 항목을 처리 할 때까지 사용자가 알지 못하는 것입니다. 먼저 문자열을 "단어"로 분리해야하며, 후자는 문자를 문자로 처리하는 대신 전체적으로 각 단어를 차례대로 처리해야합니다. – SJuan76

+0

플렉스를 사용하는 것이 더 쉽지 않을까요? 이것이 학습 운동이라면 무엇을 배웠습니까? – rici

답변

1

긴 switch 문 대신이 연습을하려면 실제로 character classification functions을 사용해야합니다. 코드가 훨씬 간단 해지고 goto을 전혀 사용할 필요가 없습니다.

는 예를 들어, 다수 (다양한 블록을 나누는 첨가 공백) 다음 일반 식으로 설명 될 수있다 :

를이 이미 가능한 상태 전이를 보여

  • 숫자는 (선택 사항) + 또는 -으로 시작할 수 있습니다 (부호있는 숫자를 지원하는 경우)
  • 0.n 자릿수
  • 다음 문자가 소수점 기호가 아닌 경우 구분 기호 여야하며, 그렇지 않으면 유효하지 않은 기호입니다. 구분 기호 인 경우 번호가 종결됩니다.
  • 소수점 후이 1..N해야 자리
  • 수는 사용자가 입력의 끝에 도달 할 때 종료 또는

모든이가 한줌의에서 수행 할 수있는 분리가 발생한다 코드의 - 현재 입력 된 문자를 가리키는 포인터를 하나씩 가져 와서 각 문자를 검사하고 문자 클래스에 따라 수행 할 작업을 결정하십시오.

이제이 특별한 접근법은 과학 표기법 등을 사용하여 부동 소수점 숫자를 처리하지 않지만 기본 사항을 완료하면 thos 추가 기능을 추가하는 작업은 매우 간단합니다.

0

상태를 유지하려면 digit_follow_peroid과 같은 변수를 사용하십시오. peroid가 발생할 때마다 변수를 false로 설정 한 다음 decimal switch 블록에서 숫자가 나타나면 true로 설정하십시오. 변수의 값을 확인하여 t를 결정하십시오.길이는 strncpy입니다. 다른 변수도 함께 사용해야 할 수도 있습니다. 가장 좋은 방법은 gotos보다 훨씬 좋은 상태 전이 행렬을 정의하는 것입니다.

1

나는 이것이 xxbbcc의 대답을 보완한다고 생각합니다.

* 매우 대략 * 이와 유사합니다.

#include <stdio.h> 
#include <stdlib.h> 
#include <ctype.h> 

yylex() { 
     int c; 
     char *p, buf[1000]; 

     for(c = get(); isspace(c); c = get()); 

     if(isdigit(c)) { 
       p = buf; 
       while(isdigit(c)) { 
         *p++ = c; 
         c = get(); 

       } 
       *p = 0; 
       if(c != '.') { 
         unget(c); 
         int i = atoi(buf); 
         return INT; 
       } 
       assert(c == '.'); 
       *p++ = c; 
       c = get(); 
       while(isdigit(c)) { 
         *p++ = c; 
         c = get(); 
       } 
       *p = 0; 
       float f = atof(buf); 
       unget(c); 
       return DECIMAL; 
     } 
} 

언급하지 않은 내용이 많이 있습니다. EOF를 지켜보고 있습니다. 버퍼 오버 플로우. yylval을 int 또는 float로 설정합니다. 단순한 숫자가 아닌 토큰을 파싱합니다.

+0

빠른 타이핑 - 일반 텍스트 답변을 입력하는 데 시간이 오래 걸렸습니다. :) 보통이 종류의 코드를 함수에 넣은 다음 호출자가 현재 컨텍스트에서 숫자를 시작하는 무언가를 만날 때 호출됩니다. – xxbbcc

+0

@xxbbc, 당신의 대답은 더 좋을 것입니다, 아마도 함께 OP에 도움이 될 것입니다. 이론과 실천. 네, 작은 기능이 좋습니다. –

+0

@CharlieBurns - 내가 틀릴 수도 있지만'get()'또는'unget()'이 ANSI C에 정의되어 있다고 생각지 않는다. OP가 C에 태그를 붙였다. – ryyker

관련 문제