-
Notifications
You must be signed in to change notification settings - Fork 8
/
Dependent-fr.js
244 lines (233 loc) · 10.9 KB
/
Dependent-fr.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
/**
jsRealB 5.0
Guy Lapalme, lapalme@iro.umontreal.ca, December 2023
*/
import { French_constituent } from "./Constituent-fr.js";
import { getRules } from "./Lexicon.js";
import {terminal, N,A,Pro,D,V,Adv,C,P,DT,NO,Q,
phrase, S,NP,AP,VP,AdvP,PP,CP,SP,
dependent, root, subj, det, mod, comp, coord} from "./jsRealB.js"
export {French_dependent}
/**
* French specific dependent class
*/
const French_dependent = (superclass) =>
class extends French_constituent(superclass) {
/**
* Link attributes in a dependent with the ones of the head in the case of copula.
*
* @param {Terminal} depTerm
* @param {Terminal} headTerm
*/
link_attributes(depTerm,headTerm){
// check for an attribute of a copula with an adjective
if (this.copules().includes(headTerm.lemma)){
const iSubj=this.findIndex(d0=>d0.isA("subj") && d0.terminal.isA("N","Pro"));
if (iSubj>=0){
depTerm.peng=this.dependents[iSubj].peng;
}
}
}
/**
* Link a past participle with a direct object appearing before.
* Empty for English
*
* @param {Dependent} dep
* @param {Terminal} HeadTerm
*/
link_pp_before(dep,headTerm){
const depTerm=dep.terminal
// rel is comp or mod
// in French past participle can agree with a cod appearing before... keep that info in case
depTerm.cod=headTerm;
// HACK: check for a "temps composé" formed by "avoir" followed by a past participle
if (depTerm.lemma=="avoir"){
const iVerb=dep.findIndex(depI=>depI.isA("comp") && depI.terminal.isA("V") && depI.terminal.getProp("t")=="pp");
if (iVerb>=0) dep.dependents[iVerb].terminal.cod=headTerm;
}
}
/**
* Link a past participle with a subject.
*
* @param {Terminal} depTerm
*/
link_pp_with_head(depTerm){
// check for past participle in French that should agree with the head
if (depTerm.getProp("t")=="pp"){
depTerm.peng=this.peng;
}
}
/**
* Make a passive agree after an auxiliary.
*
* @param {Terminal} obj
*/
passive_agree_with_auxiliary(obj){
// do this only for French because in English this is done by processTyp_en
// change verbe into an "être" auxiliary and make it agree with the newSubj
// force person to be 3rd (number and tense will come from the new subject)
const verbe=this.terminal.lemma;
this.terminal.setLemma(verbe == "être" ? "avoir" : "être");
if (this.getProp("t")=="ip"){
this.t("s") // set subjonctive present tense for an imperative
}
const pp = V(verbe,"fr").t("pp");
if (obj!==undefined){ // this can be undefined when a subject is Q or missing
this.terminal.peng=obj.peng;
pp.peng=obj.peng;
}
// insert the pp before the comp, so that it appears immediately after the verb
// calling addPre(pp) would evaluate the pp too soon...
let compIdx=this.findIndex(d=>d.isA("comp","mod"));
if (compIdx==-1)compIdx=0;
this.addDependent(dependent("*post*",[pp]),compIdx)
}
/**
* Check for passive subject with "par".
*/
check_passive_subject_with_par(){
// check for passive subject starting with par
let pp;
let parIdx=this.findIndex(d=>d.isA("comp") && d.terminal.isA("P") && d.terminal.lemma=="par");
if (parIdx>=0){
pp=this.dependents[parIdx].terminal;
this.removeDependent(parIdx);// remove the passive subject
}
return pp
}
/**
* Pronominalization in French
* Phrase structure modification but that must be called in the context of the parentConst
* because the pronoun depends on the role of the NP in the sentence
* and its position can also change relatively to the verb
* @returns a Pro corresponding to the current NP
*/
pronominalize(){
let pro;
let mySelf=this;
if (this.isA("subj")){
if (!this.terminal.isA("N","Pro"))
return this.warn("no appropriate pronoun")
pro=this.getTonicPro("nom")
} else if (this.isA("comp","mod") && this.terminal.isA("P")){
let prep=this.terminal.lemma;
if (this.dependents.length==1 && this.dependents[0].isA("comp","mod")){
if (this.dependents[0].terminal.isA("N")){
const n=this.dependents[0].terminal;
if (prep == "à"){
pro=n.getTonicPro("dat");
} else if (prep == "de") {
pro=Pro("en","fr").c("dat");
} else if (["sur","vers","dans"].includes(prep)){
pro=Pro("y","fr").c("dat");
} else { // change only the N keeping the P intact
pro=this.getTonicPro("nom");
mySelf=this.dependents[0];
}
} else {
return this.warn("no appropriate pronoun")
}
}
} else {
pro=this.getTonicPro("acc")
if (this.parentConst!==null && this.parentConst.terminal.isA("V")){// consider that it is direct complement
this.parentConst.terminal.cod=this; // indicate that this is a COD
}
}
pro.parentConst=this;
pro.peng=mySelf.peng
mySelf.terminal=pro
mySelf.dependents=[]
mySelf.dependentsSource=[]
}
/**
* French phrase modification for .prog, .mod, .neg
* @param {Object} types typ options for this Phrase
*/
processTyp_verb(types){
if (types["contr"]!==undefined && types["contr"]!==false){
this.warn("no French contraction")
}
this.processV(types,"prog",function(deprel,v){
// insert "en train","de" (separate so that élision can be done...)
// TODO::but do it BEFORE the pronouns created by .pro()
const origLemma=deprel.terminal.lemma
deprel.terminal.setLemma("être"); // change verb, but keep person, number and tense properties of the original...
deprel.addPost([Q("en train"),Q("de"),V(origLemma).t("b")])
deprel.terminal.isProg=v;
})
this.processV(types,"mod",(deprel,mod)=>{ // define an arrow function to keep the original this
let rules=getRules(this.lang);
let origLemma=deprel.terminal.lemma;
for (let key in rules.verb_option.modalityVerb){
if (key.startsWith(mod)){
deprel.terminal.setLemma(rules.verb_option.modalityVerb[key]);
break;
}
}
deprel.terminal.isMod=true
let newV=V(origLemma).t("b");
if (deprel.terminal.isProg){ // copy progressive from original verb...
newV.isProg=deprel.terminal.isProg;
delete deprel.terminal.isProg
}
deprel.addPost(newV)
})
this.processV(types,"neg",function(deprel,neg){
if (neg===true)neg="pas";
deprel.terminal.neg2=neg; // HACK: to be used when conjugating at the realization time
})
}
/**
* Move subject before the verb in question
* use inversion rule which is quite "delicate"
* rules from https://francais.lingolia.com/fr/grammaire/la-phrase/la-phrase-interrogative
* if subject is a pronoun, invert and add "-t-" or "-"
* except for first person singular ("je") which is, in some cases, non colloquial (e.g. aime-je or prends-je)
* if subject is a noun or certain pronouns, the subject stays but add a new pronoun
*
* @param {string} int : question type
*/
move_object(int){
if (!this.terminal.isA("V")) return // do not move if the head is not a verb
const v = this.terminal
const proLikeNoun = ["aucun","beaucoup","ça","ceci","cela","celui-ci","celui-là","quelqu'un","tout"];
let subjIdx=this.findIndex((d)=>d.isA("subj"));
if (subjIdx>=0){
const subject=this.dependents[subjIdx].terminal;
let pro;
if (subject.isA("Pro") && !proLikeNoun.includes(subject.lemma)){
if (subject.getProp("pe")==1 && subject.getProp("n")=="s"){ // add "est-ce que" at the start
// unless the verb is one of "ai, dis, dois, fais, puis, sais, suis, vais, veux, vois" according to
// https://www.academie-francaise.fr/questions-de-langue#42_strong-em-inversion-du-sujet-je-puis-je-em-strong
if (v.getProp("t")=="p" && v.getProp("pe")==1){
if (!["avoir","dire","devoir","faire","pouvoir","savoir","être","aller","vouloir","voir"].includes(v.lemma)){
this.add(det(Q("est-ce que")),0);
return;
}
}
}
pro=this.removeDependent(subjIdx).terminal; //remove subject
} else if (["wod","wad"].includes(int)){ // do not invert subject when "wod" or "wad"
this.add(det(Q("est-ce que")),0);
return;
} else if (subject.isA("C")){
pro=Pro("moi","fr").c("nom").g("m").n("p").pe(3); // create a "standard" pronoun, to be patched by cpReal
subject.pronoun=pro; // add a flag to be processed by cpReal
} else
pro=Pro("moi","fr").g(subject.getProp("g")).n(subject.getProp("n")).pe(3).c("nom"); // create a pronoun
if (this.terminal.isA("V")){
this.addPost(pro);
this.terminal.lier()
}
}
}
/**
* Deal with a tag question, a short question added after an affirmation to ask for verification.
* in French really simple, add "n'est-ce pas"
* @param {*} types : type options for this sentence (unused in French)
*/
tag_question(types){
this.a(", n'est-ce pas")
}
};