작업 열두 - 두 번째 실험 재귀 하강 파서

첫째, 실험의 목적 :

C 언어의 사용은 절차를 구문 분석 재귀 하강하고, 간단한 언어 구문 분석을 컴파일.

다음은 재귀 하강 파서 구문 검사 준비하고 서열 분석에 의해 제공되는 단어가 어휘 분석 프로그램의 구성을 깨닫는다.

 

둘째, 실험 원리

비단 각 심볼은 서브 루틴에 대응한다.

이 서브 루틴은 생산 후 우단에 따른 생산 처리에서 다음 입력 심볼 (SELECT 세트)에 따라 결정된다 :

  • 일치하는 경우, 터미네이터, 현재의 read 단어가 종결 일치하는지 여부를 결정 때마다 만남, 그 다음 단어가 분석을 계속 읽어, 일치하지 않는 오류 프로세스가 실행된다
  • 각각의 만남 비단, 적절한 서브 루틴 호출된다

 

셋째, 실험은 명확한 설명을 요구

문법 올바른 문장, 출력 성공 정보, "성공"을 인쇄 할 경우, 그렇지 않으면 출력 "오류", "#"끝 단어 문자열을 입력하고 유형과 위치의 문법 오류를 지적했다.

예를 들면 :

입력은 시작 = 9, X = 2 * 3, B를 : = A + X 단부 중 #

출력 성공

입력 X : = A + B * C 말단 #

출력 '끝'오류

 

넷째, 실험 절차

1. 언어의 문법은 (P90 참조) 분석 할

2. 적어도 상기 문법에서 발현되는 것으로

- 성명

- 조건

- 표현식

왼쪽 재귀를 제거합니다

4. 추출 왼쪽 공통 요인

5. 세트 컴퓨팅

제 LL (1) 문법 판단

7. 재귀 하강 파서

 

 

