영어프랑스어스페인어

Ad


온웍스 파비콘

다리 - 클라우드의 온라인

Ubuntu Online, Fedora Online, Windows 온라인 에뮬레이터 또는 MAC OS 온라인 에뮬레이터를 통해 OnWorks 무료 호스팅 제공업체에서 레그를 실행하세요.

이는 Ubuntu Online, Fedora Online, Windows 온라인 에뮬레이터 또는 MAC OS 온라인 에뮬레이터와 같은 여러 무료 온라인 워크스테이션 중 하나를 사용하여 OnWorks 무료 호스팅 제공업체에서 실행할 수 있는 명령 레그입니다.

프로그램:

이름


못, 다리 - 파서 생성기

개요


말뚝 [-hvV -출력] [파일 이름 ...]
다리 [-hvV -출력] [파일 이름 ...]

기술


말뚝다리 재귀 하강 파서를 생성하기 위한 도구입니다.
텍스트에 대한 패턴 일치. 그들은 PEG(Parsing Expression Grammar)[Ford 2004]를 처리하여
해당 문법의 법적 문장을 인식하는 프로그램을 생성합니다. 말뚝 PEG 처리
Ford에서 설명한 원래 구문을 사용하여 작성되었습니다. 다리 다음을 사용하여 작성된 PEG를 처리합니다.
매력적으로 만들기 위한 약간 다른 구문 및 규칙
로 구축된 구문 분석기 대체 법률(1)과하면 야크(1). 같지 않은 법률야크, 말뚝다리
무제한 역추적 지원, 명확화를 위한 수단으로 순서가 지정된 선택 제공,
스캐닝(어휘 분석)과 구문 분석(구문 분석)을 하나로 결합할 수 있습니다.
활동.

말뚝 지정된 읽기 파일 이름s 또는 없는 경우 표준 입력 파일 이름s가 주어진다.
생성할 구문 분석기를 설명하는 문법. 말뚝 그런 다음 C 소스 파일을 생성합니다.
함수를 정의합니다 yyparse(). 이 C 소스 파일을 포함하거나 컴파일한 다음
클라이언트 프로그램과 연결됩니다. 클라이언트 프로그램이 호출할 때마다 yyparse() 파서
의 첫 번째 규칙부터 시작하여 구문 분석 규칙에 따라 입력 텍스트를 소비합니다.
문법. yyparse()에 따라 입력을 구문 분석할 수 있는 경우 XNUMX이 아닌 값을 반환합니다.
문법; 입력을 구문 분석할 수 없으면 XNUMX을 반환합니다.

접두사 'yy' 또는 'YY'는 생성된
파서. 이는 클라이언트 프로그램에서 네임스페이스 오염의 위험을 줄이기 위한 것입니다.
('yy'의 선택은 역사적입니다. 법률(1)과하면 야크예를 들면 (1).)

옵션


말뚝다리 다음 옵션을 제공합니다.

-h 사용 가능한 옵션의 요약을 인쇄한 다음 종료합니다.

-o출력
생성된 파서를 파일에 씁니다. 출력 표준 출력 대신.

-v 작업하는 동안 자세한 정보를 표준 오류에 기록합니다.

-V 버전 정보를 표준 오류에 쓴 다음 종료합니다.

A 단순한


다음 말뚝 입력은 다음과 같은 단일 규칙('시작'이라고 함)이 있는 문법을 지정합니다.
입력에 문자열 "username"이 포함되어 있으면 만족합니다.

시작 <- "사용자 이름"

(따옴표는 지원 일치하는 텍스트의 일부; 문자 그대로를 나타내는 역할을 합니다.
일치시킬 문자열입니다.) 즉, yyparse()는 생성된 C 소스에서 반환됩니다.
입력 철자에서 다음 XNUMX개의 문자가 "username"이라는 단어를 읽는 경우에만 XNUMX이 아닙니다.
입력에 다른 것이 포함되어 있으면 yyparse()는 XNUMX을 반환하고 입력이 없을 것입니다.
소비. (이후 호출 yyparse()도 XNUMX을 반환합니다.
문자열 "username"을 찾는 것을 효과적으로 차단했습니다.) 진행을 보장하기 위해 우리는
"사용자 이름"인 경우 단일 문자와 일치하는 '시작' 규칙에 대한 대체 절
찾을 수 없습니다.

시작 <- "사용자 이름"
/.

yyparse()는 이제 항상 XNUMX이 아닌 값을 반환합니다(입력 맨 끝 제외). 할 것
규칙에 작업을 추가할 수 있습니다. 이러한 작업은
완전한 일치가 발견되고(첫 번째 규칙부터 시작) 다음에 따라 선택됩니다.
입력과 일치하도록 문법을 통해 가져온 '경로'. (언어학자들은 이 경로를
'구문 마커'.)

