LA CAMPANA

C'è chi legge questa notizia prima di te.
Iscriviti per ricevere articoli freschi.
E-mail
Nome
Cognome
Come vuoi leggere The Bell
Niente spam

J.P. -linguaggio artificiale sviluppato dall'uomo per facilitare il processo di risoluzione dei problemi utilizzando i computer. Questo linguaggio consente una descrizione dell'algoritmo per la risoluzione del problema, quindi viene chiamato orientato proceduralmenteo affermazione del problema in forma matematica - orientato al problema.

Le lingue:

1. Universale (compiti da qualsiasi area tematica)

2. Specializzato (in un'area ristretta)

Level Ya.P.

1. Basso (assemblatore, media simbolica)

2. Alto

caratteristica:esiste la possibilità di traduzione automatica, traduzione del testo scritto nell'YP in una sequenza logicamente equivalente di azioni nella lingua delle istruzioni automatiche.

Con il metodo di trasmissione:

1. Compiler

2. Interprete

3. Generatore

Alphabet -un insieme fisso di caratteri da cui deve essere composto il testo.

La sintassi èun sistema di regole definito da costruzioni consentite da caratteri alfabetici. Provano a descriverlo formalmente.

Semantica - un sistema di regole per l'interpretazione delle costruzioni linguistiche. È descritto in modo rigoroso, formale, inequivocabile, ma è descritto in forma libera.

3. Modi per definire formalmente la sintassi di un linguaggio di programmazione

Sintassi \u003d metalinguaggio + diagrammi di sintassi

Metalanguage -linguaggio speciale usato per descrivere un'altra lingua.

Set di caratteri di metalinguaggio:

< > - parentesi angolari (concludere le costruzioni linguistiche)

{ } - parentesi graffe (i concetti racchiusi in essi si verificano zero o più volte)

parentesi quadre (il concetto concluso può essere omesso)

Linea verticale(alternativa, "o", | ), ::=, =.

Simboli YaPin metalinguaggio, caratteri terminali.

Dai simboli dell'alfabeto sono costruiti costrutti di linguaggio semantico.I più semplici sono parole linguistiche.

Gettone -parola lingua, una sequenza di caratteri che non contiene spazi.

Tipi di token:

1. Identificatore: utilizzato per indicare un programma o altri oggetti (indicare il nome della funzione, il tipo, ecc.)

2. Parole chiave - identificatori di servizio registrati nel PL; sono usati per formare costrutti completi di linguaggio semantico, sono chiamati offertelinguaggio.

3. Operatore: una descrizione, una definizione, necessaria per trasmettere informazioni al traduttore. L'operatore viene utilizzato per descrivere le azioni, è un'unità di azione.

Diagramma di sintassi -è un grafico diretto con un bordo di entrata e un bordo di uscita e vertici etichettati. Il diagramma di sintassi imposta la lingua. La catena di segni ai vertici su qualsiasi percorso dal bordo di input all'output è la catena del linguaggio specificato dal diagramma di sintassi. Pertanto, possiamo supporre che il diagramma di sintassi sia una delle forme della grammatica generatrice dei linguaggi degli automi.



Oggetti programma.

Qualsiasi costruzione che abbia un significato semantico in una determinata lingua. Il valore, che è associato non solo al nome e al valore, ma anche ad alcune aree di memoria in cui è memorizzato il valore di questo valore.

Si distinguono:

1. costanti - valori costanti.

Le costanti sono l'enumerazione dei valori in un programma. Nel linguaggio di programmazione C, esistono quattro tipi di costanti: costanti intere, costanti in virgola mobile, costanti di carattere e costanti di stringa.

2. variabili

Uno dei concetti di base del linguaggio C è un oggetto: un'area di memoria denominata. Un caso speciale di un oggetto è una variabile. Una caratteristica distintiva di una variabile è la capacità di associare vari valori al suo nome, la cui totalità è determinata dal tipo di variabile. Quando si imposta il valore di una variabile, il codice di questo valore viene posizionato nell'area di memoria corrispondente. L'accesso al valore di una variabile è naturalmente fornito dal suo nome e l'accesso a un pezzo di memoria è possibile solo al suo indirizzo. Ogni variabile deve essere definita prima di essere utilizzata nel programma, ad es. la memoria deve essere allocata per la variabile. La dimensione della memoria allocata per la variabile e l'interpretazione dei contenuti dipendono dal tipo specificato nella definizione della variabile. Sono definiti tipi interi: char - un numero intero con una lunghezza di almeno 8 bit, short int - un numero intero corto, int - un numero intero, long - un numero intero lungo. Ciascuno di tipi interi può essere definito come non firmato o non firmato. Lo standard linguistico ha introdotto quanto segue tipi reali: galleggiante - precisione singola, doppia - doppia precisione, doppio lungo - massima precisione.

3. funzioni



Funzione - Questa è la parte denominata del programma a cui è possibile accedere da altre parti del programma tutte le volte che è necessario. La definizione di una funzione indica la sequenza di azioni eseguite quando si accede alla funzione, il nome della funzione, il corpo del risultato (valore restituito) e l'insieme di parametri formali che vengono sostituiti quando si accede alla funzione da parametri effettivi (argomenti).

Vista generale della definizione dell'oggetto

Digitare name [inizializzatore];

Gli oggetti della classe statica sono impostati su 0, cl. esterno - non ricevere.

L'oggetto è determinato solo una volta. Per definizione, vengono impostati gli attributi dell'oggetto, viene allocata la memoria per esso, il nome dell'oggetto associato con l'indirizzo dell'area di memoria. Se è presente un inizializzatore, anche il valore iniziale.

Concetto del tipo di dati

Tipo di questo - questa è una raccolta di informazioni sul valore di una quantità che consente di utilizzare questa quantità quando si risolve un problema su un computer.

Il tipo di dati è associato a: l'insieme di valori predefiniti (intervallo di valori), l'insieme di operazioni che possono essere eseguite sul valore di questo tipo, la dimensione della memoria allocata per l'archiviazione del valore e la struttura del valore. Struttura del valoredefinisce una classe di tipo: semplice o complessa. Valore tipo semplice è un insieme indivisibile, un valore di un tipo complesso è costituito da parti separate - elementi di un valore complesso. Intervallo di valori - questo è l'intervallo dal valore minimo al massimo che può essere rappresentato in una variabile di questo tipo.

Le variabili possono essere inizializzate al posto delle loro descrizioni.

Tipo di sistema - Questo è un sistema speciale con cui sono organizzati i dati utilizzati dalle soluzioni applicate. Il sistema dei tipi consente di presentare informazioni del mondo reale in termini "comprensibili" a Y.P.

Il concetto di un tipo semplice.

Tipo semplice - un tipo di dati i cui oggetti (variabili o costanti) che non hanno una struttura interna accessibile al programmatore.

Il valore è indivisibile in qualsiasi parte

Operazioni sull'intero valore nel suo insieme.

Si dividono in:

Di base - Un semplice tipo di dati scalare, tutti i cui componenti sono già definiti dallo sviluppatore; di nome.

Definito dal programmatore- Il programmatore stesso determina l'insieme di valori validi

I tipi scalari semplici predefiniti in C (sono chiamati tipi base) sono:

- tipi interi: char, int, long int;

- tipi flottanti: float, double, long double.

Il tipo di carattere intero viene utilizzato anche per rappresentare i valori dei caratteri (tipo di carattere). I tipi interi hanno due forme: firmata (firmata) e non firmata (non firmata). In forma abbreviata, la firma può essere omessa.

Consiste di:

insieme di valori validi

molte operazioni valide

la dimensione memoria ad accesso casualeallocato per l'archiviazione (char - 1b, int - 2b, long - 4b)

rappresentazione interna del valore (un numero intero positivo come valore binario, negativo come complemento binario, ecc.)

struttura del valore

Tipi complessi

Complicato (composito) un tipo - un tipo di dati i cui oggetti (variabili o costanti) che hanno una struttura interna disponibile per il programmatore.

I tipi complessi sono caratterizzati dal fatto che qualsiasi valore di questo tipo è costituito da molti componenti (elementi) che sono in qualche modo collegati tra loro in un unico intero, cioè ha una struttura complessa.

Il tipo complesso è costruito da seguenti regole.

1. Un elemento di una struttura complessa può avere strutture sia semplici che complesse. Pertanto, i valori di tipi complessi nel caso generale hanno una struttura gerarchica, al livello più basso del quale vi sono elementi di tipo semplice (mentre il livello di annidamento può essere limitato o meno).

2. All'interno di una struttura complessa, il tipo di tutti gli elementi può essere: - identico - struttura omogenea, - diverso - struttura eterogenea.

3. Il numero di elementi nella struttura può essere: - riparato durante la vita della struttura (strutture di dimensioni fisse o statiche); - variabili, ad es. cambia dinamicamente includendo o escludendo elementi nel processo di lavoro con la struttura (strutture di dimensioni variabili o dinamiche).

4. L'appello (accesso) agli elementi della struttura può essere: - diretto (diretto) - calcolato (per indice o luogo nella struttura) o non calcolato (in base al nome dell'elemento); - sequenziale - caratteristica per strutture di dimensioni variabili. Il tipo di trattamento è determinato dal metodo di combinazione dei componenti in un'unica struttura.

