Commit 65269ccd authored by Robert Griesemer's avatar Robert Griesemer

- more work on Go scanner

SVN=126004
parent 1efa6a05
...@@ -212,26 +212,38 @@ func is_letter (ch int) bool { ...@@ -212,26 +212,38 @@ func is_letter (ch int) bool {
} }
func is_oct_digit (ch int) bool { func digit_val (ch int) int {
return '0' <= ch && ch <= '7'; if '0' <= ch && ch <= '9' {
return ch - '0';
}
if 'a' <= ch && ch <= 'f' {
return ch - 'a' + 10;
}
if 'A' <= ch && ch <= 'F' {
return ch - 'A' + 10;
}
return 16; // larger than any legal digit val
} }
func is_dec_digit (ch int) bool { export Scanner
return '0' <= ch && ch <= '9'; type Scanner struct {
src string;
pos int;
ch int; // one char look-ahead
} }
func is_hex_digit (ch int) bool { export Token
return '0' <= ch && ch <= '9' || 'a' <= ch && ch <= 'f' || 'A' <= ch && ch <= 'F'; type Token struct {
val int;
beg, end int;
txt string;
} }
export Scanner func (T *Token) Print () {
type Scanner struct { print TokenName(T.val), " [", T.beg, ", ", T.end, "[ ", T.txt, "\n";
src string;
pos int;
ch int; // one char look-ahead
} }
...@@ -393,7 +405,7 @@ func (S *Scanner) SkipComment () { ...@@ -393,7 +405,7 @@ func (S *Scanner) SkipComment () {
func (S *Scanner) ScanIdentifier () int { func (S *Scanner) ScanIdentifier () int {
beg := S.pos - 1; beg := S.pos - 1;
for is_letter(S.ch) || is_dec_digit(S.ch) { for is_letter(S.ch) || digit_val(S.ch) < 10 {
S.Next(); S.Next();
} }
end := S.pos - 1; end := S.pos - 1;
...@@ -410,7 +422,7 @@ func (S *Scanner) ScanIdentifier () int { ...@@ -410,7 +422,7 @@ func (S *Scanner) ScanIdentifier () int {
func (S *Scanner) ScanMantissa (base int) { func (S *Scanner) ScanMantissa (base int) {
for is_dec_digit(S.ch) { for digit_val(S.ch) < base {
S.Next(); S.Next();
} }
} }
...@@ -423,6 +435,7 @@ func (S *Scanner) ScanNumber (seen_decimal_point bool) int { ...@@ -423,6 +435,7 @@ func (S *Scanner) ScanNumber (seen_decimal_point bool) int {
} }
if S.ch == '0' { if S.ch == '0' {
// TODO bug: doesn't accept 09.0 !
// int // int
S.Next(); S.Next();
if S.ch == 'x' || S.ch == 'X' { if S.ch == 'x' || S.ch == 'X' {
...@@ -458,22 +471,13 @@ exponent: ...@@ -458,22 +471,13 @@ exponent:
} }
func (S *Scanner) ScanOctDigits(n int) { func (S *Scanner) ScanDigits(n int, base int) {
for ; n > 0; n-- { for digit_val(S.ch) < base {
if !is_oct_digit(S.ch) {
panic "illegal char escape";
}
S.Next(); S.Next();
n--;
} }
} if n > 0 {
panic "illegal char escape";
func (S *Scanner) ScanHexDigits(n int) {
for ; n > 0; n-- {
if !is_hex_digit(S.ch) {
panic "illegal char escape";
}
S.Next();
} }
} }
...@@ -488,19 +492,19 @@ func (S *Scanner) ScanEscape () string { ...@@ -488,19 +492,19 @@ func (S *Scanner) ScanEscape () string {
return string(ch); return string(ch);
case '0', '1', '2', '3', '4', '5', '6', '7': case '0', '1', '2', '3', '4', '5', '6', '7':
S.ScanOctDigits(3 - 1); // 1 char already read S.ScanDigits(3 - 1, 8); // 1 char already read
return ""; // TODO fix this return ""; // TODO fix this
case 'x': case 'x':
S.ScanHexDigits(2); S.ScanDigits(2, 16);
return ""; // TODO fix this return ""; // TODO fix this
case 'u': case 'u':
S.ScanHexDigits(4); S.ScanDigits(4, 16);
return ""; // TODO fix this return ""; // TODO fix this
case 'U': case 'U':
S.ScanHexDigits(8); S.ScanDigits(8, 16);
return ""; // TODO fix this return ""; // TODO fix this
default: default:
...@@ -518,7 +522,7 @@ func (S *Scanner) ScanChar () int { ...@@ -518,7 +522,7 @@ func (S *Scanner) ScanChar () int {
S.ScanEscape(); S.ScanEscape();
} }
S.Next(); S.Expect('\'');
return NUMBER; return NUMBER;
} }
...@@ -597,16 +601,17 @@ func (S *Scanner) Select4 (tok0, tok1, ch2, tok2, tok3 int) int { ...@@ -597,16 +601,17 @@ func (S *Scanner) Select4 (tok0, tok1, ch2, tok2, tok3 int) int {
} }
func (S *Scanner) Scan () (tok, beg, end int) { func (S *Scanner) Scan (t *Token) (tok, beg, end int) {
S.SkipWhitespace(); S.SkipWhitespace();
var tok int = ILLEGAL; var tok int = ILLEGAL;
var beg int = S.pos - 1; var beg int = S.pos - 1;
var end int = beg; var end int = beg;
switch ch := S.ch; { ch := S.ch;
switch {
case is_letter(ch): tok = S.ScanIdentifier(); case is_letter(ch): tok = S.ScanIdentifier();
case is_dec_digit(ch): tok = S.ScanNumber(false); case digit_val(ch) < 10: tok = S.ScanNumber(false);
default: default:
S.Next(); S.Next();
switch ch { switch ch {
...@@ -616,7 +621,7 @@ func (S *Scanner) Scan () (tok, beg, end int) { ...@@ -616,7 +621,7 @@ func (S *Scanner) Scan () (tok, beg, end int) {
case '`': tok = S.ScanRawString(); case '`': tok = S.ScanRawString();
case ':': tok = S.Select2(COLON, DEFINE); case ':': tok = S.Select2(COLON, DEFINE);
case '.': case '.':
if is_dec_digit(S.ch) { if digit_val(S.ch) < 10 {
tok = S.ScanNumber(true); tok = S.ScanNumber(true);
} else { } else {
tok = PERIOD; tok = PERIOD;
...@@ -636,7 +641,7 @@ func (S *Scanner) Scan () (tok, beg, end int) { ...@@ -636,7 +641,7 @@ func (S *Scanner) Scan () (tok, beg, end int) {
if S.ch == '/' || S.ch == '*' { if S.ch == '/' || S.ch == '*' {
S.SkipComment(); S.SkipComment();
// cannot simply return because of 6g bug // cannot simply return because of 6g bug
tok, beg, end = S.Scan(); tok, beg, end = S.Scan(t);
return tok, beg, end; return tok, beg, end;
} }
tok = S.Select2(QUO, QUO_ASSIGN); tok = S.Select2(QUO, QUO_ASSIGN);
...@@ -653,5 +658,11 @@ func (S *Scanner) Scan () (tok, beg, end int) { ...@@ -653,5 +658,11 @@ func (S *Scanner) Scan () (tok, beg, end int) {
} }
end = S.pos - 1; end = S.pos - 1;
t.val = tok;
t.beg = beg;
t.end = end;
t.txt = S.src[beg : end];
return tok, beg, end; return tok, beg, end;
} }
...@@ -11,8 +11,10 @@ func Scan(src string) { ...@@ -11,8 +11,10 @@ func Scan(src string) {
S := new(Scanner.Scanner); S := new(Scanner.Scanner);
S.Open(src); S.Open(src);
for { for {
var t Scanner.Token;
var tok, beg, end int; var tok, beg, end int;
tok, beg, end = S.Scan(); tok, beg, end = S.Scan(&t);
//t.Print(); // TODO this doesn't compile?
print Scanner.TokenName(tok), "\t ", src[beg : end], "\n"; print Scanner.TokenName(tok), "\t ", src[beg : end], "\n";
if tok == Scanner.EOF { if tok == Scanner.EOF {
return; return;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment