22.4 The Complete Program

The complete program of the concurrent parser below runs under Mozart 3.0.0 only.

declare   
fun{RunAgenda agenda(initialize:Initialize
                     processInfo:ProcessInfo)}
   local 
      Items  
      local 
         MailBox={Port.new Items}
      in 
         proc {Post Item}
            {Port.send MailBox Item}
         end 
      end 
      local 
         proc{Process Agent Item Board}
            case Item
            of stop then raise done end 
            elseof info(Info) then 
               NewObjects = {ProcessInfo Agent Info}
            in 
               {ForAll NewObjects
                proc{$ O}
                   case O of agent(A) then {StartAgent A}
                   elseof info(I) then {Board.post info(I)}
                   end 
                end}
               {Board.post infoProcessed}
            else skip % other control items
            end 
         end 
      in 
         proc{StartAgent Agent}
            {Board.post newAgent}
            thread 
               try {ForAll Board.items
                    proc {$ Item}
                       {Process Agent Item Board}
                    end}
               catch done then skip end 
            end 
            {Show done}
         end 
      end  
   in 
      Board = board(items:Items  
                    post:Post  
                    startAgent:StartAgent)
   end 
   local 
      class WatcherState 
         attr 
            agents:0
            infos:0
            tasks:0
            initialized:false 
         meth init skip end 
         meth initialized 
            initialized<-true 
         end 
         meth infoProcessed 
            tasks<-@tasks-1
         end 
         meth newAgent 
            agents<-@agents+1
            tasks<-@tasks+@infos
         end 
         meth info(...)
            infos<-@infos+1
            tasks<-@tasks+@agents
         end 
         meth done($)
            {And @initialized @tasks==0}
         end 
      end 
   in 
      proc{StartWatcher Board}
         local 
            State={New WatcherState init}
         in 
            proc{Process Item}
               {State Item}
               if {State done($)}
               then 
                  {Board.post stop}
                  raise done end 
               else 
                  skip 
               end 
            end 
         end 
      in      
         thread 
            try {ForAll Board.items Process}
            catch done
            then skip 
            end 
         end 
      end 
   end 
   fun{FilterInfos Items}
      case Items
      of info(Info)|Is then Info|{FilterInfos Is}
      elseof stop|then nil
      elseof _|Is then {FilterInfos Is}
      end 
   end 
in 
   {StartWatcher Board}
   {Initialize Board}  
   {Board.post initialized}  
   {FilterInfos Board.items}