5. Il valore della struttura può essere memorizzato nella memoria operativa (struttura interna) o esterna

Matrici, stringhe

Un tipo regolare (array) è un tipo complesso con una struttura uniforme di dimensioni fisse e accesso diretto calcolato agli elementi. La dimensione della struttura è fissa quando si descrive l'array. Gli elementi dell'array occupano un'area continua di memoria, ad es. disposti in sequenza uno dopo l'altro. Gli elementi dell'array sono numerati a partire da zero.

L'impostazione di una variabile di tipo normale (array) ha il modulo

<спецификация типа> <идентификатор> [<константное выражение>]

Qui, le parentesi quadre sono caratteri terminali.

Espressione costante determina il numero di componenti nell'array, quindi il suo valore è di tipo intero.

Identifier Nome di una variabile di matrice.

Il tipo di componenti è impostato specifica del tipo. Il tipo di componenti può essere qualsiasi (tranne il file). Se il tipo di componenti è semplice, la struttura determinata sarà monodimensionale (lineare), se complessa, quindi multidimensionale (non lineare).

Matrice multidimensionale È un array i cui elementi sono di tipo array. Definizione di un array multidimensionale:

<спецификация типа> <идентификатор> []…

Qui K1, K2, ..., Kn sono espressioni costanti. Inoltre, K1 imposta la dimensione dell'array in base alla prima dimensione, K2 - in base alla seconda dimensione e Kn - in base all'ennesima dimensione. Ad esempio, la descrizione di x definisce un array di x costituito da elementi k1. Ogni elemento x ha un tipo di array costituito da elementi k2. Altrimenti, possiamo dire che x è matrice bidimensionale (matrice), dove k1 è la dimensione nella prima dimensione, ovvero il numero di righe in una matrice bidimensionale - matrice; k2 è la dimensione nella seconda dimensione, ad es. il numero di colonne nella matrice. Pertanto, una matrice bidimensionale è considerata una matrice unidimensionale, ogni cui elemento è anche una matrice unidimensionale. Gli elementi della matrice vengono archiviati riga per riga nella memoria del computer.

Per accedere agli elementi dell'array, è necessario specificare il nome dell'array e la posizione (indice) dell'elemento nella struttura: nome dell'array [<индекс>] o nome dell'array [<индекс1>][<индекс2>]…[<индекс n>] rispettivamente per array monodimensionali e n-dimensionali. L'indice è specificato da un'espressione il cui valore deve essere un tipo intero e determina il numero del componente. Il valore dell'indice appartiene all'intervallo compreso tra zero e le dimensioni dell'array, ridotto di uno.

Puoi accedere all'elemento array in un altro modo - usando il puntatore per questo. Un puntatore è una variabile il cui valore è l'indirizzo di un'altra variabile, ad es. il numero (indirizzo) dell'unità di memoria allocata per la variabile. Un puntatore può fare riferimento solo a oggetti di un determinato tipo. Il nome dell'array è un puntatore costante al primo elemento dell'array.

Stringhe.Il valore del tipo "stringa" è una sequenza di caratteri (la parola "stringa" è racchiusa tra virgolette, poiché questo tipo non è esplicitamente definito in C e, riferendosi al tipo di stringa, intendiamo un tipo di dati che ha le proprietà di un tipo di stringa). Un tipo "stringa" (o solo una stringa) in C è considerato come un sottoinsieme del tipo di matrice. La stringa è specificata da una matrice unidimensionale, i cui elementi sono caratteri, l'ultimo carattere della matrice è "\\ 0". Questa "lettera nulla" è un segno della fine della linea. La lettera "\\ 0", così come altri caratteri, è inclusa nella stringa. La dimensione della linea (numero di caratteri) è determinata dal problema da risolvere ed è limitata dalla memoria disponibile.

Poiché il tipo di stringa è un array speciale, tutte le proprietà del tipo normale vengono archiviate per la stringa (ovvero, è possibile eseguire operazioni su singoli elementi valide per il tipo di base). Con la "lettera zero" puoi lavorare come con il resto dei personaggi (senza dimenticare il suo scopo principale).

Testo originale di solito è una sequenza di caratteri costituita da parole separate da caratteri separatori e che termina con un segno-carattere della fine del testo. Quando si sceglie una struttura di dati da visualizzare

il testo dovrebbe cercare di garantire che il testo occupi la quantità minima di memoria richiesta e la struttura selezionata fornisce i mezzi per un accesso rapido (diretto) agli elementi del testo, che, di regola, sono le sue parole. Questi requisiti sono soddisfatti da una struttura di dati - un array.

Testo si può immaginare:

Matrice bidimensionale - una matrice la cui riga è una parola di testo che termina con un terminatore di riga - конца \\ 0 ". Il numero di colonne è uguale alla lunghezza massima della parola più una (simbolo "\\ 0"). Il numero di righe è il numero massimo di parole nel testo. Una chiamata a una riga della matrice è una chiamata a una parola. Per creare tale struttura, è necessario leggere il testo carattere per carattere, posizionando ogni parola successiva in una nuova riga della matrice e aggiungendo il simbolo "\\ 0" alla parola.

Un array monodimensionale è una stringa. Questa struttura è pienamente coerente con la rappresentazione esterna del testo. La dimensione dell'array è uguale alla lunghezza massima del testo di origine, tenendo conto

delimitatori. Per indirizzare una parola, è necessario guardare in sequenza i caratteri dell'array, scoprendo il carattere separatore successivo che completa la parola corrente, una nuova parola inizia dietro di essa. Quindi continua fino a quando la parola successiva termina con un terminatore di riga.

9. Tipi disomogenei (struttura)

Il tipo eterogeneo (struttura, record) consente di costruire strutture di dati della natura più arbitraria. È usato per rappresentare oggetti che hanno una struttura piuttosto complessa ed eterogenea e, di regola, è usato per creare vari tipi di sistemi di informazione. Il valore di un tipo eterogeneo è costituito da un numero fisso di elementi (campi) di diversi tipi, quindi ogni elemento deve avere un nome univoco che viene utilizzato per accedere all'elemento.

Il programmatore stesso descrive il tipo eterogeneo (strutturale), impostando la sua "struttura interna": il numero di elementi, il loro tipo e nomi. Descrizione del tipo eterogeneo:

struct<имя структурного типа>

{ <определения элементов> };

Qui struct - parola di servizio - identificatore di un tipo strutturale, <имя структурного типа> - identificatore del tipo scelto arbitrariamente dal programmatore (<имя структурного типа> può essere omesso) <определения элементов> - un insieme di una o più descrizioni di oggetti, ciascuna delle quali determina il tipo di elemento introdotto tipo strutturale.

La definizione di un oggetto (ad esempio una variabile) di un tipo strutturale denominato ha la struttura strutt<имя структурного типа> < список структур>;

o<имя структурного типа> < список структур> ; Dove< список структур> - un elenco di nomi di strutture selezionati dal programmatore.

Le variabili di un tipo strutturale possono essere definite contemporaneamente con una descrizione del tipo. La definizione di un oggetto di un tipo strutturale senza nome è:

{ <определения элементов> } < список структур>;

Così, la struttura (variabili) tipo strutturale senza nome sono determinati allo stesso tempo con una descrizione del tipo stesso. Questa opzione è utilizzata per singolo definizioni di strutture. Poiché gli elementi delle strutture possono essere di qualsiasi tipo, è consentito l'incorporamento delle strutture, ad es. un elemento di struttura può essere un'altra struttura. In questo caso, la descrizione dei tipi strutturali dovrebbe essere fatta in una sequenza tale che il tipo strutturale usato nella descrizione sia stato precedentemente definito.

Quando si definisce la struttura può essere inizializzato. Quando si definisce un oggetto di un tipo strutturale, viene allocato memoria in quantità tale da poter posizionare i dati di tutti gli elementi. La dimensione della memoria in byte allocata per la struttura può essere ottenuta usando l'operazione sizeof, ad esempio sizeof (punto struttura). Per accedere agli elementi della struttura utilizzata nome qualificato (espressione primaria) del modulo<имя структуры> . <имя элемента структуры> Qui, un punto indica un'operazione per accedere a un elemento della struttura; ha la massima priorità. I nomi raffinati degli elementi della struttura hanno tutti i diritti degli oggetti dei tipi corrispondenti. È possibile eseguire operazioni su elementi di struttura validi per il loro tipo.

La struttura può essere un parametro della funzione e il valore di ritorno (principale) della funzione.

pointer

