--[[ Sandwich DSL Semantic Model Module CSci 658: Software Language Engineering, Fall 2013 Exam 1, Problem 3 H. Conrad Cunningham, Professor Computer and Information Science University of Mississippi 1234567890123456789012345678901234567890123456789012345678901234567890 2013-11-25: Developed semantic model module Sandwich DSL. Suppose Emerald de Gassy, the owner of the Oxford-based catering business Deli-Gate, hires you to design a domain-specific language (DSL) for describing sandwich platters. The DSL will run as a program in Deli-Gate's robotic kitchen appliance SueChef (Sandwich and Utility Electronic Chef). SueChef's processor supports Lua and C programs. In discussing the problem with Emerald and the Deli-Gate staff, you discover the following: * A sandwich platter consists of zero or more sandwiches. * Each sandwich consists of layers of ingredients. * The categories of ingredients are breads, meats, cheeses, vegetables, and condiments. * Available breads are white, wheat, and rye. * Available meats are turkey, chicken, ham, roast beef, and tofu. (Okay, tofu is not a meat, but it is a good protein source for those who do not wish to eat meat. This is a college town after all. Oh, there is also a special meat served for football games Thanksgiving week called ``bulldog'', but it is really just chicken, so we can ignore that choice for our purposes here.) * Available cheeses are American, Swiss, jack, and cheddar. * Available vegetables are tomato, lettuce, onion, and green pepper. * Available condiments are mayo, mustard, relish, and Tabasco. (Of course, the mayo is Blue Plate Mayonnaise and the mustard is a Creole mustard.) * The sandwiches must be assembled in Oxford Standard Order (OS slice of bread on the bottom, then zero or more meats layered above that, then zero or more cheeses, then zero or more vegetables, then zero or more condiments, and then a slice of bread on top. The top and bottom slices of bread must be of the same type. (OSO was defined by the mysterious and picky food critic known as CH.) Describe an appropriate semantic model for your Sandwich DSL. That is, what concrete data structures might you use? What functions/methods to manipulate the semantic model? Remember the sandwiches must be assembled in OSO. Choose to do either an external DSL or an internal DSL. Tell me which. Describe the syntax for your DSL. Give a script for configuring the following platter: one turkey and Swiss on rye with tomatoes and mayo; one tofu and mustard on wheat. Describe a design for an implementation for your DSL. That is, how would you translate a DSL script into an appropriate configuration of the semantic model? What DSL implementation techniques or tools would you use? Be specific. DATA REPRESENTATION This semantic model design and implementation uses tables to represent platters and sandwiches. The representation is more general than needed for the Sandwich DSL problem from the exam. A list-style table { PLATTER, n, sandwich1, sandwich2, ... sandwichM } describes a set of n identical platters, for some n > 0. PLATTER is a tag constant. Each platter has M descriptions of sandwiches, for some M >= 0. A list-style table { SANDWICH, n, layer1, layer2, ... layerM } describes a set of n identical sandwiches, for some n > 0. Each sandwich has M layers of ingredients ordered from bottom to top, for some M >= 0. Unlike the Lair semantic model, this semantic model is not technically object-oriented. However, the tables described above are objects constructed and manipulated by the functions in this module. A DSL builder module should not create or access these directly. But more functions may be needed to enable effective use of this model by other tools. --]] -- Object tags local PLATTER = "Platter" local SANDWICH = "Sandwich" -- Constructor function makePlatter(n) returns a specification for a -- platter intended to have "n" copies. Initially, the platter -- contains no sandwiches. local function makePlatter(n) if n == nil or n < 1 then n = 1 end return {PLATTER, n} end -- Constructor function makeSandwich(n) returns a specification for a -- sandwich intended to have "n" copies. Initially, the sandwich has -- no ingredients. local function makeSandwich(n) if n == nil or n < 1 then n = 1 end return {SANDWICH, n} end -- Mutator function addSandwich(platter,sandwich) inserts the sandwich -- specification "sandwich" into the platter specification "platter". local function addSandwich(platter,sandwich) platter[#platter+1] = sandwich end -- Mutator function addLayer(sandwich,ingredient) inserts the -- ingredient "ingredient" as the new top layer of the sandwich -- specification "sandwich". local function addLayer(sandwich,ingredient) sandwich[#sandwich+1] = ingredient end -- Function valToString(spec) recursively converts a platter or -- sandwich specification "spec" to a parenthesized list with tags. local function valToString(spec) local function convertList(t,k) local res = {} for i = k, #t do res[#res+1] = valToString(spec[i],k) end return table.concat(res,",") end if type(spec) == "table" then local tag, n = spec[1], spec[2] local out if tag == PLATTER then return tostring(PLATTER) .. "[" .. tostring(n) .. "](" .. convertList(spec,3) .. ")" elseif tag == SANDWICH then return tostring(SANDWICH) .. "[" .. tostring(n) .. "](" .. convertList(spec,3) .. ")" else return "Unknown_Tag" end else return tostring(spec) end end -- Module export return { makePlatter = makePlatter, makeSandwich = makeSandwich, addSandwich = addSandwich, addLayer = addLayer, valToString = valToString }