0

I am currently working on a Pascal Parser using OCaml and Menhir. When I compile my parser.mly, which contains the following scriptlet of code, Menhir simply says "Warning: if_cmd generates empty language" This might happen when the rule "if_cmd" can't be reached from the initial (correct me, if I'm wrong), but logically, it was supposed to be reached. I can't figure out why this warning is happening. For example, if I use an input file for the grammar specified in parser.mly with these statements:

program ex1; 
x:=1
y:=(2)

it gives me the desired answer. But if I use this as input

program ex1; 
x:=1
y:=(2)
if(x and 2) then
   y:=3

it states Exception: Syntax.Error, probably because of that Warning

With these 4 following files within the same folder, I've used the ocamlbuild -use-menhir main.byte command, which generates the just mentioned Warning

lexer.mll

{
   open Lexing
   open Printf
   open Parser

   let incr_line_number lexbuf = 
   let pos = lexbuf.lex_curr_p in
             lexbuf.lex_curr_p <- { pos with
             pos_lnum = pos.pos_lnum + 1;
             pos_bol = pos.pos_cnum;
            }
}


let digit = ['0' - '9']
let integer = digit+

let letter = ['a' - 'z' 'A' - 'Z']
let identifier = letter ( letter | digit | '_')*

let blank = [' ' '\t']+
let newLine = '\r' | '\n' | "\r\n"

rule token = parse
  blank    { token lexbuf }
| newLine  { incr_line_number lexbuf; token lexbuf }
| integer as num { let number = int_of_string num in 
                LITINT number  }
| '('                            { OPENPAR }
| ')'                            { CLOSEPAR }
| ';'                            { SEMICOLON }
| "program " + identifier as id  { PROGRAM (id) }
| "begin"                        { BEGIN }
| "end"                          { END }
| "if"                           { IF }
| "then"                         { THEN }
| "else"                         { ELSE }
| ":="                           { ASSIGN }
| "and"                          { AND }
| "or"                           { OR } 
| identifier as id               { ID id }
| eof                            { EOF }

parser.mly

%{
  open Ast (* Abstract Syntax Tree*)
%}

%token <int> LITINT
%token <string> PROGRAM
%token <string> ID
%token BEGIN END
%token SEMICOLON
%token ASSIGN
%token IF THEN ELSE
%token OPENPAR CLOSEPAR
%token AND OR
%token EOF

%left OR
%left AND

%start program
%type <Ast.program> program

%%

program: prog=PROGRAM SEMICOLON
      c = command*
      EOF
      { Program (prog, List.flatten c) }

command: c = assignment_cmd                     { c }
       | c = if_cmd                             { c }
       | BEGIN cs=command+ END SEMICOLON        { Block cs }

assignment_cmd: id = ID ASSIGN e = expression { AssignmentCmd (id, e) }

if_cmd: IF e=expression THEN 
            c1=command
            s=option(ELSE c2=command {c2})
        { IfCmd (e, c1, s) }

expression: id=ID                           { ExpVar id }
     | i=LITINT                             { ExpInt i }
     | e1=expression op=oper e2=expression  { ExpOp (op, e1, e2) }
     | OPENPAR e=expression CLOSEPAR        { e }

%inline oper:
     | AND      { And }
     | OR       { Or }

ast.ml

type ident = string

type program = Program of ident * commands
and commands = command list
and command = AssignmentCmd of ident * expression
            | IfCmd of expression * command * (command option)
            | Block of commands

and expression = ExpVar of ident
               | ExpInt of int
               | ExpOp of oper * expression * expression

and oper = 
         | And
         | Or

main.ml

open Ast

let parse_file name =
                        let ic = open_in name in
                        let lexbuf = Lexing.from_channel ic in
                        let ast = Parser.program Lexer.token lexbuf in
                        let _ = close_in ic in
                        ast
stamblew
  • 138
  • 1
  • 11
  • 1
    You have to put here a minimized but complete code which can reproduce your problem so that ppl can easilly try it. – camlspotter May 05 '16 at 18:49
  • @camlspotter I thought it would be overwhelmingly tiresome to include everything to those who may read the problem, so I posted the main part. But as soon as I get back home, I am going to post the remaining code – stamblew May 05 '16 at 19:42
  • 1
    "minimized but complete" does not mean "include everything" nor does it mean "include a bit and let us guess about the rest". What it means is "come up with something simpler which exhibits the same problem, and post all of the simpler thing." Aside from make life easier for anyone trying to help you, it is also a good technique for figuring out for yourself what might be going on. By the way, is `expressao` a typo (eg. not translated from portuguese) or is it an actual non-terminal similar to but different from `expression`? – rici May 05 '16 at 21:45
  • @rici thanks for the hints. I tried to show a small portion of the entire program. Trust me, this is the maximum I could squeeze from it. And yes, `expressao` is the same as expression (a non-terminal symbol), I just forgot to translate it to English, sorry for that. – stamblew May 06 '16 at 00:50
  • Menhir version 20160303 does not show the warning you mention by `menhir -v parser.mly`. – camlspotter May 06 '16 at 01:55
  • In addition, `parser.mly` has a type error: at `program`, `List.flatten c` should be just `c`. With this fix, `Main.parse_file` processes both of your input examples without raising any exceptions. This is the reason why you should try posting something replayable by other people. – camlspotter May 06 '16 at 02:19
  • Thanks for the help guys @camlspotter the problem was the menhir version indeed. I updated the menhir build, and everything runs just fine. Anyway, thanks again – stamblew May 07 '16 at 18:09

0 Answers0