Polishtalk
14315 단어 PharoPetitParser
Lukas Renggli가 쓴 PetitParer는 매우 편리하다.
도쿄의 Smalltalk 학습회에서도 언급했듯이 그때는 쉬었다. 작은 단락으로 나는 덧셈과 뺄셈, 이위 연산의 폴란드 기법의 파라를 써 보았다.
폴란드 기수의 정수 가감 연산
어떤 모임을 쓰고 싶은지 EBNF라면 다음과 같은 느낌이 든다.
expr = num | add | sub | lshift | rshift;
num = non zero digit , {digit} ;
add = '+' expr expr ;
sub = '-' expr expr ;
lshift = '<<' expr expr ;
rshift = '>>' expr expr ;
non zero digit = '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' ;
digit = '0' | non zero digit ;
Polish Gramer 레벨먼저 폴란드 기법의 문법 정의를 실시한다.완전한 문법 정의를 할 때 PetitParer는 PPComositeParer라는 편의 클래스를 가지고 있다.이걸로 보자.
Polish Grammer 클래스를 PPComposiiteParer의 하위 클래스로 정의합니다.
PPCompositeParser subclass: #PolishGrammar
instanceVariableNames: ''
classVariableNames: ''
category: 'SmalltalkAdvent2015'
폴란드 기법의 문법을 정의합니다.먼저 PPComositeParer의 약정으로 start 방법을 정의해야 합니다.
그 다음에 정의를 잘 하고 먼저 빈 방법으로 얼버무리세요.
PolishGrammar
start
non zero digit 및 digit 정의먼저 non zero digit을 정의합니다.non zero digit을 적용하는 파서가 있는 인스턴스 변수를 정의합니다.
PPCompositeParser subclass: #PolishGrammar
instanceVariableNames: 'nonZeroDigit'
classVariableNames: ''
category: 'SmalltalkAdvent2015'
그런 다음 nonZeroDigit Para를 생성하는 방법을 정의합니다.PolishGrammar
nonZeroDigit
^ '1' asParser / '2' asParser / '3' asParser / '4' asParser / '5' asParser / '6' asParser / '7' asParser / '8' asParser / '9' asParser
EBNF에서 non zero digit의 정의와 동일합니다.PetitParrser에서 문자열 객체에 asperer 메시지를 던지면 문자열을 적용할 파티션을 생성할 수 있습니다.만약 순서대로 선택/결합을 표시한다면 우선/의 왼쪽 파이사가 받아들일 수 있는지 시험해 보고 성공하면 OK, 실패하면 오른쪽 파이사를 시험해 보자.그럼 nonZero Digit을 사용해 봅시다.
PolishGrammar new nonZeroDigit parse: '123'
결과는'1'이다.PolishGrammar new nonZeroDigit parse: '0123'
PPFailure 객체를 반환합니다. 객체에'1'expected at0'오류 메시지가 있습니다.다음은digit를 정의합니다.
PolishGrammar
digit
^ '0' asParser | nonZeroDigit
여기서 중점은 nonZeroDigit이라는 실례 변수는 nonZeroDigit 방법으로 정의된 해상도가 대입한 것이다.PPComposiiteParer는 하위 클래스에서 인스턴스 변수를 정의한 후 같은 이름을 가진 방법을 찾아 자동으로 초기화합니다.'nonZero Digit'같은 보일러판을 일일이 쓸 필요가 없다.스몰톡 스타일의 메탈 구조입니다.digit 동작을 직접 테스트해 보세요.
num,dd,sub,lshift,rshift 정의
마찬가지로 다음과 같이 정의합니다.
PPCompositeParser subclass: #PolishGrammar
instanceVariableNames: 'nonZeroDigit digit expr num add sub lshift rshift'
classVariableNames: ''
category: 'SmalltalkAdvent2015'
PolishGrammarnum
^ (nonZeroDigit , digit star) flatten trim
digit star는 0회 이상 digit을 연속 수락한 파라다.flaten은 Persa가 받아들인 답장 원시 문자열의 Persa이며, trim은 공백 문자를 공백으로 읽는 Perser의 메시지를 생성합니다.
PolishGrammar
add
^ '+' asParser trim , expr , expr```
PolishGrammarsub
^ '-' asParser trim , expr , expr
PolishGrammarlshift
^ '<<' asParser trim , expr , expr
PolishGrammarrshift
^ '>>' asParser trim , expr , expr
PolishGrammarexpr
^ num / add / sub / lshift / rshift
문법 정의가 대체적으로 끝났기 때문에 start 방법을 잘 정의합니다.PolishGrammar
start
^ expr
이렇게 하면 Polish Grammar 클래스의 객체는 기본적으로 expr을 지웁니다.그럼 우리 한번 실험해 봅시다.
PolishGrammar new parse: '+ 1 << 2 3'
결과:#('+' '1' #('<<' '2' '3'))
.대개 있다.PolishInterpreter 클래스
다음은 Polish Grammer를 실행하는 처리 시스템을 설치해 봅니다.아주 간단합니다.
PolishGrammar subclass: #PolishInterpreter
instanceVariableNames: ''
classVariableNames: ''
category: 'SmalltalkAdvent2015'
위에서 설명한 바와 같이 PolishGrammer 클래스의 하위 클래스로 정의하는 것이 비교적 편리하다.그리고 계승적인 방법으로 평가를 받은 결과를 답장하는 해석기를 쓰면 해석기가 완성된다.
PolishInterpreter
num
^ super num ==> [ :str | str asInteger ]
제가 위의 내용을 좀 설명하겠습니다.super num은 자연수를 나타내는 문자열을 읽는 해상도입니다.더 자세히 말하면 자연수를 나타내는 문자열을 읽고 받아들인 문자열을 출력하는 해상도입니다. ==>[:str.ster asInteger]에서 asInteger 메시지를 파서에서 내보낸 문자열의 결과 출력에 투하하는 파서를 생성합니다.결과적으로 문자열을 읽고 받아들이면 출력 정수의 해상도를 얻을 수 있습니다.
이==>의 메커니즘을 사용하여 +,-,<<>의 평가 집행을 실현한다.
PolishInterpreter
add
^ super add ==> [ :triple | triple second + triple third ]
PolishInterpretersub
^ super sub ==> [ :triple | triple second - triple third ]
PolishInterpreterlshift
^ super add ==> [ :triple | triple second << triple third ]
PolishInterpreterrshift
^ super add ==> [ :triple | triple second >> triple third ]
해석기 완성.해봐.PolishInterpreter new parse: '+ 1 << 2 3'
결과는 17.PolishTranslator 클래스
그리고 폴란드 기법에서 Smalltalk까지의 변환기를 설치해 보세요.
해석기와 마찬가지로 Polish Grammer의 하위 클래스로 정의합니다.
PolishGrammar subclass: #PolishTranslator
instanceVariableNames: ''
classVariableNames: ''
category: 'SmalltalkAdvent2015'
여러 가지 방법을 정의하다.PolishTranslator
add
^ super add ==> [ :triple | '(', triple second, ' + ', triple third, ')' ]
PolishTranslatorsub
^ super sub ==> [ :triple | '(', triple second, ' - ', triple third, ')' ]
PolishTranslatorlshift
^ super lshift ==> [ :triple | '(', triple second, ' << ', triple third, ')' ]
PolishTranslatorrshift
^ super rshift ==> [ :triple | '(', triple second, ' >> ', triple third, ')' ]
해봐.PolishTranslator new parse: '+ 1 << 2 3'
결과는 "(1+(2<3)"입니다.응, 잘 모르겠는데, 그럼 이렇게 하자.Compiler evaluate: (PolishTranslator new parse: '+ 1 << 2 3')
다행입니다. 결과는PolishInterpreter와 마찬가지로 17입니다.해결 객체 표시
검사기로 PetitParer에서 만든 분석 객체를 열면 다음과 같은 시각적 표현이 가능합니다.
이런, moldable inspector 좋네!
검사기에서 열린 객체는 EBNF 또는 클래스가 아니라 객체 구문 분석입니다.혹시 모르니까
총결산
이렇게 하면 해석기와 전송기를 문법 정의 클래스의 하위 클래스로 정의하면 문법 정의와 의미 정의를 잘 분리할 수 있고문법이 확장될 때의 대응 관계는 이해하기 쉬워 편리하다.
이외에도 PetitParer는 PPExpressionParer 등 많은 편리한 도구를 가지고 있다.
그럼 DSL을 쓰고 싶지 않나요?
좋은 개발 도구는 코드를 쓰고 싶은 기분이다.
Reference
이 문제에 관하여(Polishtalk), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/tomooda/items/cd330b0c28731a2575a4텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)