Beispiel #1
0
func lexHexConstant(l *Lexer) (Token, interface{}) {
	startPos := l.pos
	endPos := l.pos
	for {
		//Find the end of the constant
		if l.hasNextFunc(char.IsHexDigit) {
			endPos++
		} else {
			//Check if the number is invalid.
			//We already know the next rune is not a hex digit
			if char.IsInVarName(l.peek()) {
				return ArithError, LexError{
					X:   l.input[startPos-2 : endPos+1],
					Err: ErrHexConstant,
				}
			}
			break
		}
	}
	parsedVal, err := strconv.ParseInt(l.input[startPos:endPos], 16, 64)
	if err != nil {
		panic("Not Reached: Broken Hex Constant")
	}
	return ArithNumber, parsedVal
}
Beispiel #2
0
func IsAssignment(s string) bool {
	rs := []rune(s)
	if !char.IsFirstInVarName(rs[0]) {
		return false
	}
	for _, c := range rs[1:] {
		if !char.IsInVarName(c) {
			return c == '='
		}
	}
	return false
}
Beispiel #3
0
func IsGoodName(s string) bool {
	rs := []rune(s)
	if !char.IsFirstInVarName(rs[0]) {
		return false
	}
	for _, c := range rs[1:] {
		if !char.IsInVarName(c) {
			return false
		}
	}
	return true
}
Beispiel #4
0
func (l *Lexer) VariableSimple() {
	// When we enter this state we know we have at least one readable
	// char for the varname. That means that any character not valid
	// just terminates the parsing and we dont have to
	// worry about the case of an empty varname
	l.buffer.WriteRune(SentinalSubstitution)
	sv := SubVariable{SubType: VarSubNormal}
	varbuf := bytes.Buffer{}

	c := l.nextChar()
	switch {
	case char.IsSpecial(c):
		varbuf.WriteRune(c)
	case char.IsDigit(c):
		// Positional argv
		for {
			varbuf.WriteRune(c)
			c = l.nextChar()
			if !char.IsDigit(c) {
				l.backup()
				break
			}
		}
	case char.IsFirstInVarName(c):
		for {
			varbuf.WriteRune(c)
			c = l.nextChar()
			if !char.IsInVarName(c) {
				l.backup()
				break
			}
		}
	default:
		l.backup()
	}

	sv.VarName = varbuf.String()
	l.subs = append(l.subs, sv)
	return
}
Beispiel #5
0
func lexOctalConstant(l *Lexer) (Token, interface{}) {
	startPos := l.pos - l.lastRuneWidth
	endPos := l.pos
	for {
		if l.hasNextFunc(char.IsOctalDigit) {
			endPos++
		} else {
			if char.IsInVarName(l.peek()) {
				return ArithError, LexError{
					X:   l.input[startPos-1 : endPos+1],
					Err: ErrOctalConstant,
				}
			}
			break
		}
	}
	parsedVal, err := strconv.ParseInt(l.input[startPos:endPos], 8, 64)
	if err != nil {
		panic("Not Reached: Broken Octal Constant")
	}
	return ArithNumber, parsedVal
}
Beispiel #6
0
func (l *Lexer) VariableComplex() {
	// Upon entering we have read the opening '{'
	l.buffer.WriteRune(SentinalSubstitution)
	sv := SubVariable{}
	varbuf := bytes.Buffer{}

	defer func() {
		// We defer this as there are multiple return points
		sv.VarName = varbuf.String()
		l.subs = append(l.subs, sv)
	}()

	if l.hasNext('#') {
		// The NParam Special Var
		if l.hasNext('}') {
			varbuf.WriteRune('#')
			return
		}

		// Length variable operator
		sv.SubType = VarSubLength
	}

	c := l.nextChar()
	switch {
	case char.IsSpecial(c):
		varbuf.WriteRune(c)
	case char.IsDigit(c):
		for {
			varbuf.WriteRune(c)
			c = l.nextChar()
			if !char.IsDigit(c) {
				l.backup()
				break
			}
		}
	case char.IsFirstInVarName(c):
		for {
			varbuf.WriteRune(c)
			c = l.nextChar()
			if !char.IsInVarName(c) {
				l.backup()
				break
			}
		}
	case c == EOFRune:
		l.backup()
		return
	}

	// Either a Enclosed variable '${foo}' or a length operation '${#foo}'
	if l.hasNext('}') {
		return
	}

	// Length operator should have returned since only ${#varname} is valid
	if sv.SubType == VarSubLength {
		l.log.Error("Line %d: Bad substitution (%s)", l.lineNo, l.input[l.lastPosition:l.position])
		os.Exit(1)
	}

	if l.hasNext(':') {
		sv.CheckNull = true
	}

	switch l.nextChar() {
	case '-':
		sv.SubType = VarSubMinus
	case '+':
		sv.SubType = VarSubPlus
	case '?':
		sv.SubType = VarSubQuestion
	case '=':
		sv.SubType = VarSubAssign
	case '#':
		if l.hasNext('#') {
			sv.SubType = VarSubTrimLeftMax
		} else {
			sv.SubType = VarSubTrimLeft
		}
	case '%':
		if l.hasNext('%') {
			sv.SubType = VarSubTrimRightMax
		} else {
			sv.SubType = VarSubTrimRight
		}
	default:
		l.log.Error("Line %d: Bad substitution (%s)", l.lineNo, l.input[l.lastPosition:l.position])
		os.Exit(1)
	}

	// Read until '}'
	// In the future to support Nested vars etc create new sublexer from
	// l.input[l.pos:] and take the first lexitem as the sub val then adjust
	// this lexer's position and trash sublexer
	c = l.nextChar()
	subValBuf := bytes.Buffer{}
	for {
		if c == '}' {
			break
		}
		subValBuf.WriteRune(c)
		c = l.nextChar()
	}
	sv.SubVal = subValBuf.String()
}