start <- "사용자 이름" { printf("%s\n", getlogin()); }
/ < . > { putchar(yytext[0]); }

첫 번째 줄은 파서가 볼 때마다 사용자의 로그인 이름을 인쇄하도록 지시합니다.
입력에 "사용자 이름". 해당 일치가 실패하면 두 번째 줄은 파서에 반향하도록 지시합니다.
입력의 다음 문자는 표준 출력입니다. 이제 파서가 유용하게 작동하고 있습니다.
작업: 입력을 출력에 복사하고 모든 "username" 항목을 다음으로 바꿉니다.
사용자의 계정 이름.

두 번째 대안에 추가된 꺾쇠 괄호('<' 및 '>')에 유의하십시오. 이것들
규칙의 의미에 영향을 미치지 않지만 사용할 수 있는 텍스트를 구분하는 역할을 합니다.
변수의 다음 작업 yytext.

위의 문법을 파일에 넣으면 사용자 이름.peg, 명령 실행

못 -o 사용자 이름.c 사용자 이름.peg

해당 파서를 파일에 저장합니다. 사용자 이름.c. 완전한 프로그램을 만들려면
이 파서는 다음과 같이 C 프로그램에 포함될 수 있습니다.

#포함하다 /* printf(), putchar() */
#포함하다 /* getlogin() */

#include "username.c" /* yyparse() */

int main ()
{
while (yyparse()) /* EOF까지 반복 */
;
0가 돌아;
}

PEG 문법


문법은 명명된 규칙 집합으로 구성됩니다.

이름 <- 패턴

XNUMXD덴탈의 무늬 다음 요소 중 하나 이상을 포함합니다.

name 요소는 주어진 규칙의 전체 패턴을 나타냅니다. name.

"문자"
큰따옴표로 묶인 문자나 문자열은 문자 그대로 일치합니다. ANSI C
이스케이프 시퀀스는 문자.

'문자'
작은 따옴표로 묶인 문자 또는 문자열은 위와 같이 문자 그대로 일치합니다.

[문자]
대괄호로 묶인 문자 세트는 다음의 단일 문자와 일치합니다.
위와 같이 인식되는 이스케이프 문자가 있는 세트. 세트가 a로 시작하는 경우
위쪽 화살표(^)를 사용하면 집합이 부정됩니다(요소는 모든 문자와 일치함). 지원 FBI 증오 범죄 보고서
세트). 대시(-)로 구분된 문자 쌍은
첫 번째부터 두 번째까지의 문자를 포함합니다. 단일 알파벳 문자
또는 밑줄은 다음 세트와 일치합니다.

[a-zA-Z_]

마찬가지로 다음은 숫자가 아닌 단일 문자와 일치합니다.

[^0-9]

. 점은 모든 문자와 일치합니다. 이것이 실패하는 유일한 시간은
일치하는 문자가 없는 파일입니다.

( 무늬 )
괄호는 그룹화(연산자의 우선 순위 수정)에 사용됩니다.
아래에서 묘사 되어진).

{ 동작 }
중괄호는 동작을 둘러쌉니다. 작업은 임의의 C 소스 코드입니다.
일치 종료 시 실행됩니다. 작업 내의 모든 중괄호는 적절해야 합니다.
중첩. 작업 전에 일치하고 각도로 구분된 모든 입력 텍스트
대괄호(아래 참조)는
문자 배열 yytext. (문자 수)의 길이 yytext is
변수에서 사용 가능 일렝. (이러한 변수 이름은 역사적입니다.
법률(1).)

< 여는 꺾쇠 괄호는 항상 일치하며(입력을 사용하지 않음) 파서가
일치하는 텍스트 누적을 시작합니다. 이 텍스트는
변수 yytext.

> 닫는 꺾쇠 괄호는 항상 일치하며(입력을 사용하지 않음) 파서가
에 대한 텍스트 누적을 중지하려면 yytext.

위의 요소s는 다음 접미사를 사용하여 선택적 및/또는 반복 가능하게 만들 수 있습니다.

요소 ?
요소는 선택 사항입니다. 입력에 있으면 소비되고 일치
성공합니다. 입력에 없으면 텍스트가 소비되지 않고 일치가 성공합니다.
어쨌든.

요소 +
요소는 반복 가능합니다. 입력에 있는 경우 하나 이상의
요소 소비되고 일치가 성공합니다. 발생하지 않는 경우 요소 are
입력에 있으면 일치가 실패합니다.

