package parser
import (
"bytes"
"errors"
"io"
"os"
"github.com/dop251/goja/ast"
"github.com/dop251/goja/file"
"github.com/dop251/goja/token"
"github.com/dop251/goja/unistring"
)
type Mode uint
const (
IgnoreRegExpErrors Mode = 1 << iota
)
type options struct {
disableSourceMaps bool
sourceMapLoader func (path string ) ([]byte , error )
}
type Option func (*options )
func WithDisableSourceMaps (opts *options ) {
opts .disableSourceMaps = true
}
func WithSourceMapLoader (loader func (path string ) ([]byte , error )) Option {
return func (opts *options ) {
opts .sourceMapLoader = loader
}
}
type _parser struct {
str string
length int
base int
chr rune
chrOffset int
offset int
idx file .Idx
token token .Token
literal string
parsedLiteral unistring .String
scope *_scope
insertSemicolon bool
implicitSemicolon bool
errors ErrorList
recover struct {
idx file .Idx
count int
}
mode Mode
opts options
file *file .File
}
func _newParser(filename , src string , base int , opts ...Option ) *_parser {
p := &_parser {
chr : ' ' ,
str : src ,
length : len (src ),
base : base ,
file : file .NewFile (filename , src , base ),
}
for _ , opt := range opts {
opt (&p .opts )
}
return p
}
func newParser(filename , src string ) *_parser {
return _newParser (filename , src , 1 )
}
func ReadSource (filename string , src interface {}) ([]byte , error ) {
if src != nil {
switch src := src .(type ) {
case string :
return []byte (src ), nil
case []byte :
return src , nil
case *bytes .Buffer :
if src != nil {
return src .Bytes (), nil
}
case io .Reader :
var bfr bytes .Buffer
if _ , err := io .Copy (&bfr , src ); err != nil {
return nil , err
}
return bfr .Bytes (), nil
}
return nil , errors .New ("invalid source" )
}
return os .ReadFile (filename )
}
func ParseFile (fileSet *file .FileSet , filename string , src interface {}, mode Mode , options ...Option ) (*ast .Program , error ) {
str , err := ReadSource (filename , src )
if err != nil {
return nil , err
}
{
str := string (str )
base := 1
if fileSet != nil {
base = fileSet .AddFile (filename , str )
}
parser := _newParser (filename , str , base , options ...)
parser .mode = mode
return parser .parse ()
}
}
func ParseFunction (parameterList , body string , options ...Option ) (*ast .FunctionLiteral , error ) {
src := "(function(" + parameterList + ") {\n" + body + "\n})"
parser := _newParser ("" , src , 1 , options ...)
program , err := parser .parse ()
if err != nil {
return nil , err
}
return program .Body [0 ].(*ast .ExpressionStatement ).Expression .(*ast .FunctionLiteral ), nil
}
func (self *_parser ) slice (idx0 , idx1 file .Idx ) string {
from := int (idx0 ) - self .base
to := int (idx1 ) - self .base
if from >= 0 && to <= len (self .str ) {
return self .str [from :to ]
}
return ""
}
func (self *_parser ) parse () (*ast .Program , error ) {
self .openScope ()
defer self .closeScope ()
self .next ()
program := self .parseProgram ()
if false {
self .errors .Sort ()
}
return program , self .errors .Err ()
}
func (self *_parser ) next () {
self .token , self .literal , self .parsedLiteral , self .idx = self .scan ()
}
func (self *_parser ) optionalSemicolon () {
if self .token == token .SEMICOLON {
self .next ()
return
}
if self .implicitSemicolon {
self .implicitSemicolon = false
return
}
if self .token != token .EOF && self .token != token .RIGHT_BRACE {
self .expect (token .SEMICOLON )
}
}
func (self *_parser ) semicolon () {
if self .token != token .RIGHT_PARENTHESIS && self .token != token .RIGHT_BRACE {
if self .implicitSemicolon {
self .implicitSemicolon = false
return
}
self .expect (token .SEMICOLON )
}
}
func (self *_parser ) idxOf (offset int ) file .Idx {
return file .Idx (self .base + offset )
}
func (self *_parser ) expect (value token .Token ) file .Idx {
idx := self .idx
if self .token != value {
self .errorUnexpectedToken (self .token )
}
self .next ()
return idx
}
func (self *_parser ) position (idx file .Idx ) file .Position {
return self .file .Position (int (idx ) - self .base )
}
The pages are generated with Golds v0.8.2 . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds .