The Extended Backus – Naur Form ( EBNF ) är ett formellt syntaxdefinitionssystem där vissa syntaktiska kategorier definieras sekventiellt genom andra . Används för att beskriva kontextfria formella grammatiker . Föreslagen av Niklaus Wirth . Det är en utökad bearbetning av Backus-Naur-formerna , skiljer sig från BNF i mer "rymliga" konstruktioner, som med samma uttrycksförmåga gör det möjligt att förenkla och reducera beskrivningen i volym.
Men många olika varianter av RBNF används. International Organization for Standardization har antagit RBNF-standarden: ISO/IEC 14977 [1] .
Liksom i BNF är en grammatikbeskrivning i RBNF en uppsättning regler som definierar relationer mellan terminalsymboler (terminaler) och icke-terminala symboler (icke-terminaler).
Regeln i RBNF är:
идентификатор = выражение.
där identifieraren är namnet på en icke-terminal symbol, och uttrycket är en kombination av terminala och icke-terminala symboler och specialtecken som överensstämmer med RBNF-reglerna. Punkten i slutet är ett specialtecken som indikerar slutet på regeln.
Semantiken för RBNF-regeln är att det icke-terminala tecknet som anges av identifieraren till vänster om likhetstecknet är en kombination av terminala och icke-terminala tecken som definieras av ett uttryck .
En fullständig grammatikbeskrivning är en uppsättning regler som sekventiellt definierar alla icke-terminala symboler i grammatiken så att varje icke-terminal symbol kan reduceras till en kombination av terminalsymboler genom successiv (rekursiv) tillämpning av reglerna. Det finns inga särskilda regler i definitionen av RBNF angående i vilken ordning reglerna skrivs, även om sådana föreskrifter kan införas när man använder RBNF av mjukvaruverktyg som ger automatisk generering av parsers från en grammatikbeskrivning.
Uppsättningen av möjliga RBNF-konstruktioner är mycket liten. Dessa är sammanlänkning, urval, villkorad förekomst och upprepning.
Eller allt ovanstående kort och gott:
Vissa verk innehåller modifierade varianter av RBNF-syntaxen.
— En regel som specificerar grammatiken för den villkorliga operatorn för Modula-2- språket , där "Villkorlig operator" och "Group of operators" är icke-terminala symboler med sammansatta namn.
Den allmänna formen av en EBNF-beskrivningsgrammatik kan beskrivas som EBNF enligt följande:
Syntax = { SynthOperator }. SynthOperator = Identifier "=" SynthExpression "." . SyntExpression = SynTerm { "|" SinTerm }. SynTerm = SyntFactor { SyntFactor }. SynthFactor = identifierare | kedja | "(" SynthExpression ")" | "[" SynthExpression "]" | "{" SynthExpression "}" .Denna beskrivning förutsätter att identifierare och sträng är fördefinierade termer. Om så önskas är det inte svårt att skriva deras definition i RBNF, för detta behöver du bara ange ett visst alfabet och, om nödvändigt, ytterligare begränsningar för typen av identifierare.
Följande grammatiker definierar notationen av ett allmänt decimaltal (med ett inledande tecken, en möjlig bråkdel och en exponent) och en typisk programmeringsspråksidentifierare (en sekvens av bokstäver, siffror och understreck som börjar med en bokstav).
Tal = [ "+" | "-" ] NatNumber [ "." [ NatNumber ]][( "e" | "E" )[ "+" | "-" ] NatNumber ]. NatNumber = Siffra { Siffra }. Siffra = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" . Ident = Bokstav { Bokstav | Siffra | "_" }.Definitionen av den icke-terminala bokstaven ges inte här på grund av självklarhet och krånglighet - den representerar ett val från det accepterade alfabetet.
Likheterna och skillnaderna mellan BNF och RBNF framgår av beskrivningen. Skillnaden består i stort sett i två huvudpunkter:
Det kan finnas olika åsikter om framgången eller misslyckandet med den första förändringen, men i vilket fall som helst påverkar det inte formens uttrycksmöjligheter. Men den andra innovationen är mycket betydelsefull. Det tillför inte heller i grunden nya uttrycksmöjligheter (allt som skrivs i RBNF kan skrivas adekvat i vanlig BNF), men det minskar och förenklar notationen avsevärt.
Den största fördelen med RBNF framför BNF är förmågan att beskriva enkla upprepande konstruktioner av obestämd längd (listor, strängar, sekvenser, och så vidare) utan rekursiva regler. Frånvaron av upprepningskonstruktionen i BNF leder till det faktum att varje upprepning måste definieras genom att införa ytterligare mellanliggande icke-terminala symboler och rekursiva regler, vilket gör definitionen för stor och oklar. Beskrivningen av upprepningar i EBNF visar sig vara både kortare och mer bekväm för människans uppfattning.
Som ett exempel, betrakta reglerna som definierar den icke-terminala "listan", som är en uppsättning av noll till valfritt antal identifierare separerade med kommatecken (förutsatt att tecknen "RightBracket", "LeftBracket", "Comma" och "Ident " är redan definierade).
Definitionen i RBNF innehåller bara en regel:
List = LeftBracket [ Ident { Comma Ident }] HögerBracket .Definitionen i BNF ser ut så här:
<List> ::= <LeftBracket> <RightBracket> | <LeftBracket> <IdentList> <RightBracket> <IdentList> ::= <Ident> | <Ident> <Komma> <IdentList>Redan från detta exempel är skillnaderna mellan formerna synliga:
Naturligtvis är priset för fördelarna med RBNF framför BNF den större komplexiteten i automatisk tolkning av RBNF-beskrivningar. Formella grammatikparsergeneratorer som använder BNF är enklare än de som använder RBNF.
RBNF är ekvivalenta med en underklass av syntaxdiagram som används allmänt för att beskriva grammatik. Vilken RBNF-grammatik som helst kan representeras på ett adekvat sätt av ett syntaxdiagram, men i allmänhet låter syntaxdiagram dig skapa beskrivningar som inte kan representeras i RBNF (eller i alla fall inte kan översättas till RBNF direkt utan att först konvertera den grafiska beskrivningen) .
RBNF, liksom sin föregångare, BNF, används extremt flitigt som ett sätt att beskriva konstgjorda språk, främst programmeringsspråk och relaterade notationssystem. I synnerhet använde uppfinnaren av RBNF, Niklaus Wirth, denna formalism i sina böcker för att beskriva alla programmeringsspråk som övervägdes där.
Den högre komplexiteten hos RBNF jämfört med BNF leder till att det finns betydligt färre parsergeneratorer baserade på RBNF än de baserade på BNF. Men de finns och gäller. RBNF är grunden för Spirit C++ Parser Framework, Coco/R, SLK Parser Generator och några andra. För användning i sådana system utökas RBNF-syntaxen i samma riktning som BNF-syntaxen när man använder yacc- eller bison -parsergeneratorerna - koden som bearbetar den infogas direkt i grammatikbeskrivningen, och interaktionen med den lexikala analysatorn är på något sätt organiserad . Ytterligare restriktioner kan också läggas på reglernas struktur - inte alla regler som kan beskrivas i RBNF kan effektivt omvandlas till kod.
De absoluta fördelarna med RBNF inkluderar enkelhet (RBNF-språket i sig innehåller endast 10 specialtecken - tre typer av parenteser, en vertikal stapel, ett likhetstecken och citattecken, eventuellt ett kommatecken; dess syntax bestäms av fem regler), tillräcklig kraft och synlighet, vilket gör det bekvämt att göra beskrivningar avsedda inte bara för automatisk tolkning, utan också för mänsklig läsning. RBNF-konstruktionernas närhet till syntaktiska diagram gör det möjligt att dra de senare direkt från RBNF-beskrivningen.
Nackdelarna med RBNF, liksom för BNF, inkluderar det faktum att de beskriver den grammatiska strukturen i ett formellt språk utan att ta hänsyn till kontextuella beroenden, vilket innebär att i närvaro av sådana beroenden visar sig RBNF-beskrivningen vara ofullständig. , och vissa syntaxregler för det beskrivna språket måste anges i normal textform. Detta leder till att text som exakt matchar RBNF-grammatiken fortfarande kan vara syntaktisk felaktig. Till exempel, i en RBNF-grammatik är det inte möjligt att naturligt representera det faktum att en operation kräver operander av samma typ. Sådana kontroller måste utföras med handskriven grammatikanalyskod. Å andra sidan visar sig grammatikbeskrivningssystem som inkluderar definitionen av kontextberoenden, till exempel van Wiingaardens grammatik , vara mycket mer komplicerade, och deras användning för automatisk generering av parsers visar sig vara svår.