From 2526d34f21e053518036841f523fd1ba13c58e5a Mon Sep 17 00:00:00 2001 From: mae Date: Mon, 26 Jan 2026 19:26:24 -0600 Subject: [PATCH] feat/schema: add lexer --- schema/azschema.bnf | 18 + schema/lexer/acttab.go | 187 +++++ schema/lexer/lexer.go | 175 ++++ schema/lexer/transitiontable.go | 1338 +++++++++++++++++++++++++++++++ schema/main.go | 1 + schema/token/context.go | 14 + schema/token/token.go | 153 ++++ schema/util/litconv.go | 101 +++ schema/util/rune.go | 39 + 9 files changed, 2026 insertions(+) create mode 100644 schema/azschema.bnf create mode 100644 schema/lexer/acttab.go create mode 100644 schema/lexer/lexer.go create mode 100644 schema/lexer/transitiontable.go create mode 100644 schema/token/context.go create mode 100644 schema/token/token.go create mode 100644 schema/util/litconv.go create mode 100644 schema/util/rune.go diff --git a/schema/azschema.bnf b/schema/azschema.bnf new file mode 100644 index 0000000..0937c22 --- /dev/null +++ b/schema/azschema.bnf @@ -0,0 +1,18 @@ +string: '`' {.} '`' | '"' {.} '"'; + +_bin_digit: '0' - '1'; +_oct_digit: _bin_digit | '2' - '7'; +_dec_digit: _oct_digit | '8' - '9'; +_hex_digit: _dec_digit | 'A' - 'F' | 'a' - 'f'; +_negative: '-'; +number: [_negative] '0' 'b' _bin_digit {_bin_digit} + | [_negative] '0' 'o' _oct_digit {_oct_digit} + | [_negative] _dec_digit {_dec_digit} + | [_negative] '0' 'x' _hex_digit {_hex_digit}; + +_name_initial: 'A' - 'Z' | 'a' - 'z' | '_' | '~' | '!' | '@' | '#' | '$' | '%' | '^' | '&' | '*' | '-' | '_' | '+' | '=' | '?' | '/' | '.' | '\''; +_name_char: _name_initial | _dec_digit; +name: _name_initial {_name_char}; + +!whitespace: ' ' | '\t' | '\n' | '\r'; +!comment: ';' {.} '\n'; \ No newline at end of file diff --git a/schema/lexer/acttab.go b/schema/lexer/acttab.go new file mode 100644 index 0000000..91148b1 --- /dev/null +++ b/schema/lexer/acttab.go @@ -0,0 +1,187 @@ +// Code generated by gocc; DO NOT EDIT. + +package lexer + +import ( + "fmt" + + "azalea/schema/token" +) + +type ActionTable [NumStates]ActionRow + +type ActionRow struct { + Accept token.Type + Ignore string +} + +func (a ActionRow) String() string { + return fmt.Sprintf("Accept=%d, Ignore=%s", a.Accept, a.Ignore) +} + +var ActTab = ActionTable{ + ActionRow{ // S0 + Accept: 0, + Ignore: "", + }, + ActionRow{ // S1 + Accept: -1, + Ignore: "!whitespace", + }, + ActionRow{ // S2 + Accept: 2, + Ignore: "", + }, + ActionRow{ // S3 + Accept: 0, + Ignore: "", + }, + ActionRow{ // S4 + Accept: 2, + Ignore: "", + }, + ActionRow{ // S5 + Accept: 3, + Ignore: "", + }, + ActionRow{ // S6 + Accept: 3, + Ignore: "", + }, + ActionRow{ // S7 + Accept: 3, + Ignore: "", + }, + ActionRow{ // S8 + Accept: 3, + Ignore: "", + }, + ActionRow{ // S9 + Accept: 0, + Ignore: "", + }, + ActionRow{ // S10 + Accept: 0, + Ignore: "", + }, + ActionRow{ // S11 + Accept: 2, + Ignore: "", + }, + ActionRow{ // S12 + Accept: 2, + Ignore: "", + }, + ActionRow{ // S13 + Accept: 2, + Ignore: "", + }, + ActionRow{ // S14 + Accept: 2, + Ignore: "", + }, + ActionRow{ // S15 + Accept: 4, + Ignore: "", + }, + ActionRow{ // S16 + Accept: 3, + Ignore: "", + }, + ActionRow{ // S17 + Accept: 3, + Ignore: "", + }, + ActionRow{ // S18 + Accept: 3, + Ignore: "", + }, + ActionRow{ // S19 + Accept: 3, + Ignore: "", + }, + ActionRow{ // S20 + Accept: 0, + Ignore: "", + }, + ActionRow{ // S21 + Accept: 0, + Ignore: "", + }, + ActionRow{ // S22 + Accept: 0, + Ignore: "", + }, + ActionRow{ // S23 + Accept: -1, + Ignore: "!comment", + }, + ActionRow{ // S24 + Accept: 2, + Ignore: "", + }, + ActionRow{ // S25 + Accept: 2, + Ignore: "", + }, + ActionRow{ // S26 + Accept: 2, + Ignore: "", + }, + ActionRow{ // S27 + Accept: 3, + Ignore: "", + }, + ActionRow{ // S28 + Accept: 3, + Ignore: "", + }, + ActionRow{ // S29 + Accept: 3, + Ignore: "", + }, + ActionRow{ // S30 + Accept: 3, + Ignore: "", + }, + ActionRow{ // S31 + Accept: 3, + Ignore: "", + }, + ActionRow{ // S32 + Accept: 3, + Ignore: "", + }, + ActionRow{ // S33 + Accept: 3, + Ignore: "", + }, + ActionRow{ // S34 + Accept: 3, + Ignore: "", + }, + ActionRow{ // S35 + Accept: 3, + Ignore: "", + }, + ActionRow{ // S36 + Accept: 3, + Ignore: "", + }, + ActionRow{ // S37 + Accept: 3, + Ignore: "", + }, + ActionRow{ // S38 + Accept: 3, + Ignore: "", + }, + ActionRow{ // S39 + Accept: 3, + Ignore: "", + }, + ActionRow{ // S40 + Accept: 3, + Ignore: "", + }, +} diff --git a/schema/lexer/lexer.go b/schema/lexer/lexer.go new file mode 100644 index 0000000..042c5c6 --- /dev/null +++ b/schema/lexer/lexer.go @@ -0,0 +1,175 @@ +// Code generated by gocc; DO NOT EDIT. + +package lexer + +import ( + "os" + "unicode/utf8" + + "azalea/schema/token" +) + +const ( + NoState = -1 + NumStates = 41 + NumSymbols = 43 +) + +type Lexer struct { + src []byte + pos int + line int + column int + Context token.Context +} + +func NewLexer(src []byte) *Lexer { + lexer := &Lexer{ + src: src, + pos: 0, + line: 1, + column: 1, + Context: nil, + } + return lexer +} + +// SourceContext is a simple instance of a token.Context which +// contains the name of the source file. +type SourceContext struct { + Filepath string +} + +func (s *SourceContext) Source() string { + return s.Filepath +} + +func NewLexerFile(fpath string) (*Lexer, error) { + src, err := os.ReadFile(fpath) + if err != nil { + return nil, err + } + lexer := NewLexer(src) + lexer.Context = &SourceContext{Filepath: fpath} + return lexer, nil +} + +func (l *Lexer) Scan() (tok *token.Token) { + tok = &token.Token{} + if l.pos >= len(l.src) { + tok.Type = token.EOF + tok.Pos.Offset, tok.Pos.Line, tok.Pos.Column = l.pos, l.line, l.column + tok.Pos.Context = l.Context + return + } + start, startLine, startColumn, end := l.pos, l.line, l.column, 0 + tok.Type = token.INVALID + state, rune1, size := 0, rune(-1), 0 + for state != -1 { + if l.pos >= len(l.src) { + rune1 = -1 + } else { + rune1, size = utf8.DecodeRune(l.src[l.pos:]) + l.pos += size + } + + nextState := -1 + if rune1 != -1 { + nextState = TransTab[state](rune1) + } + state = nextState + + if state != -1 { + + switch rune1 { + case '\n': + l.line++ + l.column = 1 + case '\r': + l.column = 1 + case '\t': + l.column += 4 + default: + l.column++ + } + + switch { + case ActTab[state].Accept != -1: + tok.Type = ActTab[state].Accept + end = l.pos + case ActTab[state].Ignore != "": + start, startLine, startColumn = l.pos, l.line, l.column + state = 0 + if start >= len(l.src) { + tok.Type = token.EOF + } + + } + } else { + if tok.Type == token.INVALID { + end = l.pos + } + } + } + if end > start { + l.pos = end + tok.Lit = l.src[start:end] + } else { + tok.Lit = []byte{} + } + tok.Pos.Offset, tok.Pos.Line, tok.Pos.Column = start, startLine, startColumn + tok.Pos.Context = l.Context + + return +} + +func (l *Lexer) Reset() { + l.pos = 0 +} + +/* +Lexer symbols: +0: '`' +1: '`' +2: '"' +3: '"' +4: '0' +5: 'b' +6: '0' +7: 'o' +8: '0' +9: 'x' +10: '-' +11: '_' +12: '~' +13: '!' +14: '@' +15: '#' +16: '$' +17: '%' +18: '^' +19: '&' +20: '*' +21: '-' +22: '_' +23: '+' +24: '=' +25: '?' +26: '/' +27: '.' +28: ''' +29: ' ' +30: '\t' +31: '\n' +32: '\r' +33: ';' +34: '\n' +35: '0'-'1' +36: '2'-'7' +37: '8'-'9' +38: 'A'-'F' +39: 'a'-'f' +40: 'A'-'Z' +41: 'a'-'z' +42: . +*/ diff --git a/schema/lexer/transitiontable.go b/schema/lexer/transitiontable.go new file mode 100644 index 0000000..b909884 --- /dev/null +++ b/schema/lexer/transitiontable.go @@ -0,0 +1,1338 @@ +// Code generated by gocc; DO NOT EDIT. + +package lexer + +/* +Let s be the current state +Let r be the current input rune +transitionTable[s](r) returns the next state. +*/ +type TransitionTable [NumStates]func(rune) int + +var TransTab = TransitionTable{ + // S0 + func(r rune) int { + switch { + case r == 9: // ['\t','\t'] + return 1 + case r == 10: // ['\n','\n'] + return 1 + case r == 13: // ['\r','\r'] + return 1 + case r == 32: // [' ',' '] + return 1 + case r == 33: // ['!','!'] + return 2 + case r == 34: // ['"','"'] + return 3 + case r == 35: // ['#','#'] + return 2 + case r == 36: // ['$','$'] + return 2 + case r == 37: // ['%','%'] + return 2 + case r == 38: // ['&','&'] + return 2 + case r == 39: // [''','''] + return 2 + case r == 42: // ['*','*'] + return 2 + case r == 43: // ['+','+'] + return 2 + case r == 45: // ['-','-'] + return 4 + case r == 46: // ['.','.'] + return 2 + case r == 47: // ['/','/'] + return 2 + case r == 48: // ['0','0'] + return 5 + case r == 49: // ['1','1'] + return 6 + case 50 <= r && r <= 55: // ['2','7'] + return 7 + case 56 <= r && r <= 57: // ['8','9'] + return 8 + case r == 59: // [';',';'] + return 9 + case r == 61: // ['=','='] + return 2 + case r == 63: // ['?','?'] + return 2 + case r == 64: // ['@','@'] + return 2 + case 65 <= r && r <= 90: // ['A','Z'] + return 2 + case r == 94: // ['^','^'] + return 2 + case r == 95: // ['_','_'] + return 2 + case r == 96: // ['`','`'] + return 10 + case 97 <= r && r <= 122: // ['a','z'] + return 2 + case r == 126: // ['~','~'] + return 2 + } + return NoState + }, + // S1 + func(r rune) int { + switch { + } + return NoState + }, + // S2 + func(r rune) int { + switch { + case r == 33: // ['!','!'] + return 11 + case r == 35: // ['#','#'] + return 11 + case r == 36: // ['$','$'] + return 11 + case r == 37: // ['%','%'] + return 11 + case r == 38: // ['&','&'] + return 11 + case r == 39: // [''','''] + return 11 + case r == 42: // ['*','*'] + return 11 + case r == 43: // ['+','+'] + return 11 + case r == 45: // ['-','-'] + return 11 + case r == 46: // ['.','.'] + return 11 + case r == 47: // ['/','/'] + return 11 + case 48 <= r && r <= 49: // ['0','1'] + return 12 + case 50 <= r && r <= 55: // ['2','7'] + return 13 + case 56 <= r && r <= 57: // ['8','9'] + return 14 + case r == 61: // ['=','='] + return 11 + case r == 63: // ['?','?'] + return 11 + case r == 64: // ['@','@'] + return 11 + case 65 <= r && r <= 90: // ['A','Z'] + return 11 + case r == 94: // ['^','^'] + return 11 + case r == 95: // ['_','_'] + return 11 + case 97 <= r && r <= 122: // ['a','z'] + return 11 + case r == 126: // ['~','~'] + return 11 + } + return NoState + }, + // S3 + func(r rune) int { + switch { + case r == 34: // ['"','"'] + return 15 + default: + return 3 + } + }, + // S4 + func(r rune) int { + switch { + case r == 33: // ['!','!'] + return 11 + case r == 35: // ['#','#'] + return 11 + case r == 36: // ['$','$'] + return 11 + case r == 37: // ['%','%'] + return 11 + case r == 38: // ['&','&'] + return 11 + case r == 39: // [''','''] + return 11 + case r == 42: // ['*','*'] + return 11 + case r == 43: // ['+','+'] + return 11 + case r == 45: // ['-','-'] + return 11 + case r == 46: // ['.','.'] + return 11 + case r == 47: // ['/','/'] + return 11 + case r == 48: // ['0','0'] + return 16 + case r == 49: // ['1','1'] + return 17 + case 50 <= r && r <= 55: // ['2','7'] + return 18 + case 56 <= r && r <= 57: // ['8','9'] + return 19 + case r == 61: // ['=','='] + return 11 + case r == 63: // ['?','?'] + return 11 + case r == 64: // ['@','@'] + return 11 + case 65 <= r && r <= 90: // ['A','Z'] + return 11 + case r == 94: // ['^','^'] + return 11 + case r == 95: // ['_','_'] + return 11 + case 97 <= r && r <= 122: // ['a','z'] + return 11 + case r == 126: // ['~','~'] + return 11 + } + return NoState + }, + // S5 + func(r rune) int { + switch { + case 48 <= r && r <= 49: // ['0','1'] + return 6 + case 50 <= r && r <= 55: // ['2','7'] + return 7 + case 56 <= r && r <= 57: // ['8','9'] + return 8 + case r == 98: // ['b','b'] + return 20 + case r == 111: // ['o','o'] + return 21 + case r == 120: // ['x','x'] + return 22 + } + return NoState + }, + // S6 + func(r rune) int { + switch { + case 48 <= r && r <= 49: // ['0','1'] + return 6 + case 50 <= r && r <= 55: // ['2','7'] + return 7 + case 56 <= r && r <= 57: // ['8','9'] + return 8 + } + return NoState + }, + // S7 + func(r rune) int { + switch { + case 48 <= r && r <= 49: // ['0','1'] + return 6 + case 50 <= r && r <= 55: // ['2','7'] + return 7 + case 56 <= r && r <= 57: // ['8','9'] + return 8 + } + return NoState + }, + // S8 + func(r rune) int { + switch { + case 48 <= r && r <= 49: // ['0','1'] + return 6 + case 50 <= r && r <= 55: // ['2','7'] + return 7 + case 56 <= r && r <= 57: // ['8','9'] + return 8 + } + return NoState + }, + // S9 + func(r rune) int { + switch { + case r == 10: // ['\n','\n'] + return 23 + default: + return 9 + } + }, + // S10 + func(r rune) int { + switch { + case r == 96: // ['`','`'] + return 15 + default: + return 10 + } + }, + // S11 + func(r rune) int { + switch { + case r == 33: // ['!','!'] + return 11 + case r == 35: // ['#','#'] + return 11 + case r == 36: // ['$','$'] + return 11 + case r == 37: // ['%','%'] + return 11 + case r == 38: // ['&','&'] + return 11 + case r == 39: // [''','''] + return 11 + case r == 42: // ['*','*'] + return 11 + case r == 43: // ['+','+'] + return 11 + case r == 45: // ['-','-'] + return 11 + case r == 46: // ['.','.'] + return 11 + case r == 47: // ['/','/'] + return 11 + case 48 <= r && r <= 49: // ['0','1'] + return 12 + case 50 <= r && r <= 55: // ['2','7'] + return 13 + case 56 <= r && r <= 57: // ['8','9'] + return 14 + case r == 61: // ['=','='] + return 11 + case r == 63: // ['?','?'] + return 11 + case r == 64: // ['@','@'] + return 11 + case 65 <= r && r <= 90: // ['A','Z'] + return 11 + case r == 94: // ['^','^'] + return 11 + case r == 95: // ['_','_'] + return 11 + case 97 <= r && r <= 122: // ['a','z'] + return 11 + case r == 126: // ['~','~'] + return 11 + } + return NoState + }, + // S12 + func(r rune) int { + switch { + case r == 33: // ['!','!'] + return 11 + case r == 35: // ['#','#'] + return 11 + case r == 36: // ['$','$'] + return 11 + case r == 37: // ['%','%'] + return 11 + case r == 38: // ['&','&'] + return 11 + case r == 39: // [''','''] + return 11 + case r == 42: // ['*','*'] + return 11 + case r == 43: // ['+','+'] + return 11 + case r == 45: // ['-','-'] + return 11 + case r == 46: // ['.','.'] + return 11 + case r == 47: // ['/','/'] + return 11 + case 48 <= r && r <= 49: // ['0','1'] + return 12 + case 50 <= r && r <= 55: // ['2','7'] + return 13 + case 56 <= r && r <= 57: // ['8','9'] + return 14 + case r == 61: // ['=','='] + return 11 + case r == 63: // ['?','?'] + return 11 + case r == 64: // ['@','@'] + return 11 + case 65 <= r && r <= 90: // ['A','Z'] + return 11 + case r == 94: // ['^','^'] + return 11 + case r == 95: // ['_','_'] + return 11 + case 97 <= r && r <= 122: // ['a','z'] + return 11 + case r == 126: // ['~','~'] + return 11 + } + return NoState + }, + // S13 + func(r rune) int { + switch { + case r == 33: // ['!','!'] + return 11 + case r == 35: // ['#','#'] + return 11 + case r == 36: // ['$','$'] + return 11 + case r == 37: // ['%','%'] + return 11 + case r == 38: // ['&','&'] + return 11 + case r == 39: // [''','''] + return 11 + case r == 42: // ['*','*'] + return 11 + case r == 43: // ['+','+'] + return 11 + case r == 45: // ['-','-'] + return 11 + case r == 46: // ['.','.'] + return 11 + case r == 47: // ['/','/'] + return 11 + case 48 <= r && r <= 49: // ['0','1'] + return 12 + case 50 <= r && r <= 55: // ['2','7'] + return 13 + case 56 <= r && r <= 57: // ['8','9'] + return 14 + case r == 61: // ['=','='] + return 11 + case r == 63: // ['?','?'] + return 11 + case r == 64: // ['@','@'] + return 11 + case 65 <= r && r <= 90: // ['A','Z'] + return 11 + case r == 94: // ['^','^'] + return 11 + case r == 95: // ['_','_'] + return 11 + case 97 <= r && r <= 122: // ['a','z'] + return 11 + case r == 126: // ['~','~'] + return 11 + } + return NoState + }, + // S14 + func(r rune) int { + switch { + case r == 33: // ['!','!'] + return 11 + case r == 35: // ['#','#'] + return 11 + case r == 36: // ['$','$'] + return 11 + case r == 37: // ['%','%'] + return 11 + case r == 38: // ['&','&'] + return 11 + case r == 39: // [''','''] + return 11 + case r == 42: // ['*','*'] + return 11 + case r == 43: // ['+','+'] + return 11 + case r == 45: // ['-','-'] + return 11 + case r == 46: // ['.','.'] + return 11 + case r == 47: // ['/','/'] + return 11 + case 48 <= r && r <= 49: // ['0','1'] + return 12 + case 50 <= r && r <= 55: // ['2','7'] + return 13 + case 56 <= r && r <= 57: // ['8','9'] + return 14 + case r == 61: // ['=','='] + return 11 + case r == 63: // ['?','?'] + return 11 + case r == 64: // ['@','@'] + return 11 + case 65 <= r && r <= 90: // ['A','Z'] + return 11 + case r == 94: // ['^','^'] + return 11 + case r == 95: // ['_','_'] + return 11 + case 97 <= r && r <= 122: // ['a','z'] + return 11 + case r == 126: // ['~','~'] + return 11 + } + return NoState + }, + // S15 + func(r rune) int { + switch { + } + return NoState + }, + // S16 + func(r rune) int { + switch { + case r == 33: // ['!','!'] + return 11 + case r == 35: // ['#','#'] + return 11 + case r == 36: // ['$','$'] + return 11 + case r == 37: // ['%','%'] + return 11 + case r == 38: // ['&','&'] + return 11 + case r == 39: // [''','''] + return 11 + case r == 42: // ['*','*'] + return 11 + case r == 43: // ['+','+'] + return 11 + case r == 45: // ['-','-'] + return 11 + case r == 46: // ['.','.'] + return 11 + case r == 47: // ['/','/'] + return 11 + case 48 <= r && r <= 49: // ['0','1'] + return 17 + case 50 <= r && r <= 55: // ['2','7'] + return 18 + case 56 <= r && r <= 57: // ['8','9'] + return 19 + case r == 61: // ['=','='] + return 11 + case r == 63: // ['?','?'] + return 11 + case r == 64: // ['@','@'] + return 11 + case 65 <= r && r <= 90: // ['A','Z'] + return 11 + case r == 94: // ['^','^'] + return 11 + case r == 95: // ['_','_'] + return 11 + case r == 97: // ['a','a'] + return 11 + case r == 98: // ['b','b'] + return 24 + case 99 <= r && r <= 110: // ['c','n'] + return 11 + case r == 111: // ['o','o'] + return 25 + case 112 <= r && r <= 119: // ['p','w'] + return 11 + case r == 120: // ['x','x'] + return 26 + case 121 <= r && r <= 122: // ['y','z'] + return 11 + case r == 126: // ['~','~'] + return 11 + } + return NoState + }, + // S17 + func(r rune) int { + switch { + case r == 33: // ['!','!'] + return 11 + case r == 35: // ['#','#'] + return 11 + case r == 36: // ['$','$'] + return 11 + case r == 37: // ['%','%'] + return 11 + case r == 38: // ['&','&'] + return 11 + case r == 39: // [''','''] + return 11 + case r == 42: // ['*','*'] + return 11 + case r == 43: // ['+','+'] + return 11 + case r == 45: // ['-','-'] + return 11 + case r == 46: // ['.','.'] + return 11 + case r == 47: // ['/','/'] + return 11 + case 48 <= r && r <= 49: // ['0','1'] + return 17 + case 50 <= r && r <= 55: // ['2','7'] + return 18 + case 56 <= r && r <= 57: // ['8','9'] + return 19 + case r == 61: // ['=','='] + return 11 + case r == 63: // ['?','?'] + return 11 + case r == 64: // ['@','@'] + return 11 + case 65 <= r && r <= 90: // ['A','Z'] + return 11 + case r == 94: // ['^','^'] + return 11 + case r == 95: // ['_','_'] + return 11 + case 97 <= r && r <= 122: // ['a','z'] + return 11 + case r == 126: // ['~','~'] + return 11 + } + return NoState + }, + // S18 + func(r rune) int { + switch { + case r == 33: // ['!','!'] + return 11 + case r == 35: // ['#','#'] + return 11 + case r == 36: // ['$','$'] + return 11 + case r == 37: // ['%','%'] + return 11 + case r == 38: // ['&','&'] + return 11 + case r == 39: // [''','''] + return 11 + case r == 42: // ['*','*'] + return 11 + case r == 43: // ['+','+'] + return 11 + case r == 45: // ['-','-'] + return 11 + case r == 46: // ['.','.'] + return 11 + case r == 47: // ['/','/'] + return 11 + case 48 <= r && r <= 49: // ['0','1'] + return 17 + case 50 <= r && r <= 55: // ['2','7'] + return 18 + case 56 <= r && r <= 57: // ['8','9'] + return 19 + case r == 61: // ['=','='] + return 11 + case r == 63: // ['?','?'] + return 11 + case r == 64: // ['@','@'] + return 11 + case 65 <= r && r <= 90: // ['A','Z'] + return 11 + case r == 94: // ['^','^'] + return 11 + case r == 95: // ['_','_'] + return 11 + case 97 <= r && r <= 122: // ['a','z'] + return 11 + case r == 126: // ['~','~'] + return 11 + } + return NoState + }, + // S19 + func(r rune) int { + switch { + case r == 33: // ['!','!'] + return 11 + case r == 35: // ['#','#'] + return 11 + case r == 36: // ['$','$'] + return 11 + case r == 37: // ['%','%'] + return 11 + case r == 38: // ['&','&'] + return 11 + case r == 39: // [''','''] + return 11 + case r == 42: // ['*','*'] + return 11 + case r == 43: // ['+','+'] + return 11 + case r == 45: // ['-','-'] + return 11 + case r == 46: // ['.','.'] + return 11 + case r == 47: // ['/','/'] + return 11 + case 48 <= r && r <= 49: // ['0','1'] + return 17 + case 50 <= r && r <= 55: // ['2','7'] + return 18 + case 56 <= r && r <= 57: // ['8','9'] + return 19 + case r == 61: // ['=','='] + return 11 + case r == 63: // ['?','?'] + return 11 + case r == 64: // ['@','@'] + return 11 + case 65 <= r && r <= 90: // ['A','Z'] + return 11 + case r == 94: // ['^','^'] + return 11 + case r == 95: // ['_','_'] + return 11 + case 97 <= r && r <= 122: // ['a','z'] + return 11 + case r == 126: // ['~','~'] + return 11 + } + return NoState + }, + // S20 + func(r rune) int { + switch { + case 48 <= r && r <= 49: // ['0','1'] + return 27 + } + return NoState + }, + // S21 + func(r rune) int { + switch { + case 48 <= r && r <= 49: // ['0','1'] + return 28 + case 50 <= r && r <= 55: // ['2','7'] + return 29 + } + return NoState + }, + // S22 + func(r rune) int { + switch { + case 48 <= r && r <= 49: // ['0','1'] + return 30 + case 50 <= r && r <= 55: // ['2','7'] + return 31 + case 56 <= r && r <= 57: // ['8','9'] + return 32 + case 65 <= r && r <= 70: // ['A','F'] + return 33 + case 97 <= r && r <= 102: // ['a','f'] + return 33 + } + return NoState + }, + // S23 + func(r rune) int { + switch { + } + return NoState + }, + // S24 + func(r rune) int { + switch { + case r == 33: // ['!','!'] + return 11 + case r == 35: // ['#','#'] + return 11 + case r == 36: // ['$','$'] + return 11 + case r == 37: // ['%','%'] + return 11 + case r == 38: // ['&','&'] + return 11 + case r == 39: // [''','''] + return 11 + case r == 42: // ['*','*'] + return 11 + case r == 43: // ['+','+'] + return 11 + case r == 45: // ['-','-'] + return 11 + case r == 46: // ['.','.'] + return 11 + case r == 47: // ['/','/'] + return 11 + case 48 <= r && r <= 49: // ['0','1'] + return 34 + case 50 <= r && r <= 55: // ['2','7'] + return 13 + case 56 <= r && r <= 57: // ['8','9'] + return 14 + case r == 61: // ['=','='] + return 11 + case r == 63: // ['?','?'] + return 11 + case r == 64: // ['@','@'] + return 11 + case 65 <= r && r <= 90: // ['A','Z'] + return 11 + case r == 94: // ['^','^'] + return 11 + case r == 95: // ['_','_'] + return 11 + case 97 <= r && r <= 122: // ['a','z'] + return 11 + case r == 126: // ['~','~'] + return 11 + } + return NoState + }, + // S25 + func(r rune) int { + switch { + case r == 33: // ['!','!'] + return 11 + case r == 35: // ['#','#'] + return 11 + case r == 36: // ['$','$'] + return 11 + case r == 37: // ['%','%'] + return 11 + case r == 38: // ['&','&'] + return 11 + case r == 39: // [''','''] + return 11 + case r == 42: // ['*','*'] + return 11 + case r == 43: // ['+','+'] + return 11 + case r == 45: // ['-','-'] + return 11 + case r == 46: // ['.','.'] + return 11 + case r == 47: // ['/','/'] + return 11 + case 48 <= r && r <= 49: // ['0','1'] + return 35 + case 50 <= r && r <= 55: // ['2','7'] + return 36 + case 56 <= r && r <= 57: // ['8','9'] + return 14 + case r == 61: // ['=','='] + return 11 + case r == 63: // ['?','?'] + return 11 + case r == 64: // ['@','@'] + return 11 + case 65 <= r && r <= 90: // ['A','Z'] + return 11 + case r == 94: // ['^','^'] + return 11 + case r == 95: // ['_','_'] + return 11 + case 97 <= r && r <= 122: // ['a','z'] + return 11 + case r == 126: // ['~','~'] + return 11 + } + return NoState + }, + // S26 + func(r rune) int { + switch { + case r == 33: // ['!','!'] + return 11 + case r == 35: // ['#','#'] + return 11 + case r == 36: // ['$','$'] + return 11 + case r == 37: // ['%','%'] + return 11 + case r == 38: // ['&','&'] + return 11 + case r == 39: // [''','''] + return 11 + case r == 42: // ['*','*'] + return 11 + case r == 43: // ['+','+'] + return 11 + case r == 45: // ['-','-'] + return 11 + case r == 46: // ['.','.'] + return 11 + case r == 47: // ['/','/'] + return 11 + case 48 <= r && r <= 49: // ['0','1'] + return 37 + case 50 <= r && r <= 55: // ['2','7'] + return 38 + case 56 <= r && r <= 57: // ['8','9'] + return 39 + case r == 61: // ['=','='] + return 11 + case r == 63: // ['?','?'] + return 11 + case r == 64: // ['@','@'] + return 11 + case 65 <= r && r <= 70: // ['A','F'] + return 40 + case 71 <= r && r <= 90: // ['G','Z'] + return 11 + case r == 94: // ['^','^'] + return 11 + case r == 95: // ['_','_'] + return 11 + case 97 <= r && r <= 102: // ['a','f'] + return 40 + case 103 <= r && r <= 122: // ['g','z'] + return 11 + case r == 126: // ['~','~'] + return 11 + } + return NoState + }, + // S27 + func(r rune) int { + switch { + case 48 <= r && r <= 49: // ['0','1'] + return 27 + } + return NoState + }, + // S28 + func(r rune) int { + switch { + case 48 <= r && r <= 49: // ['0','1'] + return 28 + case 50 <= r && r <= 55: // ['2','7'] + return 29 + } + return NoState + }, + // S29 + func(r rune) int { + switch { + case 48 <= r && r <= 49: // ['0','1'] + return 28 + case 50 <= r && r <= 55: // ['2','7'] + return 29 + } + return NoState + }, + // S30 + func(r rune) int { + switch { + case 48 <= r && r <= 49: // ['0','1'] + return 30 + case 50 <= r && r <= 55: // ['2','7'] + return 31 + case 56 <= r && r <= 57: // ['8','9'] + return 32 + case 65 <= r && r <= 70: // ['A','F'] + return 33 + case 97 <= r && r <= 102: // ['a','f'] + return 33 + } + return NoState + }, + // S31 + func(r rune) int { + switch { + case 48 <= r && r <= 49: // ['0','1'] + return 30 + case 50 <= r && r <= 55: // ['2','7'] + return 31 + case 56 <= r && r <= 57: // ['8','9'] + return 32 + case 65 <= r && r <= 70: // ['A','F'] + return 33 + case 97 <= r && r <= 102: // ['a','f'] + return 33 + } + return NoState + }, + // S32 + func(r rune) int { + switch { + case 48 <= r && r <= 49: // ['0','1'] + return 30 + case 50 <= r && r <= 55: // ['2','7'] + return 31 + case 56 <= r && r <= 57: // ['8','9'] + return 32 + case 65 <= r && r <= 70: // ['A','F'] + return 33 + case 97 <= r && r <= 102: // ['a','f'] + return 33 + } + return NoState + }, + // S33 + func(r rune) int { + switch { + case 48 <= r && r <= 49: // ['0','1'] + return 30 + case 50 <= r && r <= 55: // ['2','7'] + return 31 + case 56 <= r && r <= 57: // ['8','9'] + return 32 + case 65 <= r && r <= 70: // ['A','F'] + return 33 + case 97 <= r && r <= 102: // ['a','f'] + return 33 + } + return NoState + }, + // S34 + func(r rune) int { + switch { + case r == 33: // ['!','!'] + return 11 + case r == 35: // ['#','#'] + return 11 + case r == 36: // ['$','$'] + return 11 + case r == 37: // ['%','%'] + return 11 + case r == 38: // ['&','&'] + return 11 + case r == 39: // [''','''] + return 11 + case r == 42: // ['*','*'] + return 11 + case r == 43: // ['+','+'] + return 11 + case r == 45: // ['-','-'] + return 11 + case r == 46: // ['.','.'] + return 11 + case r == 47: // ['/','/'] + return 11 + case 48 <= r && r <= 49: // ['0','1'] + return 34 + case 50 <= r && r <= 55: // ['2','7'] + return 13 + case 56 <= r && r <= 57: // ['8','9'] + return 14 + case r == 61: // ['=','='] + return 11 + case r == 63: // ['?','?'] + return 11 + case r == 64: // ['@','@'] + return 11 + case 65 <= r && r <= 90: // ['A','Z'] + return 11 + case r == 94: // ['^','^'] + return 11 + case r == 95: // ['_','_'] + return 11 + case 97 <= r && r <= 122: // ['a','z'] + return 11 + case r == 126: // ['~','~'] + return 11 + } + return NoState + }, + // S35 + func(r rune) int { + switch { + case r == 33: // ['!','!'] + return 11 + case r == 35: // ['#','#'] + return 11 + case r == 36: // ['$','$'] + return 11 + case r == 37: // ['%','%'] + return 11 + case r == 38: // ['&','&'] + return 11 + case r == 39: // [''','''] + return 11 + case r == 42: // ['*','*'] + return 11 + case r == 43: // ['+','+'] + return 11 + case r == 45: // ['-','-'] + return 11 + case r == 46: // ['.','.'] + return 11 + case r == 47: // ['/','/'] + return 11 + case 48 <= r && r <= 49: // ['0','1'] + return 35 + case 50 <= r && r <= 55: // ['2','7'] + return 36 + case 56 <= r && r <= 57: // ['8','9'] + return 14 + case r == 61: // ['=','='] + return 11 + case r == 63: // ['?','?'] + return 11 + case r == 64: // ['@','@'] + return 11 + case 65 <= r && r <= 90: // ['A','Z'] + return 11 + case r == 94: // ['^','^'] + return 11 + case r == 95: // ['_','_'] + return 11 + case 97 <= r && r <= 122: // ['a','z'] + return 11 + case r == 126: // ['~','~'] + return 11 + } + return NoState + }, + // S36 + func(r rune) int { + switch { + case r == 33: // ['!','!'] + return 11 + case r == 35: // ['#','#'] + return 11 + case r == 36: // ['$','$'] + return 11 + case r == 37: // ['%','%'] + return 11 + case r == 38: // ['&','&'] + return 11 + case r == 39: // [''','''] + return 11 + case r == 42: // ['*','*'] + return 11 + case r == 43: // ['+','+'] + return 11 + case r == 45: // ['-','-'] + return 11 + case r == 46: // ['.','.'] + return 11 + case r == 47: // ['/','/'] + return 11 + case 48 <= r && r <= 49: // ['0','1'] + return 35 + case 50 <= r && r <= 55: // ['2','7'] + return 36 + case 56 <= r && r <= 57: // ['8','9'] + return 14 + case r == 61: // ['=','='] + return 11 + case r == 63: // ['?','?'] + return 11 + case r == 64: // ['@','@'] + return 11 + case 65 <= r && r <= 90: // ['A','Z'] + return 11 + case r == 94: // ['^','^'] + return 11 + case r == 95: // ['_','_'] + return 11 + case 97 <= r && r <= 122: // ['a','z'] + return 11 + case r == 126: // ['~','~'] + return 11 + } + return NoState + }, + // S37 + func(r rune) int { + switch { + case r == 33: // ['!','!'] + return 11 + case r == 35: // ['#','#'] + return 11 + case r == 36: // ['$','$'] + return 11 + case r == 37: // ['%','%'] + return 11 + case r == 38: // ['&','&'] + return 11 + case r == 39: // [''','''] + return 11 + case r == 42: // ['*','*'] + return 11 + case r == 43: // ['+','+'] + return 11 + case r == 45: // ['-','-'] + return 11 + case r == 46: // ['.','.'] + return 11 + case r == 47: // ['/','/'] + return 11 + case 48 <= r && r <= 49: // ['0','1'] + return 37 + case 50 <= r && r <= 55: // ['2','7'] + return 38 + case 56 <= r && r <= 57: // ['8','9'] + return 39 + case r == 61: // ['=','='] + return 11 + case r == 63: // ['?','?'] + return 11 + case r == 64: // ['@','@'] + return 11 + case 65 <= r && r <= 70: // ['A','F'] + return 40 + case 71 <= r && r <= 90: // ['G','Z'] + return 11 + case r == 94: // ['^','^'] + return 11 + case r == 95: // ['_','_'] + return 11 + case 97 <= r && r <= 102: // ['a','f'] + return 40 + case 103 <= r && r <= 122: // ['g','z'] + return 11 + case r == 126: // ['~','~'] + return 11 + } + return NoState + }, + // S38 + func(r rune) int { + switch { + case r == 33: // ['!','!'] + return 11 + case r == 35: // ['#','#'] + return 11 + case r == 36: // ['$','$'] + return 11 + case r == 37: // ['%','%'] + return 11 + case r == 38: // ['&','&'] + return 11 + case r == 39: // [''','''] + return 11 + case r == 42: // ['*','*'] + return 11 + case r == 43: // ['+','+'] + return 11 + case r == 45: // ['-','-'] + return 11 + case r == 46: // ['.','.'] + return 11 + case r == 47: // ['/','/'] + return 11 + case 48 <= r && r <= 49: // ['0','1'] + return 37 + case 50 <= r && r <= 55: // ['2','7'] + return 38 + case 56 <= r && r <= 57: // ['8','9'] + return 39 + case r == 61: // ['=','='] + return 11 + case r == 63: // ['?','?'] + return 11 + case r == 64: // ['@','@'] + return 11 + case 65 <= r && r <= 70: // ['A','F'] + return 40 + case 71 <= r && r <= 90: // ['G','Z'] + return 11 + case r == 94: // ['^','^'] + return 11 + case r == 95: // ['_','_'] + return 11 + case 97 <= r && r <= 102: // ['a','f'] + return 40 + case 103 <= r && r <= 122: // ['g','z'] + return 11 + case r == 126: // ['~','~'] + return 11 + } + return NoState + }, + // S39 + func(r rune) int { + switch { + case r == 33: // ['!','!'] + return 11 + case r == 35: // ['#','#'] + return 11 + case r == 36: // ['$','$'] + return 11 + case r == 37: // ['%','%'] + return 11 + case r == 38: // ['&','&'] + return 11 + case r == 39: // [''','''] + return 11 + case r == 42: // ['*','*'] + return 11 + case r == 43: // ['+','+'] + return 11 + case r == 45: // ['-','-'] + return 11 + case r == 46: // ['.','.'] + return 11 + case r == 47: // ['/','/'] + return 11 + case 48 <= r && r <= 49: // ['0','1'] + return 37 + case 50 <= r && r <= 55: // ['2','7'] + return 38 + case 56 <= r && r <= 57: // ['8','9'] + return 39 + case r == 61: // ['=','='] + return 11 + case r == 63: // ['?','?'] + return 11 + case r == 64: // ['@','@'] + return 11 + case 65 <= r && r <= 70: // ['A','F'] + return 40 + case 71 <= r && r <= 90: // ['G','Z'] + return 11 + case r == 94: // ['^','^'] + return 11 + case r == 95: // ['_','_'] + return 11 + case 97 <= r && r <= 102: // ['a','f'] + return 40 + case 103 <= r && r <= 122: // ['g','z'] + return 11 + case r == 126: // ['~','~'] + return 11 + } + return NoState + }, + // S40 + func(r rune) int { + switch { + case r == 33: // ['!','!'] + return 11 + case r == 35: // ['#','#'] + return 11 + case r == 36: // ['$','$'] + return 11 + case r == 37: // ['%','%'] + return 11 + case r == 38: // ['&','&'] + return 11 + case r == 39: // [''','''] + return 11 + case r == 42: // ['*','*'] + return 11 + case r == 43: // ['+','+'] + return 11 + case r == 45: // ['-','-'] + return 11 + case r == 46: // ['.','.'] + return 11 + case r == 47: // ['/','/'] + return 11 + case 48 <= r && r <= 49: // ['0','1'] + return 37 + case 50 <= r && r <= 55: // ['2','7'] + return 38 + case 56 <= r && r <= 57: // ['8','9'] + return 39 + case r == 61: // ['=','='] + return 11 + case r == 63: // ['?','?'] + return 11 + case r == 64: // ['@','@'] + return 11 + case 65 <= r && r <= 70: // ['A','F'] + return 40 + case 71 <= r && r <= 90: // ['G','Z'] + return 11 + case r == 94: // ['^','^'] + return 11 + case r == 95: // ['_','_'] + return 11 + case 97 <= r && r <= 102: // ['a','f'] + return 40 + case 103 <= r && r <= 122: // ['g','z'] + return 11 + case r == 126: // ['~','~'] + return 11 + } + return NoState + }, +} diff --git a/schema/main.go b/schema/main.go index b9e149c..9fa82e3 100644 --- a/schema/main.go +++ b/schema/main.go @@ -1 +1,2 @@ +//go:generate gocc azschema.bnf package schema diff --git a/schema/token/context.go b/schema/token/context.go new file mode 100644 index 0000000..0f4e420 --- /dev/null +++ b/schema/token/context.go @@ -0,0 +1,14 @@ +// Code generated by gocc; DO NOT EDIT. + +package token + +// Context allows user-defined data to be associated with the +// lexer/scanner to be associated with each token that lexer +// produces. +type Context interface{} + +// Sourcer is a Context interface which presents a Source() method +// identifying e.g the filename for the current code. +type Sourcer interface { + Source() string +} diff --git a/schema/token/token.go b/schema/token/token.go new file mode 100644 index 0000000..6cbd726 --- /dev/null +++ b/schema/token/token.go @@ -0,0 +1,153 @@ +// Code generated by gocc; DO NOT EDIT. + +package token + +import ( + "bytes" + "fmt" + "strconv" + "unicode/utf8" +) + +type Token struct { + Type + Lit []byte + Pos +} + +type Type int + +const ( + INVALID Type = iota + EOF +) + +type Pos struct { + Offset int + Line int + Column int + Context Context +} + +func (p Pos) String() string { + // If the context provides a filename, provide a human-readable File:Line:Column representation. + switch src := p.Context.(type) { + case Sourcer: + return fmt.Sprintf("%s:%d:%d", src.Source(), p.Line, p.Column) + default: + return fmt.Sprintf("Pos(offset=%d, line=%d, column=%d)", p.Offset, p.Line, p.Column) + } +} + +type TokenMap struct { + typeMap []string + idMap map[string]Type +} + +func (m TokenMap) Id(tok Type) string { + if int(tok) < len(m.typeMap) { + return m.typeMap[tok] + } + return "unknown" +} + +func (m TokenMap) Type(tok string) Type { + if typ, exist := m.idMap[tok]; exist { + return typ + } + return INVALID +} + +func (m TokenMap) TokenString(tok *Token) string { + return fmt.Sprintf("%s(%d,%s)", m.Id(tok.Type), tok.Type, tok.Lit) +} + +func (m TokenMap) StringType(typ Type) string { + return fmt.Sprintf("%s(%d)", m.Id(typ), typ) +} + +// Equals returns returns true if the token Type and Lit are matches. +func (t *Token) Equals(rhs interface{}) bool { + switch rhsT := rhs.(type) { + case *Token: + return t == rhsT || (t.Type == rhsT.Type && bytes.Equal(t.Lit, rhsT.Lit)) + default: + return false + } +} + +// CharLiteralValue returns the string value of the char literal. +func (t *Token) CharLiteralValue() string { + return string(t.Lit[1 : len(t.Lit)-1]) +} + +// Float32Value returns the float32 value of the token or an error if the token literal does not +// denote a valid float32. +func (t *Token) Float32Value() (float32, error) { + if v, err := strconv.ParseFloat(string(t.Lit), 32); err != nil { + return 0, err + } else { + return float32(v), nil + } +} + +// Float64Value returns the float64 value of the token or an error if the token literal does not +// denote a valid float64. +func (t *Token) Float64Value() (float64, error) { + return strconv.ParseFloat(string(t.Lit), 64) +} + +// IDValue returns the string representation of an identifier token. +func (t *Token) IDValue() string { + return string(t.Lit) +} + +// Int32Value returns the int32 value of the token or an error if the token literal does not +// denote a valid float64. +func (t *Token) Int32Value() (int32, error) { + if v, err := strconv.ParseInt(string(t.Lit), 10, 64); err != nil { + return 0, err + } else { + return int32(v), nil + } +} + +// Int64Value returns the int64 value of the token or an error if the token literal does not +// denote a valid float64. +func (t *Token) Int64Value() (int64, error) { + return strconv.ParseInt(string(t.Lit), 10, 64) +} + +// UTF8Rune decodes the UTF8 rune in the token literal. It returns utf8.RuneError if +// the token literal contains an invalid rune. +func (t *Token) UTF8Rune() (rune, error) { + r, _ := utf8.DecodeRune(t.Lit) + if r == utf8.RuneError { + err := fmt.Errorf("Invalid rune") + return r, err + } + return r, nil +} + +// StringValue returns the string value of the token literal. +func (t *Token) StringValue() string { + return string(t.Lit[1 : len(t.Lit)-1]) +} + +var TokMap = TokenMap{ + typeMap: []string{ + "INVALID", + "␚", + "name", + "number", + "string", + }, + + idMap: map[string]Type{ + "INVALID": 0, + "␚": 1, + "name": 2, + "number": 3, + "string": 4, + }, +} diff --git a/schema/util/litconv.go b/schema/util/litconv.go new file mode 100644 index 0000000..16407a4 --- /dev/null +++ b/schema/util/litconv.go @@ -0,0 +1,101 @@ +// Code generated by gocc; DO NOT EDIT. + +package util + +import ( + "fmt" + "strconv" + "unicode" + "unicode/utf8" +) + +// Interface. + +// RuneValue will convert the literal value of a scanned token to a rune. +func RuneValue(lit []byte) rune { + if lit[1] == '\\' { + return escapeCharVal(lit) + } + r, size := utf8.DecodeRune(lit[1:]) + if size != len(lit)-2 { + panic(fmt.Sprintf("Error decoding rune. Lit: %s, rune: %d, size%d\n", lit, r, size)) + } + return r +} + +// UintValue will attempt to parse a byte-slice as a signed base-10 64-bit integer. +func IntValue(lit []byte) (int64, error) { + return strconv.ParseInt(string(lit), 10, 64) +} + +// UintValue will attempt to parse a byte-slice as an unsigned base-10 64-bit integer. +func UintValue(lit []byte) (uint64, error) { + return strconv.ParseUint(string(lit), 10, 64) +} + +// Helpers. +func escapeCharVal(lit []byte) rune { + var i, base, max uint32 + offset := 2 + switch lit[offset] { + case 'a': + return '\a' + case 'b': + return '\b' + case 'f': + return '\f' + case 'n': + return '\n' + case 'r': + return '\r' + case 't': + return '\t' + case 'v': + return '\v' + case '\\': + return '\\' + case '\'': + return '\'' + case '0', '1', '2', '3', '4', '5', '6', '7': + i, base, max = 3, 8, 255 + case 'x': + i, base, max = 2, 16, 255 + offset++ + case 'u': + i, base, max = 4, 16, unicode.MaxRune + offset++ + case 'U': + i, base, max = 8, 16, unicode.MaxRune + offset++ + default: + panic(fmt.Sprintf("Error decoding character literal: %s\n", lit)) + } + + var x uint32 + for ; i > 0 && offset < len(lit)-1; i-- { + ch, size := utf8.DecodeRune(lit[offset:]) + offset += size + d := uint32(digitVal(ch)) + if d >= base { + panic(fmt.Sprintf("charVal(%s): illegal character (%c) in escape sequence. size=%d, offset=%d", lit, ch, size, offset)) + } + x = x*base + d + } + if x > max || 0xD800 <= x && x < 0xE000 { + panic(fmt.Sprintf("Error decoding escape char value. Lit:%s, offset:%d, escape sequence is invalid Unicode code point\n", lit, offset)) + } + + return rune(x) +} + +func digitVal(ch rune) int { + switch { + case '0' <= ch && ch <= '9': + return int(ch) - '0' + case 'a' <= ch && ch <= 'f': + return int(ch) - 'a' + 10 + case 'A' <= ch && ch <= 'F': + return int(ch) - 'A' + 10 + } + return 16 // larger than any legal digit val +} diff --git a/schema/util/rune.go b/schema/util/rune.go new file mode 100644 index 0000000..bd8523a --- /dev/null +++ b/schema/util/rune.go @@ -0,0 +1,39 @@ +// Code generated by gocc; DO NOT EDIT. + +package util + +import ( + "fmt" +) + +func RuneToString(r rune) string { + if r >= 0x20 && r < 0x7f { + return fmt.Sprintf("'%c'", r) + } + switch r { + case 0x07: + return "'\\a'" + case 0x08: + return "'\\b'" + case 0x0C: + return "'\\f'" + case 0x0A: + return "'\\n'" + case 0x0D: + return "'\\r'" + case 0x09: + return "'\\t'" + case 0x0b: + return "'\\v'" + case 0x5c: + return "'\\\\\\'" + case 0x27: + return "'\\''" + case 0x22: + return "'\\\"'" + } + if r < 0x10000 { + return fmt.Sprintf("\\u%04x", r) + } + return fmt.Sprintf("\\U%08x", r) +}