요소 *
요소는 선택 사항이며 반복 가능합니다. 입력에 있는 경우 하나 이상의
의 발생 요소 소비되고 일치가 성공합니다. 발생하지 않는 경우
요소 입력에 있는 경우 어쨌든 일치가 성공합니다.

위의 요소와 접미사는 술어로 변환될 수 있습니다(임의로 일치하는
텍스트 입력 후 성공 또는 실패 없이 해당 입력 소비)
다음 접두사:

& 요소
조건자는 다음과 같은 경우에만 성공합니다. 요소 일치시킬 수 있습니다. 동안 스캔한 입력 텍스트
어울리는 요소 입력에서 소비되지 않고 계속 사용할 수 있습니다.
후속 매칭.

! 요소
조건자는 다음과 같은 경우에만 성공합니다. 요소 일치할 수 없습니다. 동안 스캔한 입력 텍스트
어울리는 요소 입력에서 소비되지 않고 계속 사용할 수 있습니다.
후속 매칭. 인기있는 관용구는

!.

입력의 마지막 문자가 이미 입력된 후 파일의 끝과 일치합니다.
소비되었습니다.

'&' 술어의 특수 형식이 제공됩니다.

&{ 표현 }
이 술어에서 간단한 C 표현 (지원 문) 즉시 평가
파서가 술어에 도달할 때. 만약 표현 XNUMX이 아닌 수율(참)
'일치'가 성공하고 파서는 패턴의 다음 요소로 계속됩니다.
경우 표현 XNUMX(거짓)을 생성하면 '일치'가 실패하고 파서는 다음으로 백업합니다.
입력의 대체 구문 분석을 찾으십시오.

접두사 및 접미사를 포함하거나 포함하지 않는 여러 요소를 하나의 요소로 결합할 수 있습니다. 순서
하나씩 하나씩 써서. 전체 시퀀스는 각 개인이 일치하는 경우에만 일치합니다.
그 안의 요소는 왼쪽에서 오른쪽으로 일치합니다.

시퀀스는 교대 연산자 '/'에 의해 분리된 대안으로 분리될 수 있습니다.

시퀀스-1 / 시퀀스-2 / ... / 시퀀스-N
각 시퀀스는 그 중 하나가 일치할 때까지 차례로 시도되며 일치하는 시점에
전체 패턴이 성공하기 때문입니다. 일치하는 시퀀스가 ​​없으면 일치
전체 패턴이 실패합니다.

