mirror of
https://github.com/typst/typst
synced 2025-05-14 04:56:26 +08:00
Just add MathText SyntaxKind
This commit is contained in:
parent
2d33393df9
commit
0b8b7d0f23
@ -99,6 +99,7 @@ impl Eval for ast::Expr<'_> {
|
|||||||
Self::Term(v) => v.eval(vm).map(Value::Content),
|
Self::Term(v) => v.eval(vm).map(Value::Content),
|
||||||
Self::Equation(v) => v.eval(vm).map(Value::Content),
|
Self::Equation(v) => v.eval(vm).map(Value::Content),
|
||||||
Self::Math(v) => v.eval(vm).map(Value::Content),
|
Self::Math(v) => v.eval(vm).map(Value::Content),
|
||||||
|
Self::MathText(v) => v.eval(vm).map(Value::Content),
|
||||||
Self::MathIdent(v) => v.eval(vm),
|
Self::MathIdent(v) => v.eval(vm),
|
||||||
Self::MathShorthand(v) => v.eval(vm),
|
Self::MathShorthand(v) => v.eval(vm),
|
||||||
Self::MathAlignPoint(v) => v.eval(vm).map(Value::Content),
|
Self::MathAlignPoint(v) => v.eval(vm).map(Value::Content),
|
||||||
|
@ -5,7 +5,7 @@ use typst_library::math::{
|
|||||||
AlignPointElem, AttachElem, FracElem, LrElem, PrimesElem, RootElem,
|
AlignPointElem, AttachElem, FracElem, LrElem, PrimesElem, RootElem,
|
||||||
};
|
};
|
||||||
use typst_library::text::TextElem;
|
use typst_library::text::TextElem;
|
||||||
use typst_syntax::ast::{self, AstNode};
|
use typst_syntax::ast::{self, AstNode, MathTextKind};
|
||||||
|
|
||||||
use crate::{Eval, Vm};
|
use crate::{Eval, Vm};
|
||||||
|
|
||||||
@ -20,6 +20,18 @@ impl Eval for ast::Math<'_> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Eval for ast::MathText<'_> {
|
||||||
|
type Output = Content;
|
||||||
|
|
||||||
|
fn eval(self, _: &mut Vm) -> SourceResult<Self::Output> {
|
||||||
|
match self.get() {
|
||||||
|
// TODO: change to `SymbolElem` when added
|
||||||
|
MathTextKind::Character(c) => Ok(Value::Symbol(Symbol::single(c)).display()),
|
||||||
|
MathTextKind::Number(text) => Ok(TextElem::packed(text.clone())),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Eval for ast::MathIdent<'_> {
|
impl Eval for ast::MathIdent<'_> {
|
||||||
type Output = Value;
|
type Output = Value;
|
||||||
|
|
||||||
|
@ -123,6 +123,8 @@ pub enum Expr<'a> {
|
|||||||
Equation(Equation<'a>),
|
Equation(Equation<'a>),
|
||||||
/// The contents of a mathematical equation: `x^2 + 1`.
|
/// The contents of a mathematical equation: `x^2 + 1`.
|
||||||
Math(Math<'a>),
|
Math(Math<'a>),
|
||||||
|
/// A lone text fragment in math: `x`, `25`, `3.1415`, `=`, `[`.
|
||||||
|
MathText(MathText<'a>),
|
||||||
/// An identifier in math: `pi`.
|
/// An identifier in math: `pi`.
|
||||||
MathIdent(MathIdent<'a>),
|
MathIdent(MathIdent<'a>),
|
||||||
/// A shorthand for a unicode codepoint in math: `a <= b`.
|
/// A shorthand for a unicode codepoint in math: `a <= b`.
|
||||||
@ -233,6 +235,7 @@ impl<'a> AstNode<'a> for Expr<'a> {
|
|||||||
SyntaxKind::TermItem => node.cast().map(Self::Term),
|
SyntaxKind::TermItem => node.cast().map(Self::Term),
|
||||||
SyntaxKind::Equation => node.cast().map(Self::Equation),
|
SyntaxKind::Equation => node.cast().map(Self::Equation),
|
||||||
SyntaxKind::Math => node.cast().map(Self::Math),
|
SyntaxKind::Math => node.cast().map(Self::Math),
|
||||||
|
SyntaxKind::MathText => node.cast().map(Self::MathText),
|
||||||
SyntaxKind::MathIdent => node.cast().map(Self::MathIdent),
|
SyntaxKind::MathIdent => node.cast().map(Self::MathIdent),
|
||||||
SyntaxKind::MathShorthand => node.cast().map(Self::MathShorthand),
|
SyntaxKind::MathShorthand => node.cast().map(Self::MathShorthand),
|
||||||
SyntaxKind::MathAlignPoint => node.cast().map(Self::MathAlignPoint),
|
SyntaxKind::MathAlignPoint => node.cast().map(Self::MathAlignPoint),
|
||||||
@ -297,6 +300,7 @@ impl<'a> AstNode<'a> for Expr<'a> {
|
|||||||
Self::Term(v) => v.to_untyped(),
|
Self::Term(v) => v.to_untyped(),
|
||||||
Self::Equation(v) => v.to_untyped(),
|
Self::Equation(v) => v.to_untyped(),
|
||||||
Self::Math(v) => v.to_untyped(),
|
Self::Math(v) => v.to_untyped(),
|
||||||
|
Self::MathText(v) => v.to_untyped(),
|
||||||
Self::MathIdent(v) => v.to_untyped(),
|
Self::MathIdent(v) => v.to_untyped(),
|
||||||
Self::MathShorthand(v) => v.to_untyped(),
|
Self::MathShorthand(v) => v.to_untyped(),
|
||||||
Self::MathAlignPoint(v) => v.to_untyped(),
|
Self::MathAlignPoint(v) => v.to_untyped(),
|
||||||
@ -706,6 +710,34 @@ impl<'a> Math<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
node! {
|
||||||
|
/// A lone text fragment in math: `x`, `25`, `3.1415`, `=`, `[`.
|
||||||
|
MathText
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The underlying text kind.
|
||||||
|
pub enum MathTextKind<'a> {
|
||||||
|
Character(char),
|
||||||
|
Number(&'a EcoString),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> MathText<'a> {
|
||||||
|
/// Return the underlying text.
|
||||||
|
pub fn get(self) -> MathTextKind<'a> {
|
||||||
|
let text = self.0.text();
|
||||||
|
let mut chars = text.chars();
|
||||||
|
let c = chars.next().unwrap();
|
||||||
|
if c.is_numeric() {
|
||||||
|
// Numbers are potentially grouped as multiple characters. This is
|
||||||
|
// done in `Lexer::math_text()`.
|
||||||
|
MathTextKind::Number(text)
|
||||||
|
} else {
|
||||||
|
assert!(chars.next().is_none());
|
||||||
|
MathTextKind::Character(c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
node! {
|
node! {
|
||||||
/// An identifier in math: `pi`.
|
/// An identifier in math: `pi`.
|
||||||
MathIdent
|
MathIdent
|
||||||
|
@ -171,6 +171,7 @@ pub fn highlight(node: &LinkedNode) -> Option<Tag> {
|
|||||||
SyntaxKind::Equation => None,
|
SyntaxKind::Equation => None,
|
||||||
|
|
||||||
SyntaxKind::Math => None,
|
SyntaxKind::Math => None,
|
||||||
|
SyntaxKind::MathText => None,
|
||||||
SyntaxKind::MathIdent => highlight_ident(node),
|
SyntaxKind::MathIdent => highlight_ident(node),
|
||||||
SyntaxKind::MathShorthand => Some(Tag::Escape),
|
SyntaxKind::MathShorthand => Some(Tag::Escape),
|
||||||
SyntaxKind::MathAlignPoint => Some(Tag::MathOperator),
|
SyntaxKind::MathAlignPoint => Some(Tag::MathOperator),
|
||||||
|
@ -75,6 +75,8 @@ pub enum SyntaxKind {
|
|||||||
|
|
||||||
/// The contents of a mathematical equation: `x^2 + 1`.
|
/// The contents of a mathematical equation: `x^2 + 1`.
|
||||||
Math,
|
Math,
|
||||||
|
/// A lone text fragment in math: `x`, `25`, `3.1415`, `=`, `|`, `[`.
|
||||||
|
MathText,
|
||||||
/// An identifier in math: `pi`.
|
/// An identifier in math: `pi`.
|
||||||
MathIdent,
|
MathIdent,
|
||||||
/// A shorthand for a unicode codepoint in math: `a <= b`.
|
/// A shorthand for a unicode codepoint in math: `a <= b`.
|
||||||
@ -408,6 +410,7 @@ impl SyntaxKind {
|
|||||||
Self::TermMarker => "term marker",
|
Self::TermMarker => "term marker",
|
||||||
Self::Equation => "equation",
|
Self::Equation => "equation",
|
||||||
Self::Math => "math",
|
Self::Math => "math",
|
||||||
|
Self::MathText => "math text",
|
||||||
Self::MathIdent => "math identifier",
|
Self::MathIdent => "math identifier",
|
||||||
Self::MathShorthand => "math shorthand",
|
Self::MathShorthand => "math shorthand",
|
||||||
Self::MathAlignPoint => "math alignment point",
|
Self::MathAlignPoint => "math alignment point",
|
||||||
|
@ -685,6 +685,7 @@ impl Lexer<'_> {
|
|||||||
if s.eat_if('.') && !s.eat_while(char::is_numeric).is_empty() {
|
if s.eat_if('.') && !s.eat_while(char::is_numeric).is_empty() {
|
||||||
self.s = s;
|
self.s = s;
|
||||||
}
|
}
|
||||||
|
SyntaxKind::MathText
|
||||||
} else {
|
} else {
|
||||||
let len = self
|
let len = self
|
||||||
.s
|
.s
|
||||||
@ -693,8 +694,14 @@ impl Lexer<'_> {
|
|||||||
.next()
|
.next()
|
||||||
.map_or(0, str::len);
|
.map_or(0, str::len);
|
||||||
self.s.jump(start + len);
|
self.s.jump(start + len);
|
||||||
}
|
if len > c.len_utf8() {
|
||||||
|
// Grapheme clusters are treated as normal text and stay grouped
|
||||||
|
// This may need to change in the future.
|
||||||
SyntaxKind::Text
|
SyntaxKind::Text
|
||||||
|
} else {
|
||||||
|
SyntaxKind::MathText
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Handle named arguments in math function call.
|
/// Handle named arguments in math function call.
|
||||||
|
@ -252,7 +252,9 @@ fn math_expr_prec(p: &mut Parser, min_prec: usize, stop: SyntaxKind) {
|
|||||||
continuable = true;
|
continuable = true;
|
||||||
p.eat();
|
p.eat();
|
||||||
// Parse a function call for an identifier or field access.
|
// Parse a function call for an identifier or field access.
|
||||||
if min_prec < 3 && p.directly_at(SyntaxKind::Text) && p.current_text() == "("
|
if min_prec < 3
|
||||||
|
&& p.directly_at(SyntaxKind::MathText)
|
||||||
|
&& p.current_text() == "("
|
||||||
{
|
{
|
||||||
math_args(p);
|
math_args(p);
|
||||||
p.wrap(m, SyntaxKind::FuncCall);
|
p.wrap(m, SyntaxKind::FuncCall);
|
||||||
@ -264,10 +266,10 @@ fn math_expr_prec(p: &mut Parser, min_prec: usize, stop: SyntaxKind) {
|
|||||||
| SyntaxKind::Comma
|
| SyntaxKind::Comma
|
||||||
| SyntaxKind::Semicolon
|
| SyntaxKind::Semicolon
|
||||||
| SyntaxKind::RightParen => {
|
| SyntaxKind::RightParen => {
|
||||||
p.convert_and_eat(SyntaxKind::Text);
|
p.convert_and_eat(SyntaxKind::MathText);
|
||||||
}
|
}
|
||||||
|
|
||||||
SyntaxKind::Text | SyntaxKind::MathShorthand => {
|
SyntaxKind::Text | SyntaxKind::MathText | SyntaxKind::MathShorthand => {
|
||||||
continuable = matches!(
|
continuable = matches!(
|
||||||
math_class(p.current_text()),
|
math_class(p.current_text()),
|
||||||
None | Some(MathClass::Alphabetic)
|
None | Some(MathClass::Alphabetic)
|
||||||
@ -316,7 +318,7 @@ fn math_expr_prec(p: &mut Parser, min_prec: usize, stop: SyntaxKind) {
|
|||||||
let mut primed = false;
|
let mut primed = false;
|
||||||
|
|
||||||
while !p.end() && !p.at(stop) {
|
while !p.end() && !p.at(stop) {
|
||||||
if p.directly_at(SyntaxKind::Text) && p.current_text() == "!" {
|
if p.directly_at(SyntaxKind::MathText) && p.current_text() == "!" {
|
||||||
p.eat();
|
p.eat();
|
||||||
p.wrap(m, SyntaxKind::Math);
|
p.wrap(m, SyntaxKind::Math);
|
||||||
continue;
|
continue;
|
||||||
@ -414,7 +416,7 @@ fn math_delimited(p: &mut Parser) {
|
|||||||
// We could be at the shorthand `|]`, which shouldn't be converted
|
// We could be at the shorthand `|]`, which shouldn't be converted
|
||||||
// to a `Text` kind.
|
// to a `Text` kind.
|
||||||
if p.at(SyntaxKind::RightParen) {
|
if p.at(SyntaxKind::RightParen) {
|
||||||
p.convert_and_eat(SyntaxKind::Text);
|
p.convert_and_eat(SyntaxKind::MathText);
|
||||||
} else {
|
} else {
|
||||||
p.eat();
|
p.eat();
|
||||||
}
|
}
|
||||||
@ -535,7 +537,7 @@ fn math_arg<'s>(p: &mut Parser<'s>, seen: &mut HashSet<&'s str>) -> bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let mut positional = true;
|
let mut positional = true;
|
||||||
if p.at_set(syntax_set!(Text, MathIdent, Underscore)) {
|
if p.at_set(syntax_set!(MathText, MathIdent, Underscore)) {
|
||||||
// Parses a named argument: `thickness: #12pt`.
|
// Parses a named argument: `thickness: #12pt`.
|
||||||
if let Some(named) = p.lexer.maybe_math_named_arg(start) {
|
if let Some(named) = p.lexer.maybe_math_named_arg(start) {
|
||||||
p.token.node = named;
|
p.token.node = named;
|
||||||
|
@ -64,6 +64,7 @@ pub const MATH_EXPR: SyntaxSet = syntax_set!(
|
|||||||
Semicolon,
|
Semicolon,
|
||||||
RightParen,
|
RightParen,
|
||||||
Text,
|
Text,
|
||||||
|
MathText,
|
||||||
MathShorthand,
|
MathShorthand,
|
||||||
Linebreak,
|
Linebreak,
|
||||||
MathAlignPoint,
|
MathAlignPoint,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user