Quando as pessoas dizem "X não compõe", o que elas querem dizer com "compor" realmente significa apenas "montar", e o que e como você as coloca podem ser muito diferentes, dependendo do que exatamente é "X".
Além disso, quando eles dizem "não compõe", eles podem significar algumas coisas um pouco diferentes:
- Você não pode colocar dois Xs juntos, ponto final.
- Você pode colocar dois Xs juntos, mas o resultado pode não ser um X (IOW: X não está fechado na composição ).
- Você pode colocar dois Xs juntos, mas o X resultante pode não funcionar da maneira que você espera.
Um exemplo para o nº 1 é analisadores com scanners / lexers. Você pode ouvir a frase "scanners / lexers não compõem". Isso não é verdade. O que eles querem dizer é "analisador que usa um estágio lexing separado não compõe".
Por que você gostaria de compor analisadores? Bem, imagine que você é um fornecedor de IDE como JetBrains, Eclipse Foundation, Microsoft ou Embarcadero e deseja criar um IDE para uma estrutura da web. No desenvolvimento típico da Web, geralmente misturamos idiomas. Você possui arquivos HTML com <script>
elementos que contêm ECMAScript e<style>
elementos que contêm CSS. Você tem arquivos de modelo que contêm HTML, alguma linguagem de programação e algumas metassintaxe da linguagem de modelo. Você não deseja gravar marcadores de sintaxe diferentes para "Python", "Python incorporado em um modelo", "CSS", "CSS dentro de HTML", "ECMASCript", "ECMAScript dentro de HTML", "HTML", "HTML dentro de" um modelo "e assim por diante. Você deseja escrever um marcador de sintaxe para Python, um para HTML, um para a linguagem de modelo e, em seguida, compor os três em um marcador de sintaxe para um arquivo de modelo.
No entanto, um lexer analisa o arquivo inteiro em um fluxo de tokens, o que só faz sentido para esse idioma. O analisador para o outro idioma não pode trabalhar com os tokens que o lexer passa. Por exemplo, os analisadores Python são tipicamente escritos de tal maneira que o lexer controla o recuo e injeta falsos INDENT
e DEDENT
tokens no fluxo de token, permitindo que o analisador fique livre de contexto, mesmo que a sintaxe do Python não seja. Um lexer HTML, no entanto, ignorará completamente os espaços em branco, pois não tem significado em HTML.
Um analisador sem scanner, no entanto, que simplesmente lê caracteres, pode transmitir o fluxo de caracteres para um analisador diferente, que pode devolvê-lo, facilitando sua composição.
Um exemplo para o número 2 são cadeias de caracteres com consultas SQL. Você pode ter duas cadeias de caracteres, cada uma com uma consulta SQL sintaticamente correta, mas se você concatenar as duas cadeias, o resultado poderá não ser uma consulta SQL sintaticamente correta. É por isso que temos de consulta álgebras como ARel
, o que fazer composição.
Bloqueios são um exemplo de # 3. Se você possui dois programas com bloqueios e os combina em um único programa, ainda possui um programa com bloqueios, mas mesmo que os dois programas originais estivessem completamente corretos, livres de impasses e corridas, o programa resultante não tem necessariamente isso propriedade. O uso correto de bloqueios é uma propriedade global de todo o programa e uma propriedade que não é preservada quando você compõe programas. Isso é diferente de, por exemplo, transações que são compostas. Um programa que usa transações corretamente pode ser composto por outro programa e produzirá um programa combinado que usa transações corretamente.