마지막으로 파운드 기호(#)는 끝까지 계속되는 주석(버려짐)을 소개합니다.
라인의.

위의 내용을 요약하면 파서는 입력 텍스트를 패턴과 일치시키려고 시도합니다.
리터럴, 이름(다른 규칙을 나타냄) 및 다양한 연산자(
시퀀싱을 위한 접두사, 접미사, 병치 및 중위 교체 연산자)
패턴 내의 요소가 일치하는 방식을 수정합니다. 일치는 왼쪽에서
오른쪽, 이름이 지정된 하위 규칙을 만나면 '내림차순'으로 이동합니다. 매칭 과정을 거치면
실패하면 파서가 '역추적'(프로세스에서 적절하게 입력을 '되감기')
문법을 통해 가장 가까운 대안 '경로'를 찾습니다. 다시 말해 파서
성공적으로 일치하는 첫 번째 경로에 대해 깊이 우선, 왼쪽에서 오른쪽 검색을 수행합니다.
규칙을 통해. 찾은 경우 성공적인 경로를 따라 작업이 실행됩니다(에서
발생한 순서).

술어가 평가된다는 점에 유의하십시오. 바로 성공적인 경기를 찾는 동안,
검색의 성공 또는 실패에 기여하기 때문입니다. 그러나 행동은
성공적인 일치가 발견된 후에만 평가됩니다.

PEG 문법 위한 PEG 문법


문법 말뚝 문법은 아래와 같습니다. 이것은 다음을 설명하고 공식화합니다.
위의 설명.

문법 <- 간격 정의+ EndOfFile

정의 <- 식별자 LEFTARROW 식
표현식 <- 시퀀스 ( SLASH 시퀀스 )*
시퀀스 <- 접두사*
접두사 <- AND 작업
/ ( 그리고 | 아님 )? 접미사
접미사 <- 기본( QUERY / STAR / PLUS )?
기본 <- 식별자 !LEFTARROW
/ OPEN 식 CLOSE
/ 리터럴
/ 수업
/ 점
/ 동작
/ 시작하다
/ 끝

식별자 <- < IdentStart IdentCont* > 간격
IdentStart <- [a-zA-Z_]
IdentCont <- IdentStart / [0-9]
리터럴 <- ['] < ( !['] Char )* > ['] 간격
/ ["] < ( !["] 문자 )* > ["] 간격
클래스 <- '[' < ( !']' 범위 )* > ']' 간격
범위 <- 문자 '-' 문자 / 문자
문자 <- '\\' [abefnrtv'"\[\]\\]
/ '\\' [0-3][0-7][0-7]
/ '\\' [0-7][0-7]?
/ '\\' '-'
/ !'\\' .
왼쪽 화살표 <- '<-' 간격
슬래시 <- '/' 간격
AND <- '&' 간격
NOT <- '!' 간격
쿼리 <- '?' 간격
STAR <- '*' 간격
더하기 <- '+' 간격
열기 <- '(' 간격
닫기 <- ')' 간격
점 <- '.' 간격
간격 <- ( 공백 / 주석 )*
주석 <- '#' ( !EndOfLine . )* EndOfLine
공백 <- ' ' / '\t' / EndOfLine
EndOfLine <- '\r\n' / '\n' / '\r'
EndOfFile <-!.
작업 <- '{' < [^}]* > '}' 간격
BEGIN <- '<' 간격
END <- '>' 간격

LEG 문법


다리 의 변종이다 말뚝 몇 가지 기능을 추가하는 법률(1)과하면 야크(1). 그것은 다르다
말뚝 다음과 같은 방법으로.

%{ 텍스트... %}
선언 섹션은 규칙 정의가 예상되는 모든 위치에 나타날 수 있습니다. 그만큼
본문 구분 기호 '%{'와 '%}' 사이는 생성된 C에 그대로 복사됩니다.
파서 코드 전에 파서 자체를 구현하는 코드.

name = 무늬
'할당' 연산자는 왼쪽 화살표 연산자 '<-'를 대체합니다.

규칙 이름
하이픈은 규칙 이름에 문자로 나타날 수 있습니다. 각 하이픈은 다음으로 변환됩니다.
생성된 C 소스 코드의 밑줄. 단일 하이픈 '-'는
법적 규칙 이름.

- = [ \t\n\r]*
숫자 = [0-9]+ -
이름 = [a-zA-Z_][a-zA_Z_0-9]* -
패렌 = '(' -
r-괄호 = ')' -

이 예는 문법을 읽을 때 무시된 공백이 어떻게 명백할 수 있는지 보여줍니다.
그러나 관련된 모든 규칙의 끝에 자유롭게 배치할 때 눈에 거슬리지 않습니다.
어휘 요소.

시퀀스-1 | 시퀀스-2
교대 연산자는 수직 막대 '|' 슬래시 '/' 대신. 그만큼
말뚝 지배

이름 <- 시퀀스-1
/ 시퀀스-2
/ 시퀀스-3

그러므로 쓰여진다

이름 = 시퀀스-1
| 시퀀스-2
| 시퀀스-3
;

in 다리 (다음에 설명된 대로 마지막 세미콜론은 선택 사항입니다).

특급 ~ { 동작 }
후위 연산자 ~{ 동작 } 모든 식 뒤에 배치할 수 있으며 동작합니다.
다음과 같은 경우에만 호출된다는 점을 제외하면 일반 작업(임의의 C 코드)과 같습니다. 특급
실패합니다. 교대 및
오류 처리 및 복구 코드를 더 쉽게 만들기 위한 것입니다.
쓰다. 참고 yytext일렝 이러한 작업 내에서는 사용할 수 없지만
포인터 변수 yy 사용자 정의에 대한 코드 액세스 권한을 부여할 수 있습니다.
파서 상태의 구성원(아래 "파서 사용자 정의" 참조). 또한
특급 는 항상 단일 표현식입니다. 내 실패에 대한 오류 조치를 호출합니다.
시퀀스, 시퀀스를 단일 그룹으로 그룹화하려면 괄호를 사용해야 합니다.
표현.

규칙 = e1 e2 e3 ~{ error("e[12] ok; e3가 실패했습니다."); }
| ...

rule = (e1 e2 e3) ~{ error("e[123] 중 하나가 실패했습니다."); }
| ...

무늬 ;
세미콜론 구두점은 선택적으로 무늬.

%% 텍스트...
이중 퍼센트 '%%'는 규칙(및 선언) 섹션을 종료합니다.
문법. 모두 본문 다음 '%%'는 생성된 C 파서 코드에 그대로 복사됩니다.
시간 내에 파서 구현 코드.

$$ = 가치
하위 규칙은 시맨틱을 반환할 수 있습니다. 가치 작업에서
의사 변수 '$$'. 모든 시맨틱 값은 동일한 유형이어야 합니다(기본값은
'int'로). 이 유형은 선언 섹션에서 YYSTYPE을 정의하여 변경할 수 있습니다.

식별자:name
하위 규칙에서 반환된 의미 값('$$'에 할당) name is
관련 식별자 후속 작업에서 참조할 수 있습니다.

아래 탁상용 계산기 예는 '$$' 및 ':'의 사용을 보여줍니다.

LEG 예 : A DESK 계산자


의 확장 다리 위에서 설명한 대로 유용한 파서 및 평가자(포함)를 허용합니다.
선언, 문법 규칙 및 'main'과 같은 지원 C 함수)
단일 소스 파일. 이를 설명하기 위해 다음을 지원하는 간단한 탁상 계산기를 보여줍니다.
XNUMX개의 일반적인 산술 연산자 및 명명된 변수. 의 중간 결과
산술 평가는 다음과 같이 반환하여 암시적 스택에 누적됩니다.
하위 규칙의 의미론적 값.

