2010-02-03 6 views
2

흥미로운 문제가 있습니다. 의 내가 이런 식으로 채워진 선 파일이 있다고 가정 해 봅시다 : boost :: iostreams를 사용하여 특별히 제작 된 데이터를 읽은 다음 해당 객체를 기반으로하여 목록에 추가하십시오.

name1[xp,y,z321](a,b,c){text};//comment 
#comment 
name2(aaaa); 

또한 내가 (간체) 한

클래스 :

class something { 
public: 
something(const std::string& name); 
addOptionalParam(const std::string& value); 
addMandatoryParam(const std::string& value); 
setData((const std::string& value); 
}; 

이름은 어떤 클래스 생성자의 이름을 param으로 대응한다. [] 대괄호 안에 나열된 것은 선택 사항이며,()은 필수 항목이며 {} 사이의 모든 항목은 문자열로 저장되어야합니다.

첫 번째 줄의 경우 "name1"을 name으로 사용하여 생성자를 호출해야합니다. addOptionalParam를 3 번 ​​호출합니다. 콜론으로 구분 된 각 항목에 대해 한 번씩. 또한 addMandatoryParam 및 setData를 "text"로 3 번 반복하십시오.

내가 코멘트를 어떻게 해결할 수 있지만, 다른 모든 나를 위해 엉망이되어 ...

는 지금은 좋은 조언을하는 방법 (또는 경우) 내가 어떻게 알아 WOR 수 있다면이 가능합니다 필요 간단한 객체의 경우에는 의미 론적 정확성과 같은 모든 추가 세부 정보를 처리하는 방법을 배울 수 있습니다.

답변

5

설명이 약간 혼란 스럽습니다 (예 : '콜론으로 구분됨'이라고 말하면 입력에 콜론이 표시되지 않음). 나는 여러분이 의도하는 것은 대괄호 안의 항목이 선택적 매개 변수이고, 괄호 안은 필수 매개 변수이며, 중괄호는 '데이터'라고 가정합니다.

func: name optionalParams '(' paramList ')' '{' data '}' 

paramList: param | 
      paramlist ',' param 

optionalParams: // empty 
       | '[' paramList ']' 

name: WORD 
param: WORD 
data: WORD 

이것은 성령이 아마 꽤 잘 작동하는 간단한 충분히 문법은 :이 경우

, 문법이 같은 것 같습니다. 성령은 더 큰 문법에 대한 컴파일 시간이 길어지는 경향이 있지만,이 문법은 컴파일 시간이 상당히 합리적이어야하는만큼 작습니다.

확실한 대안은 대신 하강 파서를 작성하는 것입니다 (재귀 적 하강 파서와 유사하지만 재귀가 필요하지 않습니다). 이 경우, 기본적으로 문법의 각 레벨에 대한 함수를 작성하고, 적절한 입력을 읽고, 읽은 데이터를 보유하는 구조 (예 : 벡터)를 반환합니다. 예를 들어, optionalParams (이것은 선택 사항이기 때문에) 구문 분석 아마도 가장 어려운 : 와우, 단순히 와우

function read_func(std::istream &in) { 
    std::string name = read_name(in); 
    std::vector<param> optional_params = read_optional_params(in); 
    std::vector<param> mandatory_params = read_mandatory_params(in); 
    std::string data = read_data(in); 

    if (in.fail()) { 
     // malformed input 
    } 

    function func = function(name); 
    for (int i=0; i<optional_params.size(); i++) 
     func.addOptionalParam(optional_params[i]); 
    for (int i=0; i<mandatory_params.size(); i++) 
     func.addMandatoryParam(mandatoryParams[i]); 
    func.setData(data); 
    return func; 
} 
+0

+1 문법을 고려하고 파싱합니다. –

-1

:

typedef std::string param; 

std::vector<param> read_optional_params(std::istream &in) { 
    std::vector<param> ret; 

    char ch = in.peek(); 
    if (ch == '[') { 
     in >> ch; 
     param temp; 
     while (in >> temp && temp != "]") 
      ret.push_back(temp); 
      if ((ch=in.peek) == ',') 
       in >> ch; 
    } 
    return ret;  
} 

를 최상위 레벨에서이 같은이있을 것이다 ...

나는 이것이 파일에서 읽는 것보다 다른 열에서 이루어질 것이라는 것을 결코 알지 못했고 Boost에 관한 한계 지식으로부터 곧바로 나오는 것은 나는 boost :: spirit과 같은 것이 있다는 것을 몰랐다. 그러나 이제는 문서를 읽는 것이 매우 어려워서 대부분의 경우 "real_p 사용"과 같은 네임 스페이스에 대한 정보가 없으므로 주어진 항목을 어디에서 찾을 지 혼란 스럽습니다. 성취한다 나는 정말로 놀란다.

나는 문법에 대한 정보를 연장하고 싶습니다 (그러나 나는 정확히 코드의 관점에서 작업을 수행하는 방법을 해독 가까운 곳을 해요) :

이름 : 숫자로 시작하지 않는 문자열을 할 수있다, 아무튼
param : 정수, double 또는 'az'문자 만 포함 된 문자열이 될 수 있습니다.
data : 중괄호 사이에있는 모든 문자 (가능한 경우 줄, 숫자, 숫자, {{{{{}}은 (문법적으로 말하자면) 실패해야합니다 (문법적으로 말하자면) {{{{{}}
';': 구분 기호로 사용되어야하고 명확한 끝이어야합니다. 반드시 가지고 있어야합니다

다른 것들은 예제에서 구현 방법을 볼 수 없기 때문에 의견입니다.

도움을 주셔서 감사합니다. 나는 그것이 어디로 가고 있는지보고 싶습니다.

+0

새 정보로 질문을 업데이트했거나 설명을 위해 의견에 질문해야합니다. 답변은 대답을 사용해야합니다. –