2017-12-04 52 views
0

그래서 flex/bison에 간단한 C 파서를 만들려고합니다. 함수 및 변수 선언과 구문 분석만을 구문 분석하면됩니다.모든 토큰을 무시하지만 규칙에있는 것들을 무시합니다.

예() I이 .c 파일을 파싱 할 =하면 fopen을 yyin 사용 :

#include <stdio.h> 
int main() 
{ 
    int firstNumber, secondNumber, sumOfTwoNumbers; 

    printf("Enter two integers: "); 

    // Two integers entered by user is stored using scanf() function 
    scanf("%d %d", &firstNumber, &secondNumber); 

    // sum of two numbers in stored in variable sumOfTwoNumbers 
    sumOfTwoNumbers = firstNumber + secondNumber; 

    // Displays sum 
    printf("%d + %d = %d", firstNumber, secondNumber, sumOfTwoNumbers); 

    return 0; 
} 

파서는 변수 선언으로

int firstNumber, secondNumber, sumOfTwoNumbers;

를 검출하고 있어야 변수를 사용할 때마다 계산하십시오.

나는 이미 그렇게 할 수 있습니다. 문제는 단지 "=, +"토큰 또는 // 주석과 같은 모든 특정 사례를 구문 분석 할 필요가 있지만 파일에있을 수 있습니다.

나는 토큰을 인식 할 수 없을 때 yyparse가 yyerror를 호출하지 않도록 모든 토큰을 무시할 수 있기를 원합니다. 따라서 파일이 구문 분석 될 때만 함수/var 선언에 대한 작업을 수행하고 다른 모든 작업은 EOF까지 부드럽게 실행됩니다. C에서 모든 변수 선언 지정자 및 규정의 목록을 시작, 그래서 당신의 규칙과 같이 보일 수 있습니다 :

+0

나는 몇 년 전부터 고대 웹 사이트를 시작했다. 그러나, 그들은 여전히 ​​살아있다 : ​​[ANSI C 문법, Lex 명세서] (https://www.lysator.liu.se/c/ANSI-C-grammar-l.html)와 [ANSI C Yacc 문법] (https://www.lysator.liu.se/c/ANSI-C-grammar-y.html). 이것은 아마도 "C11 표준 컴파일러"로는 충분하지 않지만 IMHO는 자체 실험을 시작하기에 좋은 소스입니다. (내 자신을 위해, 나는 정말로 그것을지지하지 않을 K & R C 인공물을 없애기 위해 그것을 조금 벗겨 냈다.) – Scheff

+0

한때, 나는이 파서를 마스터하는 것이 가장 힘든 일이었습니다 (나를 위해). 이를 위해 [재 지정 가능 C 컴파일러 : 설계 및 구현] (https://www.amazon.com/David-R-Hanson-Retargetable-Implementation/dp/B008VR0B1M)이 정말 도움이되었습니다. – Scheff

답변

0

첫 번째 요구 사항은 만족 상대적으로 쉽다 같은

func: 
    spec_or_qual_list identifier '(' well_nested_tokens ')'';' {...} 
| spec_or_qual_list identifier 
    '(' well_nested_tokens ')''{' body_tokens '}' {...} 
| other_token well_nested_tokens ';' { ... process uses ... } 

body_tokens: 
    %empty      {...} 
| body_tokens var_declaration {...} 
| body_tokens func    {...} 

var_declaration: spec_or_qual_list identifiers ';' { ... }과 몇 가지 규칙을 위의 간단한 규칙은 당신이 당신의 질문에서 준 것과 같은 '평평한'C 파일 (구조 선언이없는 함수와 선언의 목록 또는 함수의 본문이 아닌 다른 블록) 만 구문 분석합니다.

블록을 추가하기로 결정한 후에는 위의 func에 대한 규칙과 비슷한 규칙을 추가해야하므로 블록으로 재귀 적으로 내려 가서 거기에서 선언을 구문 분석 할 수 있습니다. 당신은 단순히 블록을 무시할 수있는 선언의 시작을 놓치기 때문에 단순히 무시할 수 없습니다. 구조체를 삽입하면 구조체 구성원과 변수를 구별하는 것이 훨씬 더 어려워집니다 (또는 범위 지정 규칙이 매우 다르므로 구조체를 구문 적으로 블록으로 처리 할 수있는 경우를 원하지 않을 수 있습니다). 이러한 모든 접근법은 범위 지정 규칙을 무시하므로, 변수가 블록 내에서 전혀 다른 것으로 다시 선언 될 수 있으므로 변수와 선언 사이의 연관을 추적 할 수 없습니다. 마지막으로, typedef 이름을 허용하면 모든 지옥이 느슨해지며 (렉서 해킹을 찾아보십시오) 전체 파서를 작성할 수 있습니다.

이 모든 것의 도덕은 다음과 같습니다. 구문 분석하려는 파일에 사소한 구조가없는 경우 C 구문의 상당 부분을 파싱하게됩니다. 내가 제안 할 수있는 또 다른 간단한 트릭은 C 표현식 (전체)을 작성하고이를 사용하여 C 선언자 (예 : (* pfunc)(int))을 구문 분석하는 것입니다. 이것은 모든 C11 선언자에게는 효과가 없지만 대부분의 '보통'선언자는 처리 할 수 ​​있습니다. 그래도 블록을 처리해야합니다.