|
26 | 26 |
|
27 | 27 | from mathics.version import __version__ # noqa used in loading to check consistency. |
28 | 28 |
|
| 29 | +from mathics_scanner.errors import IncompleteSyntaxError, InvalidSyntaxError |
29 | 30 | from mathics_scanner import TranslateError |
30 | | -from mathics.core.parser import MathicsFileLineFeeder |
| 31 | +from mathics.core.parser import MathicsFileLineFeeder, MathicsMultiLineFeeder, parse |
| 32 | + |
31 | 33 |
|
32 | 34 | from mathics.core.expression import ( |
33 | 35 | BoxError, |
@@ -394,7 +396,7 @@ class Path(Predefined): |
394 | 396 | = ... |
395 | 397 | """ |
396 | 398 |
|
397 | | - attributes = "Protected" |
| 399 | + attributes = ("Unprotected",) |
398 | 400 | name = "$Path" |
399 | 401 |
|
400 | 402 | def evaluate(self, evaluation): |
@@ -601,6 +603,12 @@ class Read(Builtin): |
601 | 603 |
|
602 | 604 | #> Quiet[Read[str, {Real}]] |
603 | 605 | = Read[InputStream[String, ...], {Real}] |
| 606 | +
|
| 607 | + Multiple lines: |
| 608 | + >> str = StringToStream["\\"Tengo una\\nvaca lechera.\\""]; Read[str] |
| 609 | + = Tengo una |
| 610 | + . vaca lechera. |
| 611 | +
|
604 | 612 | """ |
605 | 613 |
|
606 | 614 | messages = { |
@@ -713,8 +721,16 @@ def apply(self, channel, types, evaluation, options): |
713 | 721 | return |
714 | 722 |
|
715 | 723 | # Wrap types in a list (if it isn't already one) |
716 | | - if not types.has_form("List", None): |
717 | | - types = Expression("List", types) |
| 724 | + if types.has_form("List", None): |
| 725 | + types = types._leaves |
| 726 | + else: |
| 727 | + types = (types,) |
| 728 | + |
| 729 | + types = ( |
| 730 | + typ._leaves[0] if typ.get_head_name() == "System`Hold" else typ |
| 731 | + for typ in types |
| 732 | + ) |
| 733 | + types = Expression("List", *types) |
718 | 734 |
|
719 | 735 | READ_TYPES = [ |
720 | 736 | Symbol(k) |
@@ -760,19 +776,38 @@ def reader(stream, word_separators, accepted=None): |
760 | 776 |
|
761 | 777 | if tmp == "": |
762 | 778 | if word == "": |
763 | | - raise EOFError |
764 | | - yield word |
| 779 | + pos = stream.tell() |
| 780 | + newchar = stream.read(1) |
| 781 | + if pos == stream.tell(): |
| 782 | + raise EOFError |
| 783 | + else: |
| 784 | + if newchar: |
| 785 | + word = newchar |
| 786 | + continue |
| 787 | + else: |
| 788 | + yield word |
| 789 | + continue |
| 790 | + last_word = word |
| 791 | + word = "" |
| 792 | + yield last_word |
| 793 | + break |
765 | 794 |
|
766 | 795 | if tmp in word_separators: |
767 | 796 | if word == "": |
768 | | - break |
| 797 | + continue |
769 | 798 | if stream.seekable(): |
770 | | - # stream.seek(-1, 1) #Python3 |
| 799 | + # stream.seek(-1, 1) #Python3 |
771 | 800 | stream.seek(stream.tell() - 1) |
772 | | - yield word |
| 801 | + last_word = word |
| 802 | + word = "" |
| 803 | + yield last_word |
| 804 | + break |
773 | 805 |
|
774 | 806 | if accepted is not None and tmp not in accepted: |
775 | | - yield word |
| 807 | + last_word = word |
| 808 | + word = "" |
| 809 | + yield last_word |
| 810 | + break |
776 | 811 |
|
777 | 812 | word += tmp |
778 | 813 |
|
@@ -802,13 +837,27 @@ def reader(stream, word_separators, accepted=None): |
802 | 837 | result.append(tmp) |
803 | 838 | elif typ == Symbol("Expression"): |
804 | 839 | tmp = next(read_record) |
805 | | - expr = evaluation.parse(tmp) |
| 840 | + while True: |
| 841 | + try: |
| 842 | + feeder = MathicsMultiLineFeeder(tmp) |
| 843 | + expr = parse(evaluation.definitions, feeder) |
| 844 | + break |
| 845 | + except (IncompleteSyntaxError, InvalidSyntaxError) as e: |
| 846 | + try: |
| 847 | + nextline = next(read_record) |
| 848 | + tmp = tmp + "\n" + nextline |
| 849 | + except EOFError: |
| 850 | + expr = Symbol("EndOfFile") |
| 851 | + break |
| 852 | + |
806 | 853 | if expr is None: |
807 | 854 | evaluation.message( |
808 | 855 | "Read", "readt", tmp, Expression("InputSteam", name, n) |
809 | 856 | ) |
810 | 857 | return SymbolFailed |
811 | | - result.append(tmp) |
| 858 | + else: |
| 859 | + result.append(expr) |
| 860 | + |
812 | 861 | elif typ == Symbol("Number"): |
813 | 862 | tmp = next(read_number) |
814 | 863 | try: |
@@ -2180,7 +2229,6 @@ class Get(PrefixOperator): |
2180 | 2229 |
|
2181 | 2230 | def apply(self, path, evaluation, options): |
2182 | 2231 | "Get[path_String, OptionsPattern[Get]]" |
2183 | | - from mathics.core.parser import parse |
2184 | 2232 |
|
2185 | 2233 | def check_options(options): |
2186 | 2234 | # Options |
@@ -2942,7 +2990,7 @@ class ReadList(Read): |
2942 | 2990 | >> ReadList[StringToStream["a 1 b 2"], {Word, Number}] |
2943 | 2991 | = {{a, 1}, {b, 2}} |
2944 | 2992 |
|
2945 | | - >> str = StringToStream["abc123"]; |
| 2993 | + >> str = StringToStream["\\"abc123\\""]; |
2946 | 2994 | >> ReadList[str] |
2947 | 2995 | = {abc123} |
2948 | 2996 | >> InputForm[%] |
|
0 commit comments