Replace using with from

This commit is contained in:
Laurenz 2021-07-08 21:16:16 +02:00
parent 5c327e249e
commit 551e3af9d0
12 changed files with 112 additions and 107 deletions

View File

@ -728,34 +728,30 @@ fn import_expr(p: &mut Parser) -> Option<Expr> {
let start = p.next_start(); let start = p.next_start();
p.assert(Token::Import); p.assert(Token::Import);
let mut import_expr = None; let imports = if p.eat_if(Token::Star) {
if let Some(path) = expr(p) {
let imports = if p.expect(Token::Using) {
if p.eat_if(Token::Star) {
// This is the wildcard scenario. // This is the wildcard scenario.
Imports::Wildcard Imports::Wildcard
} else { } else {
// This is the list of identifier scenario. // This is the list of identifiers scenario.
p.start_group(Group::Expr, TokenMode::Code); p.start_group(Group::Imports, TokenMode::Code);
let items = collection(p).0; let items = collection(p).0;
if items.is_empty() { if items.is_empty() {
p.expected_at("import items", p.prev_end()); p.expected_at("import items", p.prev_end());
} }
let idents = idents(p, items);
p.end_group(); p.end_group();
Imports::Idents(idents) Imports::Idents(idents(p, items))
}
} else {
Imports::Idents(vec![])
}; };
let mut import_expr = None;
if p.expect(Token::From) {
if let Some(path) = expr(p) {
import_expr = Some(Expr::Import(ImportExpr { import_expr = Some(Expr::Import(ImportExpr {
span: p.span(start), span: p.span(start),
imports, imports,
path: Box::new(path), path: Box::new(path),
})); }));
} }
}
import_expr import_expr
} }

View File

@ -51,6 +51,8 @@ pub enum Group {
Stmt, Stmt,
/// A group for a single expression, ended by a line break. /// A group for a single expression, ended by a line break.
Expr, Expr,
/// A group for import items, ended by a semicolon, line break or `from`.
Imports,
} }
impl<'s> Parser<'s> { impl<'s> Parser<'s> {
@ -128,6 +130,7 @@ impl<'s> Parser<'s> {
Group::Brace => self.assert(Token::LeftBrace), Group::Brace => self.assert(Token::LeftBrace),
Group::Stmt => {} Group::Stmt => {}
Group::Expr => {} Group::Expr => {}
Group::Imports => {}
} }
} }
@ -149,6 +152,7 @@ impl<'s> Parser<'s> {
Group::Brace => Some((Token::RightBrace, true)), Group::Brace => Some((Token::RightBrace, true)),
Group::Stmt => Some((Token::Semicolon, false)), Group::Stmt => Some((Token::Semicolon, false)),
Group::Expr => None, Group::Expr => None,
Group::Imports => None,
} { } {
if self.next == Some(end) { if self.next == Some(end) {
// Bump the delimeter and return. No need to rescan in this case. // Bump the delimeter and return. No need to rescan in this case.
@ -361,6 +365,7 @@ impl<'s> Parser<'s> {
Token::RightBracket => self.inside(Group::Bracket), Token::RightBracket => self.inside(Group::Bracket),
Token::RightBrace => self.inside(Group::Brace), Token::RightBrace => self.inside(Group::Brace),
Token::Semicolon => self.inside(Group::Stmt), Token::Semicolon => self.inside(Group::Stmt),
Token::From => self.inside(Group::Imports),
Token::Space(n) => n >= 1 && self.stop_at_newline(), Token::Space(n) => n >= 1 && self.stop_at_newline(),
_ => false, _ => false,
} { } {
@ -371,7 +376,10 @@ impl<'s> Parser<'s> {
/// Whether the active group ends at a newline. /// Whether the active group ends at a newline.
fn stop_at_newline(&self) -> bool { fn stop_at_newline(&self) -> bool {
let active = self.groups.last().map(|group| group.kind); let active = self.groups.last().map(|group| group.kind);
matches!(active, Some(Group::Stmt) | Some(Group::Expr)) matches!(
active,
Some(Group::Stmt) | Some(Group::Expr) | Some(Group::Imports)
)
} }
/// Whether we are inside the given group. /// Whether we are inside the given group.

View File

@ -496,7 +496,7 @@ fn keyword(id: &str) -> Option<Token<'static>> {
"return" => Token::Return, "return" => Token::Return,
"import" => Token::Import, "import" => Token::Import,
"include" => Token::Include, "include" => Token::Include,
"using" => Token::Using, "from" => Token::From,
_ => return None, _ => return None,
}) })
} }

View File

