Blob Blame History Raw
# Syntax combination rules for german.
# Copyright © 2004 Björn Beutel.

#------------------------------------------------------------------------------

initial [constituents: <>, clause_type: main_clause],
rules (constituent, subclause_start, finite_verb);

#------------------------------------------------------------------------------

combi_rule constituent( $clause, $word, $surf ):
# Read a constituent (but not a finite verb or a subclause).
  if $word.POS in <name, pronoun> then
    $clause.constituents :=+ <[function: $word.case, surf: $surf]>;
    result $clause, rules (constituent, finite_verb, main_clause_end,
      subclause_initial_comma);
    $clause :=+ $word * gender + [subclause: rel_clause];
    result $clause, rules (subclause_initial_comma);
    
  elseif $word.POS = adverb then
    $clause.constituents :=+ <[function: $word.subtype, surf: $surf]>;
    result $clause, rules (constituent, finite_verb, subclause_initial_comma,
			   main_clause_end);

  elseif $word.POS = determiner then
    define $result := ($word * <case, gender, adj_ending>
		       + [superclause: $clause,
			  function: $word.case,
			  surf: $surf]);
    result $result, rules (substantive);
    
  elseif $word.POS = preposition then
    # A prepositional phrase consists of a preposition and a noun phrase.
    define $result := [superclause: $clause,
		       case: $word.case,
		       function: $word.subtype,
		       surf: $surf];
    result $result, rules (obligate_NP);
    
  elseif $word.POS = verb and $word.subtype /= finite then

    if $clause.clause_type /= main_clause then
      # In a subclause, the finite verb follows the infinite verb.
      $clause.constituents :=+ <[function: verb, surf: $surf]>;
      $clause :=+ [valencies: $word.valencies,
		   verb: $word.subtype];
      result $clause, rules (finite_verb);
      
    else
      # In a main clause, the valency frame must contain the subtype of the
      # nonfinite verb.
      require valencies in $clause;
      
      # Select the right valency frame.
      choose $valencies in $clause.valencies;
      
      require length( $valencies ) = 1 and $valencies.1L ~ $word.subtype;
      
      $clause.constituents :=+ <[function: verb, surf: $surf]>;
      $clause :=+ $word * valencies;
      result $clause, rules (subclause_initial_comma, main_clause_end);
    end if;
    
  elseif $word.POS = prefix then
    # A prefix will be deleted out of the valency frame of the finite verb.
    
    # Has a finite verb with prefix list already been read in?
    require prefixes in $clause;
    
    # Select the right prefix.
    choose $prefix in $clause.prefixes;
    require $prefix.surf = $surf;
    $clause.constituents :=+ <[function: prefix, surf: $surf]>;
    $clause :=+ $prefix * valencies;
    $clause :=- prefixes;
    result $clause, rules (constituent, subclause_initial_comma,
			   main_clause_end);
  end if;
end combi_rule;

#------------------------------------------------------------------------------

combi_rule obligate_NP( $clause, $word, $surf ):
# Read a noun phrase whose result category is already given
# (may be used as part of a prepositional phrase).
  
  if $word.POS in <name, pronoun> then
    require $clause.case ~ $word.case;
    
    define $result := $clause.superclause;
    $result.constituents :=+ <[function: $clause.function,
			       surf: $clause.surf + " " + $surf]>;
    result $result, rules (constituent, finite_verb, main_clause_end,
			   subclause_initial_comma);
    $result :=+ $word * gender + [subclause: rel_clause];
    result $result, rules subclause_initial_comma;
    
  elseif $word.POS = determiner then
    require $clause.case ~ $word.case;
    $clause :=+ ($word * <case, gender, adj_ending>
		 + [surf: $clause.surf + " " + $surf]);
    result $clause, rules (substantive);
  end if;
end combi_rule;

#------------------------------------------------------------------------------