Un puntatore è una variabile il cui valore è l'indirizzo di un'altra variabile, ad es. il numero (indirizzo) dell'unità di memoria allocata per la variabile. Un puntatore può fare riferimento solo a oggetti di un determinato tipo (l'identificatore può essere il nome di una variabile, matrice, struttura, stringa letterale). Nel caso in cui la variabile sia dichiarata come puntatore, contiene l'indirizzo di memoria in cui è possibile trovare un valore scalare di qualsiasi tipo. Quando si dichiara una variabile di tipo puntatore, è necessario determinare il tipo di oggetto dati il \u200b\u200bcui indirizzo conterrà la variabile e il nome del puntatore con l'asterisco precedente (o il gruppo di asterischi). Formato della dichiarazione del puntatore:

tipo identificatore [modificatore] * descrittore.

Tipo di identificatore imposta il tipo di oggetto e può essere di qualsiasi tipo base, tipo di struttura, miscela (questo sarà discusso di seguito). Impostando la parola chiave void invece dell'identificatore di tipo, è possibile in qualche modo rinviare la specifica del tipo a cui fa riferimento il puntatore. Una variabile dichiarata come puntatore a un tipo vuoto può essere utilizzata per fare riferimento a un oggetto di qualsiasi tipo. Tuttavia, per essere in grado di eseguire operazioni aritmetiche e logiche su puntatori o su oggetti a cui puntano, è necessario determinare esplicitamente il tipo di oggetti durante ciascuna operazione. Tali definizioni di tipo possono essere eseguite utilizzando l'operazione di cast di tipo.

Le parole chiave const, near, far, huge possono agire come modificatori quando si dichiara un puntatore. La parola chiave const indica che il puntatore non può essere modificato nel programma. La dimensione della variabile dichiarata come puntatore dipende dall'architettura del computer e dal modello di memoria utilizzato, per il quale verrà compilato il programma. I puntatori a tipi di dati diversi non devono avere la stessa lunghezza.

Per modificare la dimensione del puntatore, puoi usare le parole chiave vicine, lontane, enormi.

File.

Tipo di file - questo è il tipo che collega il programma con dispositivi esterni. Un valore di tipo file è una sequenza di componenti di lunghezza arbitraria.

La dimensione del file (ovvero la lunghezza della sequenza) non è affatto specificata quando si dichiara il file ed è limitata solo dalla capacità dei dispositivi di memoria esterni. Per indicare la fine della struttura, viene utilizzata la fine dell'attributo del file.

In C, un file è considerato un flusso o una sequenza di caratteri (byte), indipendentemente dal dispositivo specifico con cui vengono scambiati i dati. Quando si scambia con un flusso, viene spesso utilizzata una sezione ausiliaria della memoria principale, chiamata buffer di flusso (buffer di input, buffer di output).

Quando si lavora con uno stream, è possibile eseguire le seguenti azioni:

Aprire e chiudere flussi;

Analizzare le condizioni per raggiungere la fine del flusso (fine del file) e gli errori I / O;

Ottieni e imposta il puntatore sulla posizione corrente nel flusso;

Gestire il buffering dello stream e le dimensioni del buffer.

Tutte le operazioni di I / O vengono implementate utilizzando le funzioni presenti nella libreria C. Per utilizzare queste funzioni, è necessario includere il file di intestazione stdio.h nel programma, che contiene i prototipi delle funzioni I / O, la definizione di costanti, i tipi e le strutture necessarie per il funzionamento delle funzioni. Lo stream può essere aperto in modalità testo o binaria. In base a ciò, distinguere tra file di testo e file binari.

Quando si apre un file in testuale In una modalità, una sequenza di caratteri letti da un flusso viene convertita, se necessario, da una rappresentazione di carattere in una rappresentazione interna. Ad esempio, se con in acqua se si leggono informazioni numeriche, la sequenza di caratteri di lettura viene convertita in un numero intero binario o in un numero a virgola mobile in conformità con le specifiche del formato; nel formato conclusione Le informazioni numeriche vengono convertite dalla rappresentazione interna di un numero in una sequenza di caratteri che rappresentano un numero. La sequenza di caratteri archiviata in un file di testo può essere suddivisa in righe. Quando un carattere di nuova riga "\\ n" viene scritto nel flusso di testo, viene sostituito da una sequenza di caratteri CR ("ritorno a capo") e LR ("avanzamento riga"). A

leggendo da file di testo la sequenza di caratteri CR e LR viene convertita in un carattere di nuova riga "\\ n".

Se il file non è archiviato informazioni di testoe binario, quindi non devono essere eseguite conversioni. Ad esempio, le informazioni numeriche vengono scritte (e quindi lette) in un file nella sua rappresentazione interna. Tale file deve essere aperto come binario.

funzioni condivisione del formato sono intesi per input / output di caratteri separati, stringhe, numeri interi e numeri reali di tutti i tipi. Quando si immettono i dati, questi vengono inseriti nel buffer, quindi il byte o in determinate parti viene trasferito al programma utente. Quando i dati vengono inviati a un file, vengono prima accumulati nel buffer e quando il buffer è pieno, vengono scritti come un singolo blocco nel file per una chiamata ad esso. Pertanto, l'utilizzo di un buffer riduce il numero di scambi con il file. Il buffer viene allocato al programma per impostazione predefinita all'apertura del file.

La funzione legge una sequenza di caratteri dal flusso di input, a partire dal byte, che indica la posizione corrente del puntatore del file. L'input si interrompe se viene rilevato uno spazio bianco o viene letto il numero di caratteri specificato nella specifica di conversione. La sequenza di caratteri di lettura viene interpretata in base alla stringa di formato ( stringa di formato scansionato in sequenza dal primo all'ultimo carattere) come rappresentazione simbolica di un numero intero o di un numero reale o di un singolo carattere o stringa di caratteri. Quindi viene convertito in una rappresentazione interna e scritto nell'area di memoria della variabile successiva dall'elenco degli argomenti (il puntatore alla posizione del file corrente si sposta nella nuova posizione corrente in base al numero di byte letti).

Questo processo continua fino a quando la stringa di formato è esaurita o non è stata raggiunta la fine del file o si è verificato un errore. Nel primo caso, la funzione restituisce il numero di oggetti che hanno ricevuto un valore durante l'input, quando raggiunge la fine del file, restituisce la costante EOF, in caso di errore restituisce -1.

La funzione esegue la scansione della stringa di formato da sinistra a destra, visualizza tutti i caratteri arbitrari rilevati nel file, calcola il valore dell'espressione corrispondente dall'elenco degli argomenti quando soddisfa la specifica di conversione, la converte dalla rappresentazione interna in una sequenza di caratteri in conformità con la specifica e la visualizza nella posizione corrente del file. Per ogni argomento, è necessario specificare una specifica di conversione. Se ci sono meno argomenti rispetto alle specifiche, il risultato dipende

dall'implementazione della lingua. L'output termina quando la stringa di formato è esaurita o si verifica un errore. La funzione restituisce il numero di caratteri stampati e, in caso di errore, un numero negativo.

In modalità binaria, i contenuti di qualsiasi area di memoria possono essere scritti in un file senza conversione dalla rappresentazione interna. Pertanto, il modulo per rappresentare i dati in memoria e in un file binario è lo stesso. Pertanto, quando si legge da un file binario, non è necessaria la conversione nella rappresentazione interna. Per scambiare con un file binario, vengono utilizzate le funzioni fread e fwrite.

La sintassi viene controllata nelle prime fasi della traduzione. Nei linguaggi di programmazione interpretati, il controllo della sintassi viene eseguito nel processo di interpretazione (esecuzione) o nel processo di compilazione preliminare in codice intermedio. Inoltre, la sintassi può essere verificata direttamente durante la modifica del codice sorgente dei programmi utilizzando l'IDE.

Sintassi di scrittura delle funzioni

Sintassi di scrittura delle funzioni - regole formali che devono essere soddisfatte da un record di chiamata di definizione o funzione; modulo di registrazione delle funzioni. Se la sintassi della funzione non è corretta, il compilatore restituirà un errore e il programma non verrà creato fino a quando l'errore non verrà corretto.

Ad esempio, gli errori di sintassi di un record di funzione includono:

  • scrivere il nome della funzione quando viene chiamata, che non corrisponde alla grammatica della lingua (caso errato di caratteri per le lingue sensibili al maiuscolo / minuscolo);
  • l'uso di letterali che non corrispondono alla grammatica della lingua quando si chiama o si definisce una funzione (altri tipi di parentesi, delimitatore di argomenti);
  • l'assenza di un tipo di dati restituito dalla funzione (per quelle lingue per le quali è definita dalla grammatica).

Gli elementi principali di qualsiasi linguaggio di programmazione sono l'alfabeto, la sintassi e la semantica.

Alfabeto - una serie di caratteri visualizzati su dispositivi e schermate di stampa e / o immessi dalla tastiera del terminale. Di solito si tratta di un set di caratteri Latin-1 ad eccezione dei caratteri di controllo. A volte i caratteri non visualizzabili sono inclusi in questo set con le regole per scriverli (combinazione in token).

