partially working code

This commit is contained in:
Miek Gieben 2012-01-04 21:31:11 +01:00
parent c153bcfa22
commit fa0d78db9e
1 changed files with 93 additions and 78 deletions

171
zscan.go
View File

@ -5,11 +5,10 @@ import (
"io" "io"
"strconv" "strconv"
"strings" "strings"
"text/scanner"
) )
// Only used when debugging the parser itself. // Only used when debugging the parser itself.
var _DEBUG = false var _DEBUG = true
// Tokinize a RFC 1035 zone file. The tokenizer will normalize it: // Tokinize a RFC 1035 zone file. The tokenizer will normalize it:
// * Add ownernames if they are left blank; // * Add ownernames if they are left blank;
@ -84,9 +83,9 @@ type Token struct {
func NewRR(s string) (RR, error) { func NewRR(s string) (RR, error) {
t := make(chan Token) t := make(chan Token)
if s[len(s)-1] != '\n' { // We need a closing newline if s[len(s)-1] != '\n' { // We need a closing newline
t = ParseZone(strings.NewReader(s+"\n")) t = ParseZone(strings.NewReader(s + "\n"))
} else { } else {
t= ParseZone(strings.NewReader(s)) t = ParseZone(strings.NewReader(s))
} }
r := <-t r := <-t
if r.Error != nil { if r.Error != nil {
@ -97,21 +96,17 @@ func NewRR(s string) (RR, error) {
// ParseZone reads a RFC 1035 zone from r. It returns each parsed RR or on error // ParseZone reads a RFC 1035 zone from r. It returns each parsed RR or on error
// on the returned channel. The channel t is closed by ParseZone when the end of r is reached. // on the returned channel. The channel t is closed by ParseZone when the end of r is reached.
func ParseZone(r io.Reader) (chan Token) { func ParseZone(r io.Reader) chan Token {
t := make(chan Token) t := make(chan Token)
go parseZone(r, t) go parseZone(r, t)
return t return t
} }
func parseZone(r io.Reader, t chan Token) { func parseZone(r io.Reader, t chan Token) {
defer close(t) defer close(t)
var s scanner.Scanner
c := make(chan lex) c := make(chan lex)
s.Init(r)
s.Mode = 0
s.Whitespace = 0
// Start the lexer // Start the lexer
go zlexer(s, c) go zlexer(r, c)
// 5 possible beginnings of a line, _ is a space // 5 possible beginnings of a line, _ is a space
// 1. _OWNER _ _RRTYPE -> class/ttl omitted // 1. _OWNER _ _RRTYPE -> class/ttl omitted
// 2. _OWNER _ _STRING _ _RRTYPE -> class omitted // 2. _OWNER _ _STRING _ _RRTYPE -> class omitted
@ -291,9 +286,9 @@ func (l lex) String() string {
} }
// zlexer scans the sourcefile and returns tokens on the channel c. // zlexer scans the sourcefile and returns tokens on the channel c.
func zlexer(s scanner.Scanner, c chan lex) { func zlexer(r io.Reader, c chan lex) {
var l lex var l lex
str := "" // Hold the current read text defer close(c)
quote := false quote := false
escape := false escape := false
space := false space := false
@ -301,35 +296,39 @@ func zlexer(s scanner.Scanner, c chan lex) {
rrtype := false rrtype := false
owner := true owner := true
brace := 0 brace := 0
tok := s.Scan() p, q := 0, 0
defer close(c) buf := make([]byte, 4096)
for tok != scanner.EOF { n, err := r.Read(buf)
l.column = s.Position.Column for err != io.EOF {
l.line = s.Position.Line l.column = 0
switch x := s.TokenText(); x { l.line = 0
case " ", "\t": switch buf[q] {
escape = false case ' ', '\t':
escape = false
if commt { if commt {
p++
break break
} }
if str == "" { if p == q {
//l.value = _BLANK //l.value = _BLANK
//l.token = " " //l.token = " "
} else if owner { } else if owner {
// If we have a string and its the first, make it an owner // If we have a string and its the first, make it an owner
l.value = _OWNER l.value = _OWNER
l.token = str println(p, q)
// escape $... start with a \ not a $, so this will work l.token = string(buf[p:q])
if str == "$TTL" { // escape $... start with a \ not a $, so this will work
if l.token == "$TTL" {
l.value = _DIRTTL l.value = _DIRTTL
} }
if str == "$ORIGIN" { if l.token == "$ORIGIN" {
l.value = _DIRORIGIN l.value = _DIRORIGIN
} }
c <- l c <- l
p = q + 1
} else { } else {
l.value = _STRING l.value = _STRING
l.token = str l.token = string(buf[p:q])
if !rrtype { if !rrtype {
if _, ok := Str_rr[strings.ToUpper(l.token)]; ok { if _, ok := Str_rr[strings.ToUpper(l.token)]; ok {
@ -341,47 +340,52 @@ func zlexer(s scanner.Scanner, c chan lex) {
} }
} }
c <- l c <- l
p = q + 1
} }
str = ""
if !space && !commt { if !space && !commt {
l.value = _BLANK l.value = _BLANK
l.token = " " l.token = " "
c <- l c <- l
p = q + 1
}
if space || commt {
p++
} }
owner = false owner = false
space = true space = true
case ";": println("upping", p, q)
if escape { case ';':
escape = false if escape {
str += ";" escape = false
break
}
if quote {
// Inside quoted text we allow ;
str += ";"
break break
} }
if quote {
// Inside quoted text we allow ;
break
}
p++
commt = true commt = true
case "\n": case '\n':
// Hmmm, escape newline // Hmmm, escape newline
escape = false escape = false
if commt { if commt {
// Reset a comment // Reset a comment
commt = false commt = false
rrtype = false rrtype = false
str = "" p++
// If not in a brace this ends the comment AND the RR // If not in a brace this ends the comment AND the RR
if brace == 0 { if brace == 0 {
owner = true owner = true
l.value = _NEWLINE l.value = _NEWLINE
l.token = "\n" l.token = "\n"
c <- l c <- l
p = q + 1
} }
break break
} }
if str != "" { if p != q {
l.value = _STRING l.value = _STRING
l.token = str l.token = string(buf[p:q])
if !rrtype { if !rrtype {
if _, ok := Str_rr[strings.ToUpper(l.token)]; ok { if _, ok := Str_rr[strings.ToUpper(l.token)]; ok {
l.value = _RRTYPE l.value = _RRTYPE
@ -389,89 +393,100 @@ func zlexer(s scanner.Scanner, c chan lex) {
} }
} }
c <- l c <- l
p = q + 1
} }
if brace > 0 { if brace > 0 {
l.value = _BLANK l.value = _BLANK
l.token = " " p++
if !space { if !space {
c <- l c <- l
p = q + 1
} }
} else { } else {
l.value = _NEWLINE l.value = _NEWLINE
l.token = "\n" l.token = "\n"
c <- l c <- l
p = q + 1
} }
if l.value == _BLANK { if l.value == _BLANK {
space = true space = true
} }
str = "" p = q + 1
println("hallo")
commt = false commt = false
rrtype = false rrtype = false
owner = true owner = true
case "\\": case '\\':
if commt { if commt {
p++
break
}
if escape {
escape = false
break break
} }
if escape {
str += "\\"
escape = false
break
}
escape = true escape = true
case "\"": case '"':
if commt { if commt {
p++
break
}
if escape {
escape = false
break break
} }
if escape {
str += "\""
escape = false
break
}
// str += "\"" don't add quoted quotes
quote = !quote quote = !quote
case "(": case '(':
if commt { if commt {
p++
break
}
if escape {
escape = false
break break
} }
if escape {
str += "("
escape = false
break
}
brace++ brace++
case ")": case ')':
if commt { if commt {
p++
break
}
if escape {
escape = false
break break
} }
if escape {
str += ")"
escape = false
break
}
brace-- brace--
if brace < 0 { if brace < 0 {
l.err = "Extra closing brace" l.err = "Extra closing brace"
c <- l c <- l
p = q + 1
return return
} }
default: default:
if commt { if commt {
p++
break break
} }
escape = false escape = false
str += x
space = false space = false
} }
tok = s.Scan() // tok, err = r.ReadByte() read extra bytes
q++
if q > n {
break
}
} }
// Hmm. println("We crashen gewoon hier", p, q)
if len(str) > 0 { // It this need anymore???
/*
if p != q {
// Send remainder // Send remainder
l.token = str l.token = string(buf[p:q])
l.value = _STRING l.value = _STRING
c <- l c <- l
} }
*/
} }
func stringToTtl(l lex, t chan Token) (uint32, bool) { func stringToTtl(l lex, t chan Token) (uint32, bool) {