combi_rule substantive( $clause, $word, $surf ):
# Read an adjective or a substantive.
  
  if $word.POS = substantive then
    require $clause.case ~ $word.case;
    if gender in $clause then
      require $clause.gender ~ $word.gender;
    else
      $clause :=+ $word * gender;
    end if;
    
    select
      define $result := $clause.superclause;
      $result.constituents :=+ <$clause * <function, modifiers>
				+ [surf: $clause.surf + " " + $surf]>;
      result $result, rules (constituent, finite_verb, subclause_initial_comma,
			     main_clause_end);
      $result :=+ $clause * gender + [subclause: rel_clause];
      result $result, rules (subclause_initial_comma); 
    or
      $clause :=- <case, gender, adj_ending>;
      $clause.surf :=+ " " + $surf;
      result $clause, rules (attribute);
      
    end select;
    
  elseif $word.POS = adjective then
    require $clause.adj_ending ~ $word.adj_ending;

    $clause.surf :=+ " " + $surf;
    result $clause, rules (substantive);
  end if;
end combi_rule;

#------------------------------------------------------------------------------

combi_rule attribute( $clause, $word, $surf ):
# Read postnominal attributes of a noun phrase.
  
  if $word.POS = pronoun and $word.case ~ gen then
    define $result := $clause.superclause;
    $result.constituents :=+ <[function: $clause.case,
			       surf: $clause.surf + " " + $surf]>;
    result $result, rules (constituent, finite_verb, subclause_initial_comma,
			   main_clause_end);
    $result :=+ $clause * gender + [subclause: rel_clause];
    result $result, rules (subclause_initial_comma);

  elseif $word.POS = determiner and $word.case ~ gen then
    $clause :=+ $word * <case, gender, adj_ending>;
    $clause.surf :=+ " " + $surf;
    result $clause, rules (substantive);
    
  elseif $word.POS = preposition and $word.subtype ~ local then
    $clause :=+ $word * case;
    $clause.surf :=+ " " + $surf;
    result $clause, rules (obligate_NP);
  end if;
end combi_rule;

#------------------------------------------------------------------------------

combi_rule finite_verb( $clause, $word, $surf ):
# Read the finite verb form.
  
  # Do we read a finite verb?
  require $word.POS = verb and $word.subtype = finite;

  if $clause.clause_type = main_clause then
    # In a main clause, the valencies of the finite verb must be stored.

    foreach $constituent in $clause.constituents:
      require verb /= $constituent.function;    
    end foreach;
    define $result := $clause + $word * <subject, valencies, prefixes>;
    $result.constituents :=+  <[function: verb, surf: $surf]>;
    result $result, rules (constituent, subclause_initial_comma,
			   main_clause_end);
    
  else
    # In a subclause, the finite verb ends the subclause.
    
    $clause.constituents :=+ <[function: verb, surf: $surf]>;
    
    define $valency_frame := nil;
    if verb in $clause then
      choose $auxiliar_Valency in $word.valencies;
      require length( $auxiliar_valency ) = 1;
      require $auxiliar_valency.1 ~ $clause.verb;
      $valency_frame := $clause.valencies;
    else
      $valency_frame := $word.valencies;
    end if;
    
    define $constituent := fill_valencies( $word.subject, $valency_frame,
					   $clause.constituents );
    define $result := $clause.superclause;

    if $clause.clause_type = rel_clause then
      if not modifiers in $result.constituents.1R then
	$result.constituents.1R :=+ [modifiers: <>];
      end if;
      $result.constituents.1R.modifiers :=+ <$constituent>;
    else
      $constituent :=+ [sub_conjunction: $clause.sub_conjunction.surf]; 
      $result.constituents :=+ <$constituent
				+ [function:$clause.sub_conjunction.function]>;
    end if;
    
    result $result, rules (subclause_end, main_clause_end);
  end if;
end combi_rule;

#------------------------------------------------------------------------------

combi_rule subclause_initial_comma( $clause, $word, $surf ):
# Read the comma that starts a subclause.
  
  require $word.POS = punctuation and $surf = ",";
  result $clause, rules (subclause_start);