Vocabolario - un insieme di regole per la formazione di catene di caratteri (token) che formano identificatori (variabili ed etichette), operatori, operazioni e altri componenti lessicali del linguaggio. Ciò include anche parole riservate (vietate, parole chiave) nel linguaggio di programmazione intese a indicare operatori, funzioni integrate, ecc. Talvolta token equivalenti, a seconda del linguaggio di programmazione, possono essere indicati da uno o più simboli dell'alfabeto. Ad esempio, l'operazione di assegnazione in C è indicata come "\u003d" e in Pascal, ": \u003d". Le parentesi operatore in C sono definite dai caratteri "(" e ")" e in Pascal, inizio e fine. Il confine tra il vocabolario e l'alfabeto è quindi molto arbitrario, soprattutto perché il compilatore sostituisce solitamente le parole chiave riconosciute con codice interno (ad esempio, inizio - 512, fine - 513) durante la fase di analisi lessicale e le considera ulteriormente come caratteri separati.

Sintassi - un insieme di regole per la formazione di strutture linguistiche o frasi di un linguaggio di programmazione - blocchi, procedure, operatori composti, istruzioni condizionali, operatori di cicli, ecc. Una caratteristica di sintassi è il principio di annidamento (ricorsività) delle regole per la costruzione di strutture. Ciò significa che l'elemento di sintassi del linguaggio nella sua definizione, direttamente o indirettamente in una delle sue parti, contiene se stesso. Ad esempio, nella definizione di operatore di ciclo, il corpo del ciclo è un operatore, un caso particolare del quale è lo stesso operatore di ciclo.

È necessario il rigoroso rispetto delle regole di ortografia (sintassi) del programma. In particolare, in Pascal, lo scopo dei segni di punteggiatura è definito in modo univoco. Un punto e virgola (;) viene posizionato alla fine dell'intestazione del programma, alla fine della sezione di descrizione della variabile, dopo ogni istruzione. Non è possibile lasciare un punto e virgola prima della parola Fine. La virgola (,) è un separatore di elementi in vari elenchi: un elenco di variabili nella sezione descrizione, un elenco di valori di input e output.

La sintassi rigorosa nel linguaggio di programmazione è necessaria principalmente per il traduttore. Un traduttore è un programma che viene eseguito formalmente. Se, ad esempio, il separatore nell'elenco di variabili deve essere una virgola, qualsiasi altro segno verrà percepito come un errore. Se il punto e virgola è un separatore di operatori, il traduttore come operatore percepisce l'intera parte del testo del programma da un punto e virgola a un altro. Se dimentichi di mettere questo segno tra due operatori, il traduttore li prenderà per uno, il che porterà inevitabilmente a un errore.

Lo scopo principale delle regole sintattiche è di dare un significato inequivocabile ai costrutti del linguaggio. Se qualsiasi costruzione può essere interpretata in modo ambiguo, allora contiene necessariamente un errore. È meglio non fare affidamento sull'intuizione, ma imparare le regole della lingua.

Per descrivere la sintassi di un linguaggio di programmazione, è necessario anche un qualche tipo di linguaggio. In questo caso, stiamo parlando di un metalinguaggio ("sublanguage"), progettato per descrivere altre lingue. I metalinguaggi più comuni nella letteratura di programmazione sono le formule metalinguistiche Beckus-Naura (linguaggio BPF) e i diagrammi di sintassi. Il linguaggio dei diagrammi di sintassi è più visivo, più facile da leggere.

Nel BPF, qualsiasi concetto sintattico è descritto sotto forma di una formula costituita dalle parti destra e sinistra collegate dal segno :: ::, il cui significato è equivalente alle parole "per definizione che esiste". A sinistra del segno :: :: è il nome del concetto da definire (meta variabile), racchiuso tra parentesi angolari< >e sul lato destro viene scritta una formula o un diagramma che definisce l'intero insieme di valori che può assumere una meta-variabile.

La sintassi del linguaggio è descritta complicando sequenzialmente i concetti: prima vengono determinati i più semplici (di base), quindi tutti i più complessi che includono i concetti precedenti come componenti.

In una tale sequenza, ovviamente, il concetto definibile finale dovrebbe essere il concetto di un programma.

Alcune convenzioni sono accettate nelle voci meta-formula. Ad esempio, la formula BNF che definisce il concetto di "cifra binaria" è la seguente:

<двоичная цифра>::=0|1

L'icona | equivalente alla parola "o".

Nei diagrammi, le frecce indicano la sequenza di disposizione degli elementi della struttura sintattica; i cerchi sono cerchiati attorno ai simboli presenti nel disegno.

Il concetto di "codice binario" come sequenza non vuota di cifre binarie BNF descrive come segue:

<двоичный код>::=<двоичная цифра>|<двоичный

code\u003e<двоичная цифра>

Una definizione in cui un determinato concetto è definito da solo si chiama ricorsiva. Le definizioni ricorsive sono caratteristiche di BNF.

La freccia di ritorno indica la possibilità di ripetizione ripetuta. Ovviamente, il diagramma è più visivo del BPF.

I diagrammi di sintassi sono stati introdotti da N. Wirth e utilizzati per descrivere il linguaggio Pascal da lui creato.

Semantica - contenuto semantico di costruzioni, frasi di una lingua, analisi semantica - questo è un controllo della correttezza semantica di una costruzione. Ad esempio, se utilizziamo una variabile in un'espressione, allora deve essere determinata in precedenza dal testo del programma e il suo tipo può essere ottenuto da questa definizione. In base al tipo di variabile, possiamo parlare della validità dell'operazione con questa variabile. Errori semantici insorgono quando si utilizzano operazioni, array, funzioni, operatori, ecc., È inaccettabile.

sintassi del programma logica combinatoria

La lezione affronta questioni relative all'apparato concettuale, alla storia dello sviluppo e alle possibilità espressive della rappresentazione sintattica di teorie formali e linguaggi di programmazione.

Formalizziamo le costruzioni di base del linguaggio di programmazione SML per mezzo di forme Backus-Naur o BNF (la storia della loro creazione è presentata nella lezione introduttiva).

Informalmente, definiamo la sintassi (di un linguaggio di programmazione o teoria matematica) come la forma di costruzioni (programma o teoria) e come combinarli. Una definizione più precisa della sintassi verrà formulata più avanti nella lezione.

Definiamo il concetto di sintassi più rigorosamente.

Per sintassi, intendiamo una sezione che descrive un linguaggio matematico formale o un linguaggio di programmazione che esamina la forma, la forma e la struttura delle strutture (indipendentemente dal loro significato o applicabilità pratica).

Guardando al futuro, notiamo che il significato delle costruzioni del linguaggio di programmazione è descritto e studiato dalla semantica (ne discuteremo nella prossima lezione), e le domande e il valore dell'applicabilità pratica da parte della pragmatica.

Il compito principale della sintassi è determinare la forma e il tipo di costrutti di linguaggio validi. Questo problema può essere risolto elencando le descrizioni di tutti i costrutti del linguaggio. Uno dei meccanismi per tale descrizione è la notazione BPF già citata da noi.

Considereremo in parallelo la formalizzazione BNF della sintassi del calcolo lambda e del linguaggio di programmazione SML. In quest'ultimo caso, ci limitiamo all'insieme di base dei costrutti del linguaggio, sottolineando caratteristiche essenziali come le tuple e le espressioni let.

Per comprendere correttamente il ruolo e il posto della sintassi nello studio dei linguaggi di programmazione, consideriamo uno schema generalizzato per la traduzione del codice sorgente di un programma (scritto, ad esempio, nel linguaggio di programmazione SML) in codice macchina.

Durante la trasmissione del programma, prima di tutto, viene eseguita la cosiddetta procedura di analisi lessicale, che include la selezione nel testo del programma di costruzioni di linguaggio elementare o, in caso contrario, token (in particolare, nomi di variabili o identificatori, speciali o parole chiave, valori di costanti, variabili e così via.).

Al completamento dell'analisi lessicale, viene eseguita la cosiddetta procedura per l'analisi del testo del programma, che è una verifica della corretta sintassi del testo scritto nel linguaggio di programmazione. Questa procedura comporta probabilmente l'esecuzione della convalida della digitazione in un modo o nell'altro.

Infine, se tutti i costrutti del linguaggio presenti nel testo del programma sono sintatticamente corretti e non vi sono incoerenze di tipi proibiti dal punto di vista dell'analizzatore di correttezza di battitura, il testo del programma viene convertito in codice intermedio (assemblatore, codice di una o un'altra macchina astratta ) o il codice macchina stesso.

Considera la sintassi del linguaggio di programmazione SML rispetto alla sintassi del calcolo lambda.

Per maggiore chiarezza e comparabilità delle formalizzazioni della sintassi di entrambi i linguaggi (il linguaggio della teoria matematica formale e il linguaggio di programmazione) useremo una sola notazione, vale a dire BNF.

