2012-01-08 2 views
1

저는 Second Life의 LSL 언어로 작성된 스크립트를 Lua로 변환하는 프로젝트를 진행하고 있습니다. 이 프로젝트에서 flex와 btyacc를 배우고 있습니다. 실제로, 그것은 훨씬 더 큰 프로젝트입니다, 이것은 그것의 일부일뿐입니다. 첫 단계로, 내가 만든 AST가 입력을 정확하게 반영하는지 확인하고 싶습니다. 그래서 내 생각은 해당 AST에서 새 파일을 생성 한 다음 비교하는 것입니다. 즉, 공백과 주석을 AST에 포함해야하므로 결과 파일을 gerenate 할 때 정확히 동일한 공백과 주석이 포함되도록해야합니다.원본과 비교할 소스를 생성하여 flex 및 yacc 코드가 작동하는지 확인

나는 공백을 다루는 데 문제가있었습니다. 며칠 동안 검색 및 실험을하고 어디에도 가지 않습니다. 모든 예제는 공백을 무시하고 나중에 사용하기 위해 저장하지 않습니다. 나는 그들이 무시할 수있는 또 다른 형태의 공간이라는 점에서 코멘트와 똑같은 문제를 갖게 될 것이라고 생각합니다.

나는 이것이 표준적인 일이라고 생각했지만, 예제를 찾을 수 없다. 누구든지 비슷한 것들의 예를 알고 있습니까?

누군가가 그것을 조사하고 접근 방법을 제안하려는 경우 소스 코드가 github에 있습니다.

https://github.com/onefang/SledjHamr/blob/experimental/LuaSL/srcLuaSL_yaccer.l, LuaSL_yaccer.y, LuaSL_LSL_tree.hLuaSL_LSL_tree.c

공간을 인식 플렉스 라인은이 조치는 설명으로하고있다. 주석을 취소하면 구문 분석 오류가 발생합니다.

솔루션은 내가 bdonlan의 솔루션을 사용했다,하지만 난 그것을 구현하는 중간에 레몬 대신 btyacc를 사용하여 프로젝트를 통해 전송. 이것이 내가 한 일이다. 아래의 소스 코드는 단순화되었습니다.

레몬을 사용하면 렉서를 호출하는 루프를 작성한 다음 렉서 호출의 결과를 가져와 파서에 전달할 수 있습니다. 내 루프는 매번 새로운 yylval 구조체를 할당한다.이 구조체는 공백이나 주석을위한 char 포인터를 포함한다. 나는 이미 내가 필요로하는 대부분을 포함하고 있기 때문에 ASL 노드 구조로이 yylval을 사용하고, 메모리를 재 할당하거나 물건을 복사하는 시간을 소비하지 않아도된다.

struct AST_node 
{ 
    struct AST_node *left; 
    struct AST_node *right; 
    char    *white_space; 
    struct AST_token *token; /* common() stashes a pointer to a token structure here. */ 
    int    line, column; 
    union 
    { 
     /* The various types of symbols are stored here as per usual, including this one - */ 
     int operationValue; 
    } value; 
} 

