@@ -375,6 +375,74 @@ public class LeafParser {
375375 let expr = try parseExpression ( minimumPrecedence: 1 )
376376 try expect ( token: . expression( . rightParen) , while: " parsing parenthesized expression " )
377377 return expr
378+ case . leftBracket: // array or dictionary
379+ try consume ( )
380+ // empty array
381+ if let ( endSpan, tok) = try peek ( ) , tok == . expression( . rightBracket) {
382+ try consume ( )
383+ return . init( . arrayLiteral( [ ] ) , span: combine ( span, endSpan) )
384+ }
385+ // empty dictionary
386+ if let ( _, tok) = try peek ( ) , tok == . expression( . colon) {
387+ try consume ( )
388+ let ( endSpan, tok) = try expectExpression ( while: " parsing end bracket of dictionary literal " )
389+ guard tok == . rightBracket else {
390+ throw error ( . expectedGot( expected: . expression( . rightBracket) , got: . expression( tok) , while: " parsing end bracket of dictionary literal " ) , endSpan)
391+ }
392+ return . init( . dictionaryLiteral( [ ] ) , span: combine ( span, endSpan) )
393+ }
394+ // parse the first element
395+ let firstElement = try parseExpression ( minimumPrecedence: 0 )
396+ // now, whether the next token is a comma or a colon determines if we're parsing an array or dictionary
397+ let ( signifierSpan, signifier) = try expectPeekExpression ( while: " parsing array or dictionary literal " )
398+ if signifier == . comma { // parse an n-item array where n >= 2
399+
400+ var items : [ Expression ] = [ firstElement]
401+ repeat {
402+ try expect ( token: . expression( . comma) , while: " in the middle of parsing parameters " )
403+ items. append ( try parseExpression ( minimumPrecedence: 0 ) )
404+ } while try peek ( ) ? . 1 == . expression( . comma)
405+
406+ guard let ( endSpan, token) = try read ( ) else {
407+ throw error ( . earlyEOF( wasExpecting: " closing bracket for array " ) , . eof)
408+ }
409+ guard case . expression( . rightBracket) = token else {
410+ throw error ( . expectedGot( expected: . expression( . rightBracket) , got: token, while: " looking for closing bracket of array " ) , endSpan)
411+ }
412+
413+ return . init( . arrayLiteral( items) , span: combine ( span, endSpan) )
414+
415+ } else if signifier == . rightBracket { // parse a single-item array
416+ try consume ( )
417+ return . init( . arrayLiteral( [ firstElement] ) , span: combine ( span, signifierSpan) )
418+ } else if signifier == . colon { // parse an n-item dictionary where n >= 1
419+ try consume ( )
420+
421+ // parse the first element manually before hitting the loop
422+ let firstValue = try parseExpression ( minimumPrecedence: 0 )
423+
424+ var pairs : [ ( Expression , Expression ) ] = [ ( firstElement, firstValue) ]
425+
426+ while try peek ( ) ? . 1 == . expression( . comma) {
427+ try consume ( ) // eat comma
428+ let key = try parseExpression ( minimumPrecedence: 0 )
429+ _ = try expect ( token: . expression( . colon) , while: " parsing dictionary item " )
430+ let value = try parseExpression ( minimumPrecedence: 0 )
431+ pairs. append ( ( key, value) )
432+ }
433+
434+ guard let ( endSpan, token) = try read ( ) else {
435+ throw error ( . earlyEOF( wasExpecting: " closing bracket for dictionary " ) , . eof)
436+ }
437+ guard case . expression( . rightBracket) = token else {
438+ throw error ( . expectedGot( expected: . expression( . rightBracket) , got: token, while: " looking for closing bracket of dictionary " ) , endSpan)
439+ }
440+
441+ return . init( . dictionaryLiteral( pairs) , span: combine ( span, endSpan) )
442+ } else {
443+ let expected : [ LeafScanner . Token ] = [ . expression( . comma) , . expression( . rightBracket) , . expression( . colon) ]
444+ throw error ( . expectedOneOfGot( expected: expected, got: . expression( signifier) , while: " parsing array or dictionary literal " ) , combine ( span, signifierSpan) )
445+ }
378446 case . operator( let op) where op. data. kind. prefix:
379447 try consume ( )
380448 let expr = try parseAtom ( )
@@ -404,7 +472,7 @@ public class LeafParser {
404472 case . boolean( let val) :
405473 try consume ( )
406474 return . init( . boolean( val) , span: span)
407- case . comma, . rightParen:
475+ case . comma, . rightParen, . rightBracket , . colon :
408476 try consume ( )
409477 throw error ( . unexpected( token: . expression( expr) , while: " parsing expression atom " ) , span)
410478 }
@@ -784,6 +852,11 @@ public struct Expression: SExprRepresentable {
784852 return #"( \#( op. rawValue) \#( rhs. sexpr ( ) ) )"#
785853 case . binary( let lhs, let op, let rhs) :
786854 return #"( \#( op. rawValue) \#( lhs. sexpr ( ) ) \#( rhs. sexpr ( ) ) )"#
855+ case . arrayLiteral( let items) :
856+ return #"(array_literal \#( items. sexpr ( ) ) )"#
857+ case . dictionaryLiteral( let pairs) :
858+ let inner = pairs. map { " ( \( $0. 0 . sexpr ( ) ) \( $0. 1 . sexpr ( ) ) ) " } . joined ( separator: " " )
859+ return #"(dictionary_literal \#( inner) )"#
787860 }
788861 }
789862
@@ -797,6 +870,8 @@ public struct Expression: SExprRepresentable {
797870 case tagApplication( name: Substring , params: [ Expression ] )
798871 case unary( LeafScanner . Operator , Expression )
799872 case binary( Expression , LeafScanner . Operator , Expression )
873+ case arrayLiteral( [ Expression ] )
874+ case dictionaryLiteral( [ ( Expression , Expression ) ] )
800875 }
801876}
802877
0 commit comments