سؤال

ولدي محلل وlexer مكتوب في ocamlyacc وocamllex. إذا كان الملف لتحليل نهايات قبل الأوان، كما هو الحال في أنسى فاصلة منقوطة في نهاية السطر، التطبيق لا يثير خطأ في بناء الجملة. وأنا أدرك انها لأنني رفع واصطياد EOF والذي جعل lexer تجاهل القاعدة التي لم تكتمل، ولكن كيف <م> يجب I أن تفعل هذا لرفع خطأ لغوي؟

وهنا هو بلدي محلل الحالي (المبسطة)،

%{
    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

وحل واحد، هو إضافة مكالمة متكررة في حكم الأمر لنفسه في النهاية، وإضافة قاعدة فارغة، وكلها بناء قائمة للعودة إلى البرنامج الرئيسي. أعتقد أنني ربما تفسير الفولكلوري كما توقع، وإنهاء حالة، بدلا من خطأ في lexer، هل هذا صحيح؟

هل كانت مفيدة؟

المحلول

وocamlyacc لا تستهلك بالضرورة مدخلات كله. إذا كنت ترغب في إجبارها على تفشل إذا دخل كله يتم تحليل-قادرة، تحتاج لمطابقة EOF في قواعد اللغة الخاصة بك. بدلا من رفع Eof فيكم lexer، إضافة EOF رمز وتغيير رمز start ل

%type <Conf.config list> main

main:
    EOF { [] }
  | command main { $1::$2 }
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top