%{
#포함하다 /* 프린트프() */
#포함하다 /* atoi() */
int 변수[26];
%}

Stmt = - e:Expr EOL { printf("%d\n", e); }
| ( !EOL . )* EOL { printf("오류\n"); }

Expr = i:ID 할당 s:Sum { $$ = vars[i] = s; }
| s:합 { $$ = s; }

합계 = l:제품
( PLUS r:제품 { l += r; }
| 빼기 r:제품 { l -= r; }
)* { $$ = l; }

제품 = l:가치
( TIMES r:값 { l *= r; }
| 나누기 r:값 { l /= r; }
)* { $$ = l; }

값 = i:NUMBER { $$ = atoi(yytext); }
| i:ID !ASSIGN { $$ = vars[i]; }
| OPEN i:Expr CLOSE { $$ = i; }

NUMBER = < [0-9]+ > - { $$ = atoi(yytext); }
ID = < [az] > - { $$ = yytext[0] - 'a'; }
할당 = '=' -
더하기 = '+' -
빼기 = '-' -
시간 = '*' -
나누기 = '/' -
열기 = '(' -
닫기 = ')' -

- = [ \t]*
EOL = '\n' | '\r\n' | '\r' | ';'

%%

int main ()
{
동안 (yyparse())
;
0가 돌아;
}

LEG 문법 위한 LEG 문법


문법 다리 문법은 아래와 같습니다. 이것은 다음을 설명하고 공식화합니다.
위의 설명.

문법 = -
( 선언 | 정의 )+
트레일러? 파일 끝

선언 = '%{' < ( !'%}' . )* > RPERCENT

트레일러 = '%%' < .* >

정의 = 식별자 EQUAL 표현식 SEMICOLON?

식 = 시퀀스( BAR 시퀀스 )*

시퀀스 = 오류+

오류 = 접두사( 물결표 동작 )?

접두사 = AND 작업
| ( 그리고 | 아님 )? 접미사

접미사 = 기본( QUERY | STAR | PLUS )?

기본 = 식별자 COLON 식별자 !EQUAL
| 식별자 !EQUAL
| 열기 식 닫기
| 오자
| 수업
| 점
| 행동
| 시작하다
| 끝

식별자 = < [-a-zA-Z_][-a-zA-Z_0-9]* > -

