Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
G
golang
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
go
golang
Commits
7de610cc
Commit
7de610cc
authored
Mar 31, 2010
by
Rob Pike
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
regexp: use panic/recover to handle errors
R=rsc, gri CC=golang-dev
https://golang.org/cl/821046
parent
63e878a7
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
50 additions
and
72 deletions
+50
-72
regexp.go
src/pkg/regexp/regexp.go
+50
-72
No files found.
src/pkg/regexp/regexp.go
View file @
7de610cc
...
@@ -33,18 +33,25 @@ import (
...
@@ -33,18 +33,25 @@ import (
var
debug
=
false
var
debug
=
false
// Error is the local type for a parsing error.
type
Error
string
func
(
e
Error
)
String
()
string
{
return
string
(
e
)
}
// Error codes returned by failures to parse an expression.
// Error codes returned by failures to parse an expression.
var
(
var
(
ErrInternal
=
os
.
New
Error
(
"internal error"
)
ErrInternal
=
Error
(
"internal error"
)
ErrUnmatchedLpar
=
os
.
New
Error
(
"unmatched '('"
)
ErrUnmatchedLpar
=
Error
(
"unmatched '('"
)
ErrUnmatchedRpar
=
os
.
New
Error
(
"unmatched ')'"
)
ErrUnmatchedRpar
=
Error
(
"unmatched ')'"
)
ErrUnmatchedLbkt
=
os
.
New
Error
(
"unmatched '['"
)
ErrUnmatchedLbkt
=
Error
(
"unmatched '['"
)
ErrUnmatchedRbkt
=
os
.
New
Error
(
"unmatched ']'"
)
ErrUnmatchedRbkt
=
Error
(
"unmatched ']'"
)
ErrBadRange
=
os
.
New
Error
(
"bad range in character class"
)
ErrBadRange
=
Error
(
"bad range in character class"
)
ErrExtraneousBackslash
=
os
.
New
Error
(
"extraneous backslash"
)
ErrExtraneousBackslash
=
Error
(
"extraneous backslash"
)
ErrBadClosure
=
os
.
New
Error
(
"repeated closure (**, ++, etc.)"
)
ErrBadClosure
=
Error
(
"repeated closure (**, ++, etc.)"
)
ErrBareClosure
=
os
.
New
Error
(
"closure applies to nothing"
)
ErrBareClosure
=
Error
(
"closure applies to nothing"
)
ErrBadBackslash
=
os
.
New
Error
(
"illegal backslash escape"
)
ErrBadBackslash
=
Error
(
"illegal backslash escape"
)
)
)
// An instruction executed by the NFA
// An instruction executed by the NFA
...
@@ -252,12 +259,16 @@ func (re *Regexp) add(i instr) instr {
...
@@ -252,12 +259,16 @@ func (re *Regexp) add(i instr) instr {
type
parser
struct
{
type
parser
struct
{
re
*
Regexp
re
*
Regexp
error
os
.
Error
nlpar
int
// number of unclosed lpars
nlpar
int
// number of unclosed lpars
pos
int
pos
int
ch
int
ch
int
}
}
func
(
p
*
parser
)
error
(
err
os
.
Error
)
{
p
.
re
=
nil
panic
(
err
)
}
const
endOfFile
=
-
1
const
endOfFile
=
-
1
func
(
p
*
parser
)
c
()
int
{
return
p
.
ch
}
func
(
p
*
parser
)
c
()
int
{
return
p
.
ch
}
...
@@ -309,8 +320,7 @@ func (p *parser) charClass() instr {
...
@@ -309,8 +320,7 @@ func (p *parser) charClass() instr {
switch
c
:=
p
.
c
();
c
{
switch
c
:=
p
.
c
();
c
{
case
']'
,
endOfFile
:
case
']'
,
endOfFile
:
if
left
>=
0
{
if
left
>=
0
{
p
.
error
=
ErrBadRange
p
.
error
(
ErrBadRange
)
return
nil
}
}
// Is it [^\n]?
// Is it [^\n]?
if
cc
.
negate
&&
cc
.
ranges
.
Len
()
==
2
&&
if
cc
.
negate
&&
cc
.
ranges
.
Len
()
==
2
&&
...
@@ -328,21 +338,18 @@ func (p *parser) charClass() instr {
...
@@ -328,21 +338,18 @@ func (p *parser) charClass() instr {
p
.
re
.
add
(
cc
)
p
.
re
.
add
(
cc
)
return
cc
return
cc
case
'-'
:
// do this before backslash processing
case
'-'
:
// do this before backslash processing
p
.
error
=
ErrBadRange
p
.
error
(
ErrBadRange
)
return
nil
case
'\\'
:
case
'\\'
:
c
=
p
.
nextc
()
c
=
p
.
nextc
()
switch
{
switch
{
case
c
==
endOfFile
:
case
c
==
endOfFile
:
p
.
error
=
ErrExtraneousBackslash
p
.
error
(
ErrExtraneousBackslash
)
return
nil
case
c
==
'n'
:
case
c
==
'n'
:
c
=
'\n'
c
=
'\n'
case
specialcclass
(
c
)
:
case
specialcclass
(
c
)
:
// c is as delivered
// c is as delivered
default
:
default
:
p
.
error
=
ErrBadBackslash
p
.
error
(
ErrBadBackslash
)
return
nil
}
}
fallthrough
fallthrough
default
:
default
:
...
@@ -359,8 +366,7 @@ func (p *parser) charClass() instr {
...
@@ -359,8 +366,7 @@ func (p *parser) charClass() instr {
cc
.
addRange
(
left
,
c
)
cc
.
addRange
(
left
,
c
)
left
=
-
1
left
=
-
1
default
:
default
:
p
.
error
=
ErrBadRange
p
.
error
(
ErrBadRange
)
return
nil
}
}
}
}
}
}
...
@@ -368,28 +374,18 @@ func (p *parser) charClass() instr {
...
@@ -368,28 +374,18 @@ func (p *parser) charClass() instr {
}
}
func
(
p
*
parser
)
term
()
(
start
,
end
instr
)
{
func
(
p
*
parser
)
term
()
(
start
,
end
instr
)
{
// term() is the leaf of the recursion, so it's sufficient to pick off the
// error state here for early exit.
// The other functions (closure(), concatenation() etc.) assume
// it's safe to recur to here.
if
p
.
error
!=
nil
{
return
}
switch
c
:=
p
.
c
();
c
{
switch
c
:=
p
.
c
();
c
{
case
'|'
,
endOfFile
:
case
'|'
,
endOfFile
:
return
nil
,
nil
return
nil
,
nil
case
'*'
,
'+'
:
case
'*'
,
'+'
:
p
.
error
=
ErrBareClosure
p
.
error
(
ErrBareClosure
)
return
case
')'
:
case
')'
:
if
p
.
nlpar
==
0
{
if
p
.
nlpar
==
0
{
p
.
error
=
ErrUnmatchedRpar
p
.
error
(
ErrUnmatchedRpar
)
return
}
}
return
nil
,
nil
return
nil
,
nil
case
']'
:
case
']'
:
p
.
error
=
ErrUnmatchedRbkt
p
.
error
(
ErrUnmatchedRbkt
)
return
case
'^'
:
case
'^'
:
p
.
nextc
()
p
.
nextc
()
start
=
p
.
re
.
add
(
new
(
_Bot
))
start
=
p
.
re
.
add
(
new
(
_Bot
))
...
@@ -405,12 +401,8 @@ func (p *parser) term() (start, end instr) {
...
@@ -405,12 +401,8 @@ func (p *parser) term() (start, end instr) {
case
'['
:
case
'['
:
p
.
nextc
()
p
.
nextc
()
start
=
p
.
charClass
()
start
=
p
.
charClass
()
if
p
.
error
!=
nil
{
return
}
if
p
.
c
()
!=
']'
{
if
p
.
c
()
!=
']'
{
p
.
error
=
ErrUnmatchedLbkt
p
.
error
(
ErrUnmatchedLbkt
)
return
}
}
p
.
nextc
()
p
.
nextc
()
return
start
,
start
return
start
,
start
...
@@ -421,8 +413,7 @@ func (p *parser) term() (start, end instr) {
...
@@ -421,8 +413,7 @@ func (p *parser) term() (start, end instr) {
nbra
:=
p
.
re
.
nbra
nbra
:=
p
.
re
.
nbra
start
,
end
=
p
.
regexp
()
start
,
end
=
p
.
regexp
()
if
p
.
c
()
!=
')'
{
if
p
.
c
()
!=
')'
{
p
.
error
=
ErrUnmatchedLpar
p
.
error
(
ErrUnmatchedLpar
)
return
}
}
p
.
nlpar
--
p
.
nlpar
--
p
.
nextc
()
p
.
nextc
()
...
@@ -434,7 +425,7 @@ func (p *parser) term() (start, end instr) {
...
@@ -434,7 +425,7 @@ func (p *parser) term() (start, end instr) {
ebra
.
n
=
nbra
ebra
.
n
=
nbra
if
start
==
nil
{
if
start
==
nil
{
if
end
==
nil
{
if
end
==
nil
{
p
.
error
=
ErrInternal
p
.
error
(
ErrInternal
)
return
return
}
}
start
=
ebra
start
=
ebra
...
@@ -447,15 +438,13 @@ func (p *parser) term() (start, end instr) {
...
@@ -447,15 +438,13 @@ func (p *parser) term() (start, end instr) {
c
=
p
.
nextc
()
c
=
p
.
nextc
()
switch
{
switch
{
case
c
==
endOfFile
:
case
c
==
endOfFile
:
p
.
error
=
ErrExtraneousBackslash
p
.
error
(
ErrExtraneousBackslash
)
return
case
c
==
'n'
:
case
c
==
'n'
:
c
=
'\n'
c
=
'\n'
case
special
(
c
)
:
case
special
(
c
)
:
// c is as delivered
// c is as delivered
default
:
default
:
p
.
error
=
ErrBadBackslash
p
.
error
(
ErrBadBackslash
)
return
}
}
fallthrough
fallthrough
default
:
default
:
...
@@ -469,7 +458,7 @@ func (p *parser) term() (start, end instr) {
...
@@ -469,7 +458,7 @@ func (p *parser) term() (start, end instr) {
func
(
p
*
parser
)
closure
()
(
start
,
end
instr
)
{
func
(
p
*
parser
)
closure
()
(
start
,
end
instr
)
{
start
,
end
=
p
.
term
()
start
,
end
=
p
.
term
()
if
start
==
nil
||
p
.
error
!=
nil
{
if
start
==
nil
{
return
return
}
}
switch
p
.
c
()
{
switch
p
.
c
()
{
...
@@ -504,7 +493,7 @@ func (p *parser) closure() (start, end instr) {
...
@@ -504,7 +493,7 @@ func (p *parser) closure() (start, end instr) {
}
}
switch
p
.
nextc
()
{
switch
p
.
nextc
()
{
case
'*'
,
'+'
,
'?'
:
case
'*'
,
'+'
,
'?'
:
p
.
error
=
ErrBadClosure
p
.
error
(
ErrBadClosure
)
}
}
return
return
}
}
...
@@ -512,9 +501,6 @@ func (p *parser) closure() (start, end instr) {
...
@@ -512,9 +501,6 @@ func (p *parser) closure() (start, end instr) {
func
(
p
*
parser
)
concatenation
()
(
start
,
end
instr
)
{
func
(
p
*
parser
)
concatenation
()
(
start
,
end
instr
)
{
for
{
for
{
nstart
,
nend
:=
p
.
closure
()
nstart
,
nend
:=
p
.
closure
()
if
p
.
error
!=
nil
{
return
}
switch
{
switch
{
case
nstart
==
nil
:
// end of this concatenation
case
nstart
==
nil
:
// end of this concatenation
if
start
==
nil
{
// this is the empty string
if
start
==
nil
{
// this is the empty string
...
@@ -534,9 +520,6 @@ func (p *parser) concatenation() (start, end instr) {
...
@@ -534,9 +520,6 @@ func (p *parser) concatenation() (start, end instr) {
func
(
p
*
parser
)
regexp
()
(
start
,
end
instr
)
{
func
(
p
*
parser
)
regexp
()
(
start
,
end
instr
)
{
start
,
end
=
p
.
concatenation
()
start
,
end
=
p
.
concatenation
()
if
p
.
error
!=
nil
{
return
}
for
{
for
{
switch
p
.
c
()
{
switch
p
.
c
()
{
default
:
default
:
...
@@ -544,9 +527,6 @@ func (p *parser) regexp() (start, end instr) {
...
@@ -544,9 +527,6 @@ func (p *parser) regexp() (start, end instr) {
case
'|'
:
case
'|'
:
p
.
nextc
()
p
.
nextc
()
nstart
,
nend
:=
p
.
concatenation
()
nstart
,
nend
:=
p
.
concatenation
()
if
p
.
error
!=
nil
{
return
}
alt
:=
new
(
_Alt
)
alt
:=
new
(
_Alt
)
p
.
re
.
add
(
alt
)
p
.
re
.
add
(
alt
)
alt
.
left
=
start
alt
.
left
=
start
...
@@ -595,14 +575,11 @@ func (re *Regexp) dump() {
...
@@ -595,14 +575,11 @@ func (re *Regexp) dump() {
}
}
}
}
func
(
re
*
Regexp
)
doParse
()
os
.
Error
{
func
(
re
*
Regexp
)
doParse
()
{
p
:=
newParser
(
re
)
p
:=
newParser
(
re
)
start
:=
new
(
_Start
)
start
:=
new
(
_Start
)
re
.
add
(
start
)
re
.
add
(
start
)
s
,
e
:=
p
.
regexp
()
s
,
e
:=
p
.
regexp
()
if
p
.
error
!=
nil
{
return
p
.
error
}
start
.
setNext
(
s
)
start
.
setNext
(
s
)
re
.
start
=
start
re
.
start
=
start
e
.
setNext
(
re
.
add
(
new
(
_End
)))
e
.
setNext
(
re
.
add
(
new
(
_End
)))
...
@@ -617,14 +594,11 @@ func (re *Regexp) doParse() os.Error {
...
@@ -617,14 +594,11 @@ func (re *Regexp) doParse() os.Error {
re
.
dump
()
re
.
dump
()
println
()
println
()
}
}
if
p
.
error
==
nil
{
re
.
setPrefix
()
re
.
setPrefix
()
if
debug
{
if
debug
{
re
.
dump
()
re
.
dump
()
println
()
println
()
}
}
}
return
p
.
error
}
}
// Extract regular text from the beginning of the pattern.
// Extract regular text from the beginning of the pattern.
...
@@ -661,12 +635,16 @@ Loop:
...
@@ -661,12 +635,16 @@ Loop:
// object that can be used to match against text.
// object that can be used to match against text.
func
Compile
(
str
string
)
(
regexp
*
Regexp
,
error
os
.
Error
)
{
func
Compile
(
str
string
)
(
regexp
*
Regexp
,
error
os
.
Error
)
{
regexp
=
new
(
Regexp
)
regexp
=
new
(
Regexp
)
// doParse will panic if there is a parse error.
defer
func
()
{
if
e
:=
recover
();
e
!=
nil
{
regexp
=
nil
error
=
e
.
(
Error
)
// Will re-panic if error was not an Error, e.g. nil-pointer exception
}
}()
regexp
.
expr
=
str
regexp
.
expr
=
str
regexp
.
inst
=
new
(
vector
.
Vector
)
regexp
.
inst
=
new
(
vector
.
Vector
)
error
=
regexp
.
doParse
()
regexp
.
doParse
()
if
error
!=
nil
{
regexp
=
nil
}
return
return
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment