블로그는 귀차니즘

First Sensation
  • 공지
  • 지역로그
  • 태그
  • 방명록

boost::spirit - Parser 라이브러리

Language 2008/04/23 23:33 귀차니스트

  컴퓨터로 프로그램을 만들어보신 분이라면 컴파일러 혹은 인터프리터라는 단어를 한 번쯤은 들어보셨으리라 생각합니다. 그만큼 필수적인 단어이자 프로그램 이죠. 이 프로그램들이 없으면 실행이라는 것 자체가 불가능하니까요. 그럼 이 부분은 어떻게 인식을 하게 될까요?
  아시는대로 컴퓨터는 자동적으로 알아서 프로그램을 생성하는 것이 아니라 코딩을 통한 작동명령을 제시해주어야 합니다. 그렇지 않으면 제대로 동작하지도 않을뿐더러 어떠한 역할을 수행하지도 못하겠지요. 그럼 어떻게 문법적 구문을 인식할까요? 그건 바로 오토마타를 통한 LALR(N), LR(N) 등의 문자열 파싱 방법등으로 처리하곤 합니다. 물론 학교에서만 배운 지식이기에 현재 자주 사용하는 gcc, C++ Builder, VS.net C++ 등의 컴파일러는 더 최신의 기술을 사용할지도 모릅니다. 하지만 기본은 아마도 비슷하겠죠?
  그 문법적 문자열을 인식하는것은 일일히 코딩을 통하여 인식을 할 수도 있겠지만 그 것은 시간적으로도 키보드의 플라스틱으로도 낭비가 아닐 수 없습니다. 왜냐하면 yacc, lex 등의 좋은 툴이 많이 나와있기 때문이죠. 그 것과 더불어 boost에는 spirit 이라는 라이브러리가 존재합니다. 아마도 규모면에서는 약간 적은 프로그램에서 사용될 것 같습니다. 그럼 대충 어떻게 사용하는지 알아볼까요??

CalcExpr.h (Language : cpp)
  1. #pragma once
  2.  
  3. #include <boost/spirit/core.hpp>
  4. #include <string>
  5.  
  6. using namespace boost::spirit;
  7.  
  8. typedef rule< scanner< wchar_t const * > > Rule;
  9.  
  10. class CCalcExpr
  11. {
  12. public:
  13.     CCalcExpr(void);
  14.     ~CCalcExpr(void);
  15.  
  16.     static bool TryParse( std::wstring &Str, size_t &ErrIndex );
  17. };
