home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.cs.arizona.edu
/
ftp.cs.arizona.edu.tar
/
ftp.cs.arizona.edu
/
icon
/
historic
/
v941.tgz
/
icon.v941src.tar
/
icon.v941src
/
src
/
common
/
typespec.icn
< prev
next >
Wrap
Text File
|
2000-07-29
|
13KB
|
483 lines
#
# typespec - transform Icon type specifications into C tables.
# Specifications are read from standard input; tables are written
# to standard output.
#
# The grammar for the a type specifcation is:
#
# <type-def> ::= <identifier> <opt-abrv> : <kind> <opt-return>
#
# <kind> ::= simple |
# aggregate(<component>, ... ) |
# variable <var-type-spec>
#
# <component> ::= var <identifier> <opt-abrv> |
# <identifier>
#
# <var-type-spec> ::= initially <type> |
# always <type>
#
# <type> ::= <type-name> | <type> ++ <type-name>
#
# <opt-abrv> ::= <nil> |
# { <identifier> }
#
# <opt-return> ::= <nil> |
# return block_pointer |
# return descriptor_pointer |
# return char_pointer |
# return C_integer
# Information about an Icon type.
#
record icon_type(
id, # name of type
support_new, # supports RTL "new" construct
deref, # dereferencing needs
rtl_ret, # kind of RTL return supported if any
typ, # for variable: initial type
num_comps, # for aggregate: number of type components
compnts, # for aggregate: index of first component
abrv) # abreviation used for type tracing
# Information about a component of an aggregate type.
#
record typ_compnt (
id, # name of component
n, # position of component within type aggragate
var, # flag: this component is an Icon-level variable
aggregate, # index of type that owns the component
abrv) # abreviation used for type tracing
record token(kind, image)
global icontypes, typecompnt, type_indx, compnt_indx
global lex, line_num, saved_token, error_msg, prog_name
procedure main()
local typ, tok, compnt, indx, x
prog_name := "typespec"
lex := create tokenize_input()
icontypes := []
typecompnt := []
#
# Read each of the type specifications
#
while typ := icon_type(ident("may be EOF")) do {
#
# Check for abreviation
#
typ.abrv := opt_abrv(typ.id)
if next_token().kind ~== ":" then
input_err("expected ':'")
#
# See what kind of type this is
#
case ident() of {
"simple": {
typ.support_new := "0"
typ.deref := "DrfNone"
typ.num_comps := "0"
typ.compnts := "0"
}
"aggregate": {
typ.support_new := "1"
typ.deref := "DrfNone"
#
# get the component names for the type
#
typ.compnts := *typecompnt
if next_token().kind ~== "(" then
input_err("expected '('")
typ.num_comps := 0
tok := next_token()
if tok.kind ~== "id" then
input_err("expected type component")
while tok.kind ~== ")" do {
#
# See if this component is an Icon variable.
#
if tok.image == "var" then {
compnt := typ_compnt(ident(), typ.num_comps, "1", *icontypes)
compnt.abrv := opt_abrv(compnt.id)
}
else
compnt := typ_compnt(tok.image, typ.num_comps, "0",
*icontypes)
put(typecompnt, compnt)
typ.num_comps +:= 1
tok := next_token()
if tok.kind == "," then {
tok := next_token()
if tok.kind ~== "id" then
input_err("expected type component")
}
else if tok.kind ~== ")" then
input_err("expected type component")
}
}
"variable": {
typ.support_new := "0"
typ.num_comps := "0"
typ.compnts := "0"
case ident() of {
"initially":
typ.deref := "DrfGlbl"
"always":
typ.deref := "DrfCnst"
default:
input_err("expected 'initially' or 'always'")
}
#
# Get the initial type associated with the variable
#
typ.typ := [ident()]
tok := &null
while (tok := next_token("may be EOF")).kind == "++" do {
put(typ.typ, ident())
tok := &null
}
saved_token := tok # put token back
}
default:
input_err("expected 'simple', 'aggregate', or 'variable'")
}
#
# Check for an optional return clause
#
tok := &null
if (tok := next_token("may be EOF")).image == "return" then {
case next_token().image of {
"block_pointer":
typ.rtl_ret := "TRetBlkP"
"descriptor_pointer":
typ.rtl_ret := "TRetDescP"
"char_pointer":
typ.rtl_ret := "TRetCharP"
"C_integer":
typ.rtl_ret := "TRetCInt"
default:
input_err("expected vword type")
}
}
else {
typ.rtl_ret := "TRetNone"
saved_token := tok # put token back
}
put(icontypes, typ)
}
#
# Create tables of type and compontent indexes.
#
type_indx := table()
indx := -1
every type_indx[(!icontypes).id] := (indx +:= 1)
compnt_indx := table()
indx := -1
every compnt_indx[(!typecompnt).id] := (indx +:= 1)
write("/*")
write(" * This file was generated by the program ", prog_name, ".")
write(" */")
write()
#
# Locate the indexes of types with special semantics or which are
# explicitly needed by iconc. Output the indexes as assignments to
# variables.
#
indx := req_type("string")
icontypes[indx + 1].rtl_ret := "TRetSpcl"
write("int str_typ = ", indx, ";")
indx := req_type("integer")
write("int int_typ = ", indx, ";")
indx := req_type("record")
write("int rec_typ = ", indx, ";")
indx := req_type("proc")
write("int proc_typ = ", indx, ";")
indx := req_type("coexpr")
write("int coexp_typ = ", indx, ";")
indx := req_type("tvsubs")
icontypes[indx + 1].deref := "DrfSpcl"
icontypes[indx + 1].rtl_ret := "TRetSpcl"
write("int stv_typ = ", indx, ";")
indx := req_type("tvtbl")
icontypes[indx + 1].deref := "DrfSpcl"
write("int ttv_typ = ", indx, ";")
indx := req_type("null")
write("int null_typ = ", indx, ";")
indx := req_type("cset")
write("int cset_typ = ", indx, ";")
indx := req_type("real")
write("int real_typ = ", indx, ";")
indx := req_type("list")
write("int list_typ = ", indx, ";")
indx := req_type("table")
write("int tbl_typ = ", indx, ";")
#
# Output the type table.
#
write()
write("int num_typs = ", *icontypes, ";")
write("struct icon_type icontypes[", *icontypes, "] = {")
x := copy(icontypes)
output_typ(get(x))
while typ := get(x) do {
write(",")
output_typ(typ)
}
write("};")
#
# Locate the indexes of components which are explicitly needed by iconc.
# Output the indexes as assignments to variables.
#
write()
indx := req_compnt("str_var")
write("int str_var = ", indx, ";")
indx := req_compnt("trpd_tbl")
write("int trpd_tbl = ", indx, ";")
indx := req_compnt("lst_elem")
write("int lst_elem = ", indx, ";")
indx := req_compnt("tbl_dflt")
write("int tbl_dflt = ", indx, ";")
indx := req_compnt("tbl_val")
write("int tbl_val = ", indx, ";")
#
# Output the component table.
#
write()
write("int num_cmpnts = ", *typecompnt, ";")
write("struct typ_compnt typecompnt[", *typecompnt, "] = {")
output_compnt(get(typecompnt))
while compnt := get(typecompnt) do {
write(",")
output_compnt(compnt)
}
write("};")
end
#
# ident - insure that next token is an identifier and return its image
#
procedure ident(may_be_eof)
local tok
tok := next_token(may_be_eof) | fail
if tok.kind == "id" then
return tok.image
else
input_err("expected identifier")
end
#
# opt_abrv - look for an optional abreviation. If there is none, return the
# default value supplied by the caller.
#
procedure opt_abrv(abrv)
local tok
tok := next_token("may be EOF")
if tok.kind == "{" then {
abrv := ident()
if next_token().kind ~== "}" then
input_err("expected '}'")
}
else
saved_token := tok # put token back
return abrv
end
#
# next_token - get the next token, looking to see if one was put back.
#
procedure next_token(may_be_eof)
local tok
if \saved_token then {
tok := saved_token
saved_token := &null
return tok
}
else if tok := @lex then
return tok
else if \may_be_eof then
fail
else {
write(&errout, prog_name, ", unexpected EOF")
exit(1)
}
end
#
# req_type - get the index of a required type.
#
procedure req_type(id)
local indx
if indx := \type_indx[id] then
return indx
else {
write(&errout, prog_name, ", the type ", id, " is required")
exit(1)
}
end
#
# req_compnt - get the index of a required component.
#
procedure req_compnt(id)
local indx
if indx := \compnt_indx[id] then
return indx
else {
write(&errout, prog_name, ", the component ", id, " is required")
exit(1)
}
end
#
# output_typ - output the table entry for a type.
#
procedure output_typ(typ)
local typ_str, s, indx
writes(" {", image(typ.id), ", ", typ.support_new, ", ", typ.deref, ", ",
typ.rtl_ret, ", ")
if \typ.typ then {
typ_str := repl(".", *type_indx)
every s := !typ.typ do {
if s == "any_value" then {
every indx := 1 to *icontypes do {
if icontypes[indx].deref == "DrfNone" then
typ_str[indx] := icontypes[indx].abrv[1]
}
}
else if indx := \type_indx[s] + 1 then
typ_str[indx] := icontypes[indx].abrv[1]
else {
write(&errout, prog_name, ", the specification for ", typ.id,
" contains an illegal type: ", s)
exit(1)
}
}
writes(image(typ_str))
}
else
writes("NULL")
writes(", ", typ.num_comps, ", ", typ.compnts, ", ", image(typ.abrv), ", ")
writes(image(map(typ.id[1], &lcase, &ucase) || typ.id[2:0]), "}")
end
#
# output_compnt - output the table entry for a component.
#
procedure output_compnt(compnt)
writes(" {", image(compnt.id), ", ", compnt.n, ", ", compnt.var, ", ",
compnt.aggregate, ", ", image(\compnt.abrv) | "NULL", "}")
end
#
# input_err - signal the lexical anaylser to print an error message about
# the last token
#
procedure input_err(msg)
error_msg := msg
@lex
end
#
# tokenize_input - transform standard input into tokens and suspend them
#
procedure tokenize_input()
local line
line_num := 0
while line := read() do {
line_num +:= 1
suspend line ? tokenize_line()
}
fail
end
#
# tokenize_line - transform the subject of string scanning into tokens and
# suspend them
#
procedure tokenize_line()
local s, tok, save_pos
static id_chars
initial id_chars := &letters ++ &digits ++ '_'
repeat {
tab(many(' \t')) # skip white space
if ="#" | pos(0) then
fail # end of input on this line
save_pos := &pos
if any(&letters) then
tok := token("id", tab(many(id_chars)))
else if s := =(":" | "(" | "," | ")" | "++" | "{" | "}") then
tok := token(s, s)
else
err("unknown symbol")
suspend tok
err(\error_msg, save_pos) # was the last token erroneous?
}
end
#
# err - print an error message about the current string being scanned
#
procedure err(msg, save_pos)
local s, strt_msg
tab(\save_pos) # error occured here
strt_msg := prog_name || ", " || msg || "; line " || line_num || ": "
(s := image(tab(1))) & &fail # get front of line then undo tab
strt_msg ||:= s[1:-1] # strip ending quote from image
s := image(tab(0)) # get end of line
s := s[2:0] # strip first quote from image
write(&errout, strt_msg, s)
write(&errout, repl(" ", *strt_msg), "^") # show location of error
exit(1)
end