We also have some auxiliary signatures needed by corresponding functors. We will
see how these signatures are used by corresponding functors in section 3.3.
The Prelude Signature
This first auxiliary signature is signature PRELUDE:
signature PRELUDE =
sig
val charofdigit : int -> string
val stringofnat : int -> string
val stringofint : int -> string
val file : string -> string
exception Error
val say : string -> 'a
val error : string -> 'a
val member : ''a list -> ''a -> bool
end
In this signature, we define the types of some functions for general usage. For instance, the function stringofint changes an integer into a string and function member checks if an element is the member of a list and return a boolean value.
The Lexical Analyzer Signature
The second auxiliary signature is signature LEX:
signature LEX =
sig
datatype token = Operation of string
| Symbol of string
| Number of int
val err_lex : int ref
val keyword : string -> bool
val keycheck : string -> token
val digit : string -> bool
val letter : string -> bool
val letdigetc : string -> bool
val layout : string -> bool
val symbolchar : string -> bool
val intofdigit : string -> int
val lexanal : string list -> token list
val getword : string list -> string list -> token list
val getsymbol : string list -> string list -> token list
val getnum : int -> string list -> token list
val getnum_minus : int -> string list -> token list
end
In this signature, we define a function lexanal to do the lexical analysis. It translates the Macro COSY program from strings into token lists. The parser will read this token list to construct a syntax tree according to the datatypes given in signature COSY. We also define some functions such as getword, getsymbol, getnum and getnum_minus to assist this operation.
The Parser Builder Signature
The third auxiliary signature is signature PARSER_BUILDER(this signature is adopted from [Rea89]p.261):
signature PARSER_BUILDER =
sig
structure LX: LEX
datatype 'a possible = Ok of 'a | Fail
val pair : 'a -> 'b -> 'a * 'b
val <|>
: ('a -> 'b possible)
* ('a -> 'b possible) -> 'a -> 'b possible
val modify
: ('a -> ('b * 'c) possible)
* ('b -> 'd) -> 'a -> ('d * 'c) possible
val <&>
: ('a -> ('b * 'c) possible) * ('c -> ('d * 'e) possible)
-> 'a -> (('b * 'd) * 'e) possible
val emptyseq : 'a -> ('b list * 'a) possible
val consonto : 'a list -> 'a -> 'a list
val optional
: ('a -> ('b * 'a) possible) -> 'a -> ('b list * 'a) possible
val number : LX.token list -> (int * LX.token list) possible
val literal
: string -> LX.token list -> (string * LX.token list) possible
val operation
: LX.token list -> (string * LX.token list) possible
end
Signature PARSER_BUILDER defines parser builders to help in the
construction of the parser. We will discuss this later. The datatype 'a
possible in this signature has two constructors, Ok an Fail. If no
errors were found during parsing, the parser will return Ok. Otherwise
the parser will return Fail.
The Prelude of Context-Sensitive Restrictions Signature
The fourth auxiliary signature is signature CSR_PRELUDE:
signature CSR_PRELUDE =
sig
structure CSY: COSY
structure LX: LEX
val unboundlist : {name:string, value:int} list ref
type unbound
val iex1 : CSY.dim -> int
val iex : CSY.iexpr -> int
val power : int * int -> int
val getvalue
: string * {name:string, value:int} list -> int
val cr_unbound_list
: string * {name:string, value:int} list ref -> int
val inp : string -> int
val inp1 : LX.token list * string -> int
end
In this signature, we define some functions which are used frequently in checking context-sensitive restrictions. For example, function inp and inp1 read an string from keyboard and change the string into integer value to bound the variable.
The Transformer Signature
The fifth auxiliary is signature TRANSFORM:
signature TRANSFORM =
sig
structure CSY: COSY
val transform : CSY.mprogram -> CSY.mprogram
end
Before expansion, we need to transform all distributor subtrees into
concatenator subtrees. The function transform in signature TRANSFORM
is defined to do this job. From its type we can see that it reads a type
mprogram (syntax tree) and outputs an mprogram.
The Path First Signature
The sixth auxiliary signature is signature PFIRST:
signature PFIRST =
sig
structure CSY: COSY
val pathfirst : CSY.mprogram -> int ref -> CSY.mprogram
val chg : int ref
end
Before expansion, we need to define a function pathfirst in signature PFIRST in order to put all the paths in front of the processes. Therefore, the expanded COSY program will satisfy the Basic COSY grammar after expansion. chg acts as a flag. If the tree is not changed, then chg will remain zero. If the tree is changed, then chg will become 1, in this case, we need to use the changed tree to apply to the function pathfirst again until chg is zero.