CalcExpr.cpp (Language : cpp)
  1.  
  2. #include "stdafx.h"
  3. #include "CalcExpr.h"
  4.  
  5. CCalcExpr::CCalcExpr(void)
  6. {
  7. }
  8.  
  9. CCalcExpr::~CCalcExpr(void)
  10. {
  11. }
  12.  
  13. bool CCalcExpr::TryParse( std::wstring &Str, size_t &ErrIndex )
  14. {
  15.     Rule Expr;
  16.     Rule PowOp      = *space_p >> L'^' >> *space_p;
  17.     Rule MulOp      = *space_p >> ( ch_p< wchar_t >( L'*' ) | ch_p< wchar_t >( L'/' ) ) >> *space_p;
  18.     Rule AddOp      = *space_p >> ( ch_p< wchar_t >( L'+' ) | ch_p< wchar_t >( L'-' ) ) >> *space_p;
  19.    
  20.     Rule Symbol   = +( range_p( L'A', L'Z' ) | range_p( L'a', L'z' ) );
  21.     Rule Function      = ( Symbol >> L'{' >> ( Symbol | real_p ) >> L'}' );
  22.     Rule Value      = real_p | ( L'[' >> Function >> L']' );
  23.     Rule Element        = ( L'(' >> Expr >> L')' ) | Value;
  24.     Rule MinusElement   = ( L'-' >> Element ) | Element;
  25.     Rule Factor   = ( MinusElement >> PowOp >> Factor ) | MinusElement;
  26.     Rule Term         = ( Factor >> MulOp >> Term ) | Factor;
  27.     Expr                = ( Term >> AddOp >> Expr ) | Term | end_p;
  28.  
  29.     parse_info< wchar_t const * > Parse_Info = parse< wchar_t >( Str.c_str(), Expr );
  30.  
  31.     if( !Parse_Info.full )  {
  32.        
  33.         ErrIndex = Parse_Info.length;
  34.         return false;
  35.     }
  36.  
  37.     return true;
  38. }

  사용은 boost가 흔히 그렇듯이 boost에 속하는 hpp 파일을 include 시켜주어야 합니다. 목적 헤더파일은 core.hpp 파일입니다. 이 boost::spirit이 지원하는 부분은 문법을 분석하고 문법이 실행되는 것 까지 지원되나, 제가 거기까지는 사용을 못해봤으므로 일단 입력 문자열이 맞는지 검사하는 부분으로 진행하겠습니다.
  일단 문자열이 파싱이 되느냐 되지 않느냐를 판단하기 위해서는 Rule 이라는 것이 필요합니다. 이 것이 무엇이냐 하면 오토마타때 배우는 EBNF( Extended Backus Naur Form )와 동일하게 생각하시면 됩니다. 즉 하나의 룰이 하나의 Non-Terminal을 표현한다고 보시면 됩니다. 위 코드는 제가 IPangYa 라이브러리에서 계산수식을 인식하여 정확한 것인지 파악하기 위하여 작성하였던 코드입니다. 나름 고생도 했죠.
  룰을 만들기 위해서는 Rule 형태의 변수를 선언을 하게 되고 = 연산자 우측엔 >> 로 이루어진 룰의 조합이 존재하면 됩니다. 예를 들면 ch_p< wchar_t >( L'+' ) >> L'(' 이렇게 된다면 +( 이라는 문자열을 인식하는 룰이됩니다. C++ 에 존재하는 라이브러리 답게 *, | 연산자들을 오버로딩 하여 룰을 C++ 문법으로 간단히 표현할 수 있도록 제작이 되어있습니다. 그러므로 Expr에서 (abcc)*, (abcc)+ 와 같은 문자열 형식을 인식할 수 있습니다.
  물론 ParseTree가 제작되기 위하여 *, /, +, - 등의 연산자 오버로딩을 정해주기 위하여 룰의 위치, 순서들을 먼저 조절 해주어야 합니다. 그게 약간의 사용법에 있어서 어려움이 될 수도 있습니다. 종이의 룰은 그냥 적으면 되지만 OOP라고는 하지만 내부 함수는 절차지향이니 그 순서를 생각한다면 반대로 생각해야할 부분도 있기 때문이죠. 만약 이러한 작업들을 통하여 Rule이 생성되었다면 boost의 parse 함수를 이용하여 최상위 룰과, 입력 문자열을 같이 넣어준다면 작업을 수행하고, parse_info의 변수에 에러 위치, 혹은 성공 여부를 채워주게 됩니다. 무척 간편하죠?^^
  필요한데 간단간단하게 제작을하여 사용하려면 이러한 것들을 사용하는 것은 어떻까요?

크리에이티브 커먼즈 라이센스
Creative Commons License
이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-동일조건변경허락 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.

"Language" 분류의 다른 글

std::ostreambuf_iterator, std::istreambuf_iterator의 이유 (1)2008/04/16
std::auto_ptr - Smart Pointer 이지만?? (1)2008/04/13
C# Application - Main 에서 Try-Catch 오작동 해결하는 방법 (4)2008/04/07
Boost 1.35 - 워크샵 뒤의 포스팅 (2)2008/04/03
C# Generics - Generics 문법의 사용법 (0)2008/03/21
2008/04/23 23:33 2008/04/23 23:33
TAG C++, spirit
받은 트랙백이 없고, 댓글이 없습니다.

트랙백 주소 :: http://www.filewiki.net/tc/trackback/55

댓글을 달아 주세요

◀ 이전페이지 1 ... 53 54 55 56 57 58 59 60 61 ... 110 다음페이지 ▶

블로그 이미지
First Sensation 귀차니스트
rss
  • 관리자
  • 글쓰기

카테고리

  • 전체 (110)
    • Computer (3)
    • Language (14)
    • Reverse Engineering (1)
    • Algorithm (9)
    • TopCoder (3)
    • Library (2)
    • Programming (19)
    • Programming Tip (9)
    • PSP-Programming (10)
    • Program (5)
    • Small Talk (31)
    • Document (4)

최근에 올라온 글

  • Gradient 작성중에 있습.... (3)
  • 게임&인터랙티브 애플리....
  • 한게임 자동테트리스 Ve.... (24)
  • Intel 64 And IA32 Arch.... (2)
  • 한게임 자동테트리스 Ve.... (24)

최근에 달린 댓글

  • 다운어덯게 받아요. difl 2008
  • 멋있네요 ㅎㅎ. 준호씨 2008
  • ^^; 그러셨군요.. 사실 동영.... 귀차니스트 2008
  • ㅋㅋ 속도 튜닝의 무서움 ㅜ.... 귀차니스트 2008
  • 관리자만 볼 수 있는 댓글입.... 비밀방문자 2008

달력

«   2009/01   »
일 월 화 수 목 금 토
        1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31

링크

  • kkamagui 프로그래밍 세상.
  • 류광의 번역 이야기.
  • 서광열의 프로그래밍 언....
  • 준호씨의 블로그.
  • 최익필의 이름없는 블로그.
  • 위키는 귀차니즘.

최근에 받은 트랙백

  • 궁극의 예외처리. 이름없는 블로그 2008
  • Maximum sum. 티스토리 지점 2008

글 보관함

  • 2008/12 (1)
  • 2008/11 (4)
  • 2008/10 (2)
  • 2008/09 (3)
  • 2008/08 (5)

태그목록

  • 디코딩
  • 멀티맵
  • ASM
  • Builder
  • 테트리스
  • boost::array
  • Decompiler
  • ++i
  • VCL
  • Singleton
  • RF959
  • C++
  • FreeType
  • Logitech
  • 상속
  • 디코드
  • 참조
  • Run Length
  • priority_queue
  • 프로그래밍
  • 파이널 데이터
  • boost::random
  • multimap
  • GDI+
  • 한국가상캠퍼스
  • 이미지 프로세싱
  • Inheritance
  • Component
  • 6GB
  • Warcraft III

지역로그 : 태그 : 방명록 : 관리자 : 글쓰기
귀차니스트’s Blog is powered by Textcube 1.7.5 : Risoluto / Designed by DesignNia.net