end   
fun{MakeAgenda Rules Lexicon Words}
   fun{MoveDot Rule}
      case Rule of rule(head:Head done:Done todo:Next|Todo dot:Index)
      then rule(head:Head done:Next|Done todo:Todo dot:Index+1) end 
   end 
       
   fun{ProcessInfo Agent Edge}% computes new a info item or a new agent  
                              % whenever possible by applying the
                              % dotted rule of the Agent to the Edge
      fun{Create Pred Right}
         if Agent.rule.todo.2==nil then 
            info(edge(left: Agent.left
                      right  : Right
                      cat    : Agent.rule.head
                      pred   : Pred))
         else 
            agent(edge(left:Agent.left
                       right:Right
                       rule:{MoveDot Agent.rule}
                       pred:Pred))
         end 
      end 
   in 
      if Edge.left==Agent.right andthen 
         Edge.cat==Agent.rule.todo.1
      then 
         {Map
          {Search.allP
           proc {$ Tree}
              {Agent.pred Tree}
              {Edge.pred}.head = Tree.args.(Agent.rule.dot)
           end 1 _}
          fun{$ Pred} {Create Pred Edge.right} end}
      else 
         nil
      end 
   end  
 
   proc{Initialize Board}  
      {List.forAllInd Words
       proc {$ I Word}
          {ForAll {Lexicon Word}
           proc {$ Cat#Fun}
              fun {Pred} root(head:{Fun} args:args) end 
           in 
              {Board.post info(edge(left:I right:I+1
                                    cat:Cat pred:Pred))} end}
       end}
      {ForAll Rules
       proc {$ Rule}
          %% -- for each rule
          case Rule of rule(Head Body Fun) then 
             N = {Length Body}
             R = rule(head:Head done:nil todo:Body dot:1)
             fun {Pred}
                Args = {Tuple.make args N}
             in 
                root(head:{Fun Args} args:Args)
             end 
          in 
             {List.forAllInd Words
              proc {$ I _}
                 %% -- for each position
                 {Board.startAgent edge(left:I right:I rule:R pred:Pred)}
              end}
          end 
       end}
   end 
 
in 
   agenda(initialize:Initialize
          processInfo:ProcessInfo)
end    
local  
   Dir='www.ps.uni-sb.de/~niehren/vorlesung/Programs/Functors/'   
   URL='http://'#Dir
   [GrammarMod] = {Module.link [URL#'Grammar.ozf']}
in 
   Rules = GrammarMod.rules
   Lexicon = GrammarMod.lexicon
end 
 
fun{Parse Words}
    Agenda = {MakeAgenda Rules Lexicon Words}
    Edges = {RunAgenda Agenda}  
    {Browse Edges}
    FullEdges ={Filter Edges fun{$ E}  
                                {And E.left==1  
                                 E.right=={Length Words}+1}
                             end}
in 
    {Map FullEdges fun{$ E}  
                      {E.pred}.head
                   end}
end 
 
/*
 
declare Words = [john saw the man with the telescope]
{Browse {Parse Words}}
 
*/

If you want another Mozart version instead then you have to recompile the grammar functor and to use your new version. Here is the code of the grammar functor:

functor 
export 
   Lexicon Rules
define 
   Lex =
   lex(
      the:
         [det   #fun {$} det(phon:the number:_) end]
      a:
         [det   #fun {$} det(phon:a number:singular) end]
      john:
         [np    #fun {$} np(phon:john number:singular) end]
      man:
         [n     #fun {$} n(phon:man number:singular) end]
      men:
         [n     #fun {$} n(phon:men number:plural) end]
      woman:
         [n     #fun {$} n(phon:woman number:singular) end]
      women:
         [n     #fun {$} n(phon:women number:plural) end]
      'with':
         [prep  #fun {$} prep(phon:'with'end]
      telescope:
         [n     #fun {$} np(phon:telescope number:singular) end]
      saw:
         [v     #fun {$} v(phon:saw number:_) end]
      sees:
         [v     #fun {$} v(phon:see number:singular) end]
      likes:
         [v     #fun {$} v(phon:likes number:singular) end 
          n     #fun {$} n(phon:likes number:plural  ) end]
      like:
         [v     #fun {$} v(phon:like number:plural) end]
      )
   fun {Lexicon Word} Lex.Word end 
   Rules =
   [rule(s [np vp]
         fun {$ Args}
            Args.1^number=Args.2^number
            s(Args.1 Args.2)
         end)
    rule(np [det n]
         fun {$ Args}
            Args.1^number=Args.2^number
            np(number:Args.2^number Args.1 Args.2)
         end)
    rule(np [n]
         fun {$ Args}
            Args.1^number=plural
            np(number:plural Args.1)
         end)
    rule(np [np pp]
         fun {$ Args}
            np(number:Args.1^number Args.1 Args.2)
         end)
    rule(vp [v np]
         fun {$ Args}
            vp(number:Args.1^number Args.1 Args.2)
         end)
    rule(vp [vp pp]
         fun {$ Args}
            vp(number:Args.1^number Args.1 Args.2)
         end)
    rule(pp [prep np]
         fun {$ Args}
            pp(Args.1 Args.2)
         end)
    rule(vp [v]
         fun {$ Args}
            vp(number:Args.1^number Args.1)
         end)
   ]
end


Denys Duchier, Claire Gardent and Joachim Niehren
Version 1.3.99 (20050412)