Exemple #1
0
// nextPeriod parse a '.'.
func (s *Scanner) nextPeriod() token.Token {

	// skip '.'
	if err := s.next(); err != nil {
		return token.New(token.ERROR, err.Error(), s.pos)
	}

	if digit(s.char) {
		return s.nextNumber(true)
	}

	pos := s.pos

	if s.char == '.' {
		if err := s.next(); err != nil {
			return token.New(token.ERROR, err.Error(), s.pos)
		}
		if s.char == '.' {
			s.next()
			return token.New(token.ELLIPSIS, "...", pos)
		}
		return token.New(token.ERROR, "unexpected "+string(s.char), s.pos)
	}
	return token.New(token.PERIOD, token.PERIOD.String(), s.pos)
}
Exemple #2
0
// nextNumber parse a number.
func (s *Scanner) nextNumber(decimal bool) token.Token {
	pos := s.pos
	if decimal {

		buffer := bytes.NewBufferString(".")

		for digit(s.char) {
			buffer.WriteRune(s.char)
			if err := s.next(); err != nil {
				return token.New(token.ERROR, err.Error(), s.pos)
			}
		}
		return token.New(token.FLOAT, buffer.String(), pos)
	}

	tok := token.INT
	buffer := bytes.NewBufferString("")

	for digit(s.char) || s.char == '.' {
		buffer.WriteRune(s.char)
		if s.char == '.' {
			tok = token.FLOAT
		}
		if err := s.next(); err != nil {
			return token.New(token.ERROR, err.Error(), s.pos)
		}
	}
	return token.New(tok, buffer.String(), pos)
}
Exemple #3
0
// scanner method helpers
//
func (s *Scanner) switch2(tok0, tok1 token.Type) token.Token {
	if s.char == '=' {
		if err := s.next(); err != nil {
			return token.New(token.ERROR, err.Error(), s.pos)
		}
		return token.New(tok1, tok1.String(), s.pos)
	}
	return token.New(tok0, tok0.String(), s.pos)
}
Exemple #4
0
// nextAmpersand parse a '&'.
func (s *Scanner) nextAmpersand() token.Token {
	// skip '&'
	if err := s.next(); err != nil {
		return token.New(token.ERROR, err.Error(), s.pos)
	}
	if s.char == '^' {
		if err := s.next(); err != nil {
			return token.New(token.ERROR, err.Error(), s.pos)
		}
		return s.switch2(token.AndNot, token.AndNotAssign)
	}
	return s.switch3(token.AND, token.AndAssign, '&', token.LAND)
}
Exemple #5
0
// nextPipe parse a '|'.
func (s *Scanner) nextPipe() token.Token {
	// skip '|'
	if err := s.next(); err != nil {
		return token.New(token.ERROR, err.Error(), s.pos)
	}
	return s.switch3(token.OR, token.ORAssign, '|', token.LOR)
}
Exemple #6
0
// nextStar parse a '*'.
func (s *Scanner) nextStar() token.Token {
	// skip '*'
	if err := s.next(); err != nil {
		return token.New(token.ERROR, err.Error(), s.pos)
	}
	return s.switch2(token.MUL, token.MulAssign)
}
Exemple #7
0
// nextLess parse a '<'.
func (s *Scanner) nextLess() token.Token {

	// skip '<'
	if err := s.next(); err != nil {
		return token.New(token.ERROR, err.Error(), s.pos)
	}
	if s.char == '-' {

		// skip '-'
		if err := s.next(); err != nil {
			return token.New(token.ERROR, err.Error(), s.pos)
		}
		return token.New(token.ARROW, token.ARROW.String(), s.pos)
	}
	return s.switch4(token.LSS, token.LEQ, '<', token.SHL, token.ShlAssign)
}
Exemple #8
0
// nextDash parse a '-'.
func (s *Scanner) nextDash() token.Token {
	// skip '-'
	if err := s.next(); err != nil {
		return token.New(token.ERROR, err.Error(), s.pos)
	}
	return s.switch3(token.SUB, token.SubAssign, '-', token.DEC)
}
Exemple #9
0
// nextCaret parse a '^'.
func (s *Scanner) nextCaret() token.Token {
	// skip '^'
	if err := s.next(); err != nil {
		return token.New(token.ERROR, err.Error(), s.pos)
	}
	return s.switch2(token.XOR, token.XORAssign)
}
Exemple #10
0
// nextGreater parse a '>'.
func (s *Scanner) nextGreater() token.Token {
	// skip '>'
	if err := s.next(); err != nil {
		return token.New(token.ERROR, err.Error(), s.pos)
	}
	return s.switch4(token.GTR, token.GEQ, '>', token.SHR, token.ShrAssign)
}
Exemple #11
0
// nextEqual parse a '='.
func (s *Scanner) nextEqual() token.Token {
	// skip '='
	if err := s.next(); err != nil {
		return token.New(token.ERROR, err.Error(), s.pos)
	}
	return s.switch2(token.ASSIGN, token.EQL)
}
Exemple #12
0
// nextBang parse a '!'.
func (s *Scanner) nextBang() token.Token {
	// skip '!'
	if err := s.next(); err != nil {
		return token.New(token.ERROR, err.Error(), s.pos)
	}
	return s.switch2(token.NOT, token.NEQ)
}
Exemple #13
0
// nextPercent parse a '%'.
func (s *Scanner) nextPercent() token.Token {
	// skip '%'
	if err := s.next(); err != nil {
		return token.New(token.ERROR, err.Error(), s.pos)
	}
	return s.switch2(token.REM, token.RemAssign)
}
Exemple #14
0
// nextPlus parse a '+'.
func (s *Scanner) nextPlus() token.Token {
	// skip '+'
	if err := s.next(); err != nil {
		return token.New(token.ERROR, err.Error(), s.pos)
	}
	return s.switch3(token.ADD, token.AddAssign, '+', token.INC)
}
Exemple #15
0
// nextIdentifier sets a global token to next name.
func (s *Scanner) nextIdentifier() token.Token {
	pos := s.pos
	buffer := bytes.NewBufferString("")

	for letterOrDigit(s.char) {
		buffer.WriteRune(s.char)
		if err := s.next(); err != nil {
			return token.New(token.ERROR, err.Error(), s.pos)
		}
	}

	lit := buffer.String()
	if len(lit) > 1 {
		return token.New(token.Lookup(lit), lit, pos)
	}
	return token.New(token.IDENT, lit, s.pos)
}
Exemple #16
0
// nextColon parse a ':'.
func (s *Scanner) nextColon() token.Token {

	// skip ':'
	if err := s.next(); err != nil {
		return token.New(token.ERROR, err.Error(), s.pos)
	}
	return s.switch2(token.COLON, token.DEFINE)
}
Exemple #17
0
// nextSlash parse a '/'.
func (s *Scanner) nextSlash() token.Token {
	// skip '/'
	if err := s.next(); err != nil {
		return token.New(token.ERROR, err.Error(), s.pos)
	}
	if s.char == '/' || s.char == '*' {
		return s.nextComment()
	}
	return s.switch2(token.QUO, token.QuoAssign)
}
Exemple #18
0
// nextString parse a string constant.
func (s *Scanner) nextString() token.Token {
	pos := s.pos
	buffer := bytes.NewBufferString("")

	// skip '"'
	if err := s.next(); err != nil {
		return token.New(token.ERROR, err.Error(), s.pos)
	}

	for s.char != '"' && !endOfLine(s.char) {
		buffer.WriteRune(s.char)
		if err := s.next(); err != nil {
			return token.New(token.ERROR, err.Error(), s.pos)
		}
	}

	if s.char != '"' {
		return token.New(token.ERROR, "string has no closing quote", pos)
	}
	if err := s.next(); err != nil {
		return token.New(token.ERROR, err.Error(), s.pos)
	}
	return token.New(token.STRING, buffer.String(), pos)
}
Exemple #19
0
// nextEOF parse a EOF.
func (s *Scanner) nextEOF() token.Token {
	return token.New(token.EOF, token.EOF.String(), s.pos)
}
Exemple #20
0
// nextComma parse a ','.
func (s *Scanner) nextComma() token.Token {
	if err := s.next(); err != nil {
		return token.New(token.ERROR, err.Error(), s.pos)
	}
	return token.New(token.COMMA, token.COMMA.String(), s.pos)
}
Exemple #21
0
// nextCloseParen parse a ')'.
func (s *Scanner) nextCloseParen() token.Token {
	if err := s.next(); err != nil {
		return token.New(token.ERROR, err.Error(), s.pos)
	}
	return token.New(token.RPAREN, token.RPAREN.String(), s.pos)
}
Exemple #22
0
// nextOpenBracket parse a '['.
func (s *Scanner) nextOpenBracket() token.Token {
	if err := s.next(); err != nil {
		return token.New(token.ERROR, err.Error(), s.pos)
	}
	return token.New(token.LBRACK, token.LBRACK.String(), s.pos)
}
Exemple #23
0
// Scan returns the next token.Tokem in the source.
func (s *Scanner) Scan() token.Token {

	// skip any blank spaces
	if err := s.skipSpaces(); err != nil {
		return token.New(token.ERROR, err.Error(), s.pos)
	}

	// letters yield identifiers
	if letter(s.char) {
		return s.nextIdentifier()
	}

	// digits yield numbers
	if digit(s.char) {
		return s.nextNumber(false)
	}

	// determine char
	switch s.char {
	case reader.EOF:
		return s.nextEOF()
	case '"':
		return s.nextString()
	case ':':
		return s.nextColon()
	case '.':
		return s.nextPeriod()
	case ',':
		return s.nextComma()
	case '(':
		return s.nextOpenParen()
	case ')':
		return s.nextCloseParen()
	case '[':
		return s.nextOpenBracket()
	case ']':
		return s.nextCloseBracket()
	case '{':
		return s.nextOpenBrace()
	case '}':
		return s.nextCloseBrace()
	case '+':
		return s.nextPlus()
	case '-':
		return s.nextDash()
	case '*':
		return s.nextStar()
	case '/':
		return s.nextSlash()
	case '%':
		return s.nextPercent()
	case '^':
		return s.nextCaret()
	case '<':
		return s.nextLess()
	case '>':
		return s.nextGreater()
	case '=':
		return s.nextEqual()
	case '!':
		return s.nextBang()
	case '&':
		return s.nextAmpersand()
	case '|':
		return s.nextPipe()
	default:
		return token.New(token.ERROR, fmt.Sprintf("unexpected '%c'", s.char), s.pos)
	}
}
Exemple #24
0
// nextCloseBrace parse a '}'.
func (s *Scanner) nextCloseBrace() token.Token {
	if err := s.next(); err != nil {
		return token.New(token.ERROR, err.Error(), s.pos)
	}
	return token.New(token.RBRACE, token.RBRACE.String(), s.pos)
}
Exemple #25
0
// nextComment parse comment styles '//' or '/**/'.
func (s *Scanner) nextComment() token.Token {
	pos := s.pos
	// '/' already consumed

	buffer := bytes.NewBufferString("")

	//- style comment
	if s.char == '/' {
		if err := s.next(); err != nil {
			return token.New(token.ERROR, err.Error(), s.pos)
		}

		if err := s.skipSpaces(); err != nil {
			return token.New(token.ERROR, err.Error(), s.pos)
		}

		for !endOfLine(s.char) && s.char != reader.EOF {
			buffer.WriteRune(s.char)
			if err := s.next(); err != nil {
				return token.New(token.ERROR, err.Error(), s.pos)
			}
		}
		return token.New(token.COMMENT, buffer.String(), pos)
	}

	/*- style comment */
	if s.char == '*' {
		if err := s.next(); err != nil {
			return token.New(token.ERROR, err.Error(), s.pos)
		}

		if err := s.skipSpaces(); err != nil {
			return token.New(token.ERROR, err.Error(), s.pos)
		}

		ch := s.char

		if err := s.next(); err != nil {
			return token.New(token.ERROR, err.Error(), s.pos)
		}
		for s.char != reader.EOF {
			if ch == '*' && s.char == '/' {
				return token.New(token.COMMENT, buffer.String(), pos)
			}

			buffer.WriteRune(ch)
			ch = s.char

			if err := s.next(); err != nil {
				return token.New(token.ERROR, err.Error(), s.pos)
			}
		}
		return token.New(token.ERROR, "comment never terminated", s.pos)
	}

	return token.New(token.ERROR, "bug: comment parsing", s.pos)
}