struct AST_node *lval = calloc(1, sizeof(struct AST_node); 

while((yv = yylex(lval)) != 0) 
{ 
    Parse(pParser, yv, lval); 
    lval = calloc(1, sizeof(struct AST_node)); 
} 

렉서에는 각 정규 표현식 작업 섹션에서 호출되는 common() 함수가 있습니다. 무엇보다도 주석이나 공백 인 경우 텍스트를 정적 축약기에 저장합니다. 주석 또는 공백이 아닌 경우, 누락 자 (있는 경우)를 yylval 구조에 저장하고 누적기를 지 웁니다. 이 누적 기는 공백과 주석을 함께 모으므로, yylval의 주어진 임의의 것이 누락 될 수 있습니다.

렉서는 단지 공백/주석일 경우 심볼을 반환하지 않으므로 실제 심볼을 방출 할 때까지 렉서가 누적됩니다.

레몬에서는 모든 터미널과 비 터미널이 yylval에 사용되는 유형이므로이 코드를 작업 섹션의 C 코드에 전달할 수 있습니다. 예를 들어 -

expr(A) ::= expr(B) LSL_ADD(D) expr(C). { A = addOperation(D, LSL_ADD, B, C); } 

LSL_ADD는 렉서로부터 방출 된 심볼이며, D는 I 메인 루프에서 생성하는 yylval가 렉서로 전달하는 값이다이다. 이 경우 addOperation()은 왼쪽 및 오른쪽 AST 노드 (B 및 C)에 대한 포인터를 AST 구조 (D)에 추가하고 여기에 심볼을 넣습니다 (나중에이 특정 연산이 추가됨을 알 수 있도록) .

struct AST_node *addOperation(struct AST_node *lval, int type, struct AST_node *left, struct AST_node *right) 
{ 
    lval->left = left; 
    lval->right = right; 
    lval->value.operationValue = type; 
    return lval; 
} 

나중에, 나는 AST에서 원본 소스 코드를 재구성있을 때, 같은 AST 노드의 기호를 출력하기 전에 바로 출력 공백/코멘트.

예, 위 코드에 중복이 있다는 것을 알고 있습니다. 토큰 구성원과 공용체 모두에서 유형을 숨길 필요가 없습니다. 나는 나중에 그것을 코드에서 제거 할 것이다. 당장은 서버가 무슨 일이 일어나고 있는지 설명합니다.

+0

나는이 사이트를 처음 접했기 때문에 Sangeeth의 편집 내용이 무엇인지 확신 할 수 없습니다. 내 공간을 좋아하는 방식으로 내 공간을 좋아하고, "주석 처리 해제"하이픈 추가는 지나치게 과장된 것처럼 보입니다. 으시시하다. –

+0

그래, 네가 나에게 모든 걸 묻는다면 파일 이름 인상은 과도했다. 그것이 '제안 된 편집'기능의 단점입니다. 상대적으로 새로운 사용자가 지나치게 많은 편집을하는 경우가 많으며 자주 보지 않는 한 자주지나갑니다 ... :/편집을 좋아하지 않는 경우 항상 자신의 게시물을 자유롭게 되돌릴 수 있습니다. – bdonlan

+0

AST에서 원본 텍스트를 재생성하는 방법에 대한 내 SO 답변을 확인하십시오. 캡처해야 할 내용에 대해 설명하고 방법에 대한 몇 가지 아이디어를 제공합니다. http://stackoverflow.com/a/5834775/120163 –

답변

3

AST가 원본 소스의 정확한 가역 변환이되는 경우는 거의 없습니다. 예를 들어 괄호는 구문 분석 프로세스에서 손실 될 수 있습니다 (우선 순위에서만 사용되지만 최종 AST에서는 생략 됨). 공백은 제거 될 수 있습니다.

토큰에 대한 줄 및/또는 문자 오프셋을 저장하는 것이 일반적이므로 오류 메시지가 그 원인을 인용 할 수 있지만 완전한 가역성을 위해서는 충분하지 않습니다.

나는 완전히 뒤집을 수있는 AST가 아니라, 알려진 AST 결과의 테스트 세트와이를 생성하는 입력이있는 것이 좋습니다. 하지만, 당신은 터미널 토큰과 함께 모든 공백을 저장할 수 있어야합니다 경우 - 예를 들어,이 코드가 같은 경우 :

1 + /* this is a comment */ 2 

다음 +에 해당하는 AST 노드가 + 전에 하나의 공간을 포함 할 것이며, 노드 2의 경우 추가 공백 데이터로 /* this is a comment */이 포함됩니다. 그런 다음 변환을 되돌릴 때이 공백을 복원 할 수 있습니다. 당연히 괄호와 같은 구문 기능을 명시 적으로 인코딩해야합니다.

lex/yacc를 사용하면 공백/주석 (또는 입력 버퍼의 인덱스)을 별도로 누적하여이를 구현할 수 있습니다. 공백이나 주석이 표시되면이 누적기를 업데이트하지만 은 토큰을 내 보내지 않습니다.. EOF를 포함한 다른 토큰을 누르면이 데이터를 다른 누적기로 옮기고 주 누적기를 재설정합니다. yacc로 돌아 가면 yacc 터미널은이 보조 누적기를 검사하여 터미널에 할당 한 데이터 구조에 관계없이 숨길 수 있습니다.

+0

을 참조하십시오. 괄호 같은 것을 추적하고 있으며, 공백을 분류하면 커미션을 추적합니다. 나는 또한 기존의 많은 스크립트를 가지고 있지만, "알려진 결과"는이 스크립트가하는 일의 성격 상, 인코딩하기가 다소 어렵습니다. 따라서 쉽게 할 수있는 일은 AST를 역전시키고 기존 스크립트의 큰 몸체와 비교하는 것입니다. –

+0

나는 귀하의 축전지 아이디어를 좋아합니다. 나는 그것으로 실험 할 것이고 내가 어떻게 가는지 볼 것이다. –

+0

나는이 사이트를 처음 사용하고 있으며 분명히 당신의 답변에 투표 할만큼 충분한 평판이 없다. –

관련 문제