문제

좋아, 텍스트 파일에 이와 같은 문자열이 있다고 가정 해 봅시다.

((( var1 AND var2 AND var3) OR var4) AND ((var5 OR var6) AND var7))

이것을 C 프로그램에 구문 분석하면 VARS가 처리되고 올바르게 설정된 후에는 다음과 같은 것을 보게됩니다.

((( 1 AND 0 AND 0) OR 1) AND ((0 OR 1) AND 1))

이와 같은 하나의 문자열로 표시되는 표현식을 평가하는 데 유용한 라이브러리가 있습니까? 나는 문자열이있는 Perl 프로그램을 문자열로 호출 할 수 있지만 결과를 쉽게 반환 할 수 있지만 C 에이 작업을 수행 한 라이브러리가 있는지 확실하지 않은 인수 또는 해결을위한 알려진 알고리즘이 있는지 확실하지 않았습니다. 그런 표현?

편집 : 내가 실제로 찾고있는 것은이 표현에 대한 답을 뱉어내는 것입니다. 아마도 구문 분석은 나쁜 단어 일 것입니다. 즉 1 또는 0

너트 쉘에서는 0 또는 1으로 평가 해야하는 무작위 표현식 (이미 올바른 형식으로 알려진 것으로 알려짐)이 포함 된 파일입니다 (위의 위는 (1 및 1)가 발생하기 때문에 1로 평가합니다.

도움이 되었습니까?

해결책

이 bool 표현 평가 문제에 대해 가장 작곡 된 C 코드를 작성하려고했습니다. 내 최종 코드는 다음과 같습니다.

편집 : 삭제

추가 부정 취급은 다음과 같습니다.

편집 : 테스트 코드가 추가되었습니다

char *eval( char *expr, int *res ){
  enum { LEFT, OP1, MID, OP2, RIGHT } state = LEFT;
  enum { AND, OR } op;
  int mid=0, tmp=0, NEG=0;

  for( ; ; expr++, state++, NEG=0 ){
    for( ;; expr++ )
         if( *expr == '!'     ) NEG = !NEG;
    else if( *expr != ' '     ) break;

         if( *expr == '0'     ){ tmp  =  NEG; }
    else if( *expr == '1'     ){ tmp  = !NEG; }
    else if( *expr == 'A'     ){ op   = AND; expr+=2; }
    else if( *expr == '&'     ){ op   = AND; expr+=1; }
    else if( *expr == 'O'     ){ op   = OR;  expr+=1; }
    else if( *expr == '|'     ){ op   = OR;  expr+=1; }
    else if( *expr == '('     ){ expr = eval( expr+1, &tmp ); if(NEG) tmp=!tmp; }
    else if( *expr == '\0' ||
             *expr == ')'     ){ if(state == OP2) *res |= mid; return expr; }

         if( state == LEFT               ){ *res  = tmp;               }
    else if( state == MID   && op == OR  ){  mid  = tmp;               }
    else if( state == MID   && op == AND ){ *res &= tmp; state = LEFT; }
    else if( state == OP2   && op == OR  ){ *res |= mid; state = OP1;  }
    else if( state == RIGHT              ){  mid &= tmp; state = MID;  }
  }
}

테스트 :

#include <stdio.h> 

void test( char *expr, int exprval ){
  int result;
  eval( expr, &result );
  printf("expr: '%s' result: %i  %s\n",expr,result,result==exprval?"OK":"FAILED");
}
#define TEST(x)   test( #x, x ) 

#define AND       && 
#define OR        || 

int main(void){
  TEST( ((( 1 AND 0 AND 0) OR 1) AND ((0 OR 1) AND 1)) );
  TEST( !(0 OR (1 AND 0)) OR !1 AND 0 );
}

다른 팁

당신은 포함시킬 수 있습니다 루아 프로그램에서 통역사를 호출하여 표현식을 평가합니다.

직접 굴리는 것은 쉽습니다 재귀 하강 파서 이와 같은 간단한 표현.

나는 구현 된 재귀적인 소개 파서에 비슷한 프로그램을 가지고 있으므로 그것을 닦고 여기에 있습니다.

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

int 도어 (int poprd1, int poprd2) {if (poprd1 == -1) return poprd2; POPRD1 ||를 반환합니다 poprd2; } int doand (int poprd1, int poprd2) {if (poprd1 == -1) return poprd2; POPRD1 && POPRD2를 반환합니다. } int doprocess (char popert, int poprd1, int poprd2) {if (popert == '0') return poprd2; if (popert == 'O') Return Door (Poprd1, Poprd2); if (popert == 'a') return doand (poprd1, poprd2); 풋 ( "알 수없는 연산자 !!!"); 출구 (-1); } int* doparse (char PSTR, int pstart) {char c; int i = pstart; int 값 = -1; char 연산자 = '0'; for (; 계속하다; } if (c == '1') {value = doprocess (연산자, 값, 1); 계속하다; } if (c == '') 계속; if (c == ')') {int Areturn; Areturn = Malloc (2*Areturn의 크기); Areturn [0] = 값; Areturn [1] = i + 1; Areturn의 귀환; } if (c == '(') {int * aresult = doparse (pstr, i + 1); value = doprocess (연산자, 값, aresult [0]); i = aresult [1]; if (pstr [i ] == 0) break; 계속;} if ((c == 'a') && ((pstr [i + 1] == 'n') && (pstr [i + 2] == 'd')) ) {if (((Operator == '0') || (Operator = 'a')) {Operator = 'a'; i += 2; 계속;} else {puts ( "믹스 연산자가 허용되지 않습니다 (그리고 ) !!! "); exit (-1);}} if ((c == 'o') && (pstr [i + 1] == 'r')) {if ((Operator == '0' ) || (OPERATOR == 'O')) {OPERATOR = 'O'; i += 1; 계속;} else {puts ( "믹스 연산자가 허용되지 않습니다 (또는) !!!"); 종료 (-1 );}} printf ( "알 수없는 문자 : '%c ("%s [%d]) !!!", c, pstr, i); exit (-1);} int* areturn; areturn = malloc (2*Areturn의 크기); Areturn [0] = value; areturn [1] = i; return areturn;}

그리고 이것은 테스트 코드입니다.

int main(void) {
    char* aExpr   = "1";
    int*  aResult = doParse(aExpr, 0);
    printf("%s = %d\n", aExpr, ((int*)aResult)[0]);
    free(aResult);
    aExpr   = "0";
    aResult = doParse(aExpr, 0);
    printf("%s = %d\n", aExpr, ((int*)aResult)[0]);
    free(aResult);
    aExpr   = "1 AND 0";
    aResult = doParse(aExpr, 0);
    printf("%s = %d\n", aExpr, ((int*)aResult)[0]);
    free(aResult);
    aExpr   = "1 AND 1";
    aResult = doParse(aExpr, 0);
    printf("%s = %d\n", aExpr, ((int*)aResult)[0]);
    free(aResult);
    aExpr   = "0 OR 0 OR 0";
    aResult = doParse(aExpr, 0);
    printf("%s = %d\n", aExpr, ((int*)aResult)[0]);
    free(aResult);
    aExpr   = "1 OR 0 OR 0";
    aResult = doParse(aExpr, 0);
    printf("%s = %d\n", aExpr, ((int*)aResult)[0]);
    free(aResult);
    aExpr   = "1 OR 1 OR 0";
    aResult = doParse(aExpr, 0);
    printf("%s = %d\n", aExpr, ((int*)aResult)[0]);
    free(aResult);
    aExpr   = "(1 OR 0)";
    aResult = doParse(aExpr, 0);
    printf("%s = %d\n", aExpr, ((int*)aResult)[0]);
    free(aResult);
    aExpr   = "(0 OR 0)";
    aResult = doParse(aExpr, 0);
    printf("%s = %d\n", aExpr, ((int*)aResult)[0]);
    free(aResult);
    aExpr   = "((( 1 AND 0 AND 0) OR 1) AND ((0 OR 1) AND 1))";
    aResult = doParse(aExpr, 0);
    printf("%s = %d\n", aExpr, ((int*)aResult)[0]);
    free(aResult);
    puts("DONE!!!");
    return EXIT_SUCCESS;
}

이것은 재미있다 : -D.

나는 믿는다 Lex와 YACC 이와 같은 간단한 구문 분석 작업을위한 최고의 도구입니다.

얼마 전, 나는 명령 줄 프로세서에 대한 완전한 C 표현 평가자 (예 : C 구문을 사용하여 작성된 표현식)를 작성하고 임베디드 시스템에서 언어를 스크립팅했습니다. 나는 사용했다 이것 시작점으로 알고리즘에 대한 설명. 동반 코드를 직접 사용할 수는 있지만 구현이 마음에 들지 않았고 알고리즘 설명에서 나 자신의 글을 썼습니다. 모든 C 연산자, 기능 호출 및 변수를 지원하기 위해서는 일부 작업이 필요했지만 특히 완전성 수준이 필요하지 않은 경우 명확한 설명이므로 좋은 출발점입니다.

기본 원칙은 스택 및 '리버스 폴란드 표기법'을 사용하여 컴퓨터가 더 쉽게 표현식 평가를 수행하므로 알고리즘은 우선 순서와 괄호와 관련된 순서대로 픽스 표기 표현식을 RPN으로 변환 한 다음, 오페라를 팝핑하여이를 평가합니다. 스택에 작동이 남지 않고 값 1 개가 남아있을 때까지 작업을 수행하고 결과를 누릅니다.

표현 파서를 작성하는 것은 원칙적으로 쉽지만 상당한 노력이 필요합니다.

다음은 Java에서 쓴 기본 to-down recursive descent expression 파서입니다. http://david.tribble.com/src/java/tribble/parse/sql/queryparser.java http://david.tribble.com/src/java/tribble/parse/sql/exprlexer.java http://david.tribble.com/src/java/tribble/parse/sql/exprlexer.java http://david.tribble.com/docs/tribble/parse/sql/package-summary.html

이것은 정확히 당신이 찾고있는 것이 아닐 수도 있지만, 필요한 것에 대한 아이디어를 줄 것입니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top