package js_parser

import (
	

	
	
	
)

type jsonParser struct {
	log     logger.Log
	source  logger.Source
	lexer   js_lexer.Lexer
	options JSONOptions
}

func ( *jsonParser) ( js_lexer.T) bool {
	 := .lexer.Range()
	.lexer.Expect(js_lexer.TComma)

	if .lexer.Token ==  {
		if !.options.AllowTrailingCommas {
			.log.AddRangeError(&.source, , "JSON does not support trailing commas")
		}
		return false
	}

	return true
}

func ( *jsonParser) () js_ast.Expr {
	 := .lexer.Loc()

	switch .lexer.Token {
	case js_lexer.TFalse:
		.lexer.Next()
		return js_ast.Expr{Loc: , Data: &js_ast.EBoolean{Value: false}}

	case js_lexer.TTrue:
		.lexer.Next()
		return js_ast.Expr{Loc: , Data: &js_ast.EBoolean{Value: true}}

	case js_lexer.TNull:
		.lexer.Next()
		return js_ast.Expr{Loc: , Data: &js_ast.ENull{}}

	case js_lexer.TStringLiteral:
		 := .lexer.StringLiteral
		.lexer.Next()
		return js_ast.Expr{Loc: , Data: &js_ast.EString{Value: }}

	case js_lexer.TNumericLiteral:
		 := .lexer.Number
		.lexer.Next()
		return js_ast.Expr{Loc: , Data: &js_ast.ENumber{Value: }}

	case js_lexer.TMinus:
		.lexer.Next()
		 := .lexer.Number
		.lexer.Expect(js_lexer.TNumericLiteral)
		return js_ast.Expr{Loc: , Data: &js_ast.ENumber{Value: -}}

	case js_lexer.TOpenBracket:
		.lexer.Next()
		 := !.lexer.HasNewlineBefore
		 := []js_ast.Expr{}

		for .lexer.Token != js_lexer.TCloseBracket {
			if len() > 0 {
				if .lexer.HasNewlineBefore {
					 = false
				}
				if !.parseMaybeTrailingComma(js_lexer.TCloseBracket) {
					break
				}
				if .lexer.HasNewlineBefore {
					 = false
				}
			}

			 := .()
			 = append(, )
		}

		if .lexer.HasNewlineBefore {
			 = false
		}
		.lexer.Expect(js_lexer.TCloseBracket)
		return js_ast.Expr{Loc: , Data: &js_ast.EArray{
			Items:        ,
			IsSingleLine: ,
		}}

	case js_lexer.TOpenBrace:
		.lexer.Next()
		 := !.lexer.HasNewlineBefore
		 := []js_ast.Property{}
		 := make(map[string]bool)

		for .lexer.Token != js_lexer.TCloseBrace {
			if len() > 0 {
				if .lexer.HasNewlineBefore {
					 = false
				}
				if !.parseMaybeTrailingComma(js_lexer.TCloseBrace) {
					break
				}
				if .lexer.HasNewlineBefore {
					 = false
				}
			}

			 := .lexer.StringLiteral
			 := .lexer.Range()
			 := js_ast.Expr{Loc: .Loc, Data: &js_ast.EString{Value: }}
			.lexer.Expect(js_lexer.TStringLiteral)
Warn about duplicate keys
			 := js_lexer.UTF16ToString()
			if [] {
				.log.AddRangeWarning(&.source, , fmt.Sprintf("Duplicate key %q in object literal", ))
			} else {
				[] = true
			}

			.lexer.Expect(js_lexer.TColon)
			 := .()

			 := js_ast.Property{
				Kind:  js_ast.PropertyNormal,
				Key:   ,
				Value: &,
			}
			 = append(, )
		}

		if .lexer.HasNewlineBefore {
			 = false
		}
		.lexer.Expect(js_lexer.TCloseBrace)
		return js_ast.Expr{Loc: , Data: &js_ast.EObject{
			Properties:   ,
			IsSingleLine: ,
		}}

	default:
		.lexer.Unexpected()
		return js_ast.Expr{}
	}
}

type JSONOptions struct {
	AllowComments       bool
	AllowTrailingCommas bool
}

func ( logger.Log,  logger.Source,  JSONOptions) ( js_ast.Expr,  bool) {
	 = true
	defer func() {
		 := recover()
		if ,  := .(js_lexer.LexerPanic);  {
			 = false
		} else if  != nil {
			panic()
		}
	}()

	 := &jsonParser{
		log:     ,
		source:  ,
		options: ,
		lexer:   js_lexer.NewLexerJSON(, , .AllowComments),
	}

	 = .parseExpr()
	.lexer.Expect(js_lexer.TEndOfFile)
	return