Prima di tutto, è necessario concordare la notazione.

Considera le designazioni tradizionali di BNF e spiega il significato di ciascuna di esse.

In effetti, i BPF sono definizioni di alcuni concetti attraverso altri. In questo caso, i concetti sono racchiusi tra parentesi angolari e vengono utilizzati numerosi simboli e convenzioni specializzati, la cui essenza è spiegata di seguito.

Il simbolo di definizione ":: \u003d" separa la struttura definita dalle strutture di base precedentemente definite che la compongono.

Il costrutto definito è scritto a sinistra di ":: \u003d" tra parentesi angolari "<" и ">".

Le alternative (possibili opzioni) delle strutture sono elencate verticalmente.

La citazione (così come abbiamo citato caratteri speciali, racchiudendoli tra virgolette doppie) non ha una designazione.

Illustriamo la formalizzazione della sintassi per mezzo della notazione BNF, considerando come esempio di un sistema formale il calcolo lambda che ci è familiare dalle lezioni precedenti.

<выражение> ::= <константа> | <переменная> |

(<выражение> <выражение>) |

l<переменная> . <выражение>

Spieghiamo il significato della notazione sopra.

NEL questo esempio definisce il concetto di espressione, la cui rappresentazione sintattica può essere espressa sotto forma di una delle seguenti alternative:

  • 1. costanti;
  • 2. variabile;
  • 3. due espressioni racchiuse tra parentesi, ad es. l'operazione familiare di applicare espressioni lambda;
  • 4. carattere l seguito da una variabile, un punto e un'espressione, ad es. l'operazione familiare di astrazione.

Si scopre che la sintassi del linguaggio di programmazione SML ha una serie di ovvie analogie con la sintassi del calcolo lambda. Queste analogie sono inevitabili, sia per la natura funzionale del linguaggio di programmazione in questione, sia per il fatto che il linguaggio SML è stato sviluppato come mezzo per dimostrare i teoremi, il che significa che la sua sintassi (e, guardando al futuro, notiamo che la semantica dovrebbe essere matematicamente trasparente) .

Per illustrare i punti precedenti, consideriamo le più importanti categorie sintattiche del linguaggio di programmazione SML.

Di seguito, chiameremo una descrizione un record che collega l'espressione di un linguaggio di programmazione con il nome che lo indica nel programma (identificatore).

Con il termine "riservato" (o, in altre parole, un servizio), intendiamo un costrutto linguistico che viene interpretato in modo inequivocabile come un'istruzione del linguaggio di programmazione (ad esempio "if", "then", "let"). Ricordiamo che in questa notazione, la citazione viene fatta senza virgolette o altri caratteri di delimitazione.

Un commento è un testo esplicativo arbitrario per un programma che, secondo la sintassi del linguaggio SML, dovrebbe essere racchiuso tra delimitatori del modulo "(*" e "*)".

In particolare, consideriamo la struttura dei principali tipi di espressioni linguistiche sintatticamente valide.

<выражение> ::= <идентификатор> | <литерал> |

<выражение> <выражение> |

<выражение> <идентификатор> <выражение>

Come si può vedere dalla formalizzazione BNF, l'espressione sintatticamente corretta nel linguaggio di programmazione SML è:

  • 1. identificatore (ovvero il nome di una variabile, costante, funzione o tipo, di solito rappresentato come una sequenza alfanumerica di lunghezza limitata e che inizia con un carattere alfabetico) o
  • 2. letterale (i letterali saranno discussi più avanti nella lezione) o
  • 3. una sequenza di due espressioni o
  • 4. una sequenza di due espressioni collegate da un identificatore.

Continuiamo la discussione sulle espressioni.

Oltre alle alternative elencate, le espressioni sintatticamente valide del linguaggio di programmazione SML sono anche:

se<выражение> poi<выражение>

altro<выражение> |

(<выражение> ... <выражение>) |

permettere<описание> nel<выражение> fine |

  • 1. tre espressioni collegate dalle parole riservate if ("if"), then ("then") e else ("else"), hanno chiamato un'espressione condizionale e rappresentano effettivamente una funzione predicata che implementa l'esecuzione della seconda espressione se la prima è vera ed eseguendo un terzo altrimenti;
  • 2. la sequenza finale di espressioni racchiusa tra parentesi (o la cosiddetta tupla) e utilizzata per strutturare i dati;
  • 3. descrizione ed espressione, collegate dalle parole riservate let ("put"), in ("in") e end ("end"), che determinano l'operazione di sostituzione della descrizione nell'espressione, tenendo conto di tutte le possibili occorrenze del frammento specificato della descrizione in essa;
  • 4. un'espressione racchiusa tra parentesi (come già sappiamo, nel calcolo lambda e nella logica combinatoria questa operazione può essere eseguita senza restrizioni) e utilizzata per indicare esplicitamente la priorità dell'operazione.

Continuiamo la discussione sulle categorie sintattiche del linguaggio di programmazione SML.

Procediamo a considerare la struttura di tipi sintatticamente validi di descrizioni di oggetti linguaggio.

Diamo la corrispondente formalizzazione in termini di BNF.

<описание> ::=

val< идентификатор > = < выражение > |

divertimento< идентификатор > < идентификатор > =

< выражение > |

locale< описание > nel<описание> fine

Le descrizioni sintatticamente valide del linguaggio di programmazione SML, come segue dal BNF presentato, sono:

  • 1. identificatore ed espressione, collegati da parole riservate val e "\u003d", che indicano il legame dell'identificatore (variabile, costante o altro oggetto sintatticamente valido del linguaggio di programmazione) con una o un'altra espressione;
  • 2. tre identificatori e un'espressione collegata dalle parole riservate fun e "\u003d", che indicano l'associazione della funzione (indicata dal primo identificatore) con il parametro (indicato dal secondo identificatore) con l'espressione che determina l'ordine in cui viene calcolato il valore;
  • 3. due descrizioni collegate dalle parole riservate local, in e end, che indicano la definizione locale della prima descrizione nel contesto della seconda.

Continuiamo la discussione sulle categorie sintattiche del linguaggio di programmazione SML.

Procediamo a considerare la struttura di descrizioni sintatticamente valide di tipi di oggetti linguaggio.

Diamo la corrispondente formalizzazione in termini di BNF.

<тип> :: \u003d int | bool |

<тип> * ... * <тип> |

<тип> -> <тип>

Come risulta dal BNF presentato, i tipi sintatticamente validi del linguaggio di programmazione SML sono:

  • 1. valori interi indicati dalla parola riservata int;
  • 2. valori logici indicati dalla parola riservata bool;
  • 3. tuple - ordinate n-elementi di elementi di determinati tipi;
  • 4. funzioni - ordinato n-elementi di alcuni tipi collegati da caratteri riservati "-\u003e".

Si consideri il seguente esempio che illustra l'assegnazione dei tipi in SML. Una costante di tipo una tupla della forma (0, false, 1, true) è di tipo (int * bool * int * bool).

Si noti che le varianti dei tipi (1) e (2) sono elementari, mentre (3) e (4) sono tipi derivati \u200b\u200bcon una struttura esplicitamente indicata (o dedotta), da cui deriva il nome "tipo strutturato".

Durante la lezione, abbiamo già menzionato una categoria sintattica come i letterali, o sui tipi base di SML, costituiti da alcune sequenze di personaggi.

Considerare più in dettaglio le caratteristiche sintattiche dei principali tipi di letterali.

Diamo la corrispondente formalizzazione in termini di BNF.

<литерал> ::= <литерал целого типа> |

<литерал строкового типа> |

<литерал вещественного типа>

Come risulta dal BNF presentato, i tipi di letterali sintatticamente validi nel linguaggio di programmazione SML sono i seguenti:

  • 1. letterali interi di tipo int e compresi nell'intervallo da -230 a +230 (quest'ultima circostanza è associata alle caratteristiche della rappresentazione dei dati macchina);
  • 2. letterali stringa di tipo stringa e che rappresentano sequenze alfanumeriche di caratteri in codice in formato ASCII;
  • 3. letterali reali aventi il \u200b\u200btipo di base reale, una forma generalizzata della forma M x 10E, dove M è la mantissa nell'intervallo compreso tra -1 e +1 ed E è l'ordine nell'intervallo corrispondente.

Si noti che il significato (cioè la semantica) dei letterali è completamente determinato dalla loro rappresentazione lessicale (e quindi sintattica).

Continuiamo la discussione sulle categorie sintattiche del linguaggio di programmazione SML.

Passiamo alla considerazione del fondamentale dal punto di vista della formalizzazione dei linguaggi di programmazione funzionale - calcolo lambda - il funzionamento delle funzioni applicative.

<выражение> <выражение>

Come risulta dal BNF presentato, la costruzione sintatticamente valida del linguaggio di programmazione SML che descrive l'operazione dell'applicazione corrisponde in modo molto preciso alla descrizione dell'operazione dell'applicazione nel calcolo lambda.

