11. Reguljära uttryck och grammatiker

Objektorienterad modellering och diskreta strukturer
11. Reguljära uttryck och grammatiker
Sven Gestegård Robertz
Datavetenskap, LTH
2015
Rekaputilation
Vi har talat om
I
satslogik och härledning
I
predikatlogik och substitution
I
mängder och språk
I
reguljära uttryck
Vi kommer att studera
I
reguljära uttryck och deras begränsning
I
grammatiker
Rekapitulation
11. Reguljära uttryck och grammatiker
2/36
Alfabeten, strängar och språk
Ett
En
alfabet
sträng
Med ett
Rekapitulation
är en ändlig icketom mängd
symboler
.
på ett alfabet är en ändlig följd av symboler ur alfabetet.
språk
på ett alfabet menas en mängd strängar på alfabetet.
11. Reguljära uttryck och grammatiker
3/36
Operationer på språk
Konkatenering
M
M
L1 ◦ L2 = L1 L2 = {u ◦ v | u ∈ L1 ∧ v ∈ L2 }
Lk : konkateneringen av exakt k strängar ur L
M
L0 = {}
M
Lk+1 = L ◦ Lk
Kleene-stjärna, hölje
∗ M
L =
∞
[
Lk
k=0
Rekapitulation
11. Reguljära uttryck och grammatiker
4/36
Exempel
(0 | 1)?
betecknar språket av alla binära strängar.
L[(0 | 1)? ] = (L[(0 | 1)])? = (L[0] ∪ L[1])? = ({0} ∪ {1})? =
{0, 1}? = {, 0, 1, 00, 01, 10, 11, 000, . . .}.
Exempel
(0 | (1 (0 | 1)? ))
beskriver språket av alla binära strängar utan extra inledande nollor,
{0, 1, 10, 11, 100, . . .}
Exempel
Språket
i i
ab |i≥0
är inte reguljärt
Reguljära uttryck : Exempel
11. Reguljära uttryck och grammatiker
10/36
Exempel: Reguljära uttryck och maskiner
a ( (bc)*d) | ef* ) accepteras av
Det reguljära uttrycket
en tillståndsmaskin
start
q0
b
a
c
q1
q2
q3
b
e
d
q5
d
q4
f
Ett språk är reguljärt omm det kan accepteras av en nit
tillståndsmaskin.
Reguljära uttryck : Finita tillståndsmaskiner och reguljära uttryck
11. Reguljära uttryck och grammatiker
11/36
an b n
är inte reguljärt
Sats
För ett reguljärt språk,
L,
∀n . an bn ∈ L → ∃m 6= n . am bn ∈ L
Bevis.
Låt M vara en nit maskin sådan at L(M ) = L, och
p vara antal tillstånd i maskinen
Då gäller ∀n . an bn ∈ L → ∃k . ak bk ∈ L ∧ k > p
Om |ak | > p så måste det nnas en cykel i M som passeras mer än
en gång när ak accepteras.
Låt j vara längden på cykeln. Då måste även ak+j bk ∈ L. (Ett
extra varv i cykeln)
Reguljära uttryck : Finita tillståndsmaskiner och reguljära uttryck
11. Reguljära uttryck och grammatiker
12/36
Pumplemmat
För ett alfabet Σ gäller
∀L ⊆ Σ∗ . Regular(L) →
∃p ≥ 1 . ∀w ∈ L . |w| ≥ p →
∃x, y, z ∈ Σ∗ . w = xyz ∧ |y| ≥ 1 ∧ |xy| ≤ p∧
∀i ≥ 0 . xy i z ∈ L
→, nödvändigt men ej tillräckligt villkor, omvändningen gäller inte
för en sträng w, |w| = p
...
y
start
q0
...
x
Reguljära uttryck : Finita tillståndsmaskiner och reguljära uttryck
q
...
qp
z
11. Reguljära uttryck och grammatiker
13/36
Pumplemmat, bevisskiss
1
2
3
4
5
6
För varje reguljärt språk nns det en nit tillståndsmaskin
(FSA) som accepterar språket
Låt p vara antalet tillstånd i en sådan maskin
För en sträng, w, sådan att |w| = p, låt q0 vara starttillståndet
och q1 , . . . , qp vara tillstånden som passeras när w accepteras.
Eftersom maskinen endast har p tillstånd måste det i denna
följd av p + 1 tillstånd nnas något tillstånd som förekommer
mer än en gång.
Låt q vara ett sådant tillstånd. Tillståndsöverångarna som tar
maskinen från första gången den är i q till nästa gång q
passeras utgör någon sträng. Kalla den y .
Maskinen kommer att acceptera en sträng som inte innehåller
y som delsträng, och strängar som har y , upprepad ett
godtyckligt antal gånger, som delsträng.
Reguljära uttryck : Finita tillståndsmaskiner och reguljära uttryck
11. Reguljära uttryck och grammatiker
14/36
Reguljära uttryck: Utvidgad notation
M
DIGIT = [0 − 9]
M
NAT = DIGIT+
M
INT = (−)?NAT
M
FLOAT = INT . NAT
Namn får inte användas rekursivt.
Reguljära uttryck : Finita tillståndsmaskiner och reguljära uttryck
11. Reguljära uttryck och grammatiker
15/36
Reguljära uttryck enligt POSIX
Syntax för de grundläggande delarna i reguljära uttryck så som de
skrivs i Java och verktyg som grep, sed, awk m. .
symbol
-----.
[ ]
[^ ]
^
$
*
{n}
{n,m}
matchar
-------------------------------------------------------------------ett godtyckligt tecken (utom radbrytningar).
ett av tecknen inom klamrarna.
ett tecken som inte finns mellan klamrarna.
början av en sträng. I radbaserade verktyg, första tecknet på en rad.
slutet av en sträng eller eller (tecknet före) en radbrytning.
föregående ellement noll eller fler gånger.
föregående element n gånger
föregående element minst n, max m gånger
Kommentarer:
* är en kortform för {0,} : noll eller flera
+ är en kortform för {1,} : en eller flera
? är en kortform för {0,1} : noll eller ett
.* matchar alla strängar
Reguljära uttryck : Exempel på användning i Java och POSIX
11. Reguljära uttryck och grammatiker
16/36
Reguljära uttryck med Java
java.util.regex
boolean b = Pattern.matches("a*b", "aaaaab");
Pattern p = Pattern.compile("a*b");
Matcher m = p.matcher("aaaaab");
boolean b = m.matches();
Reguljära uttryck : Exempel på användning i Java och POSIX
11. Reguljära uttryck och grammatiker
17/36
java.util.Scanner
Ett agrant brott mot principen om enkelt ansvar.
public final class Scanner implements Iterator<String>
public Scanner(Readable source)
public Scanner(InputStream source)
public Scanner(InputStream source, String charsetName)
public Scanner(File source)
public Scanner(File source, String charsetName)
public Scanner(String source)
public Scanner(ReadableByteChannel source)
public Scanner(ReadableByteChannel source, String charsetName)
public void close()
public IOException ioException()
public Pattern delimiter()
public Scanner useDelimiter(Pattern pattern)
public Scanner useDelimiter(String pattern)
public Locale locale()
public Scanner useLocale(Locale locale)
public int radix()
public Scanner useRadix(int radix)
public MatchResult match()
public String toString()
public boolean hasNext()
public String next()
public void remove()
public boolean hasNext(String pattern)
public String next(String pattern)
public boolean hasNext(Pattern pattern)
public String next(Pattern pattern)
public boolean hasNextLine()
public String nextLine()
public :String
findInLine(String
pattern)
Reguljära uttryck
Exempel
på användning i Java
och POSIX
11. Reguljära uttryck
och grammatiker
18/36
java.util.Scanner
public String findWithinHorizon(String pattern, int horizon)
public String findWithinHorizon(Pattern pattern, int horizon)
public Scanner skip(Pattern pattern)
public Scanner skip(String pattern)
public boolean hasNextBoolean()
public boolean nextBoolean()
public boolean hasNextByte()
public boolean hasNextByte(int radix)
public byte nextByte()
public byte nextByte(int radix)
public boolean hasNextShort()
public boolean hasNextShort(int radix)
public short nextShort()
public short nextShort(int radix)
public boolean hasNextInt()
public boolean hasNextInt(int radix)
public int nextInt()
public int nextInt(int radix)
public boolean hasNextLong()
public boolean hasNextLong(int radix)
public long nextLong()
public long nextLong(int radix)
public boolean hasNextFloat()
public float nextFloat()
public boolean hasNextDouble()
public double nextDouble()
public boolean hasNextBigInteger()
public boolean hasNextBigInteger(int radix)
public BigInteger nextBigInteger()
public BigInteger nextBigInteger(int radix)
public :boolean
Reguljära uttryck
ExempelhasNextBigDecimal()
på användning i Java och POSIX
11. Reguljära uttryck
och grammatiker
19/36
Grammatik
Reguljära uttryck klarar inte av att beskriva t ex. mängden av
aritmetiska uttryck.
Om vi tillåter att man sätter namn på reguljära uttryck och
använder dessa rekursivt kan vi beskriva språk med mer
komplicerad struktur.
Grammatiker
11. Reguljära uttryck och grammatiker
20/36
Grammatik för
S
T
T
U
an bn
::= T
::= {}
::= U
:= 'a' T 'b'
Grammatiken kan skrivas
kompaktare (men kanske inte
läsbarare), tex:
S ::= 'a' S 'b' | {}
där {} beteckar tomma strängen
Exempel: härledning av strängen aaabbb
S ⇒ T ⇒ U ⇒
'a' T 'b' ⇒ 'a' U 'b' ⇒
'a' 'a' T 'b' 'b' ⇒ 'a' 'a' U 'b' 'b' ⇒
'a' 'a' 'a' T 'b' 'b' 'b' ⇒ 'a' 'a' 'a' 'b' 'b' 'b'
Grammatiker
11. Reguljära uttryck och grammatiker
21/36
Grammatik för aritmetiska uttryck
I
Ett uttryck består av en eller era
plus- eller minus-tecken.
I
En term består i sin tur av en eller era faktorer separerade av
enkla multiplikations- eller divisions- tecken.
I
En faktor är ett
parenteser.
Grammatiker
, en
tal
variabel
termer
eller ett
separerade av enkla
uttryck
inom
11. Reguljära uttryck och grammatiker
22/36
BNF-grammatik
BackusNaur-form
expr ::= term (addop term)*
term ::= factor (mulop factor)*
factor ::= NUMBER | NAME | '(' expr ')'
addop ::= '+' | '-'
mulop ::= '*' | '/'
M
G = (N, Σ, R, S)
Grammatiker
11. Reguljära uttryck och grammatiker
23/36
Begrepp
syntaxsymboler (icke terminalsymboler, nonterminal symbols)
M
N = {expr, term, factor, addop, mulop}
slutsymboler, (terminalsymboler, terminal symbols)
M
Σ = {+, -, *, /, (, ), NUMBER, NAME}
produktioner,
R = {expr ::= term (addop term)∗, . . .}
startsymbol,
M
S = expr
M
G = (N, Σ, R, S)
Grammatiker
11. Reguljära uttryck och grammatiker
24/36
Som i Algol 60 Report
Markera icketerminalsymboler (med < >) i stället för
terminalsymboler.
<expr> ::= <term> (<addop> <term>)*
<term> ::= <factor> (<mulop> <factor>)*
<factor> ::= NUMBER | NAME | ( <expr> )
<addop> ::= + | <mulop> ::= * | /
Exempel
Härledning av 1 + x
Grammatiker
11. Reguljära uttryck och grammatiker
25/36
Härledning
expr ⇒ term addop term ⇒
factor addop term ⇒
NUMBER addop term ⇒
NUMBER addop term ⇒
NUMBER + term ⇒
NUMBER + factor ⇒
NUMBER + NAME
expr
Grammatiker : Härledning och syntaxanalys
⇒∗
NUMBER + NAME
11. Reguljära uttryck och grammatiker
26/36
L[G]
Låt G vara en grammatik
M
G = (N, Σ, R, S)
Denition
Språket som
genereras
av grammatiken G är
M
L[G] = {w ∈ Σ∗ | S ⇒∗ w}
Grammatiker : Härledning och syntaxanalys
11. Reguljära uttryck och grammatiker
27/36
Härledning för en enkel grammatik
expr ::= expr'+'expr
expr ::= expr'*'expr
expr ::= IN T
Härledning av INT + INT * INT.
expr =>
expr + expr =>
expr + expr * expr =>
INT + expr * expr =>
INT + INT * expr =>
INT + INT * INT
Grammatiker : Härledning och syntaxanalys
Härledningsträd
expr
/ |
\
expr
+
expr
|
/ | \
INT
expr *
expr
|
|
INT
INT
11. Reguljära uttryck och grammatiker
28/36
En annan härledning
expr ::= expr'+'expr
expr ::= expr'*'expr
expr ::= IN T
Härledning av INT + INT * INT.
expr =>
expr * expr =>
expr + expr * expr =>
INT + expr * expr =>
INT + INT * expr =>
INT + INT * INT
Grammatiker : Härledning och syntaxanalys
Härledningsträd
expr
/ | \
expr
*
expr
/ | \
|
expr + expr
INT
|
|
INT
INT
11. Reguljära uttryck och grammatiker
29/36
Tvetydig grammatik
En grammatik är tvetydig om det nns mer än ett härledningsträd
för någon sträng i språket.
Om en grammatik är tvetydig måste man försöka hitta en
grammatik som inte är det och som genererar samma språk. I det
aktuella fallet vill man ha en grammatik som respekterar gängse
precedens för operatorerna.
Grammatiker : Härledning och syntaxanalys
11. Reguljära uttryck och grammatiker
30/36
Syntaxanalys av aritmetiska uttryck
expr ::= term (addop term)*
term ::= factor (mulop factor)*
factor ::= ID | INT | '(' expr ')'
addop ::= '+' | '-'
mulop ::= '*' | '/'
Härledning av INT + INT * INT.
expr =>
term + term =>
term + factor * factor =>
factor + factor * factor =>
factor + INT * factor =>
factor + INT * INT
INT + INT * INT
Grammatiker : Härledning och syntaxanalys
Härledningsträd
expr
/ | \
term +
term
|
/ | \
factor factor * factor
|
|
|
INT
INT
INT
11. Reguljära uttryck och grammatiker
31/36
Syntaxanalys av en faktor
f a c t o r : : = ID | INT |
private
Expr
switch
factor ()
( token )
case
:
name =
=
token
new
V a r i a b l e ( name ) ;
number
=
return
'( '
:
=
scanner . token ( ) ;
s c a n n e r . nextToken ( ) ;
I n t e g e r . p a r s e I n t ( number ) ;
:
token
Expr
scanner . token ( ) ;
s c a n n e r . nextToken ( ) ;
S c a n n e r . INT
String
case
{
S c a n n e r . ID
return
case
') '
{
String
token
'( ' expr
=
e
token
return
s c a n n e r . nextToken ( ) ;
=
=
expr ( ) ;
//
Check
that
t o k e n == ') '
s c a n n e r . nextToken ( ) ;
e ;
}
}
Grammatiker : Härledning och syntaxanalys
11. Reguljära uttryck och grammatiker
32/36
Syntaxanalys av en term
term : : = f a c t o r ( mulop f a c t o r ) ∗
private
Expr
Expr
term ( )
result ,
result
while
=
factor ();
( token
int
{
factor ;
op
token
factor
switch
=
=
==
'
∗'
||
token
==
'/ ')
{
token ;
s c a n n e r . nextToken ( ) ;
=
factor ();
( op )
case
'
∗'
{
:
result
= new
Mul ( r e s u l t ,
factor );
= new
Div ( r e s u l t ,
factor );
break ;
case
'/ '
:
result
break ;
}
}
return
result ;
}
Grammatiker : Härledning och syntaxanalys
11. Reguljära uttryck och grammatiker
33/36
Delar av BNF-grammatik för Java
CompilationU nit
::=
[P ackageDecl](ImportDecl)∗ (T ypeDecl)∗
P ackageDeclaration
::=
'package'N ame';'
ImportDeclaration
::=
'import'N ame ["." '*']';'
T ypeDecl
::=
ClassDecl | Interf aceDecl | ';'
ClassDecl
::=
("abstract" | 'nal' | "public")∗ CleanClassDecl
CleanClassDecl
::=
'class'ID["extends" N ame]
ClassBody
::=
'{'(ClassBodyDecl)∗ '}'
N ame
::=
ID("." ID)∗
N ameList
::=
N ame("," N ame)∗
["implements" N ameList]ClassBody
...
...
Around 100 nonterminals and 200 rules
Grammatiker : Härledning och syntaxanalys
11. Reguljära uttryck och grammatiker
34/36
Kompilatorer
I
Lexikalanalys - Reguljära uttryck och automater
I
Syntaxanalys - Recursive descent och LR-parsing
I
Semantisk analys - Namn- och typkontroll
I
Interpretering
I
Kodgenerering
I
d v s Bygg en egen kompilator
I
Vertyg: javacc, jastadd, ddd
Kursen är valbar.
Grammatiker : Härledning och syntaxanalys
11. Reguljära uttryck och grammatiker
35/36
Sammanfattning
Vi har talat om
I
reguljära uttryck
I
grammatiker
Nästa föreläsning
I
relationer
I
funktioner
I
laboration 3: syntaxanalys (parsing)
Grammatiker : Härledning och syntaxanalys
11. Reguljära uttryck och grammatiker
36/36