Previous Next Contents

5   Creating the parser

Let the name of the grammar specification file be denoted by {grammar} and the name of the lexer specification file be denoted by {lexer} (e.g. in our calculator example these would stand for calc.grm and calc.lex, respectively). Let the parser name in the specification be represented by {n} (e.g. Calc in our calculator example).

To construct a parser, do the following:
  1. In the appropriate CM description file (e.g. for your main program or one of its subgroups or libraries), include the lines:
    ml-yacc-lib.cm
    {lexer}
    {grammar}
    
    This will cause ML-Yacc to be run on {grammar}, producing source files {grammar}.sig and {grammar}.sml, and ML-Lex to be run on {lexer}, producing a source file {lexer}.sml. Then these files will be compiled after loading the necessary signatures and modules from the ML-Yacc library as specified by ml-yacc-lib.cm.
  2. Apply functors to create the parser:
    structure {n}LrVals =
      {n}LrValsFun(structure Token = LrParser.Token)
    structure {n}Lex = 
      {n}LexFun(structure Tokens = {n}LrVals.Tokens)
    structure {n}Parser=
      Join(structure ParserData = {n}LrVals.ParserData
           structure Lex={n}Lex
           structure LrParser=LrParser)
    
    If the lexer was created using the %arg declaration in ML-Lex, the definition of {n}Parser must be changed to use another functor called JoinWithArg:
    structure {n}Parser=
      JoinWithArg
        (structure ParserData={n}LrVals.ParserData
         structure Lex={n}Lex
         structure LrParser=LrParser)
    
The following outline summarizes this process:
(* available at top level *)

TOKEN
LR_TABLE
STREAM
LR_PARSER
PARSER_DATA
structure LrParser : LR_PARSER

(* printed out in .sig file created by parser generator: *)

signature {n}_TOKENS = 
sig
  structure Token : TOKEN
  type svalue
  val PLUS : 'pos * 'pos ->
             (svalue,'pos) Token.token
  val INTLIT : int * 'pos * 'pos ->
               (svalue,'pos) Token.token
  ...
end

signature {n}_LRVALS =
sig
  structure Tokens : {n}_TOKENS
  structure ParserData : PARSER_DATA
  sharing ParserData.Token = Tokens.Token
  sharing type ParserData.svalue = Tokens.svalue
end

(* printed out by lexer generator: *)

functor {n}LexFun(structure Tokens : {n}_TOKENS)=
struct
  ...
end

(* printed out in .sml file created by parser generator: *)

functor {n}LrValsFun(structure Token : TOKENS) =
struct

  structure ParserData =
  struct
    structure Token = Token

    (* code in header section of specification *)

    structure Header = ...
    type svalue = ...
    type result = ...
    type pos = ...
    structure Actions = ...
    structure EC = ...
    val table = ...
  end

  structure Tokens : {n}_TOKENS =
  struct
    structure Token = ParserData.Token
    type svalue = ...
    fun PLUS(p1,p2) = ...
    fun INTLIT(i,p1,p2) = ... 
  end

end

(* to be done by the user: *)
 
structure {n}LrVals =
  {n}LrValsFun(structure Token = LrParser.Token)

structure {n}Lex = 
  {n}LexFun(structure Tokens = {n}LrVals.Tokens)

structure {n}Parser =
  Join(structure Lex = {n}Lex
       structure ParserData = {n}ParserData
       structure LrParser = LrParser)

Previous Next Contents