213 lines
4.2 KiB
Go
213 lines
4.2 KiB
Go
|
// Copyright (c) 2017 Ernest Micklei
|
||
|
//
|
||
|
// MIT License
|
||
|
//
|
||
|
// Permission is hereby granted, free of charge, to any person obtaining
|
||
|
// a copy of this software and associated documentation files (the
|
||
|
// "Software"), to deal in the Software without restriction, including
|
||
|
// without limitation the rights to use, copy, modify, merge, publish,
|
||
|
// distribute, sublicense, and/or sell copies of the Software, and to
|
||
|
// permit persons to whom the Software is furnished to do so, subject to
|
||
|
// the following conditions:
|
||
|
//
|
||
|
// The above copyright notice and this permission notice shall be
|
||
|
// included in all copies or substantial portions of the Software.
|
||
|
//
|
||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||
|
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||
|
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||
|
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||
|
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||
|
|
||
|
package proto
|
||
|
|
||
|
import (
|
||
|
"strings"
|
||
|
)
|
||
|
|
||
|
// token represents a lexical token.
|
||
|
type token int
|
||
|
|
||
|
const (
|
||
|
// Special tokens
|
||
|
tILLEGAL token = iota
|
||
|
tEOF
|
||
|
tWS
|
||
|
|
||
|
// Literals
|
||
|
tIDENT
|
||
|
|
||
|
// Misc characters
|
||
|
tSEMICOLON // ;
|
||
|
tCOLON // :
|
||
|
tEQUALS // =
|
||
|
tQUOTE // "
|
||
|
tSINGLEQUOTE // '
|
||
|
tLEFTPAREN // (
|
||
|
tRIGHTPAREN // )
|
||
|
tLEFTCURLY // {
|
||
|
tRIGHTCURLY // }
|
||
|
tLEFTSQUARE // [
|
||
|
tRIGHTSQUARE // ]
|
||
|
tCOMMENT // /
|
||
|
tLESS // <
|
||
|
tGREATER // >
|
||
|
tCOMMA // ,
|
||
|
tDOT // .
|
||
|
|
||
|
// Keywords
|
||
|
keywordsStart
|
||
|
tSYNTAX
|
||
|
tSERVICE
|
||
|
tRPC
|
||
|
tRETURNS
|
||
|
tMESSAGE
|
||
|
tIMPORT
|
||
|
tPACKAGE
|
||
|
tOPTION
|
||
|
tREPEATED
|
||
|
tWEAK
|
||
|
tPUBLIC
|
||
|
|
||
|
// special fields
|
||
|
tONEOF
|
||
|
tMAP
|
||
|
tRESERVED
|
||
|
tENUM
|
||
|
tSTREAM
|
||
|
|
||
|
// BEGIN proto2
|
||
|
tOPTIONAL
|
||
|
tGROUP
|
||
|
tEXTENSIONS
|
||
|
tEXTEND
|
||
|
tREQUIRED
|
||
|
// END proto2
|
||
|
keywordsEnd
|
||
|
)
|
||
|
|
||
|
// typeTokens exists for future validation
|
||
|
// const typeTokens = "double float int32 int64 uint32 uint64 sint32 sint64 fixed32 sfixed32 sfixed64 bool string bytes"
|
||
|
|
||
|
// isKeyword returns if tok is in the keywords range
|
||
|
func isKeyword(tok token) bool {
|
||
|
return keywordsStart < tok && tok < keywordsEnd
|
||
|
}
|
||
|
|
||
|
// isWhitespace checks for space,tab and newline
|
||
|
func isWhitespace(r rune) bool {
|
||
|
return r == ' ' || r == '\t' || r == '\n'
|
||
|
}
|
||
|
|
||
|
// isDigit returns true if the rune is a digit.
|
||
|
func isDigit(ch rune) bool { return (ch >= '0' && ch <= '9') }
|
||
|
|
||
|
// isString checks if the literal is quoted (single or double).
|
||
|
func isString(lit string) bool {
|
||
|
return (strings.HasPrefix(lit, "\"") &&
|
||
|
strings.HasSuffix(lit, "\"")) ||
|
||
|
(strings.HasPrefix(lit, "'") &&
|
||
|
strings.HasSuffix(lit, "'"))
|
||
|
}
|
||
|
|
||
|
func isComment(lit string) bool {
|
||
|
return strings.HasPrefix(lit, "//") || strings.HasPrefix(lit, "/*")
|
||
|
}
|
||
|
|
||
|
func unQuote(lit string) string {
|
||
|
return strings.Trim(lit, "\"'")
|
||
|
}
|
||
|
|
||
|
func asToken(literal string) token {
|
||
|
switch literal {
|
||
|
// delimiters
|
||
|
case ";":
|
||
|
return tSEMICOLON
|
||
|
case ":":
|
||
|
return tCOLON
|
||
|
case "=":
|
||
|
return tEQUALS
|
||
|
case "\"":
|
||
|
return tQUOTE
|
||
|
case "'":
|
||
|
return tSINGLEQUOTE
|
||
|
case "(":
|
||
|
return tLEFTPAREN
|
||
|
case ")":
|
||
|
return tRIGHTPAREN
|
||
|
case "{":
|
||
|
return tLEFTCURLY
|
||
|
case "}":
|
||
|
return tRIGHTCURLY
|
||
|
case "[":
|
||
|
return tLEFTSQUARE
|
||
|
case "]":
|
||
|
return tRIGHTSQUARE
|
||
|
case "<":
|
||
|
return tLESS
|
||
|
case ">":
|
||
|
return tGREATER
|
||
|
case ",":
|
||
|
return tCOMMA
|
||
|
case ".":
|
||
|
return tDOT
|
||
|
// words
|
||
|
case "syntax":
|
||
|
return tSYNTAX
|
||
|
case "service":
|
||
|
return tSERVICE
|
||
|
case "rpc":
|
||
|
return tRPC
|
||
|
case "returns":
|
||
|
return tRETURNS
|
||
|
case "option":
|
||
|
return tOPTION
|
||
|
case "message":
|
||
|
return tMESSAGE
|
||
|
case "import":
|
||
|
return tIMPORT
|
||
|
case "package":
|
||
|
return tPACKAGE
|
||
|
case "oneof":
|
||
|
return tONEOF
|
||
|
// special fields
|
||
|
case "map":
|
||
|
return tMAP
|
||
|
case "reserved":
|
||
|
return tRESERVED
|
||
|
case "enum":
|
||
|
return tENUM
|
||
|
case "repeated":
|
||
|
return tREPEATED
|
||
|
case "weak":
|
||
|
return tWEAK
|
||
|
case "public":
|
||
|
return tPUBLIC
|
||
|
case "stream":
|
||
|
return tSTREAM
|
||
|
// proto2
|
||
|
case "optional":
|
||
|
return tOPTIONAL
|
||
|
case "group":
|
||
|
return tGROUP
|
||
|
case "extensions":
|
||
|
return tEXTENSIONS
|
||
|
case "extend":
|
||
|
return tEXTEND
|
||
|
case "required":
|
||
|
return tREQUIRED
|
||
|
case "ws":
|
||
|
return tWS
|
||
|
case "ill":
|
||
|
return tILLEGAL
|
||
|
default:
|
||
|
// special cases
|
||
|
if isComment(literal) {
|
||
|
return tCOMMENT
|
||
|
}
|
||
|
return tIDENT
|
||
|
}
|
||
|
}
|