<< Demo046 >> << Section 6.6: Semantic Analysis >> use TextInput, LexicalAnalysis, SearchBestFirst; component SemanticAnalysis; UserInput(text) -> term; begin nil = null(sequence); term & sequence => sequence; text & sequence => sequence; Map = Graph:alist(Arc); PatternList = { Pattern("Q1","What is the distance between X and Y?"), Pattern("Q1","Distance X and Y?"), Pattern("Q2","What is the best route from X to Y?"), Pattern("Q3","What are the routes from X to Y?"), Pattern("A1","The distance between X and Y is Z kilometers."), Pattern("A1","Distance X and Y is Z km.")}; Pattern(text, text) -> optional(sequence); Pattern(Label, Pattern) = Label & tokenize(Input(Pattern)); UserInput(text) -> term; UserInput(input) = [ Result:=nil; [ Result:=Process(input)]; if Result <> nil then Result else term:"Sentence not understood!"]; Process(text) -> optional(term); Process(input) = [ Input = tokenize(Input(input)); Pattern = items(PatternList); Action(Head(Pattern), Match(Input,Tail(Pattern)))]; Match(Input = sequence, Pattern = sequence) -> optional(sequence); Match(= nil, = nil) = nil; Match(= nil, X) = no(sequence); Match(X, = nil) = no(sequence); Match( H1 & T1, H1 & T2) = Match(T1,T2); Match( H1 & T1, H2 & T2) = if Variable(H2) then H1 & Match(T1,T2) else no(sequence); Match( X , Y ) = no(sequence); Variable(term) -> boolean; Variable(text:T) = [ C = T[1]; size(T) == 1 & 'A' <= C & C <= 'Z']; Action(Code = term, sequence) -> optional(term); Action(Q, =nil) = no(term); Action("Q1", X & (Y & =nil)) = Distance(SearchBestFirst(Map,Node(X),Node(Y))); Action("Q2", X & (Y & =nil)) = Route(SearchBestFirst(Map,Node(X),Node(Y))); Action("Q3", X & (Y & =nil)) = term: {Route(SearchBestFirst(Map,Node(X),Node(Y)))}; Action("A1", X & (Y & (Z & =nil))) = [ add(Map,arc(Node(X),Node(Y),Cost(Z))); term:"accepted"]; Distance(sequence) -> term; Distance( cost( State, integer:Cost) & Z) = term: ("The distance is " & text(Cost,-1) & " kilometers."); Node(term) -> Node; Node(text:T) = Node:symbol(T); Route(sequence) -> term; Route( S) = term:{prioritems({State(Items(S))})}; Cost(term) -> Cost; Cost(text:T) = Cost:integer(T); Items(sequence) -> multi(term); Items(=nil) = no(term); Items( Head & Tail) = (Head, Items(Tail)); State(term) -> State; State(cost(State, Cost)) = State; Head(sequence) -> optional(term); Head(Head & Tail) = Head; Tail(sequence) -> optional(sequence); Tail(Head & Tail) = Tail; end component SemanticAnalysis; UserInput("Distance Amsterdam and Berlin is 669 km.")? UserInput("Distance Berlin and Vienna is 648 km.")? UserInput("Distance Vienna and Rome is 1150 km.")? UserInput("Distance Amsterdam and Paris is 517 km.")? UserInput("Distance Paris and Vienna is 1271 km.")? UserInput("Distance Paris and Nice is 912 km.")? UserInput("Distance Nice and Vienna is 1130 km.")? UserInput("Distance Nice and Rome is 723 km.")? UserInput("What is the distance between Amsterdam and Rome?")? UserInput("Distance Amsterdam and Nice?")? UserInput("What is the best route from Amsterdam to Nice?")? UserInput("What are the routes from Amsterdam to Rome?")?