리터럴 = ['] < ( !['] 문자 )* > ['] -
| ["] < ( !["] 문자 )* > ["] -

클래스 = '[' < ( !']' 범위 )* > ']' -

범위 = 문자 '-' 문자 | 숯

문자 = '\\' [abefnrtv'"\[\]\\]
| '\\' [0-3][0-7][0-7]
| '\\' [0-7][0-7]?
| !'\\' .

작업 = '{' < 중괄호* > '}' -

중괄호 = '{' 중괄호* '}'
| !'}' .

같음 = '=' -
콜론 = ':' -
세미콜론 = ';' -
바 = '|' -
그리고 = '&' -
NOT = '!' -
쿼리 = '?' -
스타 = '*' -
더하기 = '+' -
열기 = '(' -
닫기 = ')' -
점 = '.' -
시작 = '<' -
종료 = '>' -
물결표 = '~' -
RPERCENT = '%}' -

- = ( 공백 | 주석 )*
공백 = ' ' | '\t' | 줄 끝
comment = '#' ( !행 끝 . )* 행 끝
라인 끝 = '\r\n' | '\n' | '\아르 자형'
파일 끝 = !.

커스터마이징 L' 파서


선언 섹션에서 다음 기호를 재정의하여 생성된
파서 코드.

YYSTYPE
시맨틱 값 유형입니다. 의사 변수 '$$' 및 식별자 '바운드'
콜론 연산자 ':'가 있는 규칙 결과는 모두 선언된 것으로 간주되어야 합니다.
이 유형을 가지려면. 기본값은 'int'입니다.

YYPARSE
파서에 대한 기본 진입점의 이름입니다. 기본값은 'yyparse'입니다.

예파세프롬
구문 분석기에 대한 대체 진입점의 이름입니다. 이 함수는 하나를 기대합니다
인수: 일치를 검색하는 규칙에 해당하는 함수
시작해야 합니다. 기본값은 'yyparsefrom'입니다. yyparse()는 다음과 같이 정의됩니다.

int yyparse() { return yyparsefrom(yy_foo); }

여기서 'foo'는 문법의 첫 번째 규칙 이름입니다.

YY_INPUT(buf, 결과, 최대 크기)
이 매크로는 더 많은 입력 텍스트를 얻기 위해 구문 분석기에 의해 호출됩니다. buf 을 가리킨다
최대 저장할 수 있는 메모리 영역 최대 크기 문자. 매크로는 복사해야 합니다.
에 텍스트 입력 buf 그런 다음 정수 변수를 할당합니다. 결과 표시하기 위해
복사된 문자 수. 더 이상 입력할 수 없는 경우 매크로는
에 0 할당 결과. 기본적으로 YY_INPUT 매크로는 다음과 같이 정의됩니다.

#define YY_INPUT(buf, 결과, 최대 크기) \
{ \
int yyc= getchar(); \
결과= (EOF == yyc) ? 0 : (*(buf)= yyc, 1); \
}

YY_CTX_LOCAL이 정의된 경우(아래 참조) 추가 첫 번째 인수,
파서 컨텍스트를 포함하는 YY_INPUT으로 전달됩니다.

YY_DEBUG
이 기호가 정의되면 파서에 추가 코드가 포함됩니다.
파서가 표준 오류에 방대한 양의 난해한 정보를 인쇄하는 동안
실행 중입니다.

YY_BEGIN
이 매크로는 사용할 수 있게 될 입력 텍스트의 시작을 표시하기 위해 호출됩니다.
행동에서 'yytext'로. 이것은 문법에서 '<'의 발생에 해당합니다.
이들은 성공할 것으로 예상되는 술어로 변환됩니다. 기본값
정의

#define YY_BEGIN(yybegin= yypos, 1)

따라서 현재 입력 위치를 저장하고 다음 결과로 1('true')을 반환합니다.
술어.

YY_END 이 매크로는 문법에서 '>'에 해당합니다. 다시 말하지만 술어이므로
기본 정의는 '성공' 전에 입력 위치를 저장합니다.

#define YY_END (yyend= yypos, 1)

YY_PARSE(T)
이 매크로는 구문 분석기 진입점(yyparse 및 yyparsefrom)을 다음 유형으로 선언합니다.
T. 기본 정의

#define YY_PARSE(T) T

yyparse() 및 yyparsefrom()은 전역 가시성을 유지합니다. 그들이해서는 안되는 경우
다른 소스 파일에서 외부적으로 볼 수 있으므로 이 매크로를 재정의하여 선언할 수 있습니다.
그것들은 '정적'입니다.

#define YY_PARSE(T) 정적 T

YY_CTX_LOCAL
생성된 파서를 컴파일하는 동안 이 기호가 정의되면 전역
파서 상태는 선언될 수 있는 'yycontext' 유형의 구조에 보관됩니다.
지역 변수로. 이를 통해 파서의 여러 인스턴스가 공존하고
스레드로부터 안전해야 합니다. 구문 분석 기능 yyparse()는 첫 번째를 기대한다고 선언됩니다.
'yycontext *' 유형의 인수, 전역을 보유하는 구조의 인스턴스
파서의 상태. 이 인스턴스는 다음에 의해 할당되고 XNUMX으로 초기화되어야 합니다.
클라이언트. 사소하지만 완전한 예는 다음과 같습니다.

#포함하다

#YY_CTX_LOCAL 정의

#include "the-generated-parser.peg.c"

int main ()
{
yycontext ctx;
memset(&ctx, 0, sizeof(yycontext));
동안 (yyparse(&ctx));
0가 돌아;
}

이 기호가 정의되지 않은 경우 컴파일된 파서는 정적으로
전역 상태를 할당하고 재진입도 스레드로부터 안전하지도 않습니다. 또한 참고
파서 yycontext 구조가 처음에 자동으로 초기화됨
yyparse()가 호출됩니다. 이 구조 절대로 필요한 것 따라서 적절하게 XNUMX으로 초기화되어야 합니다.
처음 전화하기 전에 yyparse().

YY_CTX_멤버
YY_CTX_LOCAL이 정의된 경우(위 참조) 매크로 YY_CTX_MEMBERS를 정의할 수 있습니다.
클라이언트가 원하는 추가 멤버 필드 선언으로 확장
'yycontext' 구조 유형의 선언에 포함됩니다. 이러한 추가
그렇지 않으면 생성된 파서에서 멤버를 무시합니다. 'yycontext'의 인스턴스
현재 활성 파서와 관련된
포인터 변수 yy.

YY_BUFFER_SIZE
텍스트 버퍼의 초기 크기(바이트)입니다. 기본값은 1024이고 버퍼는
구문 분석 중에 수요를 충족하기 위해 필요할 때마다 크기가 두 배가 됩니다. 지원서
일반적으로 훨씬 더 긴 문자열을 구문 분석하는 경우 불필요한 것을 방지하기 위해 이 값을 늘릴 수 있습니다.
버퍼 재할당.

YY_STACK_SIZE
변수 및 작업 스택의 초기 크기입니다. 기본값은 128입니다.
구문 분석 중에 수요를 충족해야 할 때마다 두 배가 됩니다. 가지고 있는 애플리케이션
로컬 변수가 많거나 여러 작업을 수행하는 딥 콜 스택
하나의 성공적인 일치, 불필요한 버퍼를 피하기 위해 이 값을 높일 수 있음
재할당.

YY_MALLOC(YY, SIZE)
모든 파서 관련 저장소의 메모리 할당자입니다. 매개변수는
현재 yycontext 구조 및 할당할 바이트 수. 기본값
정의는: malloc(SIZE)

YY_REALOC(YY, PTR, SIZE)
동적으로 확장되는 스토리지(예: 텍스트 버퍼 및
변수 스택). 매개변수는 현재 yycontext 구조,
이전에 할당된 스토리지 및 해당 스토리지가 할당해야 하는 바이트 수
성장하다. 기본 정의는 다음과 같습니다.PTR, SIZE)

YY_FREE(YY, PTR)
메모리 할당 해제자. 매개변수는 현재 yycontext 구조와
할당을 해제할 저장소입니다. 기본 정의는 다음과 같습니다.PTR)

