Separated data.go
This commit is contained in:
		
							parent
							
								
									845c12c78b
								
							
						
					
					
						commit
						aff2e55aa5
					
				
							
								
								
									
										270
									
								
								parser/data.go
									
									
									
									
									
								
							
							
						
						
									
										270
									
								
								parser/data.go
									
									
									
									
									
								
							| @ -2,7 +2,6 @@ package parser | |||||||
| 
 | 
 | ||||||
| import "git.tebibyte.media/arf/arf/types" | import "git.tebibyte.media/arf/arf/types" | ||||||
| import "git.tebibyte.media/arf/arf/lexer" | import "git.tebibyte.media/arf/arf/lexer" | ||||||
| import "git.tebibyte.media/arf/arf/infoerr" |  | ||||||
| 
 | 
 | ||||||
| // parseData parses a data section. | // parseData parses a data section. | ||||||
| func (parser *ParsingOperation) parseDataSection () ( | func (parser *ParsingOperation) parseDataSection () ( | ||||||
| @ -46,272 +45,3 @@ func (parser *ParsingOperation) parseDataSection () ( | |||||||
| 	} | 	} | ||||||
| 	return | 	return | ||||||
| } | } | ||||||
| 
 |  | ||||||
| // parseInitializationValues starts on the line after a data section, or a set |  | ||||||
| // phrase. It checks for an indent greater than the indent of the aforementioned |  | ||||||
| // data section or set phrase (passed through baseIndent), and if there is, |  | ||||||
| // it parses initialization values. |  | ||||||
| func (parser *ParsingOperation) parseInitializationValues ( |  | ||||||
| 	baseIndent int, |  | ||||||
| ) ( |  | ||||||
| 	initializationArgument Argument, |  | ||||||
| 	err error, |  | ||||||
| ) { |  | ||||||
| 	// check if line is indented one more than baseIndent |  | ||||||
| 	if !parser.token.Is(lexer.TokenKindIndent) { return } |  | ||||||
| 	if parser.token.Value().(int) != baseIndent + 1 { return } |  | ||||||
| 
 |  | ||||||
| 	initializationArgument.location = parser.token.Location() |  | ||||||
| 	 |  | ||||||
| 	err = parser.nextToken() |  | ||||||
| 	if err != nil { return } |  | ||||||
| 
 |  | ||||||
| 	if parser.token.Is(lexer.TokenKindDot) { |  | ||||||
| 
 |  | ||||||
| 		// object initialization |  | ||||||
| 		parser.previousToken() |  | ||||||
| 		var initializationValues ObjectInitializationValues |  | ||||||
| 		initializationValues, err    = parser.parseObjectInitializationValues() |  | ||||||
| 		initializationArgument.kind  = ArgumentKindObjectInitializationValues |  | ||||||
| 		initializationArgument.value = initializationValues |  | ||||||
| 		 |  | ||||||
| 	} else { |  | ||||||
| 	 |  | ||||||
| 		// array initialization |  | ||||||
| 		parser.previousToken() |  | ||||||
| 		var initializationValues ArrayInitializationValues |  | ||||||
| 		initializationValues, err    = parser.parseArrayInitializationValues() |  | ||||||
| 		initializationArgument.kind  = ArgumentKindArrayInitializationValues |  | ||||||
| 		initializationArgument.value = initializationValues |  | ||||||
| 	} |  | ||||||
| 	 |  | ||||||
| 	return |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // parseObjectInitializationValues parses a list of object initialization |  | ||||||
| // values until the indentation level drops. |  | ||||||
| func (parser *ParsingOperation) parseObjectInitializationValues () ( |  | ||||||
| 	initializationValues ObjectInitializationValues, |  | ||||||
| 	err                  error, |  | ||||||
| ) { |  | ||||||
| 	initializationValues.attributes = make(map[string] Argument) |  | ||||||
| 
 |  | ||||||
| 	baseIndent := 0 |  | ||||||
| 	begin      := true |  | ||||||
| 	 |  | ||||||
| 	for { |  | ||||||
| 		// if there is no indent we can just stop parsing |  | ||||||
| 		if !parser.token.Is(lexer.TokenKindIndent) { break} |  | ||||||
| 		indent := parser.token.Value().(int) |  | ||||||
| 		 |  | ||||||
| 		if begin == true { |  | ||||||
| 			initializationValues.location = parser.token.Location() |  | ||||||
| 			baseIndent = indent  |  | ||||||
| 			begin      = false |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		// do not parse any further if the indent has changed |  | ||||||
| 		if indent != baseIndent { break } |  | ||||||
| 
 |  | ||||||
| 		// move on to the beginning of the line, which must contain |  | ||||||
| 		// a member initialization value |  | ||||||
| 		err = parser.nextToken(lexer.TokenKindDot) |  | ||||||
| 		if err != nil { return } |  | ||||||
| 		err = parser.nextToken(lexer.TokenKindName) |  | ||||||
| 		if err != nil { return } |  | ||||||
| 		name := parser.token.Value().(string) |  | ||||||
| 
 |  | ||||||
| 		// if the member has already been listed, throw an error |  | ||||||
| 		_, exists := initializationValues.attributes[name] |  | ||||||
| 		if exists { |  | ||||||
| 			err = parser.token.NewError ( |  | ||||||
| 				"duplicate member \"" + name + "\" in object " + |  | ||||||
| 				"member initialization", |  | ||||||
| 				infoerr.ErrorKindError) |  | ||||||
| 			return |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		// parse the argument determining the member initialization |  | ||||||
| 		// value |  | ||||||
| 		err = parser.nextToken() |  | ||||||
| 		if err != nil { return } |  | ||||||
| 		var value Argument |  | ||||||
| 		if parser.token.Is(lexer.TokenKindNewline) { |  | ||||||
| 		 |  | ||||||
| 			// recurse |  | ||||||
| 			err = parser.nextToken(lexer.TokenKindIndent) |  | ||||||
| 			if err != nil { return } |  | ||||||
| 			 |  | ||||||
| 			value, err = parser.parseInitializationValues(baseIndent) |  | ||||||
| 			initializationValues.attributes[name] = value |  | ||||||
| 			if err != nil { return } |  | ||||||
| 			 |  | ||||||
| 		} else { |  | ||||||
| 
 |  | ||||||
| 			// parse as normal argument |  | ||||||
| 			value, err = parser.parseArgument() |  | ||||||
| 			initializationValues.attributes[name] = value |  | ||||||
| 			if err != nil { return } |  | ||||||
| 			 |  | ||||||
| 			err = parser.expect(lexer.TokenKindNewline) |  | ||||||
| 			if err != nil { return } |  | ||||||
| 			err = parser.nextToken() |  | ||||||
| 			if err != nil { return } |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	 |  | ||||||
| 	return |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // parseArrayInitializationValues parses a list of array initialization values |  | ||||||
| // until the indentation lexel drops. |  | ||||||
| func (parser *ParsingOperation) parseArrayInitializationValues () ( |  | ||||||
| 	initializationValues ArrayInitializationValues, |  | ||||||
| 	err                  error, |  | ||||||
| ) { |  | ||||||
| 	baseIndent := 0 |  | ||||||
| 	begin      := true |  | ||||||
| 	 |  | ||||||
| 	for { |  | ||||||
| 		// if there is no indent we can just stop parsing |  | ||||||
| 		if !parser.token.Is(lexer.TokenKindIndent) { break} |  | ||||||
| 		indent := parser.token.Value().(int) |  | ||||||
| 		 |  | ||||||
| 		if begin == true { |  | ||||||
| 			initializationValues.location = parser.token.Location() |  | ||||||
| 			baseIndent = indent  |  | ||||||
| 			begin      = false |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		// do not parse any further if the indent has changed |  | ||||||
| 		if indent != baseIndent { break } |  | ||||||
| 
 |  | ||||||
| 		// move on to the beginning of the line, which must contain |  | ||||||
| 		// arguments |  | ||||||
| 		err = parser.nextToken(validArgumentStartTokens...) |  | ||||||
| 		if err != nil { return } |  | ||||||
| 
 |  | ||||||
| 		for { |  | ||||||
| 			// stop parsing this line and go on to the next if a |  | ||||||
| 			// newline token is encountered |  | ||||||
| 			if parser.token.Is(lexer.TokenKindNewline) { |  | ||||||
| 				err = parser.nextToken() |  | ||||||
| 				if err != nil { return } |  | ||||||
| 				break |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			// otherwise, parse the argument |  | ||||||
| 			var argument Argument |  | ||||||
| 			argument, err = parser.parseArgument() |  | ||||||
| 			if err != nil { return } |  | ||||||
| 			initializationValues.values = append ( |  | ||||||
| 				initializationValues.values, |  | ||||||
| 				argument) |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	return |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // parseType parses a type notation of the form Name, {Name}, etc. |  | ||||||
| func (parser *ParsingOperation) parseType () (what Type, err error) { |  | ||||||
| 	err = parser.expect(lexer.TokenKindName, lexer.TokenKindLBrace) |  | ||||||
| 	if err != nil { return } |  | ||||||
| 	what.location = parser.token.Location() |  | ||||||
| 
 |  | ||||||
| 	if parser.token.Is(lexer.TokenKindLBrace) { |  | ||||||
| 		what.kind = TypeKindPointer |  | ||||||
| 
 |  | ||||||
| 		err = parser.nextToken() |  | ||||||
| 		if err != nil { return } |  | ||||||
| 	 |  | ||||||
| 		var points Type |  | ||||||
| 		points, err = parser.parseType() |  | ||||||
| 		if err != nil { return } |  | ||||||
| 		what.points = &points |  | ||||||
| 
 |  | ||||||
| 		err = parser.expect ( |  | ||||||
| 			lexer.TokenKindUInt, |  | ||||||
| 			lexer.TokenKindRBrace, |  | ||||||
| 			lexer.TokenKindElipsis) |  | ||||||
| 		if err != nil { return } |  | ||||||
| 
 |  | ||||||
| 		if parser.token.Is(lexer.TokenKindUInt) { |  | ||||||
| 			what.kind = TypeKindArray |  | ||||||
| 		 |  | ||||||
| 			what.length = parser.token.Value().(uint64) |  | ||||||
| 		 |  | ||||||
| 			err = parser.nextToken(lexer.TokenKindRBrace) |  | ||||||
| 			if err != nil { return } |  | ||||||
| 		} else if parser.token.Is(lexer.TokenKindElipsis) { |  | ||||||
| 			what.kind = TypeKindArray |  | ||||||
| 		 |  | ||||||
| 			err = parser.nextToken(lexer.TokenKindRBrace) |  | ||||||
| 			if err != nil { return } |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		err = parser.nextToken() |  | ||||||
| 		if err != nil { return } |  | ||||||
| 	} else { |  | ||||||
| 		what.name, err = parser.parseIdentifier() |  | ||||||
| 		if err != nil { return } |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if parser.token.Is(lexer.TokenKindColon) { |  | ||||||
| 		err = parser.nextToken(lexer.TokenKindName) |  | ||||||
| 		if err != nil { return } |  | ||||||
| 
 |  | ||||||
| 		qualifier := parser.token.Value().(string) |  | ||||||
| 		switch qualifier { |  | ||||||
| 		case "mut": |  | ||||||
| 			what.mutable = true |  | ||||||
| 		default: |  | ||||||
| 			err = parser.token.NewError ( |  | ||||||
| 				"unknown type qualifier \"" + qualifier + "\"", |  | ||||||
| 				infoerr.ErrorKindError) |  | ||||||
| 			return |  | ||||||
| 		} |  | ||||||
| 		 |  | ||||||
| 		err = parser.nextToken() |  | ||||||
| 		if err != nil { return } |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	return |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // parseIdentifier parses an identifier made out of dot separated names. |  | ||||||
| func (parser *ParsingOperation) parseIdentifier () ( |  | ||||||
| 	identifier Identifier, |  | ||||||
| 	err        error, |  | ||||||
| ) { |  | ||||||
| 	err = parser.expect(lexer.TokenKindName) |  | ||||||
| 	if err != nil { return } |  | ||||||
| 	identifier.location = parser.token.Location() |  | ||||||
| 
 |  | ||||||
| 	for { |  | ||||||
| 		if !parser.token.Is(lexer.TokenKindName) { break } |  | ||||||
| 
 |  | ||||||
| 		identifier.trail = append ( |  | ||||||
| 			identifier.trail, |  | ||||||
| 			parser.token.Value().(string)) |  | ||||||
| 
 |  | ||||||
| 		err = parser.nextToken() |  | ||||||
| 		if err != nil { return } |  | ||||||
| 		 |  | ||||||
| 		if !parser.token.Is(lexer.TokenKindDot) { break } |  | ||||||
| 
 |  | ||||||
| 		err = parser.nextToken() |  | ||||||
| 		if err != nil { return } |  | ||||||
| 
 |  | ||||||
| 		// allow the identifier to continue on to the next line if there |  | ||||||
| 		// is a line break right after the dot |  | ||||||
| 		for parser.token.Is(lexer.TokenKindNewline) || |  | ||||||
| 			parser.token.Is(lexer.TokenKindIndent) { |  | ||||||
| 
 |  | ||||||
| 			err = parser.nextToken() |  | ||||||
| 			if err != nil { return } |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	return |  | ||||||
| } |  | ||||||
|  | |||||||
							
								
								
									
										170
									
								
								parser/initialization-values.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										170
									
								
								parser/initialization-values.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,170 @@ | |||||||
|  | package parser | ||||||
|  | 
 | ||||||
|  | import "git.tebibyte.media/arf/arf/lexer" | ||||||
|  | import "git.tebibyte.media/arf/arf/infoerr" | ||||||
|  | 
 | ||||||
|  | // parseInitializationValues starts on the line after a data section, or a set | ||||||
|  | // phrase. It checks for an indent greater than the indent of the aforementioned | ||||||
|  | // data section or set phrase (passed through baseIndent), and if there is, | ||||||
|  | // it parses initialization values. | ||||||
|  | func (parser *ParsingOperation) parseInitializationValues ( | ||||||
|  | 	baseIndent int, | ||||||
|  | ) ( | ||||||
|  | 	initializationArgument Argument, | ||||||
|  | 	err error, | ||||||
|  | ) { | ||||||
|  | 	// check if line is indented one more than baseIndent | ||||||
|  | 	if !parser.token.Is(lexer.TokenKindIndent) { return } | ||||||
|  | 	if parser.token.Value().(int) != baseIndent + 1 { return } | ||||||
|  | 
 | ||||||
|  | 	initializationArgument.location = parser.token.Location() | ||||||
|  | 	 | ||||||
|  | 	err = parser.nextToken() | ||||||
|  | 	if err != nil { return } | ||||||
|  | 
 | ||||||
|  | 	if parser.token.Is(lexer.TokenKindDot) { | ||||||
|  | 
 | ||||||
|  | 		// object initialization | ||||||
|  | 		parser.previousToken() | ||||||
|  | 		var initializationValues ObjectInitializationValues | ||||||
|  | 		initializationValues, err    = parser.parseObjectInitializationValues() | ||||||
|  | 		initializationArgument.kind  = ArgumentKindObjectInitializationValues | ||||||
|  | 		initializationArgument.value = initializationValues | ||||||
|  | 		 | ||||||
|  | 	} else { | ||||||
|  | 	 | ||||||
|  | 		// array initialization | ||||||
|  | 		parser.previousToken() | ||||||
|  | 		var initializationValues ArrayInitializationValues | ||||||
|  | 		initializationValues, err    = parser.parseArrayInitializationValues() | ||||||
|  | 		initializationArgument.kind  = ArgumentKindArrayInitializationValues | ||||||
|  | 		initializationArgument.value = initializationValues | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | 	return | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // parseObjectInitializationValues parses a list of object initialization | ||||||
|  | // values until the indentation level drops. | ||||||
|  | func (parser *ParsingOperation) parseObjectInitializationValues () ( | ||||||
|  | 	initializationValues ObjectInitializationValues, | ||||||
|  | 	err                  error, | ||||||
|  | ) { | ||||||
|  | 	initializationValues.attributes = make(map[string] Argument) | ||||||
|  | 
 | ||||||
|  | 	baseIndent := 0 | ||||||
|  | 	begin      := true | ||||||
|  | 	 | ||||||
|  | 	for { | ||||||
|  | 		// if there is no indent we can just stop parsing | ||||||
|  | 		if !parser.token.Is(lexer.TokenKindIndent) { break} | ||||||
|  | 		indent := parser.token.Value().(int) | ||||||
|  | 		 | ||||||
|  | 		if begin == true { | ||||||
|  | 			initializationValues.location = parser.token.Location() | ||||||
|  | 			baseIndent = indent  | ||||||
|  | 			begin      = false | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		// do not parse any further if the indent has changed | ||||||
|  | 		if indent != baseIndent { break } | ||||||
|  | 
 | ||||||
|  | 		// move on to the beginning of the line, which must contain | ||||||
|  | 		// a member initialization value | ||||||
|  | 		err = parser.nextToken(lexer.TokenKindDot) | ||||||
|  | 		if err != nil { return } | ||||||
|  | 		err = parser.nextToken(lexer.TokenKindName) | ||||||
|  | 		if err != nil { return } | ||||||
|  | 		name := parser.token.Value().(string) | ||||||
|  | 
 | ||||||
|  | 		// if the member has already been listed, throw an error | ||||||
|  | 		_, exists := initializationValues.attributes[name] | ||||||
|  | 		if exists { | ||||||
|  | 			err = parser.token.NewError ( | ||||||
|  | 				"duplicate member \"" + name + "\" in object " + | ||||||
|  | 				"member initialization", | ||||||
|  | 				infoerr.ErrorKindError) | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		// parse the argument determining the member initialization | ||||||
|  | 		// value | ||||||
|  | 		err = parser.nextToken() | ||||||
|  | 		if err != nil { return } | ||||||
|  | 		var value Argument | ||||||
|  | 		if parser.token.Is(lexer.TokenKindNewline) { | ||||||
|  | 		 | ||||||
|  | 			// recurse | ||||||
|  | 			err = parser.nextToken(lexer.TokenKindIndent) | ||||||
|  | 			if err != nil { return } | ||||||
|  | 			 | ||||||
|  | 			value, err = parser.parseInitializationValues(baseIndent) | ||||||
|  | 			initializationValues.attributes[name] = value | ||||||
|  | 			if err != nil { return } | ||||||
|  | 			 | ||||||
|  | 		} else { | ||||||
|  | 
 | ||||||
|  | 			// parse as normal argument | ||||||
|  | 			value, err = parser.parseArgument() | ||||||
|  | 			initializationValues.attributes[name] = value | ||||||
|  | 			if err != nil { return } | ||||||
|  | 			 | ||||||
|  | 			err = parser.expect(lexer.TokenKindNewline) | ||||||
|  | 			if err != nil { return } | ||||||
|  | 			err = parser.nextToken() | ||||||
|  | 			if err != nil { return } | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | 	return | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // parseArrayInitializationValues parses a list of array initialization values | ||||||
|  | // until the indentation lexel drops. | ||||||
|  | func (parser *ParsingOperation) parseArrayInitializationValues () ( | ||||||
|  | 	initializationValues ArrayInitializationValues, | ||||||
|  | 	err                  error, | ||||||
|  | ) { | ||||||
|  | 	baseIndent := 0 | ||||||
|  | 	begin      := true | ||||||
|  | 	 | ||||||
|  | 	for { | ||||||
|  | 		// if there is no indent we can just stop parsing | ||||||
|  | 		if !parser.token.Is(lexer.TokenKindIndent) { break} | ||||||
|  | 		indent := parser.token.Value().(int) | ||||||
|  | 		 | ||||||
|  | 		if begin == true { | ||||||
|  | 			initializationValues.location = parser.token.Location() | ||||||
|  | 			baseIndent = indent  | ||||||
|  | 			begin      = false | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		// do not parse any further if the indent has changed | ||||||
|  | 		if indent != baseIndent { break } | ||||||
|  | 
 | ||||||
|  | 		// move on to the beginning of the line, which must contain | ||||||
|  | 		// arguments | ||||||
|  | 		err = parser.nextToken(validArgumentStartTokens...) | ||||||
|  | 		if err != nil { return } | ||||||
|  | 
 | ||||||
|  | 		for { | ||||||
|  | 			// stop parsing this line and go on to the next if a | ||||||
|  | 			// newline token is encountered | ||||||
|  | 			if parser.token.Is(lexer.TokenKindNewline) { | ||||||
|  | 				err = parser.nextToken() | ||||||
|  | 				if err != nil { return } | ||||||
|  | 				break | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			// otherwise, parse the argument | ||||||
|  | 			var argument Argument | ||||||
|  | 			argument, err = parser.parseArgument() | ||||||
|  | 			if err != nil { return } | ||||||
|  | 			initializationValues.values = append ( | ||||||
|  | 				initializationValues.values, | ||||||
|  | 				argument) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return | ||||||
|  | } | ||||||
							
								
								
									
										107
									
								
								parser/misc.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										107
									
								
								parser/misc.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,107 @@ | |||||||
|  | package parser | ||||||
|  | 
 | ||||||
|  | import "git.tebibyte.media/arf/arf/lexer" | ||||||
|  | import "git.tebibyte.media/arf/arf/infoerr" | ||||||
|  | 
 | ||||||
|  | // parseType parses a type notation of the form Name, {Name}, etc. | ||||||
|  | func (parser *ParsingOperation) parseType () (what Type, err error) { | ||||||
|  | 	err = parser.expect(lexer.TokenKindName, lexer.TokenKindLBrace) | ||||||
|  | 	if err != nil { return } | ||||||
|  | 	what.location = parser.token.Location() | ||||||
|  | 
 | ||||||
|  | 	if parser.token.Is(lexer.TokenKindLBrace) { | ||||||
|  | 		what.kind = TypeKindPointer | ||||||
|  | 
 | ||||||
|  | 		err = parser.nextToken() | ||||||
|  | 		if err != nil { return } | ||||||
|  | 	 | ||||||
|  | 		var points Type | ||||||
|  | 		points, err = parser.parseType() | ||||||
|  | 		if err != nil { return } | ||||||
|  | 		what.points = &points | ||||||
|  | 
 | ||||||
|  | 		err = parser.expect ( | ||||||
|  | 			lexer.TokenKindUInt, | ||||||
|  | 			lexer.TokenKindRBrace, | ||||||
|  | 			lexer.TokenKindElipsis) | ||||||
|  | 		if err != nil { return } | ||||||
|  | 
 | ||||||
|  | 		if parser.token.Is(lexer.TokenKindUInt) { | ||||||
|  | 			what.kind = TypeKindArray | ||||||
|  | 		 | ||||||
|  | 			what.length = parser.token.Value().(uint64) | ||||||
|  | 		 | ||||||
|  | 			err = parser.nextToken(lexer.TokenKindRBrace) | ||||||
|  | 			if err != nil { return } | ||||||
|  | 		} else if parser.token.Is(lexer.TokenKindElipsis) { | ||||||
|  | 			what.kind = TypeKindArray | ||||||
|  | 		 | ||||||
|  | 			err = parser.nextToken(lexer.TokenKindRBrace) | ||||||
|  | 			if err != nil { return } | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		err = parser.nextToken() | ||||||
|  | 		if err != nil { return } | ||||||
|  | 	} else { | ||||||
|  | 		what.name, err = parser.parseIdentifier() | ||||||
|  | 		if err != nil { return } | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if parser.token.Is(lexer.TokenKindColon) { | ||||||
|  | 		err = parser.nextToken(lexer.TokenKindName) | ||||||
|  | 		if err != nil { return } | ||||||
|  | 
 | ||||||
|  | 		qualifier := parser.token.Value().(string) | ||||||
|  | 		switch qualifier { | ||||||
|  | 		case "mut": | ||||||
|  | 			what.mutable = true | ||||||
|  | 		default: | ||||||
|  | 			err = parser.token.NewError ( | ||||||
|  | 				"unknown type qualifier \"" + qualifier + "\"", | ||||||
|  | 				infoerr.ErrorKindError) | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
|  | 		 | ||||||
|  | 		err = parser.nextToken() | ||||||
|  | 		if err != nil { return } | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // parseIdentifier parses an identifier made out of dot separated names. | ||||||
|  | func (parser *ParsingOperation) parseIdentifier () ( | ||||||
|  | 	identifier Identifier, | ||||||
|  | 	err        error, | ||||||
|  | ) { | ||||||
|  | 	err = parser.expect(lexer.TokenKindName) | ||||||
|  | 	if err != nil { return } | ||||||
|  | 	identifier.location = parser.token.Location() | ||||||
|  | 
 | ||||||
|  | 	for { | ||||||
|  | 		if !parser.token.Is(lexer.TokenKindName) { break } | ||||||
|  | 
 | ||||||
|  | 		identifier.trail = append ( | ||||||
|  | 			identifier.trail, | ||||||
|  | 			parser.token.Value().(string)) | ||||||
|  | 
 | ||||||
|  | 		err = parser.nextToken() | ||||||
|  | 		if err != nil { return } | ||||||
|  | 		 | ||||||
|  | 		if !parser.token.Is(lexer.TokenKindDot) { break } | ||||||
|  | 
 | ||||||
|  | 		err = parser.nextToken() | ||||||
|  | 		if err != nil { return } | ||||||
|  | 
 | ||||||
|  | 		// allow the identifier to continue on to the next line if there | ||||||
|  | 		// is a line break right after the dot | ||||||
|  | 		for parser.token.Is(lexer.TokenKindNewline) || | ||||||
|  | 			parser.token.Is(lexer.TokenKindIndent) { | ||||||
|  | 
 | ||||||
|  | 			err = parser.nextToken() | ||||||
|  | 			if err != nil { return } | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return | ||||||
|  | } | ||||||
		Reference in New Issue
	
	Block a user