, yylineno
2.
라인을 가리켜 야합니다 메시지를 다른 줄 번호로 인쇄하려면 어떤 줄을 인쇄할지 결정해야합니다. 여기서 오류는 토큰 int
과 토큰 true
사이에 있기 때문에 최소한 두 가지 가능성이 있습니다. 이 경우, 그 모두가 1 행에 있지만, 어떤 프로그램 텍스트가 있었다면 :
int x =
true;
그 토큰 중 하나가 오류를 일으키는 것으로 플래그해야한다는 합리적인 것 같다, 그래서 문제가 파악에 감소 토큰이 표시된 행을 찾아냅니다. 그 토큰은 감축이 일어날 때까지의 고대의 역사이기 때문에 여전히 필요로하는 모든 토큰의 위치를 기억하는 것이 유일한 방법입니다. 이것은 일반적으로 파서 스택에있는 모든 토큰입니다.
다행히도 bison
에는이를 수행하는 간단한 방법이 있습니다. 필요한 경우 파서 스택과 평행하게 위치 스택을 유지 한 다음 @1
을 참조하여 토큰 1의 위치 개체에 액세스 할 수 있습니다. 심지어 바이슨 파일의 어딘가에 위치 객체에 대한 참조를 사용하는 것만으로도이 정보를 유지하도록 바이슨을 설득하는 것으로 충분합니다. 그래서 당신은 당신의 작업을 변경할 수 있습니다 : (. 당신이이 Exp
에 오류를 돌리는 것이 더 적절하다고 생각하는 경우, 또는 @4
)
Statement : Type ID ASSIGN Exp {check_types_match($1.type, $4.type, @1)} SC
을 물론
, 그것은 아주 간단 적이 없다. bison
에 모든 수신 토큰의 위치를 알리고 새로 만든 비 종단 용 위치를 만드는 방법을 이해해야합니다 (위의 예에서 Exp
등).)
위치 객체가 여러 행에 걸쳐있을 수있는 토큰 시퀀스의 위치를 참조 할 수 있기 때문에 (비 - 종단의 경우처럼) 위치 객체가 시작과 끝을 모두 나타내는 것은 정상입니다 끝 점. 또한 정확한 오류 메시지를 생성하기 위해 행 번호와 열 오프셋을 모두 사용하는 것이 일반적입니다. N
이이다 어디
@$.first_line = @1.first_line;
@$.first_column = @1.first_column;
@$.last_line = @N.last_line;
@$.last_column = @N.last_column;
같은 것을 쓴 것처럼
typedef struct YYLTYPE {
int first_line;
int first_column;
int last_line;
int last_column;
} YYLTYPE;
그리고 기본적으로
이 아닌 단말기의 위치 개체가 계산된다 : 따라서, 기본 위치 객체는 다음과 같은 유형이 오른쪽에있는 마지막 문법 기호의 색인. (
bison
에는 "문법 기호 수"에 대한 표기가없고
$N
구문의 변수를 사용할 수 없으므로 실제로는 작성할 수 없습니다.)
꽤 잘 당신이 원하는, 들소의 측면에서 아무런 문제가 없습니다. 그러나 당신은 또한 처음에 flex
에서 정보를 얻을 필요가 있습니다. 당신이 전역 변수에 의존 flex
과 bison
사이의 간단한 인터페이스를 사용하는 경우
, 현재 토큰을 사용하여 해당 위치의 객체의 이름 (yylval
유사) yylloc
입니다. flex
은 yylineno
을 자동으로 만들 수 있지만 yylloc
에 자동으로 저장하지 않으며 열 번호를 추적하거나 리턴 된 토큰이 두 줄 이상으로 퍼져있는 경우를 처리하는 기본 제공 메커니즘도 없습니다 (이 기능은 문자열 상수 등).
정확한 인프라 정보를 얻는 것은이 질문의 범위를 벗어납니다. 회선 번호 정보 만 요구하기 때문입니다. 당신은 단지 라인 번호를 추적해야하고 여러 줄의 토큰이없는 경우, 모든 플렉스 규칙에 다음을 추가 할 수있는 충분한 것 :
yylloc.first_line = yylloc.last_line = yylineno;
당신은 멀티 라인 토큰이있는 경우, 당신 에 모든 토큰 액션, 무엇이든 (주석과 공백을)하지 않아도 사람을 추가 할 것
yylloc.first_line = yylloc.last_line;
yylloc.last_line = yylineno;
: 대신 다음을 사용할 수 있습니다. 다행히도 flex
에는 모든 액션의 시작 부분에 추가되는 매크로가 있으므로 전체 flex 파일을 복잡하게 만들 필요가 없습니다. 그것은 같은 것을 추가 할 수있는 충분한입니다 :
#define YY_USER_ACTION do { \
yylloc.first_line = yylloc.last_line; \
yylloc.last_line = yylineno; \
} while(0)
을 (. 당신이 열 번호를 추적 끝날 경우, 너무, 당신은 그것을 수정해야합니다)
또한
yylloc.last_line
이
1
으로 초기화되어 있는지 확인해야합니다
; 그렇지 않으면 첫 번째 토큰이 0 행에서 시작됩니다.
자세한 내용은 설명서를 읽어 보시기 바랍니다 : 당신이 재진입/순수 스캐너와 파서를 사용하는 경우
을, 당신은 설명서를 참조해야합니다 위치 객체가 전역없이 전달되는 방법. %bison-locations
선언은 항상 원하는 것은 아닙니다 (재진입/순수 스캐너 및 파서를 사용하지 않는 경우에는 원하는 것은 아닙니다.)
답장을 보내 주셔서 감사합니다! 그것은 나를 도왔습니다 :) 건배! – Loay