YY 릴리스
yycontext 구조가 보유한 모든 리소스를 해제하는 함수의 이름입니다.
기본값은 'yyrelease'입니다.

작업 내에서 참조할 수 있는 변수는 다음과 같습니다.

이륜 전차 *yybuf
이 변수는 다음과 같은 입력 텍스트를 저장하는 데 사용되는 파서의 입력 버퍼를 가리킵니다.
아직 일치하지 않았습니다.

INT 이포스
일치하고 사용할 다음 문자의 오프셋(yybuf)입니다.

이륜 전차 *yy텍스트
'<' 및 '>'로 구분된 가장 최근 일치 텍스트가 이 변수에 저장됩니다.

INT 일렝
이 변수는 'yytext'의 문자 수를 나타냅니다.

yy 문맥 *년
이 변수는 다음과 관련된 'yycontext'의 인스턴스를 가리킵니다.
현재 활성 파서.

파서와 관련된 모든 리소스를 해제하려는 프로그램은 다음을 사용할 수 있습니다.
다음 기능.

yyrelease(yy컨텍스트*yy)
관련된 모든 구문 분석기 할당 저장소를 반환합니다. yy 시스템에. 저장
다음에 호출할 때 재할당됩니다. yyparse().

yycontext 구조 자체에 대한 스토리지는 할당되거나 회수되지 않습니다.
암묵적으로. 애플리케이션은 이러한 구조를 자동 스토리지에 할당하거나
Calloc() 및 비어 있는() 명시적으로 관리합니다. 다음 섹션의 예
리소스 관리에 대한 한 가지 접근 방식을 보여줍니다.

LEG 예 : 확장 L' 파서의 문맥


XNUMXD덴탈의 yy 작업에 전달된 변수에는 구문 분석기의 상태와 추가 정보가 포함됩니다.
YY_CTX_MEMBERS에 의해 정의된 필드. 이러한 필드는 응용 프로그램별 저장에 사용할 수 있습니다.
의 특정 호출에 대한 전역 정보 yyparse(). 사소하지만 완전한 다리
yycontext 구조가 계산 의 수
지금까지 입력에 표시된 개행 문자(그렇지 않으면 문법이 소비하고 무시합니다.
전체 입력). 발신자 yyparse() 용도 계산 의 줄 수를 인쇄하려면
읽은 입력.

