Beispiel #1
0
func (s *Scanner) scanNumber() (token.Pos, string) {
	start := s.off
	for unicode.IsDigit(s.ch) {
		s.next()
	}
	return token.Pos(start), s.str[start:s.off]
}
Beispiel #2
0
func (s *Scanner) scanComment() (token.Pos, string) {
	start := s.off - 1
	for s.ch != '\n' && s.off < len(s.str) {
		s.next()
	}
	return token.Pos(start), s.str[start:s.off]
}
Beispiel #3
0
func (s *Scanner) scanIdentifier() (token.Pos, string) {
	start := s.off
	for unicode.IsDigit(s.ch) || isAlpha(s.ch) || s.ch == '_' || s.ch == '-' {
		s.next()
	}
	return token.Pos(start), s.str[start:s.off]
}
Beispiel #4
0
func ParseFile(f *token.File, str string) *ast.File {
	if f.Size() != len(str) {
		fmt.Println("File size does not match string length.")
		return nil
	}

	root := ast.NewFile(token.Pos(1), token.Pos(len(str)+1))
	p := new(parser)
	p.init(f, str)
	p.topScope = root.Scope
	p.curScope = root.Scope
	n := p.parse()
	for p.file.NumErrors() < 10 && p.tok != token.EOF {
		root.Nodes = append(root.Nodes, n)
		p.next()
		n = p.parse()
	}
	if p.topScope != p.curScope {
		panic("Imbalanced scope!")
	}
	return root
}
Beispiel #5
0
func (s *Scanner) next() {
	s.off = s.roff
	if s.off < len(s.str) {
		r, n := utf8.DecodeRuneInString(s.str[s.off:])
		if r == utf8.RuneError {
			s.file.AddError(s.file.Base()+token.Pos(s.off), "Invalid UTF8 string!")
			return
		}
		s.ch = r
		s.roff += n
	} else {
		s.ch = 0
	}
	if s.ch == '\n' {
		s.file.AddLine(s.off)
	}
	//s.roff++
}
Beispiel #6
0
func (s *Scanner) Scan() (tok token.Token, pos token.Pos, lit string) {
	s.skipWhitespace()

	if isAlpha(s.ch) {
		pos, lit = s.scanIdentifier()
		tok = token.Lookup(lit)
		return
	}
	if unicode.IsDigit(s.ch) {
		pos, lit = s.scanNumber()
		return token.NUMBER, pos, lit
	}
	ch := s.ch
	pos = token.Pos(s.off)
	s.next()
	switch ch {
	case '+':
		tok = token.ADD
	case '-':
		if unicode.IsDigit(s.ch) { // is '-' a unary operator for a number?
			pos, lit = s.scanNumber()
			pos, lit, tok = pos-1, string('-')+lit, token.NUMBER
			return
		}
		tok = token.SUB
	case '*':
		tok = token.MUL
	case '/':
		tok = token.DIV
	case '%':
		tok = token.MOD
	case '(':
		tok = token.LPAREN
	case ')':
		tok = token.RPAREN
	case ';':
		pos, lit = s.scanComment()
		tok = token.COMMENT
		return
	case '=':
		tok = token.EQ
	case '<':
		switch s.ch {
		case '=':
			lit = string(ch) + string(s.ch)
			tok = token.LTE
			s.next()
			return
		case '>':
			lit = string(ch) + string(s.ch)
			tok = token.NEQ
			s.next()
			return
		}
		tok = token.LT
	case '>':
		if s.ch == '=' {
			lit = string(ch) + string(s.ch)
			tok = token.GTE
			s.next()
			return
		}
		tok = token.GT
	case '"':
		lit = s.scanString()
		tok = token.STRING
		return
	default:
		if s.off >= len(s.str) {
			tok = token.EOF
			pos = token.Pos(s.off)
			return
		}
	}
	lit = string(ch)
	return
}
Beispiel #7
0
func (n *Number) End() token.Pos { return n.Num + token.Pos(len(n.Lit)) }
Beispiel #8
0
func (i *Identifier) End() token.Pos { return i.Id + token.Pos(len(i.Lit)) }
Beispiel #9
0
func (s *String) End() token.Pos { return s.Str + token.Pos(len(s.Lit)) }