mirror of
https://github.com/erg-lang/erg.git
synced 2025-09-30 04:44:44 +00:00
Merge branch 'main' into beta
This commit is contained in:
commit
a9d4e5982b
8 changed files with 107 additions and 19 deletions
2
TODO.md
2
TODO.md
|
@ -135,4 +135,4 @@
|
||||||
* [ ] Write educational materials to learn Erg while creating applications (e.g. CLI chess game -> GUI chess game, calculator -> toy language)
|
* [ ] Write educational materials to learn Erg while creating applications (e.g. CLI chess game -> GUI chess game, calculator -> toy language)
|
||||||
* [ ] Develop Dyne (CPython compatible VM)
|
* [ ] Develop Dyne (CPython compatible VM)
|
||||||
* [ ] Develop Kayser (WebAssembly backend)
|
* [ ] Develop Kayser (WebAssembly backend)
|
||||||
* [ ] Develop Barye (LLVM backend)
|
* [ ] Develop Gal (LLVM backend)
|
||||||
|
|
|
@ -1330,13 +1330,13 @@ impl Context {
|
||||||
proc.register_superclass(Obj, &obj);
|
proc.register_superclass(Obj, &obj);
|
||||||
// TODO: lambda
|
// TODO: lambda
|
||||||
proc.register_marker_trait(mono("Named"));
|
proc.register_marker_trait(mono("Named"));
|
||||||
let mut func = Self::mono_class("Function", Self::TOP_LEVEL);
|
let mut func = Self::mono_class("Func", Self::TOP_LEVEL);
|
||||||
func.register_superclass(mono("Procedure"), &proc);
|
func.register_superclass(mono("Proc"), &proc);
|
||||||
func.register_superclass(Obj, &obj);
|
func.register_superclass(Obj, &obj);
|
||||||
// TODO: lambda
|
// TODO: lambda
|
||||||
func.register_marker_trait(mono("Named"));
|
func.register_marker_trait(mono("Named"));
|
||||||
let mut qfunc = Self::mono_class("QuantifiedFunction", Self::TOP_LEVEL);
|
let mut qfunc = Self::mono_class("QuantifiedFunc", Self::TOP_LEVEL);
|
||||||
qfunc.register_superclass(mono("Function"), &func);
|
qfunc.register_superclass(mono("Func"), &func);
|
||||||
qfunc.register_superclass(Obj, &obj);
|
qfunc.register_superclass(Obj, &obj);
|
||||||
self.register_builtin_type(Obj, obj, Const);
|
self.register_builtin_type(Obj, obj, Const);
|
||||||
// self.register_type(mono("Record"), vec![], record, Const);
|
// self.register_type(mono("Record"), vec![], record, Const);
|
||||||
|
@ -1423,9 +1423,9 @@ impl Context {
|
||||||
self.register_builtin_type(array_mut_t, array_mut_, Const);
|
self.register_builtin_type(array_mut_t, array_mut_, Const);
|
||||||
self.register_builtin_type(range_t, range, Const);
|
self.register_builtin_type(range_t, range, Const);
|
||||||
self.register_builtin_type(mono("Tuple"), tuple_, Const);
|
self.register_builtin_type(mono("Tuple"), tuple_, Const);
|
||||||
self.register_builtin_type(mono("Procedure"), proc, Const);
|
self.register_builtin_type(mono("Proc"), proc, Const);
|
||||||
self.register_builtin_type(mono("Function"), func, Const);
|
self.register_builtin_type(mono("Func"), func, Const);
|
||||||
self.register_builtin_type(mono("QuantifiedFunction"), qfunc, Const);
|
self.register_builtin_type(mono("QuantifiedFunc"), qfunc, Const);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn init_builtin_funcs(&mut self) {
|
fn init_builtin_funcs(&mut self) {
|
||||||
|
|
|
@ -1089,13 +1089,13 @@ impl Context {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Type::Quantified(_) => {
|
Type::Quantified(_) => {
|
||||||
if let Some(res) = self.get_nominal_type_ctx(&mono("QuantifiedFunction")) {
|
if let Some(res) = self.get_nominal_type_ctx(&mono("QuantifiedFunc")) {
|
||||||
return Some(res);
|
return Some(res);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Type::Subr(_subr) => match _subr.kind {
|
Type::Subr(_subr) => match _subr.kind {
|
||||||
SubrKind::Func => {
|
SubrKind::Func => {
|
||||||
if let Some(res) = self.get_nominal_type_ctx(&mono("Function")) {
|
if let Some(res) = self.get_nominal_type_ctx(&mono("Func")) {
|
||||||
return Some(res);
|
return Some(res);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1157,7 +1157,7 @@ impl Context {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Type::Quantified(_) => {
|
Type::Quantified(_) => {
|
||||||
if let Some(res) = self.get_mut_nominal_type_ctx(&mono("QuantifiedFunction")) {
|
if let Some(res) = self.get_mut_nominal_type_ctx(&mono("QuantifiedFunc")) {
|
||||||
return Some(res);
|
return Some(res);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -285,6 +285,62 @@ impl Lexer /*<'a>*/ {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn lex_multi_line_comment(&mut self) -> LexResult<()> {
|
||||||
|
let mut s = "".to_string();
|
||||||
|
let mut nest_level = 0;
|
||||||
|
loop {
|
||||||
|
match self.peek_cur_ch() {
|
||||||
|
Some(c) => {
|
||||||
|
if let Some(next_c) = self.peek_next_ch() {
|
||||||
|
match (c, next_c) {
|
||||||
|
('#', '[') => nest_level += 1,
|
||||||
|
(']', '#') => {
|
||||||
|
nest_level -= 1;
|
||||||
|
if nest_level == 0 {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
if c == '\n' {
|
||||||
|
self.lineno_token_starts += 1;
|
||||||
|
self.col_token_starts = 0;
|
||||||
|
}
|
||||||
|
s.push(self.consume().unwrap());
|
||||||
|
}
|
||||||
|
if Self::is_bidi(self.peek_cur_ch().unwrap()) {
|
||||||
|
let comment = self.emit_token(Illegal, &s);
|
||||||
|
return Err(LexError::syntax_error(
|
||||||
|
0,
|
||||||
|
comment.loc(),
|
||||||
|
switch_lang!(
|
||||||
|
"japanese" => "不正なユニコード文字(双方向オーバーライド)がコメント中に使用されています",
|
||||||
|
"simplified_chinese" => "注释中使用了非法的unicode字符(双向覆盖)",
|
||||||
|
"traditional_chinese" => "註釋中使用了非法的unicode字符(雙向覆蓋)",
|
||||||
|
"english" => "invalid unicode character (bi-directional override) in comments",
|
||||||
|
),
|
||||||
|
None,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
let comment = self.emit_token(Illegal, &s);
|
||||||
|
return Err(LexError::syntax_error(
|
||||||
|
0,
|
||||||
|
comment.loc(),
|
||||||
|
switch_lang!(
|
||||||
|
"japanese" => "複数行コメントが]#で閉じられていません",
|
||||||
|
"simplified_chinese" => "未用]#号结束的多处评论",
|
||||||
|
"traditional_chinese" => "多條評論未用]#關閉",
|
||||||
|
"english" => "Multi-comment is not closed with ]#",
|
||||||
|
),
|
||||||
|
None,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn lex_space_indent_dedent(&mut self) -> Option<LexResult<Token>> {
|
fn lex_space_indent_dedent(&mut self) -> Option<LexResult<Token>> {
|
||||||
let is_toplevel = self.cursor > 0
|
let is_toplevel = self.cursor > 0
|
||||||
&& !self.indent_stack.is_empty()
|
&& !self.indent_stack.is_empty()
|
||||||
|
@ -349,6 +405,11 @@ impl Lexer /*<'a>*/ {
|
||||||
}
|
}
|
||||||
// ignore indents if the current line is a comment
|
// ignore indents if the current line is a comment
|
||||||
if let Some('#') = self.peek_cur_ch() {
|
if let Some('#') = self.peek_cur_ch() {
|
||||||
|
if let Some('[') = self.peek_next_ch() {
|
||||||
|
if let Err(e) = self.lex_multi_line_comment() {
|
||||||
|
return Some(Err(e));
|
||||||
|
}
|
||||||
|
}
|
||||||
if let Err(e) = self.lex_comment() {
|
if let Err(e) = self.lex_comment() {
|
||||||
return Some(Err(e));
|
return Some(Err(e));
|
||||||
}
|
}
|
||||||
|
@ -562,6 +623,7 @@ impl Lexer /*<'a>*/ {
|
||||||
'r' => s.push('\r'),
|
'r' => s.push('\r'),
|
||||||
'n' => s.push('\n'),
|
'n' => s.push('\n'),
|
||||||
'\'' => s.push('\''),
|
'\'' => s.push('\''),
|
||||||
|
'"' => s.push('"'),
|
||||||
't' => s.push_str(" "), // tab is invalid, so changed into 4 whitespace
|
't' => s.push_str(" "), // tab is invalid, so changed into 4 whitespace
|
||||||
'\\' => s.push('\\'),
|
'\\' => s.push('\\'),
|
||||||
_ => {
|
_ => {
|
||||||
|
@ -630,6 +692,11 @@ impl Iterator for Lexer /*<'a>*/ {
|
||||||
return indent_dedent;
|
return indent_dedent;
|
||||||
}
|
}
|
||||||
if let Some('#') = self.peek_cur_ch() {
|
if let Some('#') = self.peek_cur_ch() {
|
||||||
|
if let Some('[') = self.peek_next_ch() {
|
||||||
|
if let Err(e) = self.lex_multi_line_comment() {
|
||||||
|
return Some(Err(e));
|
||||||
|
}
|
||||||
|
}
|
||||||
if let Err(e) = self.lex_comment() {
|
if let Err(e) = self.lex_comment() {
|
||||||
return Some(Err(e));
|
return Some(Err(e));
|
||||||
}
|
}
|
||||||
|
|
7
compiler/erg_parser/tests/comment.er
Normal file
7
compiler/erg_parser/tests/comment.er
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
#[
|
||||||
|
aa
|
||||||
|
#[ aa ]#
|
||||||
|
aa
|
||||||
|
]#
|
||||||
|
|
||||||
|
a = 1
|
|
@ -1,12 +1,24 @@
|
||||||
# 基本的な構文をパーサーがパスできるかチェックする
|
#[
|
||||||
# Check that a parser can pass the basic syntax
|
基本的な構文をパーサーがパスできるかチェックする
|
||||||
|
Check that a parser can pass the basic syntax
|
||||||
|
#[
|
||||||
|
`#[`から`]#`までが複数行コメントとして扱われる
|
||||||
|
コメント内部で入れ子で複数行コメントを付けれるが、閉じ忘れに注意
|
||||||
|
The comment from `#[` to `]#` is treated as a multi-line comment.
|
||||||
|
Nested multi-line comments can be added inside comments, but be careful not to forget to close them.
|
||||||
|
]#
|
||||||
|
]#
|
||||||
|
|
||||||
_a = 1_234 + 1113.* 3_000.2e-4 ** 0003 * .4
|
_a = 1_234 + 1113.* 3_000.2e-4 ** 0003 * .4
|
||||||
a, _, ...b = five_elem_tuple
|
a, _, ...b = five_elem_tuple
|
||||||
f x, y =
|
f x, y =
|
||||||
x + y
|
x + y
|
||||||
if! True, do!:
|
if! True, do!:
|
||||||
print! "\\hello, world\""
|
print! "\"\\hello, world\\\""
|
||||||
|
#[
|
||||||
|
indented comment
|
||||||
|
dedented comment
|
||||||
|
]#
|
||||||
10.times! do!:
|
10.times! do!:
|
||||||
if! x.y.z, do!:
|
if! x.y.z, do!:
|
||||||
print! ""
|
print! ""
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
0.00, -0.0, .1, 400.
|
0.00, -0.0, .1, 400.
|
||||||
|
|
||||||
# Str Literal
|
# Str Literal
|
||||||
"", "a", "こんにちは", "\" \\ "
|
"", "a", "こんにちは", "\"\\", "\"\'\\\0\r\n\t"
|
||||||
|
|
||||||
# Boolean Litteral
|
# Boolean Litteral
|
||||||
True, False
|
True, False
|
||||||
|
|
|
@ -18,7 +18,6 @@ fn test_lexer_for_basic() -> ParseResult<()> {
|
||||||
let mut lexer = Lexer::new(Input::File(FILE1.into()));
|
let mut lexer = Lexer::new(Input::File(FILE1.into()));
|
||||||
let newline = "\n";
|
let newline = "\n";
|
||||||
let /*mut*/ token_array = vec![
|
let /*mut*/ token_array = vec![
|
||||||
(Newline, newline),
|
|
||||||
(Newline, newline),
|
(Newline, newline),
|
||||||
(Newline, newline),
|
(Newline, newline),
|
||||||
(Symbol, "_a"),
|
(Symbol, "_a"),
|
||||||
|
@ -37,7 +36,7 @@ fn test_lexer_for_basic() -> ParseResult<()> {
|
||||||
(Comma, ","),
|
(Comma, ","),
|
||||||
(UBar, "_"),
|
(UBar, "_"),
|
||||||
(Comma, ","),
|
(Comma, ","),
|
||||||
(Spread, "..."), // EllipsisLit
|
(EllipsisLit, "..."),
|
||||||
(Symbol, "b"),
|
(Symbol, "b"),
|
||||||
(Equal, "="),
|
(Equal, "="),
|
||||||
(Symbol, "five_elem_tuple"),
|
(Symbol, "five_elem_tuple"),
|
||||||
|
@ -62,7 +61,8 @@ fn test_lexer_for_basic() -> ParseResult<()> {
|
||||||
(Newline, newline),
|
(Newline, newline),
|
||||||
(Indent, " "),
|
(Indent, " "),
|
||||||
(Symbol, "print!"),
|
(Symbol, "print!"),
|
||||||
(StrLit, "\"\\\\hello, world\\\"\""),
|
(StrLit, "\"\"\\hello, world\\\"\""),
|
||||||
|
(Newline, newline),
|
||||||
(Newline, newline),
|
(Newline, newline),
|
||||||
(NatLit, "10"),
|
(NatLit, "10"),
|
||||||
(Dot, "."),
|
(Dot, "."),
|
||||||
|
@ -264,7 +264,9 @@ fn test_lexer_for_literals() -> ParseResult<()> {
|
||||||
(Comma, ","),
|
(Comma, ","),
|
||||||
(StrLit, "\"こんにちは\""),
|
(StrLit, "\"こんにちは\""),
|
||||||
(Comma, ","),
|
(Comma, ","),
|
||||||
(StrLit, "\"\\\" \\\\ \""),
|
(StrLit, "\"\"\\\""),
|
||||||
|
(Comma, ","),
|
||||||
|
(StrLit, "\"\"\'\\\0\r\n \""),
|
||||||
(Newline, newline),
|
(Newline, newline),
|
||||||
(Newline, newline),
|
(Newline, newline),
|
||||||
(Newline, newline),
|
(Newline, newline),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue