Added string literal to parser

This commit is contained in:
Sasha Koshka 2023-11-26 05:16:40 -05:00
parent 496a8c5e78
commit d0245e4375
4 changed files with 99 additions and 57 deletions

View File

@ -1,6 +1,7 @@
package entity
import "fmt"
import "unicode"
import "github.com/alecthomas/participle/v2/lexer"
// LiteralInt specifies an integer value. It can be assigned to any type that is
@ -42,6 +43,46 @@ func (this *LiteralFloat) String () string {
return fmt.Sprint(this.Value)
}
// LiteralString specifies a string value. It takes on different data
// representations depending on what the base type of what it is assigned to is
// structurally equivalent to:
// - Integer: Single unicode code point. When assigning to an integer, the
// string literal may not be longer than one code point, and that code point
// must fit in the integer.
// - Slice of 8 bit integers: UTF-8 string.
// - Slice of 16 bit integers: UTF-16 string.
// - Slice of 32 bit (or larger) integers: UTF-32 string.
// - Array of integers: The same as slices of integers, but the string literal
// must fit inside of the array.
// - Byte pointer: Null-terminated UTF-8 string (AKA C-string).
// A string literal cannot be directly assigned to an interface because it
// contains no inherent type information. A value cast may be used for this
// purpose.
type LiteralString struct {
// Syntax
Pos lexer.Position
Value string `parser:" @String "`
// Semantics
Ty Type
}
func (*LiteralString) expression(){}
func (*LiteralString) statement(){}
func (this *LiteralString) Type () Type { return this.Ty }
func (this *LiteralString) String () string {
out := "'"
for _, char := range this.Value {
if char == '\'' {
out += "\\'"
} else if unicode.IsPrint(char) {
out += string(char)
} else {
out += fmt.Sprintf("\\%03o", char)
}
}
return out + "'"
}
// LiteralArray is a composite array literal. It can contain any number of
// values. It can be assigned to any array type that:
// 1. has an identical length, and

View File

@ -149,9 +149,7 @@ func (this *fsplLexer) nextInternal () (token lexer.Token, err error) {
err = this.nextRune()
if err != nil { return }
println("NEW STRING")
for this.rune != '\'' {
println(string(this.rune))
if this.rune == '\\' {
var result rune
result, err = this.escapeSequence()

View File

@ -35,7 +35,8 @@ testString (test,
[float]:F64 = 324.23409
[boolean]:Bool = true
[boolean2]:Bool = false
[struct]:(x:Int y:(w:F64 z:F64)) = (x:1 y:(w:1.2 z:78.5))`,
[struct]:(x:Int y:(w:F64 z:F64)) = (x:1 y:(w:1.2 z:78.5))
[string]:String = 'hahah \'sup\005'`,
// input
`
[int]:Int = 5
@ -43,6 +44,7 @@ testString (test,
[boolean]:Bool = true
[boolean2]:Bool = false
[struct]:(x:Int y:(w:F64 z:F64)) = (x: 1 y: (w: 1.2 z: 78.5))
[string]:String = 'hahah \'sup\005'
`)
}

View File

@ -9,63 +9,64 @@ import flexer "git.tebibyte.media/sashakoshka/fspl/lexer"
var parser = participle.MustBuild[Tree] (
participle.Union[entity.TopLevel] (
&entity.Function { },
&entity.Typedef { },
&entity.Method { }),
new(entity.Function),
new(entity.Typedef),
new(entity.Method)),
participle.Union[entity.Type] (
&entity.TypeNamed { },
&entity.TypePointer { },
&entity.TypeInterface { },
&entity.TypeStruct { },
&entity.TypeArray { },
&entity.TypeSlice { }),
new(entity.TypeNamed),
new(entity.TypePointer),
new(entity.TypeInterface),
new(entity.TypeStruct),
new(entity.TypeArray),
new(entity.TypeSlice)),
participle.Union[entity.Expression] (
&entity.LiteralInt { },
&entity.LiteralFloat { },
&entity.LiteralArray { },
&entity.LiteralStruct { },
&entity.LiteralBoolean { },
&entity.Break { },
&entity.Return { },
&entity.IfElse { },
&entity.Loop { },
&entity.MethodCall { },
&entity.MemberAccess { },
&entity.Declaration { },
&entity.Variable { },
&entity.Subscript { },
&entity.Slice { },
&entity.Dereference { },
&entity.Reference { },
&entity.ValueCast { },
&entity.BitCast { },
&entity.Operation { },
&entity.Call { },
&entity.Block { }),
new(entity.LiteralInt),
new(entity.LiteralFloat),
new(entity.LiteralString),
new(entity.LiteralArray),
new(entity.LiteralStruct),
new(entity.LiteralBoolean),
new(entity.Break),
new(entity.Return),
new(entity.IfElse),
new(entity.Loop),
new(entity.MethodCall),
new(entity.MemberAccess),
new(entity.Declaration),
new(entity.Variable),
new(entity.Subscript),
new(entity.Slice),
new(entity.Dereference),
new(entity.Reference),
new(entity.ValueCast),
new(entity.BitCast),
new(entity.Operation),
new(entity.Call),
new(entity.Block)),
participle.Union[entity.Statement] (
&entity.LiteralInt { },
&entity.LiteralFloat { },
&entity.LiteralArray { },
&entity.LiteralStruct { },
&entity.LiteralBoolean { },
&entity.Break { },
&entity.Return { },
&entity.Assignment { },
&entity.IfElse { },
&entity.Loop { },
&entity.MethodCall { },
&entity.MemberAccess { },
&entity.Declaration { },
&entity.Variable { },
&entity.Subscript { },
&entity.Slice { },
&entity.Dereference { },
&entity.Reference { },
&entity.ValueCast { },
&entity.BitCast { },
&entity.Operation { },
&entity.Call { },
&entity.Block { }),
new(entity.LiteralInt),
new(entity.LiteralFloat),
new(entity.LiteralArray),
new(entity.LiteralStruct),
new(entity.LiteralBoolean),
new(entity.Break),
new(entity.Return),
new(entity.Assignment),
new(entity.IfElse),
new(entity.Loop),
new(entity.MethodCall),
new(entity.MemberAccess),
new(entity.Declaration),
new(entity.Variable),
new(entity.Subscript),
new(entity.Slice),
new(entity.Dereference),
new(entity.Reference),
new(entity.ValueCast),
new(entity.BitCast),
new(entity.Operation),
new(entity.Call),
new(entity.Block)),
participle.UseLookahead(participle.MaxLookahead),
participle.Lexer(flexer.NewDefinition()))