Add parsing int, float, and string literals

This commit is contained in:
Sasha Koshka 2024-02-07 14:15:06 -05:00
parent a053eeb207
commit ebfaba0d7d
2 changed files with 81 additions and 5 deletions

View File

@ -22,8 +22,15 @@ func (this *Parser) parseExpression () (entity.Expression, error) {
// the very next token AKA the current one after parsing the
// expression.
// 3. Then, use the previously parsed expression and use it as the left
// side, and go on to parse the right side. We need a more
// 4. Repeat from step 2 if needed.
// side, and go on to parse the right side. Assignment (=) is the
// only infix expression where both left and right sides are
// expressions, so it gets to call parseExpression() and recurse. The
// implied associativity matters here.
// 4. If not assignment, then this has to do with member access (the
// right side is not an expression), so we repeat from step 2 in order
// to chain member accesses and method calls. Step 2 will test
// whether or not we need to continue repeating afterward. The
// implied associativity matters here.
// 5. Return the expression, whether it was directly parsed or is a tree
// of infix operator(s).
expression, err := this.parseExpressionRoot()
@ -40,9 +47,9 @@ func (this *Parser) parseExpressionRoot () (entity.Expression, error) {
case lexer.Ident: return this.parseExpressionRootIdent()
case lexer.LBracket: // TODO
case lexer.LParen: // TODO
case lexer.Int: // TODO
case lexer.Float: // TODO
case lexer.String: // TODO
case lexer.Int: return this.parseLiteralInt()
case lexer.Float: return this.parseLiteralFloat()
case lexer.String: return this.parseLiteralString()
}
panic(this.bug())
}
@ -55,6 +62,7 @@ func (this *Parser) parseExpressionRootIdent () (entity.Expression, error) {
this.next()
if this.token.Is(lexer.Colon) {
// Colon: declaration
return this.parseDeclarationCore(pos, name)
} else {
switch name {
@ -98,3 +106,42 @@ func (this *Parser) parseDeclarationCore (pos errors.Position, name string) (*en
Ty: ty,
}, nil
}
func (this *Parser) parseLiteralInt () (*entity.LiteralInt, error) {
err := this.expect(lexer.Int)
if err != nil { return nil, err }
defer this.next()
value, err := parseInteger(this.value())
if err != nil { return nil, errors.Errorf(this.pos(), err.Error()) }
return &entity.LiteralInt {
Position: this.pos(),
Value: int(value), // TODO struct should store as int64
}, nil
}
func (this *Parser) parseLiteralFloat () (*entity.LiteralFloat, error) {
err := this.expect(lexer.Float)
if err != nil { return nil, err }
defer this.next()
value, err := parseFloat(this.value())
if err != nil { return nil, errors.Errorf(this.pos(), err.Error()) }
return &entity.LiteralFloat {
Position: this.pos(),
Value: value,
}, nil
}
func (this *Parser) parseLiteralString () (*entity.LiteralString, error) {
err := this.expect(lexer.String)
if err != nil { return nil, err }
defer this.next()
return &entity.LiteralString {
Position: this.pos(),
ValueUTF8: this.value(),
}, nil
}

View File

@ -1,5 +1,6 @@
package parser
import "strconv"
import "git.tebibyte.media/sashakoshka/fspl/lexer"
import "git.tebibyte.media/sashakoshka/fspl/entity"
@ -41,3 +42,31 @@ func (this *Parser) parseSignature () (*entity.Signature, error) {
return signature, nil
}
func parseInteger (value string) (int64, error) {
base := 10
if len(value) >= 1 && value[0] == '0' {
base = 8
value = value[1:]
if len(value) >= 1 {
switch value[0] {
case 'x':
value = value[1:]
base = 16
case 'b':
value = value[1:]
base = 1
}
}
}
integer, err := strconv.ParseInt(value, base, 64)
if err != nil { return 0, err }
return integer, nil
}
func parseFloat (value string) (float64, error) {
float, err := strconv.ParseFloat(value, 64)
if err != nil { return 0, err }
return float, nil
}