mirror of https://github.com/boa-dev/boa.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
177 lines
4.3 KiB
177 lines
4.3 KiB
//! Boa parser implementation. |
|
|
|
mod cursor; |
|
pub mod error; |
|
mod expression; |
|
pub(crate) mod function; |
|
mod statement; |
|
#[cfg(test)] |
|
mod tests; |
|
|
|
pub use self::error::{ParseError, ParseResult}; |
|
|
|
use self::cursor::Cursor; |
|
use crate::syntax::{ast::node::StatementList, lexer::TokenKind}; |
|
use boa_interner::Interner; |
|
use std::io::Read; |
|
|
|
/// Trait implemented by parsers. |
|
/// |
|
/// This makes it possible to abstract over the underlying implementation of a parser. |
|
trait TokenParser<R>: Sized |
|
where |
|
R: Read, |
|
{ |
|
/// Output type for the parser. |
|
type Output; // = Node; waiting for https://github.com/rust-lang/rust/issues/29661 |
|
|
|
/// Parses the token stream using the current parser. |
|
/// |
|
/// This method needs to be provided by the implementor type. |
|
fn parse( |
|
self, |
|
cursor: &mut Cursor<R>, |
|
interner: &mut Interner, |
|
) -> Result<Self::Output, ParseError>; |
|
} |
|
|
|
/// Boolean representing if the parser should allow a `yield` keyword. |
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)] |
|
struct AllowYield(bool); |
|
|
|
impl From<bool> for AllowYield { |
|
fn from(allow: bool) -> Self { |
|
Self(allow) |
|
} |
|
} |
|
|
|
/// Boolean representing if the parser should allow a `await` keyword. |
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)] |
|
struct AllowAwait(bool); |
|
|
|
impl From<bool> for AllowAwait { |
|
fn from(allow: bool) -> Self { |
|
Self(allow) |
|
} |
|
} |
|
|
|
/// Boolean representing if the parser should allow a `in` keyword. |
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)] |
|
struct AllowIn(bool); |
|
|
|
impl From<bool> for AllowIn { |
|
fn from(allow: bool) -> Self { |
|
Self(allow) |
|
} |
|
} |
|
|
|
/// Boolean representing if the parser should allow a `return` keyword. |
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)] |
|
struct AllowReturn(bool); |
|
|
|
impl From<bool> for AllowReturn { |
|
fn from(allow: bool) -> Self { |
|
Self(allow) |
|
} |
|
} |
|
|
|
/// Boolean representing if the parser should allow a `default` keyword. |
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)] |
|
struct AllowDefault(bool); |
|
|
|
impl From<bool> for AllowDefault { |
|
fn from(allow: bool) -> Self { |
|
Self(allow) |
|
} |
|
} |
|
|
|
#[derive(Debug)] |
|
pub struct Parser<R> { |
|
/// Cursor of the parser, pointing to the lexer and used to get tokens for the parser. |
|
cursor: Cursor<R>, |
|
} |
|
|
|
impl<R> Parser<R> { |
|
pub fn new(reader: R, strict_mode: bool) -> Self |
|
where |
|
R: Read, |
|
{ |
|
let mut cursor = Cursor::new(reader); |
|
cursor.set_strict_mode(strict_mode); |
|
|
|
Self { cursor } |
|
} |
|
|
|
pub fn parse_all(&mut self, interner: &mut Interner) -> Result<StatementList, ParseError> |
|
where |
|
R: Read, |
|
{ |
|
Script.parse(&mut self.cursor, interner) |
|
} |
|
} |
|
|
|
/// Parses a full script. |
|
/// |
|
/// More information: |
|
/// - [ECMAScript specification][spec] |
|
/// |
|
/// [spec]: https://tc39.es/ecma262/#prod-Script |
|
#[derive(Debug, Clone, Copy)] |
|
pub struct Script; |
|
|
|
impl<R> TokenParser<R> for Script |
|
where |
|
R: Read, |
|
{ |
|
type Output = StatementList; |
|
|
|
fn parse( |
|
self, |
|
cursor: &mut Cursor<R>, |
|
interner: &mut Interner, |
|
) -> Result<Self::Output, ParseError> { |
|
match cursor.peek(0, interner)? { |
|
Some(tok) => { |
|
let mut strict = false; |
|
match tok.kind() { |
|
// Set the strict mode |
|
TokenKind::StringLiteral(string) |
|
if interner.resolve_expect(*string) == "use strict" => |
|
{ |
|
cursor.set_strict_mode(true); |
|
strict = true; |
|
} |
|
_ => {} |
|
} |
|
let mut statement_list = ScriptBody.parse(cursor, interner)?; |
|
statement_list.set_strict(strict); |
|
Ok(statement_list) |
|
} |
|
None => Ok(StatementList::from(Vec::new())), |
|
} |
|
} |
|
} |
|
|
|
/// Parses a script body. |
|
/// |
|
/// More information: |
|
/// - [ECMAScript specification][spec] |
|
/// |
|
/// [spec]: https://tc39.es/ecma262/#prod-ScriptBody |
|
#[derive(Debug, Clone, Copy)] |
|
pub struct ScriptBody; |
|
|
|
impl<R> TokenParser<R> for ScriptBody |
|
where |
|
R: Read, |
|
{ |
|
type Output = StatementList; |
|
|
|
fn parse( |
|
self, |
|
cursor: &mut Cursor<R>, |
|
interner: &mut Interner, |
|
) -> Result<Self::Output, ParseError> { |
|
self::statement::StatementList::new(false, false, false, false, &[]).parse(cursor, interner) |
|
} |
|
}
|
|
|