Illustriamo l'applicazione di una funzione a un argomento nel linguaggio di programmazione SML con il seguente esempio.

Considera la funzione succ definita dalla definizione

fun succ n \u003d n + 1;

e ne aggiunge uno all'argomento (intero).

Per la funzione succ in questione, l'applicazione sintatticamente corretta può essere nella forma succ 2 e viene calcolata come 3 durante l'esecuzione del programma.

Continuiamo la discussione sulle categorie sintattiche del linguaggio di programmazione SML.

Passiamo alla considerazione delle costruzioni sintatticamente valide del linguaggio di programmazione SML, chiamate espressioni condizionali.

Diamo la corrispondente formalizzazione in termini di BNF:

se<выражение> poi<выражение> altro<выражение>;

Come si può vedere dalla formalizzazione di BNF, l'espressione condizionale sintatticamente corretta consiste di tre sottoespressioni collegate dalle parole riservate se, quindi e altro, che abbiamo già menzionato durante la lezione.

Aggiungiamo a quanto sopra una serie di osservazioni necessarie. Innanzitutto, il risultato del calcolo della prima espressione dovrebbe essere un valore booleano. In secondo luogo, i tipi di seconda e terza espressione devono corrispondere. Infine, la parte dell'espressione condizionale che inizia con else è facoltativa.

Si noti inoltre che le funzioni di confronto sono integrate nel linguaggio SML e hanno la forma: "\u003d" (uguale), "<" (меньше), ">"(Di Più),"<=" (меньше или равно), ">\u003d "(maggiore o uguale a),"<>"(non uguale). Il risultato del calcolo di una di queste funzioni è un valore booleano.

Illustriamo la sintassi di un'espressione condizionale con il seguente esempio in SML:

se n\u003e \u003d 10 allora 1 altro 0;

Si noti che l'espressione sopra può essere utilizzata per analizzare il parametro di una funzione che calcola, ad esempio, il numero di cifre di un numero decimale.

Continuiamo la discussione delle principali categorie sintattiche del linguaggio di programmazione SML.

Considera la struttura di costrutti sintatticamente validi noti come let-espressioni.

Diamo la corrispondente formalizzazione in termini di BNF:

permettere<описание> nel<выражение> fine;

Come si può vedere dalla formalizzazione BNF, un'espressione let sintatticamente corretta consiste in una descrizione e un'espressione collegate dalle parole riservate let, in e end.

Come puoi concludere dalla sintassi, let-expression non è altro che una sostituzione di un valore in un'astrazione lambda. Le espressioni let sono utilizzate nel linguaggio di programmazione SML per associare valori e ottimizzare i calcoli, in particolare per fornire calcoli multipli di frammenti di programma ripetuti.

Illustriamo la sintassi delle espressioni let con esempi tratti dal linguaggio di programmazione SML.

Considera le seguenti espressioni let:

lascia val n \u003d 2 in n + 1 fine;

lascia k \u003d 9876 * 8765 in (k-1, k, k + 1) fine;

Come puoi vedere, la prima espressione non è altro che una sostituzione che può essere formalizzata con un termine lambda della forma (xx.x + 1) 2. La seconda espressione ci consente di ridurre il calcolo multiplo di un'operazione ingombrante (moltiplicazione) a una sola.

La conferenza ha menzionato più volte il concetto di tupla.

Consideriamo più in dettaglio questo tipo molto importante (specialmente quando si implementano le funzioni) di costruzioni sintattiche del linguaggio di programmazione SML.

Ecco una formalizzazione della rappresentazione sintatticamente valida di una tupla in termini di BNF:

(<выражение>, ..., <выражение>)

In base al tipo di formalizzazione BNF, chiariamo il concetto di tupla. Una tupla è un gruppo costituito da almeno due espressioni (possibilmente di tipo diverso), combinate in un insieme separato.

Si noti che le tuple vengono utilizzate in SML per implementare funzioni multi-posto (con più di un argomento), e più ampiamente nella teoria e nella pratica di programmazione, nei database relazionali (in cui i dati sono presentati sotto forma di tabelle), poiché una tupla è, in effetti, una stringa tale tavolo.

Illustriamo la sintassi della costruzione della tupla con esempi tratti dal linguaggio di programmazione SML:

Esempio 1: (1, 2 * 1, 2 * 2 * 1)

Esempio 2: (1, vero, 0, falso)

Si noti che nel caso di una singola espressione, una tupla degenera in un'espressione tra parentesi. Naturalmente, qualsiasi espressione SML può essere racchiusa tra parentesi, ad esempio, per indicare esplicitamente la priorità di applicazioni, aritmetica e operazioni logiche.

L'esperienza acquisita durante la lezione sui principali tipi di costruzioni sintattiche del linguaggio di programmazione SML ci consente di passare alla sintassi formale di tali costruzioni fondamentali del linguaggio come la descrizione di variabili e funzioni.

Considera la formalizzazione di descrizioni sintatticamente corrette di variabili e funzioni in termini di BNF:

<описание> ::=

val<идентификатор> = <выражение>

<описание> ::=

divertimento<идентификатор> <идентификатор> =

<выражение>

La prima definizione è una descrizione della variabile, la seconda è funzioni. Inoltre, entrambe le definizioni hanno una struttura simile.

Illustriamo le descrizioni formali di variabili e funzioni con i seguenti esempi:

Esempio 1. val x \u003d 2;

Esempio 2. fatto divertente n \u003d

se n<2 then 1

altro n * fatto (n - 1);

Esempio 3. fun f (x, y) \u003d x * x + y * y;

Il primo degli esempi forniti è una descrizione della variabile (intera) x, il secondo è la funzione fattuale ricorsiva (auto-applicabile) del calcolo fattoriale (il prodotto di numeri naturali da 1 a n), e il terzo è la doppia funzione f, che calcola la somma dei quadrati degli argomenti.

