@@ -51,7 +51,8 @@ type foundTypeDefinition struct {
5151
5252type context struct {
5353 imports map [string ]string // Maps import aliases to file hashes.
54- types map [string ]typeDefinition // Stores the defined types.
54+ types map [string ]typeDefinition // Stores the declared types.
55+ structs map [string ]StructDeclaration // Stores the declared structs.
5556 namedValues map [string ][]NamedValue // Stores the variable/constant name to variable/constant relation.
5657 functions map [string ]FunctionDefinition // Stores the function name to function relation.
5758 scopeStack []scope // Stores the current scopes.
@@ -63,6 +64,7 @@ func newContext() context {
6364 c := context {
6465 imports : map [string ]string {},
6566 types : map [string ]typeDefinition {},
67+ structs : map [string ]StructDeclaration {},
6668 namedValues : map [string ][]NamedValue {},
6769 functions : map [string ]FunctionDefinition {},
6870 layer : - 1 , // Init at -1 since program increases it right away.
@@ -145,7 +147,7 @@ func (c context) addType(typeName string, valueType ValueType, isAlias bool, isE
145147 _ , exists := c .findType (typeName , false )
146148
147149 if exists {
148- return fmt .Errorf ("%s has already been defined" , typeName )
150+ return fmt .Errorf ("type %s has already been defined" , typeName )
149151 }
150152 if valueType .IsSlice () {
151153 // TODO: Add support.
@@ -159,6 +161,16 @@ func (c context) addType(typeName string, valueType ValueType, isAlias bool, isE
159161 return nil
160162}
161163
164+ func (c context ) addStruct (structName string , structDeclaration StructDeclaration ) error {
165+ _ , exists := c .findStruct (structName )
166+
167+ if exists {
168+ return fmt .Errorf ("struct %s has already been defined" , structName )
169+ }
170+ c .structs [structName ] = structDeclaration
171+ return nil
172+ }
173+
162174func (c context ) addNamedValues (prefix string , global bool , namedValues ... NamedValue ) error {
163175 for _ , namedValue := range namedValues {
164176 prefixedName , err := c .buildPrefixedName (namedValue .Name (), prefix , global , false )
@@ -214,6 +226,11 @@ func (c context) findType(typeName string, searchUntilElementary bool) (foundTyp
214226 return foundDefinition , exists
215227}
216228
229+ func (c context ) findStruct (name string ) (StructDeclaration , bool ) {
230+ structDeclaration , exists := c .structs [name ]
231+ return structDeclaration , exists
232+ }
233+
217234func (c context ) findNamedValue (name string , prefix string , global bool ) (NamedValue , bool ) {
218235 prefixedName , err := c .buildPrefixedName (name , prefix , global , true )
219236
@@ -246,7 +263,8 @@ func (c context) clone() context {
246263 return context {
247264 imports : maps .Clone (c .imports ),
248265 types : maps .Clone (c .types ),
249- namedValues : maps .Clone (c .namedValues ),
266+ structs : maps .Clone (c .structs ),
267+ namedValues : maps .Clone (c .namedValues ), // TODO: Make sure this is appropriate cloning because each entry contains a slice.
250268 functions : maps .Clone (c .functions ),
251269 scopeStack : slices .Clone (c .scopeStack ),
252270 layer : c .layer ,
@@ -361,8 +379,8 @@ func allowedBinaryOperators(t ValueType) []BinaryOperator {
361379 case DATA_TYPE_STRING :
362380 operators = []BinaryOperator {BINARY_OPERATOR_ADDITION }
363381 default :
364- // For other types no operations are permitted.
365382 }
383+ // For other types no operations are permitted.
366384 }
367385 return operators
368386}
@@ -859,7 +877,7 @@ func (p *Parser) evaluateImports(ctx context) ([]Statement, error) {
859877 return nil , err
860878 }
861879 regexp := regexp .MustCompile (`package \w+` )
862- bodyBytes = regexp .ReplaceAll (bodyBytes , []byte ("" )) // Remove package statemnt.
880+ bodyBytes = regexp .ReplaceAll (bodyBytes , []byte ("" )) // Remove package statemnt.
863881
864882 err = os .WriteFile (absPath , bodyBytes , 0400 )
865883
@@ -1209,6 +1227,66 @@ func (p *Parser) evaluateValueType(ctx context) (ValueType, error) {
12091227 return evaluatedType , nil
12101228}
12111229
1230+ func (p * Parser ) evaluateStructDeclaration (ctx context ) (Statement , error ) {
1231+ structToken := p .eat ()
1232+
1233+ if structToken .Type () != lexer .STRUCT {
1234+ return nil , p .expectedKeywordError ("struct" , structToken )
1235+ }
1236+ nextToken := p .eat ()
1237+
1238+ if nextToken .Type () != lexer .OPENING_CURLY_BRACKET {
1239+ return nil , p .expectedError (`"{"` , nextToken )
1240+ }
1241+ nextToken = p .eat ()
1242+
1243+ if nextToken .Type () != lexer .NEWLINE {
1244+ return nil , p .expectedNewlineError (nextToken )
1245+ }
1246+ fields := []StructField {}
1247+
1248+ // Evaluate fields.
1249+ for {
1250+ nameTokens , err := p .evaluateNames ()
1251+
1252+ if err != nil {
1253+ return nil , err
1254+ }
1255+ valueTypeToken := p .peek ()
1256+ valueType , err := p .evaluateValueType (ctx )
1257+
1258+ if err != nil {
1259+ return nil , err
1260+ }
1261+
1262+ // Don't allow nested structs for now.
1263+ if valueType .DataType () == DATA_TYPE_STRUCT {
1264+ return nil , p .atError ("nested structs are not allowed" , valueTypeToken )
1265+ }
1266+
1267+ for _ , nameToken := range nameTokens {
1268+ fields = append (fields , StructField {
1269+ name : nameToken .Value (),
1270+ valueType : valueType ,
1271+ })
1272+ }
1273+ nextToken = p .eat ()
1274+
1275+ if nextToken .Type () != lexer .NEWLINE {
1276+ return nil , p .expectedNewlineError (nextToken )
1277+ }
1278+ nextToken = p .peek ()
1279+
1280+ if nextToken .Type () == lexer .CLOSING_CURLY_BRACKET {
1281+ p .eat () // Eat closing curly bracket and break.
1282+ break
1283+ }
1284+ }
1285+ return StructDeclaration {
1286+ fields ,
1287+ }, nil
1288+ }
1289+
12121290func (p * Parser ) evaluateTypeDeclaration (ctx context ) (Statement , error ) {
12131291 typeToken := p .eat ()
12141292
@@ -1221,20 +1299,42 @@ func (p *Parser) evaluateTypeDeclaration(ctx context) (Statement, error) {
12211299 return nil , p .expectedIdentifierError (nameToken )
12221300 }
12231301 isAlias := false
1302+ assignToken := p .peek ()
12241303
12251304 // If a type is assigned to the new type with an assign-operator,
12261305 // then it's just an alias.
1227- if p . peek () .Type () == lexer .ASSIGN_OPERATOR {
1306+ if assignToken .Type () == lexer .ASSIGN_OPERATOR {
12281307 isAlias = true
12291308 p .eat ()
12301309 }
1310+ name := nameToken .Value ()
12311311 valueTypeToken := p .peek ()
1232- valueType , err := p .evaluateValueType (ctx )
12331312
1234- if err != nil {
1235- return nil , err
1313+ var valueType ValueType
1314+ var err error
1315+
1316+ if valueTypeToken .Type () == lexer .STRUCT {
1317+ if isAlias {
1318+ return nil , p .atError ("struct alias is not supported" , assignToken )
1319+ }
1320+ structDeclaration , err := p .evaluateStructDeclaration (ctx )
1321+
1322+ if err != nil {
1323+ return nil , err
1324+ }
1325+ err = ctx .addStruct (name , structDeclaration .(StructDeclaration ))
1326+
1327+ if err != nil {
1328+ return nil , p .atError (err .Error (), nameToken )
1329+ }
1330+ valueType = NewValueType (DATA_TYPE_STRUCT , false )
1331+ } else {
1332+ valueType , err = p .evaluateValueType (ctx )
1333+
1334+ if err != nil {
1335+ return nil , err
1336+ }
12361337 }
1237- name := nameToken .Value ()
12381338 err = ctx .addType (name , valueType , isAlias , false )
12391339
12401340 if err != nil {
0 commit comments