마지막 블로그 (연결 https://www.cnblogs.com/a131452/p/11646345.html 향상 코드) :

사용법 #include <conio.h와>
#INCLUDE <STDIO.H>
사용법 #include <string.h>
#INCLUDE <stdlib.h>

숯 두루 [100] zuche [20];
숯불 채널;
INT FG, P, M, N, NUM; 
숯 * 지수 [35] = { "경우", "수행", "동안", "다음", "더블", "ENUM", "플로트"를 "문자"를 "단부", "시작", "INT ","긴 ","짧은 ","서명 ",
"구조체 ","노동 조합 ","서명 ","무효 "," ","휴식 ","계속위한 ","다른 사람 ","고토 " "스위치", "경우", "기본",
"반환", "자동", "통근",}, "휘발성", "고정", "CONST", "를 sizeof", "형식 정의"를 "등록";


보이드 E ();
) (T 무효화;
보이드 E1 ();
보이드 T1 ();
보이드 F ();
빈 에러 ();

보이드 scaner () {
대 (N = 0, N <20; N ++)
zuche [N] = NULL;
m = 0;
NUM = 0;
CH = 두루 [P ++];
(CH2 == '') {//跳过空格동안
CH = 두루 [P ++];
}
경우 (CH2> = 'A'&& CH <= 'Z') {//判断单词
동안 (CH2> = 'A'&& CH <= 'Z') {
zuche [m ++ = CH;
CH = 두루 [P ++];
}
FG = 10;
피--;
대 (N = 0, N <6; N ++) {
경우 (STRCMP (zuche 인덱스 [N]) == 0) {
FG = N + 1;
단절;
}
}
}
또 { 
경우 (CH2> = 0 && CH <= '9') {//判断数字
동안 (CH2> = 0 && CH <= '9') {
NUM = NUM * 10 + (CH- '0');
CH = 두루 [P ++];
}
FG = 11;
피--;




zuche [m ++ = CH;
CH = 두루 [P ++];
경우 (CH2 == '>') {// <>
FG = 22;
zuche [m ++ = CH;
}
다른 경우 (CH2 == '=') {// <=
FG = 21;
zuche [m ++ = CH;
}
다른 {// <
FG = 20;
피--;
}
휴식;

케이스 '>'
m = 0;
zuche [m ++ = CH;
CH = 두루 [P ++];
경우 (CH2 == '=') {//> =
FG = 24;
zuche [m ++ = CH;
}
다른 {//>
FG = 23;
피--;
}
휴식;

케이스 ''
m = 0;
zuche [m ++ = CH;
CH = 두루 [P ++];
경우 (CH2 == '=') {// =
FG = 18;
zuche [m ++ = CH;
}
다른 {// :
FG = 17;
피--;
}
단절;

경우 '+': FG = 13; zuche [0] = CH; 체류;
경우에 '-': FG = 14; zuche [0] = CH; 체류;
경우에 '*': FG = 15; zuche [0] = CH; 체류;
경우에 '/': FG = 16; zuche [0] = CH; 체류;
케이스 '=': FG = 25; zuche [0] = CH; 체류;
케이스 '' ': FG = 26; zuche [0] = CH; 체류;
경우에 '(': FG = 27; zuche [0] = CH; 체류;
케이스 ')': FG = 28; zuche [0] = CH; 체류;
경우에는 '#': FG = 0; zuche [0] = CH; 체류;
기본 : FG = -1; zuche [0] = CH; 체류;
}
}
}
}

보이드 E () {
T ();
E1 ();
}

보이드 E1 () {
경우 (FG == 13) {
scaner ();
티();
E1 ();
}
다른 경우 (FG == 0 || FG == 28) {
}
다른
에러 ();
}

빈 T () {
F ();
T1 ();
}

보이드 T1 () {
경우 (FG == 15) {
scaner ();
에프();
T1 ();
}
다른 경우 (FG == 0 || FG == 28 || FG == 13) {
}
다른
에러 ();
}

보이드 F () {
경우 (FG == 27) {
scaner ();
이자형();
경우 (FG == 28)
scaner ();
다른
오류 ();
}
다른 경우 (FG == 11 || FG == 10)
scaner ();
다른
오류 ();
}

오류 무효 () {
의 printf ( "\ n - (% S, 오류)!", zuche);
}

int로 주 () {
P = 0;
( " '#')와 기호 문자열을 입력합니다 (종료 : \ N-")은 printf와;

{
CH = getchar가 ();
두루 [P ++] = CH;
}는 동안 (CH =! '#');
P = 0;
수행
{
Scaner ()을,
E ();
} while 회 (FG = 0)!


() getch; 프로그램이 표시 페이지에 남아 //위한
}

스크린 샷 결과 :

 

 2,

사용법 #include <conio.h와>
#INCLUDE <STDIO.H>
사용법 #include <string.h>
#INCLUDE <stdlib.h>

숯 두루 [100] zuche [20];
숯불 채널;
INT FG, P, M, N, NUM; 
숯 * 지수 [35] = { "경우", "수행", "동안", "다음", "더블", "ENUM", "플로트"를 "문자"를 "단부", "시작", "INT ","긴 ","짧은 ","서명 ",
"구조체 ","노동 조합 ","서명 ","무효 "," ","휴식 ","계속위한 ","다른 사람 ","고토 " "스위치", "경우", "기본",
"반환", "자동", "통근",}, "휘발성", "고정", "CONST", "를 sizeof", "형식 정의"를 "등록";
INT KK = 0; //判断是否有错误

Scaner 공극 ()
공극 panduan ()
공극 yinzi ()
공극 yuju ()
공극 yucuan ()
공극 tiaojian ()
공극 biaoda ()
공극 시앙 ();


보이드 scaner () {
대 (N = 0, N <20; N ++)
zuche [N] = NULL;
m = 0;
NUM = 0;
CH = 두루 [P ++];
(CH2 == '') {//跳过空格동안
CH = 두루 [P ++];
}
경우 (CH2> = 'A'&& CH <= 'Z') {//判断单词
동안 (CH2> = 'A'&& CH <= 'Z') {
zuche [m ++ = CH;
CH = 두루 [P ++];
}
FG = 10;
피--;
대 (N = 0, N <6; N ++) {
경우 (STRCMP (zuche 인덱스 [N]) == 0) {
FG = N + 1;
단절;
}
}
}
또 { 
경우 (CH2> = 0 && CH <= '9') {//判断数字
동안 (CH2> = 0 && CH <= '9') {
NUM = NUM * 10 + (CH- '0');
CH = 두루 [P ++];
}
FG = 11;
피--;




zuche [m ++ = CH;
CH = 두루 [P ++];
경우 (CH2 == '>') {// <>
FG = 22;
zuche [m ++ = CH;
}
다른 경우 (CH2 == '=') {// <=
FG = 21;
zuche [m ++ = CH;
}
다른 {// <
FG = 20;
피--;
}
휴식;

케이스 '>'
m = 0;
zuche [m ++ = CH;
CH = 두루 [P ++];
경우 (CH2 == '=') {//> =
FG = 24;
zuche [m ++ = CH;
}
다른 {//>
FG = 23;
피--;
}
휴식;

케이스 ''
m = 0;
zuche [m ++ = CH;
CH = 두루 [P ++];
경우 (CH2 == '=') {// =
FG = 18;
zuche [m ++ = CH;
}
다른 {// :
FG = 17;
피--;
}
휴식;

경우 '+': FG = 13; zuche [0] = CH; 체류;
경우에 '-': FG = 14; zuche [0] = CH; 체류;
경우에 '*': FG = 15; zuche [0] = CH; 체류;
경우에 '/': FG = 16; zuche [0] = CH; 체류;
케이스 '=': FG = 25; zuche [0] = CH; 체류;
케이스 '' ': FG = 26; zuche [0] = CH; 체류;
경우에 '(': FG = 27; zuche [0] = CH; 체류;
케이스 ')': FG = 28; zuche [0] = CH; 체류;
경우에는 '#': FG = 0; zuche [0] = CH; 체류;
기본 : FG = -1; zuche [0] = CH; 체류;
}
}
}
}
//程序,判断是否以,开始단부 # 시작结束
공극을 panduan () {
경우 (FG == 1) {// 시작
) (scaner 단계;
() yucuan;
(FG == 6) {// 종료하는 경우
) (scaner;
(FG == 0 && KK == 0) {경우
의 printf ( "성공 \ n");



의 printf ( "오류, 잃다 '끝'\ n!");
KK = 1;
출구 (0);
}
}
다른 {
의 printf ( "오류, 잃다 '시작'\ n!");
KK = 1;
출구 (0);
}
반환;
}
//语句串 
공극 yucuan () {
yuju ();
(FG == 26) {동안 
) (scaner;
yuju ();
}
반환;
}

//语句
공극 yuju () {
경우 (FG == 10) {//为标识符
scaner ();
경우 (FG == 18) {// =
scaner ();
biaoda ();
}
{다른 사람
의 printf ( "오류!");
KK = 1;
출구 (0);
}
}
다른 경우 (FG == 2) {// 경우
tiaojian ();
scaner ();
경우 (FG == 3) {
yuju ();
}
다른 {
의 printf ( "오류, '다음'잃을 \ n!");
KK = 1;
출구 (0);
}
}
다른 {
의 printf ( "오류!");
KK = 1;
출구 (0);
}

반환;
}
//条件
공극 tiaojian () {
biaoda ();
(FG == 25 || FG == 0 || FG == 20 || FG == 21 || FG == 23 || FG == 24) {경우
) (scaner;
}
다른 {
의 printf ( "오류 \ n!");
KK = 1;
출구 (0);
}
biaoda ();
반환;
}
//表达式 
공극 biaoda () {
시앙 ();
(FG == 13 || FG == 14) {동안
) (scaner;
시앙 ();
}
반환;
}
//项 
공극 시앙 () {
yinzi ();
(FG == 15 || FG == 16) {동안
) (scaner;
yinzi ();
}
반환;
}
//因子 
공극 yinzi () {
경우 (FG == 10 || FG == 11) {
scaner (); // 또는 식별자는 정수 상수, 다음 판독 워드 심볼이다
}
다른 IF (FG == 27) {
Scaner ();
biaoda ();
IF (FG == 28) {
Scaner ();
}
{다른
인 printf ( " ')'오류 \ N- ')
KK = 1].
출구 (0);
}
} {다른
의 printf ("오류 식 \ N-')
KK = 1].
출구 (0)
}
리턴;
}

주 (무효) {int로
P = 0;
INT I;
의 printf ( "소스 입력하십시오 : \ N-을");
{할 수
는 scanf ( "%의 C"를, CH을)
두루을 [P ++] = CH;
}는 동안 (CH를! = '#');
P = 0;
{할
Scaner을 ();
panduan를 ();
} while 회 (FG = 0)!
인 printf ( "END \ n 파싱!");

}

다음 샷은 다음과 같습니다 :

추천

출처www.cnblogs.com/dianshuizheng/p/11960152.html