Notiamo in conclusione che è durante l'implementazione di quest'ultima funzione che vengono usate le tuple (poiché la sintassi SML nella sua forma “pura”, come segue dal BNF, consente l'uso di sole singole funzioni).

Quindi, in questa lezione abbiamo esaminato i principali tipi di costruzioni sintattiche del linguaggio di programmazione SML. Dopo la discussione, si possono trarre le seguenti conclusioni:

  • · La sintassi dei linguaggi di programmazione funzionale è abbastanza vicina alla sintassi delle teorie formali su cui si basano (in particolare, questo è vero per il calcolo lambda e SML);
  • · I BPF sono formalizzazione pertinente e adeguata della sintassi del linguaggio;
  • · Il linguaggio di programmazione SML, a differenza dei primi linguaggi di programmazione funzionale, ha una serie di costruzioni avanzate (tuple, let-espressioni, ecc.).

Backus-Naur Form (BNF)

Il Backus-Naur Form (BNF) è stato usato per la prima volta nella descrizione di Algol-60. Il BPF coincide essenzialmente con la notazione delle grammatiche CS, differendo solo per le designazioni. Sono forniti i seguenti metacaratteri:

<> - serve per evidenziare i concetti non linguistici. | - "o". Separa i lati alternativi alternativi delle regole. - "è per definizione". Sostituisce la freccia utilizzata durante la registrazione di produzioni di grammatiche CS.

I caratteri terminali sono registrati così come sono, non sono previsti modi speciali per evidenziarli. Ecco un esempio di definizioni sul BPF, prese dalla specifica Algol-60 - "Messaggio modificato":

<простое арифметическое выражение> ::= <терм> 1 Operazione tipo aggiunta Okak\u003e<терм> | <простое арифметическое выражение> <знак операции типа сложения> <терм> <знак операции типа сложения> ::= + | -

Come puoi vedere, la ricorsione è usata per esprimere ripetizioni e ovunque - a sinistra. BNF è stato usato da N. Wirth nel descrivere il linguaggio Pascal. Sebbene alla notazione siano state aggiunte parentesi (e) che indicano la ripetizione, sono state applicate solo in singoli casi, mentre, ad esempio, la grammatica delle espressioni è ricorsiva.

Grafici di sintassi

Diagramma di sintassi è un grafico diretto con un bordo di entrata e un bordo di uscita e vertici etichettati. Il diagramma di sintassi definisce un linguaggio formale. La catena di segni ai vertici su qualsiasi percorso dal bordo di input all'output è la catena del linguaggio specificato dal diagramma di sintassi. Pertanto, possiamo supporre che il diagramma di sintassi sia una delle forme della grammatica generatrice dei linguaggi degli automi. I diagrammi sintattici e le macchine a stati finiti hanno una stretta relazione: qualsiasi linguaggio automa è definito da un diagramma di sintassi e viceversa, usando qualsiasi diagramma sintattico si può costruire un automa finito (in generale, non deterministico) che riconosce lo stesso linguaggio definito dal diagramma.

Costruendo la macchina a stati finiti di riconoscimento corrispondente dal diagramma di sintassi, è quindi possibile implementare questa macchina sia hardware che software.

Pertanto, i diagrammi di sintassi possono servire non solo per la generazione, ma anche per il riconoscimento dei linguaggi degli automi. I grafici divennero popolari dopo la pubblicazione del libro di K. Jensen e N. Wirth "Pascal". Sono utilizzati nella sua prima parte - "Guida" - un libro di testo in lingua compatta. In fig. 3.1 mostra uno dei diagrammi lì.

Modulo Backus-Naur espanso

Come già accennato, la mancanza di notazione grammaticale formale (e BNF) per la ripetizione esplicita crea una serie di difficoltà. In primo luogo, le definizioni sono difficili da capire, non abbastanza visive a causa dell'abbondanza di ricorsioni. In secondo luogo, ci sono problemi con il fatto che le grammatiche che danno alberi semantici adeguati risultano essere ricorsive. Nel descrivere Modula-2 e Oberon, N. Wirth ha usato la forma estesa Backus-Naura (RBNF). Le principali modifiche riguardano l'introduzione di parentesi (e) per le ripetizioni e [e] per indicare l'inclusione facoltativa di catene di terminali e non terminali nelle giuste parti delle regole. Anche gli accordi riguardanti la designazione di terminali e non terminali sono cambiati, il che non è così fondamentale. In futuro utilizzeremo l'RBNF. Ecco come viene definito nella specifica Oberon-2: Le opzioni sono separate da un |. Le parentesi quadre [e] indicano il carattere facoltativo dell'espressione scritta al loro interno e le parentesi graffe (e) indicano la sua ripetizione (possibilmente 0 volte). I caratteri non terminali iniziano con una lettera maiuscola (ad esempio Operatore). I caratteri terminali iniziano con una lettera minuscola (ad esempio, ident) o sono scritti interamente in lettere maiuscole (ad esempio, inizio) o sono racchiusi tra virgolette (ad esempio ": \u003d"). Va aggiunto che nel ruolo del segno "per definizione", nell'RBNF viene utilizzato "\u003d" e ciascuna regola termina con un punto. Ecco come si può determinare la sintassi di un identificatore (nome) usando RBNF:

Nome \u003d Lettera (Lettera | Numero).

Come metalinguaggio, RBNF dovrebbe essere adatto a descrivere linguaggi di interesse pratico. Includendo l'utilizzo di RBNF, è possibile determinare la sintassi dell'RBNF stesso:

Sintassi \u003d (regola). Regola \u003d Nome "\u003d" Espressione Espressione \u003d Variante (variante "I"). Opzione - Elemento (elemento). Elemento \u003d Nome | Catena | "(" Espressione ")" | "[" Expression "]" | "(" Espressione ")". Catena \u003d "" "(carattere)" "" | "" "(simbolo)" "".

In queste definizioni, non viene fatta alcuna distinzione tra i nomi che designano terminali e non terminali, sebbene non sarebbe difficile formularlo sull'RBNF. La distinzione dei nomi va oltre lo scopo della sintassi e può essere specificata (e specificata) separatamente. Lo stesso si fa spesso quando si definiscono i linguaggi di programmazione.

Descrizioni della sintassi del linguaggio C.

C (inglese C) - un linguaggio di programmazione procedurale standardizzato sviluppato nei primi anni '70 dagli impiegati di Bell Labs Ken Thompson e Denis Ritchie come sviluppo del linguaggio Bee. C è stato creato per l'uso nel sistema operativo UNIX. Da allora è stato portato su molti altri. sistemi operativi ed è diventato uno dei linguaggi di programmazione più utilizzati. C è apprezzato per la sua efficacia; È la lingua più popolare per la creazione di software di sistema. Inoltre, viene spesso utilizzato per creare programmi applicativi. Nonostante il fatto che C non sia stato progettato per i principianti, è attivamente utilizzato per insegnare la programmazione. In futuro, la sintassi del linguaggio C divenne la base per molte altre lingue. C è caratterizzato dal laconicismo, una moderna serie di costruzioni per il controllo del flusso, strutture di dati e una vasta serie di operazioni.

Nel famoso libro di B. Kernigan e D. Ritchie, la descrizione della sintassi del linguaggio C è data in una notazione equivalente al BNF, ma utilizza altre convenzioni sulla notazione di terminali e non terminali, lati alternativi alternativi delle regole, costruzioni opzionali. I non terminali sono scritti in corsivo, i terminali - in carattere diretto. Parti alternative delle regole sono scritte in una colonna una alla volta o contrassegnate con le parole "uno di" (uno di). Le parti opzionali sono seguite dal pedice "opt (da facoltativo) - facoltativo; "Neo" - in alcune traduzioni russe). Lato sinistro le regole sono scritte in una riga separata rientrata a sinistra. Ecco un esempio di definizioni di costrutti in linguaggio C:

Operatore composto (elenco descrizioni elenco opt elenco operatori opt) elenco operatori operatore operatore elenco operatori

Come puoi vedere, a causa della mancanza di un modo esplicito di esprimere le ripetizioni, le definizioni abbondano nella ricorsione. Una notazione simile con modifiche minime è stata utilizzata per descrivere la sintassi dei linguaggi discendenti di C: C ++, Java, C #. Ecco un estratto dallo standard ECMA-334 in C #:

Block: (Statement-listopt) statement-list: istruzione statement-list statement

Apparentemente, questa notazione non ha un nome speciale. E sembra, almeno, strano. È scomodo non solo per la lettura, ma anche per l'elaborazione su un computer. Il suo uso nel descrivere nuove lingue è difficile da spiegare con qualcosa di diverso dal bisogno incompreso di seguire le tradizioni.

Funzionalità del linguaggio C.

  1. Ha una semplice base linguistica da cui vengono portate molte funzionalità essenziali nelle librerie, come funzioni matematiche o funzioni di gestione dei file;
  2. Si concentra sulla programmazione procedurale, fornendo la comodità di applicare lo stile strutturale di programmazione;
  3. Ha un sistema di tipi che protegge da operazioni insignificanti;
  4. Utilizzo di un preprocessore per, ad esempio, definire macro e includere file con codice sorgente;
  5. Ha accesso diretto alla memoria del computer attraverso l'uso di puntatori;
  6. Ha un numero minimo di parole chiave;
  7. Passare i parametri a una funzione per valore, non per riferimento (mentre il passaggio per riferimento viene eseguito utilizzando i puntatori);
  8. Puntatori a funzioni e variabili statiche;
  9. Ha ambiti di dominio;
  10. Record: tipi di dati collettivi (strutture) definiti dall'utente che possono essere manipolati nel loro insieme;

Programma C "Hello world"

main () (printf ("Hello, World! \\ n");) #include int main () (printf ("Hello, World! \\ n"); return 0;)

Descrizioni della sintassi della lingua Ada

Ada - un linguaggio di programmazione creato nel 1979-1980 a seguito di un progetto intrapreso dal Dipartimento della Difesa degli Stati Uniti con l'obiettivo di sviluppare un linguaggio di programmazione unificato per sistemi embedded (vale a dire sistemi di controllo per complessi automatizzati che operano in tempo reale). Questi erano, prima di tutto, sistemi di controllo di bordo per oggetti militari (navi, aerei, carri armati, missili, proiettili, ecc.). Gli sviluppatori non avevano il compito di creare un linguaggio universale, pertanto le decisioni prese dagli autori di Ada devono essere percepite nel contesto delle caratteristiche dell'area tematica selezionata. Il linguaggio prende il nome da Ada Lovelace. Studi condotti all'inizio e alla metà degli anni '70 hanno dimostrato che se il Pentagono utilizza un unico linguaggio di programmazione per risolvere tutti i suoi problemi anziché circa 450 lingue e i loro dialetti, sarà possibile ottenere enormi risparmi sui costi ( circa 24 miliardi di dollari per il periodo dal 1983 al 1999). Il linguaggio di Ada si basa sulle idee di programmazione strutturale e fornisce supporto per lo sviluppo di complessi programmi multi-modulo, un alto grado di indipendenza e portabilità della macchina. Durante la progettazione del linguaggio, l'attenzione era principalmente sull'affidabilità e efficienza - il linguaggio è stato creato appositamente per lo sviluppo di grandi dimensioni sistemi software in tempo reale per sistemi embedded con requisiti di alta affidabilità.

Caratteristiche

Ada è un linguaggio di programmazione strutturale, modulare e orientato agli oggetti che contiene strumenti di programmazione di alto livello per processi paralleli. La sintassi di Ada è ereditata da lingue come Algol o Pascal, ma espansa e resa anche più rigorosa e logica. Ada è un linguaggio fortemente tipizzato, esclude il lavoro con oggetti che non hanno tipi e le conversioni automatiche dei tipi sono ridotte al minimo assoluto.

Funzioni di sintassi

  1. I programmi sono modulari, il meccanismo per controllare l'importazione / esportazione delle descrizioni tra i moduli include due direttive diverse: una per collegare un altro modulo (con), l'altra per importare le sue descrizioni (uso). È anche possibile rinominare un modulo durante l'importazione (rinomina): questa opzione consente di utilizzare identificatori più convenienti per un programmatore per indicare un pacchetto.
  2. I pacchetti (uno dei tipi di moduli) possono contenere un'intestazione e una parte personale: ciò che è contenuto non viene esportato e non è disponibile per altri moduli.
  3. È supportato il meccanismo di moduli generalizzati (personalizzabili): pacchetti, procedure e funzioni che consentono di descrivere algoritmi di elaborazione dati generalizzati senza specificare un tipo specifico.
  4. Un sistema di tipo avanzato, sia integrato che generato dal programmatore. Esistono molti modi per creare nuovi tipi, la lingua supporta due concetti diversi: "sottotipo" e "tipo derivato". Le variabili di tipo e sottotipo sono compatibili, mentre il tipo e le variabili di tipo derivato non lo sono.
  5. Mezzi avanzati di accesso a procedure e funzioni: sono supportati i parametri di input e output, la trasmissione di parametri effettivi in \u200b\u200bun ordine arbitrario con nomi formali, parametri con valori predefiniti.
  6. È supportata la ridefinizione di procedure, funzioni e operatori: la creazione di diverse varianti di una procedura, funzione o operatore con lo stesso nome, ma con firme diverse (tipi e numero di parametri).
  7. Costrutti costruttivi di supporto integrati nel linguaggio: sono supportati i concetti di "compito" (frammento eseguibile parallelo del programma), "input del compito" (mezzi di sincronizzazione e comunicazione di compiti paralleli), il meccanismo di "rendezvous" (protocollo per l'interazione di compiti paralleli attraverso l'ingresso di uno di essi è supportato) ), esiste un operatore di selezione SELECT per organizzare l'interazione condizionale tra flussi (scegliendo un'attività parallela con cui interagire, in base alla disponibilità all'appuntamento e ad alcune altre condizioni).