%{
#YY_CTX_LOCAL 1 정의
#YY_CTX_MEMBERS 정의 \
정수 수;
%}

문자 = ('\n' | '\r\n' | '\r') { yy->카운트++ }
| .

%%

#포함하다
#포함하다

int main ()
{
/* 자동 저장소에 로컬 파서 컨텍스트 생성 */
yy 문맥 yy;
/* 컨텍스트는 *반드시* 처음 사용하기 전에 XNUMX으로 초기화되어야 합니다*/
memset(&yy, 0, sizeof(yy));

동안 (yyparse(&yy))
;
printf("%d 개행\n", yy.count);

/* 컨텍스트와 관련된 모든 리소스 해제 */
yyrelease(&yy);

0가 돌아;
}

진단


말뚝다리 문법을 파서로 변환하는 동안 다음 조건에 대해 경고합니다.

구문 오류
입력 문법이 어떤 식으로든 잘못되었습니다. 오류 메시지에는 다음이 포함됩니다.
매칭을 앞둔 텍스트(종종 실제 위치에서 엄청난 양을 백업
오류) 및 가장 최근에 고려된 문자의 줄 번호(
종종 문제의 실제 위치).

지배 '푸' 익숙한 비자 면제 프로그램에 해당하는 국가의 시민권을 가지고 있지만 지원 한정된
문법은 'foo'라는 이름의 규칙을 참조했지만 그에 대한 정의는 제공되지 않았습니다.
생성된 파서를 사용하려고 하면 링커에서 오류가 발생할 수 있습니다.
누락된 규칙과 관련된 정의되지 않은 기호로 인해.

지배 '푸' 한정된 비자 면제 프로그램에 해당하는 국가의 시민권을 가지고 있지만 지원 익숙한
문법은 'foo'라는 규칙을 정의한 다음 무시했습니다. 관련된 코드
규칙과 함께 생성된 파서에 포함되어 다른 모든 측면에서
건강.

가능한 무한의 왼쪽 (left) 재귀 in 지배 '푸'
규칙 'foo'에서 이어지는 문법을 통해 적어도 하나의 경로가 존재합니다.
입력을 사용하지 않고 동일한 규칙으로 되돌립니다(재귀 호출).

특히 표준 문서에서 발견되는 왼쪽 재귀는 종종 '직접'이고
사소한 반복을 의미합니다.

#(6.7.6)
직접 추상 선언자 =
LPAREN 추상 선언자 RPAREN
| 직접 추상 선언자? LBRACKET assign-expr? R브래킷
| 직접 추상 선언자? L브래킷 스타 R브래킷
| 직접 추상 선언자? LPAREN 매개변수 유형 목록? RPAREN

재귀는 다음 패턴의 일부를 변환하여 쉽게 제거할 수 있습니다.
반복 가능한 접미사로의 재귀.

#(6.7.6)
직접 추상 선언자 =
직접 추상 선언자 머리?
직접-추상-선언자-꼬리*

직접 추상 선언자 헤드 =
LPAREN 추상 선언자 RPAREN

직접 추상 선언자 꼬리 =
LBRACKET assign-expr? R브래킷
| L브래킷 스타 R브래킷
| LPAREN 매개변수 유형 목록? RPAREN

경고


빈 입력을 받아들이는 파서는 항상 성공하다. 다음 예를 고려하십시오.
PEG 기반 파서를 작성하려는 첫 번째 시도가 이례적이지 않습니다.

프로그램 = 표현식*
표현 = "아무거나"
%%
int main () {
동안 (yyparse())
puts("성공!");
0가 돌아;
}

이 프로그램은 stdin에 어떤 입력이 제공되더라도 영원히 반복됩니다. 많은
수정이 가능하며 가장 쉬운 방법은 파서가 항상 일부를 소비하도록 주장하는 것입니다.
비어 있지 않은 입력. 첫 줄을 다음으로 변경

프로그램 = 익스프레션+

이것을 성취합니다. 파서가 전체 입력을 사용할 것으로 예상되는 경우 명시적으로
파일 끝을 요구하는 것도 적극 권장됩니다.

프로그램 = 표현식+ !.

이것은 구문 분석기가 모든 문자를 일치시키는 데 실패("!" 술어)하기 때문에 작동합니다.
("." 식) 입력의 끝을 넘어 읽으려고 할 때.

onworks.net 서비스를 사용하여 온라인으로 다리를 사용하세요


무료 서버 및 워크스테이션

Windows 및 Linux 앱 다운로드

Linux 명령

Ad