Merge pull request #31 from edsrzf/parse-include

This commit is contained in:
Ryan Chandler 2022-09-12 11:45:51 +01:00 committed by GitHub
commit 0f0629ff8b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 97 additions and 27 deletions

View File

@ -846,6 +846,8 @@ fn identifier_to_keyword(ident: &str) -> Option<TokenKind> {
"foreach" => TokenKind::Foreach,
"function" => TokenKind::Function,
"if" => TokenKind::If,
"include" => TokenKind::Include,
"include_once" => TokenKind::IncludeOnce,
"implements" => TokenKind::Implements,
"interface" => TokenKind::Interface,
"instanceof" => TokenKind::Instanceof,

View File

@ -90,6 +90,8 @@ pub enum TokenKind {
Identifier(String),
If,
Implements,
Include,
IncludeOnce,
Increment,
InlineHtml(String),
Instanceof,

View File

@ -143,6 +143,26 @@ pub struct StaticVar {
pub default: Option<Expression>,
}
#[derive(Debug, PartialEq, Clone, Serialize)]
pub enum IncludeKind {
Include,
IncludeOnce,
Require,
RequireOnce,
}
impl From<&TokenKind> for IncludeKind {
fn from(k: &TokenKind) -> Self {
match k {
TokenKind::Include => IncludeKind::Include,
TokenKind::IncludeOnce => IncludeKind::IncludeOnce,
TokenKind::Require => IncludeKind::Require,
TokenKind::RequireOnce => IncludeKind::RequireOnce,
_ => unreachable!(),
}
}
}
#[derive(Debug, PartialEq, Clone, Serialize)]
pub enum Statement {
InlineHtml(String),
@ -166,10 +186,8 @@ pub enum Statement {
value_var: Expression,
body: Block,
},
Require {
path: Expression,
},
RequireOnce {
Include {
kind: IncludeKind,
path: Expression,
},
Var {

View File

@ -1,7 +1,7 @@
use crate::{
ast::{
Arg, ArrayItem, BackedEnumType, ClassFlag, ClosureUse, ElseIf, MagicConst, MethodFlag,
StaticVar, Use, UseKind,
Arg, ArrayItem, BackedEnumType, ClassFlag, ClosureUse, ElseIf, IncludeKind, MagicConst,
MethodFlag, StaticVar, Use, UseKind,
},
Block, Case, Catch, Expression, Identifier, MatchArm, Program, Statement, Type,
};
@ -208,23 +208,18 @@ impl Parser {
Statement::While { condition, body }
}
TokenKind::Require => {
TokenKind::Include
| TokenKind::IncludeOnce
| TokenKind::Require
| TokenKind::RequireOnce => {
let kind: IncludeKind = (&self.current.kind).into();
self.next();
let path = self.expression(0)?;
self.semi()?;
Statement::Require { path }
}
TokenKind::RequireOnce => {
self.next();
let path = self.expression(0)?;
self.semi()?;
Statement::RequireOnce { path }
Statement::Include { kind, path }
}
TokenKind::For => {
self.next();
@ -2089,7 +2084,7 @@ impl Display for ParseError {
mod tests {
use super::Parser;
use crate::{
ast::{Arg, ArrayItem, ElseIf, InfixOp, MethodFlag, PropertyFlag},
ast::{Arg, ArrayItem, ElseIf, IncludeKind, InfixOp, MethodFlag, PropertyFlag},
Expression, Identifier, Param, Statement, Type,
};
use trunk_lexer::Lexer;
@ -2161,6 +2156,49 @@ mod tests {
};
}
#[test]
fn include() {
assert_ast(
"<?php include 'foo.php';",
&[Statement::Include {
path: Expression::ConstantString {
value: "foo.php".into(),
},
kind: IncludeKind::Include,
}],
);
assert_ast(
"<?php include_once 'foo.php';",
&[Statement::Include {
path: Expression::ConstantString {
value: "foo.php".into(),
},
kind: IncludeKind::IncludeOnce,
}],
);
assert_ast(
"<?php require 'foo.php';",
&[Statement::Include {
path: Expression::ConstantString {
value: "foo.php".into(),
},
kind: IncludeKind::Require,
}],
);
assert_ast(
"<?php require_once 'foo.php';",
&[Statement::Include {
path: Expression::ConstantString {
value: "foo.php".into(),
},
kind: IncludeKind::RequireOnce,
}],
);
}
#[test]
fn instanceof() {
assert_ast(
@ -2986,15 +3024,25 @@ mod tests {
#[test]
fn comment_at_end_of_class() {
assert_ast("<?php
assert_ast(
"<?php
class MyClass {
protected $a;
// my comment
}", &[
Statement::Class { name: "MyClass".into(), extends: None, implements: vec![], body: vec![
Statement::Property { var: "a".into(), value: None, r#type: None, flags: vec![PropertyFlag::Protected] }
], flag: None }
]);
}",
&[Statement::Class {
name: "MyClass".into(),
extends: None,
implements: vec![],
body: vec![Statement::Property {
var: "a".into(),
value: None,
r#type: None,
flags: vec![PropertyFlag::Protected],
}],
flag: None,
}],
);
}
fn assert_ast(source: &str, expected: &[Statement]) {