Le grammatiche senza contesto delle lingue Ada-83 e Ada-95 sono definite usando la variante BNF, in cui vengono aggiunte designazioni di ripetizioni e parti opzionali. I nomi dei non terminali sono scritti in caratteri regolari usando un trattino basso se il nome è composto e le parole riservate in grassetto. Dal momento che né parentesi né parentesi graffe vengono utilizzate nell'inferno, né viene utilizzato il segno "|" (tutti questi sono metacaratteri), non viene fornita una designazione speciale per i terminali. La definizione della sintassi dell'istruzione if, presa dallo standard Ada-95, è simile alla seguente:

If_statement :: \u003d if condition then sequence_of_statements (elsif condition then sequence_of_statements) termina se;

Una caratteristica interessante e utile: le regole sintattiche delle costruzioni strutturali sono presentate nella forma corrispondente alla loro formattazione raccomandata nei programmi (divisione in linee, rientri).

Per soddisfare i requisiti di affidabilità, il linguaggio è strutturato in modo tale da rilevare il maggior numero possibile di errori in fase di compilazione. Inoltre, uno dei requisiti per lo sviluppo della lingua era la più facile leggibilità dei testi dei programmi, anche a scapito della facilità di scrittura. Il risultato di questo approccio è una sintassi un po '"pesante" e molte limitazioni che sono assenti nei linguaggi industriali più comuni (C e C ++) e spesso percepite dai programmatori professionisti come ridondanti, ad esempio la stessa rigida tipizzazione. Ciò portò alla formazione dell'idea dell'inferno come linguaggio complesso, oscuro e scomodo da usare.

Programma campione del mondo infernale di Ada

con Ada.Text_IO; procedura Hello è utilizzare Ada.Text_IO; inizia Put_Line ("Ciao, mondo!"); fine Ciao;

Definizione di Kobol e sintassi PL / 1

Cobol (COBOL, COmmon Linguaggio orientato al business), un linguaggio di programmazione di terza generazione (la prima versione nel 1959), destinato principalmente allo sviluppo di applicazioni aziendali. Lo sviluppatore del primo standard unificato di Kobol fu Grace Hopper (la nonna di Kobol). Nel 1997, circa 240 miliardi di righe di codice su Kobol furono utilizzate attivamente. Circa il 90% delle transazioni finanziarie nel mondo viene elaborato tramite codice su Kobol e il 75% del trattamento dei dati commerciali è scritto su Kobol. Il valore totale del codice Kobolovsky attualmente utilizzato è stimato a $ 2 trilioni. Fino ad ora, miliardi di nuove righe di codice vengono scritte ogni anno su Kobol.

Un sistema di notazione particolare, che è un esempio di notazioni precedenti, è stato usato nella descrizione delle lingue Kobol e PL / 1. Ecco un esempio: definire il formato del verbo MOVE in Kobol:


Le parole di servizio sono sottolineate, le parentesi quadre indicano parti opzionali del disegno e le parentesi graffe indicano la scelta di diverse alternative scritte in una colonna. La ripetizione, come si può vedere, è indicata da un'ellissi. Equazioni dello stesso tipo sono state utilizzate per definire i linguaggi di gestione del database.

Caratteristiche del linguaggio Kobol

  1. Ingombrante, prolisso
  2. Buoni e moderni strumenti per lavorare con strutture e file di dati, che gli hanno fornito una lunga vita nelle applicazioni aziendali (almeno negli Stati Uniti).
  3. Fornisce un registro chiaro e abbastanza compatto di algoritmi in una forma indipendente da macchine specifiche progettate per risolvere i problemi.
  4. Contiene un gran numero di squadre, che sono complessi complessi di routine tipiche che forniscono soluzioni ai problemi economici pianificati.

Esempio di programma "Hello world" su Kobol

DIVISIONE IDENTIFICAZIONE. PROGRAMMA-ID. CIAO MONDO. * DIVISIONE AMBIENTALE. * DIVISIONE DATI. * DIVISIONE PROCEDURA. PARA-1. DISPLAY "Ciao, mondo". * ESCI DAL PROGRAMMA.

PL / 1- (PL / I, Linguaggio di programmazione I - "Linguaggio di programmazione numero uno") - un linguaggio di programmazione sviluppato nel 1964, progettato per l'elaborazione scientifica, ingegneristica e orientata al business. Contiene una gamma così ampia di costruzioni sintattiche e funzioni integrate che, probabilmente, non esiste un solo compilatore che supporti tutte le funzionalità del linguaggio PL / 1. PL / 1 supporta la ricorsione e programmazione strutturalee il suo principale campo di applicazione è l'elaborazione dei dati

Proprietà di base di PL / 1

  1. Sintassi libera
  2. Parole chiave e identificatori non fanno distinzione tra maiuscole e minuscole
  3. Per impostazione predefinita (nelle versioni classiche del mainframe - sempre) passando i parametri per riferimento
  4. Supporto per strutture complesse con associazioni (nella terminologia di Pascal - record con varianti)
  5. Un sistema estremamente sviluppato di tipi di dati integrati, con la possibilità di conversioni implicite tra la maggior parte di essi
  6. Diversi tipi di allocazione dinamica della memoria
  7. Operatori molto generalizzati con molte varianti di sintassi
  8. Semantica rigorosamente definita delle strutture di controllo
  9. Operazioni su array
  10. Sviluppato meccanismo dello stato di eccezione
  11. Supporto per multitasking e I / O asincrono
  12. Supporto a livello di lingua per metodi di accesso I / O complessi
  13. Un preprocessore molto sviluppato, che a sua volta è in realtà un sottoinsieme di PL / 1

Esempio di programma "Hello world" su PL / 1

Test: opzioni di procedura (principale); dichiarare l'inizializzazione variabile My_String (20) ("Ciao, mondo!"); mettere skip list (My_String); test finale;

Alfabeto della lingua

L'alfabeto iniziale PL / 1 includeva 60 caratteri:

$ @ # A B C D E F G H I J K L M N O P Q R S T U V W X Y Z 0 1 2 3 4 5 6 7 8 9 \u003d + - * / () ,. "% ;: ¬ & |\u003e< _ ? пробел

È stato anche possibile lavorare con un alfabeto di 48 caratteri più limitato, che non includeva:

@ # ; : ¬ & | > < _ ? -

Invece di caratteri mancanti, sono state utilizzate parole chiave aggiuntive. Nelle versioni moderne della lingua, è anche possibile utilizzare lettere latine minuscole (le parole chiave possono essere scritte sia in maiuscolo che in minuscolo). Invece del carattere ¬ (negazione) che non si trova nel set di caratteri portatile, usa ~.

Letteratura

  1. Sverdlov S.Z. Linguaggi di programmazione e metodi di traduzione: Guida allo studio. - SPb.: Peter, 2007 .-- 638 p .: Ill.

LA CAMPANA

C'è chi legge questa notizia prima di te.
Iscriviti per ricevere articoli freschi.
E-mail
Nome
Cognome
Come vuoi leggere The Bell
Niente spam