2009-09-18 3 views
4

나는 파서와 렉서가 ocamlyacc와 ocamllex로 쓰여졌다. 구문 분석 할 파일이 너무 일찍 끝나면 줄 끝의 세미콜론을 잊어 버린 것처럼 응용 프로그램은 구문 오류를 발생시키지 않습니다. 내가 깨닫고 EOF를 잡아서 렉서가 끝나지 않은 규칙을 무시하게 만들었 기 때문에 그것이 실현되었다. 그러나 어떻게 이되어야 하는가? 내가 문법 오류를 제기하기 위해이 일을하고 있는가? 여기 불완전한 문법 규칙을 무시한 파서/렉서

내 전류 파서 (간체),

%{ 
    let parse_error s = Printf.ksprinf failwith "ERROR: %s" s 
%} 

%token COLON 
%token SEPARATOR 
%token SEMICOLON 
%token <string> FLOAT 
%token <string> INT 
%token <string> LABEL 

%type <Conf.config> command 
%start command 
%% 
    command: 
     | label SEPARATOR data SEMICOLON { Conf.Pair ($1,$3)  } 
     | label SEPARATOR data_list   { Conf.List ($1,$3)  } 
     | label SEMICOLON     { Conf.Single ($1)  } 
    label : 
     | LABEL        { Conf.Label $1   } 
    data : 
     | label        { $1     } 
     | INT        { Conf.Integer $1  } 
     | FLOAT        { Conf.Float $1   } 
    data_list : 
     | star_data COMMA star_data data_list_ending 
              { $1 :: $3 :: $4  } 
    data_list_ending: 
     | COMMA star_data data_list_ending { $2 :: $3    } 
     | SEMICOLON       { []     } 

및 lexxer (간체),

{ 
    open ConfParser 
    exception Eof 
} 

rule token = parse 
    | ['\t' ' ' '\n' '\010' '\013' '\012'] 
         { token lexbuf } 
    | ['0'-'9']+ ['.'] ['0'-'9']* ('e' ['-' '+']? ['0'-'9']+)? as n 
         { FLOAT n  } 
    | ['0'-'9']+ as n { INT n   } 
    | '#'    { comment lexbuf } 
    | ';'    { SEMICOLON  } 
    | ['=' ':']   { SEPARATOR  } 
    | ','    { COMMA   } 
    | ['_' 'a'-'z' 'A'-'Z']([' ']?['a'-'z' 'A'-'Z' '0'-'9' '_' '-' '.'])* as w 
         { LABEL w  } 
    | eof    { raise Eof  } 

and comment = parse 
    | ['#' '\n']  { token lexbuf } 
    | _     { comment lexbuf } 

예시 입력 파일

one = two, three, one-hundred; 
single label; 
list : command, missing, a, semicolon 

한 해결책이 추가하는 끝에있는 명령 규칙에서 재귀 호출을 호출하고 빈 규칙을 추가합니다.이 규칙은 모두 반환 목록을 만듭니다. 주요 프로그램. 아마 Eof를 기대치로 해석하고 렉서의 오류가 아니라 종료 조건이 맞을 것이라고 생각합니다.

답변

5

ocamlyacc은 전체 입력을 반드시 소모하지 않습니다. 전체 입력을 구문 분석 할 수없는 경우 강제로 실패 시키려면 문법에 EOF과 일치해야합니다. 대신 렉서에 Eof 인상의 토큰 EOF를 추가하고

%type <Conf.config list> main 

main: 
    EOF { [] } 
    | command main { $1::$2 } 
+0

예에 start 기호를 변경,이 솔루션입니다. 나는 EOF를 올리지 않고 문법으로 목록을 작성하지 않고 놀고 있었지만 당신은 정확합니다. Chris에게 감사드립니다. – nlucaroni