end combi_rule;

#------------------------------------------------------------------------------

combi_rule subclause_start( $clause, $word, $surf ):
# Read the conjunction or relative pronoun that starts a subclause.

  if not subclause in $clause then
    $clause :=+ [subclause: subclause];
  end if;
  
  $clause := [superclause: $clause - subclause,
	      clause_type: $clause.subclause,
	      constituents: <>];
  
  if $clause.clause_type = subclause and $word.POS = sub_conjunction then
    $clause :=+ [sub_conjunction: [function: $word.subtype, surf: $surf]];
    if constituent in $word then
      $clause.constituents :=+ <[function: $word.constituent, surf: $surf]>;
    end if;

  elseif $clause.clause_type = rel_clause and $word.POS = rel_pronoun then
    # Check if gender is congruent
    if gender in $clause.superclause and gender in $word then
      require $clause.superclause.gender ~ $word.gender;
    end if;
    $clause.constituents :=+ <[function: $word.case, surf: $surf]>; 
  else
    stop;
  end if;
  result $clause, rules (constituent, finite_verb);
  
end combi_rule;

#------------------------------------------------------------------------------

combi_rule subclause_end( $clause, $word, $surf ):
# Read the comma that finishes a subclause.
  
  require $word.POS = punctuation and $surf = ",";
  result $clause, rules (constituent, finite_verb, subclause_start);
end combi_rule;

#------------------------------------------------------------------------------
						       
combi_rule main_clause_end( $clause, $word, $surf ):
# Read the punctuation sign that finishes a main clause.
  
  require $word.POS = punctuation;
  require $clause.clause_type = main_clause;
  require length( $clause.constituents ) greater_equal 2;
  
  define $clause_type := nil;
  if $surf = "." and $clause.constituents.2L.function = verb then
    $clause_type := declarative;
  elseif ($surf = "?" and ($clause.constituents.1L.function = verb
			   or $clause.constituents.2L.function = verb))
  then
    $clause_type := interrogative;
  else
    stop;
  end if;

  define $result := ([clause_type: $clause_type]
		     + fill_valencies( $clause.subject, $clause.valencies,
				       $clause.constituents ));
  result $result, accept;
end combi_rule;

#------------------------------------------------------------------------------

subrule fill_valencies( $subject, $valency_frame, $constituents ):
# Check if $constituents fill all valencies for $subject and $valency_frame.
# If the test succeeds, return a record with the attributes predicate,
# arguments, and modifiers.
    
  choose $valencies in $valency_frame;
  
  # Check if all valencies are filled.
  define $arguments := <>;
  define $other_constituents := $constituents;
  foreach $valency in <subject> + $valencies:

    define $agrees_with := $valency;
    if $valency = subject then
      $agrees_with := $subject;
    elseif $valency ~ nom then
      $valency := nom;
    end if;
    
    choose $index in length( $other_constituents );
    define $constituent := $other_constituents.$index;
    $other_constituents :=- $index;

    require $agrees_with ~ $constituent.function;

    $arguments :=+ <$constituent + [function: $valency]>;
  end foreach;
  
  # Check if all other constituents are modifiers or parts of the predicate.
  define $predicate := nil;
  define $modifiers := <>;
  foreach $constituent in $other_constituents:
    require $constituent.function in <causal, local, modal, temporal, verb,
          prefix>;
    if $constituent.function in <verb, prefix> then
      if $predicate = nil then
	$predicate := $constituent.surf;
      else
	$predicate :=+ " " + $constituent.surf;
      end if;
    else
      $modifiers :=+ <$constituent>;
    end if;
  end foreach;
  
  define $result := [predicate: $predicate, arguments: $arguments];
  if $modifiers /= <> then
    $result :=+ [modifiers: $modifiers];
  end if;
  return $result;
  
end subrule;

# End of file. ================================================================