내가 들소를 사용하여 장난감 프로그래밍 언어에 대한 파서를 쓰고 있어요,하지만 난 벽에 충돌 한
%{
#include <stdio.h>
#include "util.h"
#include "errormsg.h"
#define YYDEBUG 1
int yylex(void); /* function prototype */
void yyerror(char *s)
{
EM_error(EM_tokPos, "%s", s);
}
%}
%union {
int pos;
int ival;
string sval;
}
%token <sval> TK_ID TK_STRING
%token <ival> TK_INT
%token <pos>
TK_COMMA TK_COLON TK_SEMICOLON TK_LPAREN TK_RPAREN TK_LBRACK TK_RBRACK
TK_LBRACE TK_RBRACE TK_DOT TK_ASSIGN
TK_ARRAY TK_IF TK_THEN TK_ELSE TK_WHILE TK_FOR TK_TO TK_DO TK_LET TK_IN
TK_END TK_OF TK_BREAK TK_NIL
TK_FUNCTION TK_VAR TK_TYPE
/* Precedence in Bison is weird: lower is higher. Take a look at the spec too. */
%left <pos> TK_OR
%left <pos> TK_AND
%nonassoc <pos> TK_EQ TK_NEQ TK_LT TK_LE TK_GT TK_GE
%left <pos> TK_PLUS TK_MINUS
%left <pos> TK_TIMES TK_DIVIDE
%left <pos> TK_UMINUS
%error-verbose
%start program
%%
/* According to the spec, Tiger programs are just an expression exp. */
program: exp
/* An expression can be many things; consult the spec for more info: Expressions. */
/* For the %prec rule, take a look at 5.4 Context-Dependent Precedence on bison manual */
exp:
lvalue
| TK_NIL
| exp exp_seq_aug
| TK_LPAREN TK_RPAREN
| TK_LET TK_IN TK_END
| TK_INT
| TK_STRING
| TK_MINUS exp %prec TK_UMINUS
| TK_ID TK_LPAREN TK_RPAREN
| TK_ID TK_LPAREN exp params TK_RPAREN
| exp TK_PLUS exp
| exp TK_MINUS exp
| exp TK_TIMES exp
| exp TK_DIVIDE exp
| exp TK_EQ exp
| exp TK_NEQ exp
| exp TK_GT exp
| exp TK_LT exp
| exp TK_GE exp
| exp TK_LE exp
| exp TK_AND exp
| exp TK_OR exp
| TK_ID TK_LBRACE TK_RBRACE
| TK_ID TK_LBRACE TK_ID TK_EQ exp record_exp TK_RBRACE
| TK_ID TK_LBRACK exp TK_RBRACK TK_OF exp
| lvalue TK_ASSIGN exp
| TK_IF exp TK_THEN exp TK_ELSE exp
| TK_IF exp TK_THEN exp
| TK_WHILE exp TK_DO exp
| TK_FOR TK_ID TK_ASSIGN exp TK_TO exp TK_DO exp
| TK_BREAK
| TK_LET decl_seq TK_IN exp_seq_aug TK_END
;
decl_seq:
/* empty */
| decl_seq decl
;
decl:
type_decl
| var_decl
| func_decl
;
var_decl:
TK_VAR TK_ID TK_ASSIGN exp
| TK_VAR TK_ID TK_COLON TK_ID TK_ASSIGN exp
;
func_decl:
TK_FUNCTION TK_ID TK_LPAREN type_fields TK_RPAREN TK_EQ exp
| TK_FUNCTION TK_ID TK_LPAREN type_fields TK_COLON TK_ID TK_EQ exp
;
type_decl:
TK_TYPE TK_ID TK_EQ type
;
type:
TK_TYPE
| TK_LBRACE type_fields TK_RBRACE
| TK_ARRAY TK_OF TK_ID
;
type_fields:
/* empty */
| TK_ID TK_COLON TK_ID type_fields
| TK_COMMA TK_ID TK_COLON TK_ID type_fields
;
lvalue:
TK_ID
| lvalue TK_DOT TK_ID
| lvalue TK_LBRACK exp TK_RBRACK
;
exp_seq:
/* epsilon */
| TK_SEMICOLON exp
| exp_seq TK_SEMICOLON exp
;
exp_seq_aug:
TK_LPAREN exp_seq TK_RPAREN
;
params:
/* epsilon */
| params TK_COMMA exp
;
record_exp:
/* epsilon */
| record_exp TK_COMMA TK_ID TK_EQ exp
;
그것은이다 :
내 grammar.y
파일은 다음과 같다 그다지 공상적인 것은 아니며, (96) shift/reduce conflicts를 얻는다. (아마도 if 문과 함수 호출 문으로 인한 것 같다). 나는 그것이 분명하지 않아야한다는 것을 알고 있지만 같은 연습에 대한 다른 대안 구현은 더 많은 시프트/충돌을 통해 구문 분석을 깨끗하게 처리하므로 너무 많은 오류 메시지는 고려하지 않아도됩니다.
토큰 파일이 내가 얻을 %token
지침 (y.tab.h와 y.tab.c가) 및 특정 오류 메시지에서 들소에 의해 생산된다 :
[email protected] ~/Software/tigerc $ ./a.out tests/test4.tig
tests/test4.tig:2.1: syntax error, unexpected TK_GE
Parsing failed
,
/* define a recursive function */
let
/* calculate n! */
function nfactor(n: int): int =
if n = 0
then 1
else n * nfactor(n-1)
in
nfactor(10)
end
가 어떻게 가능성이 디버깅 할 수 있습니다 : 파서가 말한다 때문에 테스트 파일이 하나도없는 때는 크거나 같은 토큰을 발견?
[편집] : 여기의 요청에 따라, 내 flex
렉서의 소스 코드입니다 : 우선 들어
%{
#include <string.h>
#include "util.h"
#include "tokens.h"
#include "errormsg.h"
int charPos = 1;
int
yywrap (void)
{
charPos = 1;
return 1;
}
// Adjust the token position in the string
// Mainly used for error checking
void
adjust (void)
{
EM_tokPos = charPos;
charPos += yyleng;
}
%}
/* Will be used for conditional activation of the comment rule. */
%x C_COMMENT
digits [0-9]+
letters [_a-zA-Z]+
%%
" " {adjust(); continue;}
\n {adjust(); EM_newline(); continue;}
\t {adjust(); continue;}
"/*" {adjust(); BEGIN(C_COMMENT);}
<C_COMMENT>[^*\n] {adjust();}
<C_COMMENT>"*/" {adjust(); BEGIN(INITIAL);}
\"(\\.|[^"])*\" {adjust(); yylval.sval = String(yytext); return STRING;}
"," {adjust(); return COMMA;}
";" {adjust(); return SEMICOLON;}
":" {adjust(); return COLON;}
"." {adjust(); return DOT;}
"+" {adjust(); return PLUS;}
"-" {adjust(); return MINUS;}
"*" {adjust(); return TIMES;}
"/" {adjust(); return DIVIDE;}
"=" {adjust(); return EQ;}
"<>" {adjust(); return NEQ;}
"<" {adjust(); return LT;}
"<=" {adjust(); return LE;}
">" {adjust(); return GT;}
">=" {adjust(); return GE;}
"&" {adjust(); return AND;}
"|" {adjust(); return OR;}
":=" {adjust(); return ASSIGN;}
"(" {adjust(); return LPAREN;}
")" {adjust(); return RPAREN;}
"{" {adjust(); return LBRACE;}
"}" {adjust(); return RBRACE;}
"[" {adjust(); return LBRACK;}
"]" {adjust(); return RBRACK;}
for {adjust(); return FOR;}
if {adjust(); return IF;}
then {adjust(); return THEN;}
else {adjust(); return ELSE;}
while {adjust(); return WHILE;}
to {adjust(); return TO;}
do {adjust(); return DO;}
let {adjust(); return LET;}
in {adjust(); return IN;}
end {adjust(); return END;}
of {adjust(); return OF;}
break {adjust(); return BREAK;}
nil {adjust(); return NIL;}
function {adjust(); return FUNCTION;}
var {adjust(); return VAR;}
type {adjust(); return TYPE;}
array {adjust(); return ARRAY;}
{digits} {adjust(); yylval.ival = atoi (yytext); return INT;}
{letters}[a-zA-Z0-9_]* {adjust(); yylval.sval = String (yytext); return ID;}
. {adjust(); EM_error (EM_tokPos,"illegal token");}
렉서는 어디에 있습니까? – codenheim
@codenheim이 렉서 코드를 포함하도록 질문을 업데이트했습니다. – NlightNFotis
좋아, 대답하고있다. 간단히 말해서 렉서는 들소 토큰 지시어로 정의 된 실제 토큰을 반환하지 않습니다. – codenheim