@ -440,9 +440,9 @@ impl Pretty for ForPattern {
impl Pretty for ImportExpr { impl Pretty for ImportExpr {
fn pretty(&self, p: &mut Printer) { fn pretty(&self, p: &mut Printer) {
p.push_str("import "); p.push_str("import ");
self.path.pretty(p);
p.push_str(" using ");
self.imports.pretty(p); self.imports.pretty(p);
p.push_str(" from ");
self.path.pretty(p);
} }
} }
@ -737,7 +737,7 @@ mod tests {
roundtrip("#while x {y}"); roundtrip("#while x {y}");
roundtrip("#for x in y {z}"); roundtrip("#for x in y {z}");
roundtrip("#for k, x in y {z}"); roundtrip("#for k, x in y {z}");
roundtrip("#import \"file.typ\" using *"); roundtrip("#import * from \"file.typ\"");
roundtrip("#include \"chapter1.typ\""); roundtrip("#include \"chapter1.typ\"");
} }

View File

@ -59,7 +59,7 @@ pub enum Expr {
While(WhileExpr), While(WhileExpr),
/// A for loop expression: `for x in y { z }`. /// A for loop expression: `for x in y { z }`.
For(ForExpr), For(ForExpr),
/// An import expression: `import "utils.typ" using a, b, c`. /// An import expression: `import a, b, c from "utils.typ"`.
Import(ImportExpr), Import(ImportExpr),
/// An include expression: `include "chapter1.typ"`. /// An include expression: `include "chapter1.typ"`.
Include(IncludeExpr), Include(IncludeExpr),
@ -466,7 +466,7 @@ pub struct LetExpr {
pub init: Option<Box<Expr>>, pub init: Option<Box<Expr>>,
} }
/// An import expression: `import "utils.typ" using a, b, c`. /// An import expression: `import a, b, c from "utils.typ"`.
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub struct ImportExpr { pub struct ImportExpr {
/// The source code location. /// The source code location.

View File

@ -101,8 +101,8 @@ pub enum Token<'s> {
Import, Import,
/// The `include` keyword. /// The `include` keyword.
Include, Include,
/// The `using` keyword. /// The `from` keyword.
Using, From,
/// One or more whitespace characters. /// One or more whitespace characters.
/// ///
/// The contained `usize` denotes the number of newlines that were contained /// The contained `usize` denotes the number of newlines that were contained
@ -254,7 +254,7 @@ impl<'s> Token<'s> {
Self::Return => "keyword `return`", Self::Return => "keyword `return`",
Self::Import => "keyword `import`", Self::Import => "keyword `import`",
Self::Include => "keyword `include`", Self::Include => "keyword `include`",
Self::Using => "keyword `using`", Self::From => "keyword `from`",
Self::Space(_) => "space", Self::Space(_) => "space",
Self::Text(_) => "text", Self::Text(_) => "text",
Self::UnicodeEscape(_) => "unicode escape sequence", Self::UnicodeEscape(_) => "unicode escape sequence",

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

@ -21,7 +21,7 @@
--- ---
// Double block creates a scope. // Double block creates a scope.
{{ {{
import "target.typ" using b import b from "target.typ"
test(b, 1) test(b, 1)
}} }}

View File

@ -4,21 +4,21 @@
// Test importing semantics. // Test importing semantics.
// A named import. // A named import.
#import "target.typ" using item #import item from "target.typ"
#test(item(1, 2), 3) #test(item(1, 2), 3)
// Test that this will be overwritten. // Test that this will be overwritten.
#let value = [foo] #let value = [foo]
// Import multiple things. // Import multiple things.
// Error: 28-29 expected expression, found comma // Error: 9-10 expected expression, found comma
#import "target.typ" using ,fn, value #import ,fn, value from "target.typ"
#fn[Like and Subscribe!] #fn[Like and Subscribe!]
#value #value
// Code mode // Code mode
{ {
import "target.typ" using b import b from "target.typ"
test(b, 1) test(b, 1)
} }
@ -29,91 +29,92 @@
#d #d
// A wildcard import. // A wildcard import.
#import "target.typ" using * #import * from "target.typ"
// It exists now! // It exists now!
#d #d
// Who needs whitespace anyways?
#import*from"target.typ"
// Should output `Hi`.
// Stop at semicolon.
#import a, c from "target.typ";bye
// Allow the trailing comma.
#import a, c, from "target.typ"
--- ---
// Test bad imports. // Test bad imports.
// Ref: false // Ref: false
// Error: 9-11 file not found // Error: 19-21 file not found
#import "" using name #import name from ""
// Error: 9-20 file not found // Error: 16-27 file not found
#import "lib/0.2.1" using * #import * from "lib/0.2.1"
// Error: 9-20 file not found
#import "lib@0.2.1" using *
// Some non-text stuff. // Some non-text stuff.
// Error: 9-30 file is not valid utf-8 // Error: 16-37 file is not valid utf-8
#import "../../res/rhino.png" using * #import * from "../../res/rhino.png"
// Unresolved import. // Unresolved import.
// Error: 28-40 unresolved import // Error: 9-21 unresolved import
#import "target.typ" using non_existing #import non_existing from "target.typ"
// Cyclic import. // Cyclic import.
// Error: 9-34 cyclic import // Error: 16-41 cyclic import
#import "./importable/cycle1.typ" using * #import * from "./importable/cycle1.typ"
--- ---
// Test syntax. // Test bad syntax.
// Missing file. // Error: 2:8 expected import items
// Error: 9-10 expected expression, found star // Error: 1:8 expected keyword `from`
#import * #import
// Should output `"target.typ"`. // Error: 2:9-2:19 expected identifier
// Error: 1-7 unexpected keyword `using` // Error: 1:19 expected keyword `from`
#using "target.typ" #import "file.typ"
// Should output `target`. // Error: 2:16-2:19 expected identifier
// Error: 3:9-4:8 file not found // Error: 1:22 expected keyword `from`
// Error: 3:8 expected semicolon or line break #import afrom, "b", c
// Error: 2:8 expected keyword `using`
#import "target.typ
using "target
// Should output `@ 0.2.1 using`. // Error: 8 expected import items
// Error: 2:21 expected semicolon or line break #import from "target.typ"
// Error: 1:21 expected keyword `using`
#import "target.typ" @ 0.2.1 using *
// Error: 3:21 expected keyword `using` // Error: 2:9-2:10 expected expression, found assignment operator
// Error: 2:21 expected semicolon or line break // Error: 1:10 expected import items
// Error: 1:22-1:28 unexpected keyword `using` #import = from "target.typ"
#import "target.typ" #using *
// Error: 2:21 expected semicolon or line break // Error: 15 expected expression
// Error: 1:21 expected keyword `using` #import * from
#import "target.typ" usinga,b,c
// Error: 27 expected import items
#import "target.typ" using
// Error: 2:28-2:29 expected expression, found assignment operator
// Error: 1:29 expected import items
#import "target.typ" using =
// Allow the trailing comma.
#import "target.typ" using a, c,
// An additional trailing comma. // An additional trailing comma.
// Error: 36-37 expected expression, found comma // Error: 17-18 expected expression, found comma
#import "target.typ" using a, b, c,, #import a, b, c,, from "target.typ"
// Star in the list. // Should output `"target.typ"`.
// Error: 2:31-2:32 expected expression, found star // Error: 1-6 unexpected keyword `from`
// Error: 32-33 expected expression, found comma #from "target.typ"
#import "target.typ" using a, *, b
// Stop at semicolon. // Should output `target`.
#import "target.typ" using a, c;Hi // Error: 2:16-3:2 file not found
// Error: 2:2 expected semicolon or line break
#import * from "target.typ
"target
// Who needs whitespace anyways? // Should output `@ 0.2.1`.
#import "target.typ"using * // Error: 28 expected semicolon or line break
#import"target.typ"using* #import * from "target.typ" @ 0.2.1
#import "target.typ"using *
// A star in the list.
// Error: 2:12-2:13 expected expression, found star
// Error: 1:13-1:14 expected expression, found comma
#import a, *, b from "target.typ"
// An item after a star.
// Should output `, a from "target.typ"`.
// Error: 10 expected keyword `from`
#import *, a from "target.typ"

View File

@ -1,7 +1,7 @@
// Ref: false // Ref: false
// Error: 9-21 cyclic import // Error: 16-28 cyclic import
#import "cycle2.typ" using * #import * from "cycle2.typ"
#let inaccessible = "wow" #let inaccessible = "wow"
This is the first element of an import cycle. This is the first element of an import cycle.

View File

@ -1,7 +1,7 @@
// Ref: false // Ref: false
// Error: 9-21 cyclic import // Error: 16-28 cyclic import
#import "cycle1.typ" using * #import * from "cycle1.typ"
#let val = "much cycle" #let val = "much cycle"
This is the second element of an import cycle. This is the second element of an import cycle.

View File

@ -119,7 +119,7 @@
}, },
{ {
"name": "keyword.other.typst", "name": "keyword.other.typst",
"match": "(#)(as|in|with|from|using)\\b", "match": "(#)(as|in|with|from)\\b",
"captures": { "1": { "name": "punctuation.definition.keyword.typst" } } "captures": { "1": { "name": "punctuation.definition.keyword.typst" } }
}, },
{ {
@ -231,7 +231,7 @@
}, },
{ {
"name": "keyword.other.typst", "name": "keyword.other.typst",
"match": "\\b(pub|let|as|in|with|import|include|from|using)\\b" "match": "\\b(pub|let|as|in|with|import|include|from)\\b"
}, },
{ "include": "#constants" }, { "include": "#constants" },
{ {