저는 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.h
및 LuaSL_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 노드의 기호를 출력하기 전에 바로 출력 공백/코멘트.
예, 위 코드에 중복이 있다는 것을 알고 있습니다. 토큰 구성원과 공용체 모두에서 유형을 숨길 필요가 없습니다. 나는 나중에 그것을 코드에서 제거 할 것이다. 당장은 서버가 무슨 일이 일어나고 있는지 설명합니다.
나는이 사이트를 처음 접했기 때문에 Sangeeth의 편집 내용이 무엇인지 확신 할 수 없습니다. 내 공간을 좋아하는 방식으로 내 공간을 좋아하고, "주석 처리 해제"하이픈 추가는 지나치게 과장된 것처럼 보입니다. 으시시하다. –
그래, 네가 나에게 모든 걸 묻는다면 파일 이름 인상은 과도했다. 그것이 '제안 된 편집'기능의 단점입니다. 상대적으로 새로운 사용자가 지나치게 많은 편집을하는 경우가 많으며 자주 보지 않는 한 자주지나갑니다 ... :/편집을 좋아하지 않는 경우 항상 자신의 게시물을 자유롭게 되돌릴 수 있습니다. – bdonlan
AST에서 원본 텍스트를 재생성하는 방법에 대한 내 SO 답변을 확인하십시오. 캡처해야 할 내용에 대해 설명하고 방법에 대한 몇 가지 아이디어를 제공합니다. http://stackoverflow.com/a/5834775/120163 –