TL; DR VERSİYONU: Aşağıdakileri destekleyen bir çözümleyici üreteci var mı: bazı kurallar azaldığında (LALR (1) ayrıştırıcı varsayalım), azaltma gerçekleştirilmez. ancak ayrıştırıcı, bu kuraldaki değerleri kullanarak girdiyi farklı kodla değiştirir ve değiştirir ve bu kodu ayrıştırır. Gerekirse tekrarlayın.Benzer yapıların kaynak kodu ayrıştırma ve makro benzeri işleme
expr POST_INCR -> "(tmp = expr; expr = expr + 1; tmp)"
Yani temelde kod yeniden yazma makroları kullanarak: Kod "i ++" ve kural "expr POST_INCR" Yani, eğer ben daha fazla veya daha az yapabilirim?
UZUN VERSİYON:
I (basitlik için Java) bir başka basit yorumlanır dili yazdım. Tamam çalışıyor, ama bazı soruları gündeme getirdi. Giriş oldukça uzun, ancak basit ve sorunumu açıkça göstermeye yardımcı oluyor (bence).
"while" döngüsüne sahibim. Bu göz önüne alındığında, oldukça basittir:
new WhileNode(boolean_expression, statement);
Bu sonradan ziyaret ettiğinde, benim sanal makine için kod üretir, yeni bir düğüm oluşturur:
WHILE LPARE boolean_expression RPAREN statement
aşağıdaki az ya da çok üretir. Bu Oluşturduğum yukarıda belirtilen kurala Java'ya veya C'den bilinen "döngü" aşağı yukarı takip ediyor
FOR LPAREN for_init_expr SEMICOLON boolean_expression SEMICOLON for_post_expr RPAREN statement
: Ama aynı zamanda şu var
new ListNode(
for_init_expr,
new WhileNode(
boolean_expression,
new ListNode(
statement,
new ListNode(for_post_expr, null))))
Bu elbette basit dönüşümdür dan:
for (for_init ; boolean_expression ; for_post_expr)
statement
için:
for_init
while (boolean_expression) {
statement
for_post_expr;
}
Tüm iyi, güzel, ama işler aşağıdakiler için kıllı olsun: iyi bilinen ve sevdiysen
FOR LPAREN var_decl COLON expression RPAREN statement
This:
for (int x : new int[] { 1, 2 })
print(x);
Ben AST üretir kod yayınlamaktan kaçının döngü temel beri, Zaten biraz uzun oldu, ve buraya geldiğimiz daha da kötü. Bu yapı eşittir:
int[] tmp = new int[] { 1, 2 };
for (int it = 0 ; it < tmp.length; it = it + 1) {
int x = tmp[it];
print(x);
}
Ve türlerini kullanarak değilim çünkü ben sadece "ifadesi" (çok doğru tarafı KOLON sonra) ben adımlayabilirsiniz şey olduğunu varsayalım (ve diziler iterable değildir), Iterable örneğini döndüren bu "ifade" nin bir sonucu olarak adlandırıyorum. Yani, aslında, benim yeniden yazılmış kod, yukarıdaki gibi basit değildir az ya da çok bu:
Iterator it = makeIterable(new int[] { 1, 2 });
while (it.hasNext()) {
int x = it.next();
print(x);
}
O OLDUĞUNU kötü görünüyor, ama bunun için o AST üç fonksiyon çağrıları ve süre üretir dikkat etmez döngü.
113 | FOR LPAREN var_decl_name.v PIPE simple_value_field_or_call.o RPAREN statement.s
114 {: Symbol sv = ext(_symbol_v, _symbol_o);
115 String autoVarName = generateAutoVariableName();
116 Node iter = new StatementEndNode(sv, "",
117 new BinNode(sv, CMD.SET, "=",
118 new VarDeclNode(sv, autoVarName),
119 new CallNode(sv, "()",
120 new BinNode(sv, CMD.DOT, ".",
121 new MkIterNode(sv, o),
122 new PushConstNode(sv, "iterator")))));
123 Node varinit = new StatementEndNode(sv, "",
124 new BinNode(sv, CMD.SET, "=",
125 v,
126 new PushConstNode(sv, "null")));
127 Node hasnext = new CallNode(sv, "()",
128 new BinNode(sv, CMD.DOT, ".",
129 new VarNode(sv, autoVarName),
130 new PushConstNode(sv, "hasNext")));
131 Node vargennext = new StatementEndNode(sv, "",
132 new BinNode(sv, CMD.SET, "=",
133 new VarNode(sv, v.name),
134 new CallNode(sv, "()",
135 new BinNode(sv, CMD.DOT, ".",
136 new VarNode(sv, autoVarName),
137 new PushConstNode(sv, "next")))));
138 return new ListNode(sv, "",
139 new ListNode(sv, "",
140 new ListNode(sv, "",
141 iter
142 ),
143 varinit
144 ),
145 new WhileNode(sv, "while",
146 hasnext,
147 new ListNode(sv, "",
148 new ListNode(sv, "",
149 vargennext
150 ),
151 s)));
Sorularınızı cevaplamak için: ne karışıklık göstermek için, ben ne var şimdi sonrası evet, bu kodun utanıyorum.
SORU: Bu bana, bu konuda yani verilen kural şey yapmak var izin ayrıştırıcı jeneratör vardır: başka bir şey sanki onu yeniden yazmak için
FOR LPAREN var_decl COLON expr RPAREN statement
söyle ayrıştırıcı. Bu iyi bilinen ise
FOR LPAREN var_decl COLON expr RPAREN statement =
{ with [ x = generateAutoName(); ]
emit [ "Iterator $x = makeIterable($expr).iterator();"
"while (${x}.hasNext()) {"
"$var_decl = ${x}.next();"
"$statement"
"}"
]
}
bilmiyorum: Ben bu belki benzer (nedeniyle herhangi gramer temelde eksikliği lisp kolaydır) Lisp makro mekanizmasının bir çeşit, gerektirecektir hayal sorun ya da değil, sadece neyi arayacağımı bile bilmiyorum - bulduğum en benzer soru şu: Any software for pattern-matching and -rewriting source code? ama ihtiyaç duyduğum yere yakın değil çünkü ayrı bir adım olarak çalışması gerekiyordu ve derleme sırasında değil, bu yüzden uygun değil.
Herhangi bir yardım için teşekkür ederiz.
Teşekkür ederim, bu çok ilginç. Tabii ki DMS'yi "sadece fakir bir çocuğum" olduğu için ödeyemem, ama tam da aradığım şey bu. –
Asla "DMS ücretsiz değil, bu yüzden karşılayamayacağım" konusunda nasıl tepki vereceğimi bilmiyorum. Bu doğrudur kitle pazar yazılım standartlarına göre ucuz değil, daha sonra kitle pazar yazılımı değil; milyonlarca kullanıcının ihtiyaç duyduğu ürün değil. Ve mühendisler gerçekten ciddi araçlar üretmeye çalışırken, muhtemelen bir yıllık bir mühendislik veya daha fazlasını kurtarabilir. Bu değer nedir? Son olarak, kaç kişinin bazı yazılımlar satın almaya gücü yetmez, ancak bir şekilde bir bilgisayar, ekran ve yazıcı satın almayı başarması dikkat çekicidir. (Bir projenin hobi olup olmadığını anlayabilirim, birinin ek yazılım satın almak istememesi nasıl olur.) –
@ JędrzejDudkiewicz: PS: İltifat için teşekkürler. –