From c6aa7a023346b7b56c47598fafc964cb098253a7 Mon Sep 17 00:00:00 2001 From: Largo Date: Fri, 23 Oct 2026 15:55:02 +0200 Subject: [PATCH 1/9] Store into a boxed struct's field, not into a copy of it RubyFieldInfo built a field store as Assign(Field(Convert(target, S), f), v). Convert unboxes into a temporary, so once the rule is compiled the store changes that copy and the box Ruby holds keeps its old fields - silently. OpenSSL::PKey fills RSAParameters / DSAParameters / ECParameters this way, so a PEM loaded about 35 times and then failed for the rest of the process ("The specified RSA parameters are not valid"): the interpreter updated the box, compiled code did not. With today's upstream DLR the interpreter copies too (IronLanguages/dlr#368), and it fails on the first load. The store now goes through Unbox, which addresses the value inside the box, in compiled and interpreted code alike. Calls to mutating methods on a boxed struct already reached the box. ClrValueTypes1, commented out since 2011 as "fails with /noadaptive", is the same bug and runs again; ClrValueTypes3 fills S2 and RSAParameters in a method called 100 times and checks every result. --- Src/IronRuby.Tests/RubyTests.cs | 4 +-- Src/IronRuby.Tests/Runtime/ClrTests.cs | 41 +++++++++++++++++++++++++ Src/Ruby/Runtime/Calls/RubyFieldInfo.cs | 9 ++++++ 3 files changed, 52 insertions(+), 2 deletions(-) diff --git a/Src/IronRuby.Tests/RubyTests.cs b/Src/IronRuby.Tests/RubyTests.cs index 3937efc1b..a57f106f0 100644 --- a/Src/IronRuby.Tests/RubyTests.cs +++ b/Src/IronRuby.Tests/RubyTests.cs @@ -554,9 +554,9 @@ public Tests(Driver/*!*/ driver) { ClrToString1, ClrHashEquals4, ClrTypeVariance1, - // TODO: fails with /noadaptive - // ClrValueTypes1, + ClrValueTypes1, ClrValueTypes2, + ClrValueTypes3, HostingDefaultOptions1, Interactive1, Interactive2, diff --git a/Src/IronRuby.Tests/Runtime/ClrTests.cs b/Src/IronRuby.Tests/Runtime/ClrTests.cs index a9baed17d..722c39add 100644 --- a/Src/IronRuby.Tests/Runtime/ClrTests.cs +++ b/Src/IronRuby.Tests/Runtime/ClrTests.cs @@ -2419,6 +2419,47 @@ public void ClrValueTypes1() { Assert(unboxed.Y == 4); } + // A struct built and filled in Ruby (OpenSSL::PKey fills RSAParameters this way). The stores used to + // go to a temporary copy once the call sites were compiled, so after ~32 calls every field read nil. + public void ClrValueTypes3() { + Context.ObjectClass.SetConstant("S2", Context.GetClass(typeof(S2))); + Context.ObjectClass.SetConstant("RSAParameters", Context.GetClass(typeof(System.Security.Cryptography.RSAParameters))); + + AssertOutput(() => CompilerTest(@" +def fill(i) + s = S2.new + s.X = i + s.Y = i + 1 + s +end + +def set_x(i) + s = S2.new(i, i) + s.SetX + s +end + +def rsa(i) + p = RSAParameters.new + p.Modulus = System::Array[System::Byte].new(i + 1) + p +end + +bad = (0...100).reject { |i| s = fill(i); s.X == i && s.Y == i + 1 } +puts ""fill: #{bad.inspect}"" + +bad = (0...100).reject { |i| set_x(i).X == 1 } +puts ""set_x: #{bad.inspect}"" + +bad = (0...100).reject { |i| m = rsa(i).Modulus; m && m.Length == i + 1 } +puts ""rsa: #{bad.inspect}"" +"), @" +fill: [] +set_x: [] +rsa: [] +"); + } + public class ClassWithValueTypeField1 { public S2 Value = new S2(1, 2); } diff --git a/Src/Ruby/Runtime/Calls/RubyFieldInfo.cs b/Src/Ruby/Runtime/Calls/RubyFieldInfo.cs index a282f8372..51b3ce4e1 100644 --- a/Src/Ruby/Runtime/Calls/RubyFieldInfo.cs +++ b/Src/Ruby/Runtime/Calls/RubyFieldInfo.cs @@ -71,6 +71,15 @@ internal override void BuildCallNoFlow(MetaObjectBuilder/*!*/ metaBuilder, CallA Expression instance = _fieldInfo.IsStatic ? null : Ast.Convert(args.TargetExpression, _fieldInfo.DeclaringType); if (_isSetter) { + if (instance != null && _fieldInfo.DeclaringType.IsValueType) { + // Convert unboxes a struct into a temporary, so the store would change the copy and leave the + // box Ruby holds untouched - silently, and only once the rule is compiled (the interpreter used + // to update the box). Unbox addresses the value inside the box instead. + instance = args.TargetExpression.Type.IsValueType + ? args.TargetExpression + : Ast.Unbox(AstUtils.Convert(args.TargetExpression, typeof(object)), _fieldInfo.DeclaringType); + } + var actualArgs = RubyOverloadResolver.NormalizeArguments(metaBuilder, args, 1, 1); if (!metaBuilder.Error) { metaBuilder.Result = Ast.Assign( From b8bcedaaec97b171ff675650a67dce02d6581d85 Mon Sep 17 00:00:00 2001 From: Largo Date: Fri, 23 Oct 2026 16:00:52 +0200 Subject: [PATCH 2/9] Windows: the local zone keeps daylight saving time MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With TZ unset the zone came from /etc/localtime, and where there is none (Windows) from TimeZoneInfo.Local's base offset alone, so all summer Time.now, Time.local, Time.at and File.mtime were an hour off and isdst was false. The zone is now backed by TimeZoneInfo there, transitions included. An Olson TZ ("Europe/Zurich") without a zoneinfo file falls back to TimeZoneInfo as well, instead of to UTC; a POSIX string ("EST5EDT", "JST-9") keeps its own meaning. Such a zone is named by its id, "W. Europe Standard Time", winter and summer, which is what CRuby on Windows reports. StandardName is in the language of the Windows installation: on a German one it was "Mitteleuropäische Zeit", which Time#zone printed garbled and Marshal.dump of a local time stopped the process on (CreateAscii's assertion in a Debug build). ruby/spec on Windows: core/time 1 failure -> 0, core/file/mtime and core/file/stat/mtime 1 -> 0 each. Time_MachineZone1 compares with .NET's own answer, so it holds in any machine zone; Time_OlsonZone1 sets TZ. --- Src/IronRuby.Tests/RubyTests.cs | 2 + Src/IronRuby.Tests/Runtime/MiscTests.cs | 54 +++++++++++++++++ Src/Libraries/Builtins/RubyTimeSupport.cs | 71 ++++++++++++++++++----- 3 files changed, 112 insertions(+), 15 deletions(-) diff --git a/Src/IronRuby.Tests/RubyTests.cs b/Src/IronRuby.Tests/RubyTests.cs index a57f106f0..3a8b1f589 100644 --- a/Src/IronRuby.Tests/RubyTests.cs +++ b/Src/IronRuby.Tests/RubyTests.cs @@ -700,6 +700,8 @@ public Tests(Driver/*!*/ driver) { Scenario_MainSingleton, Time_LoadZone1, Time_DumpLoadedZone1, + Time_MachineZone1, + Time_OlsonZone1, Scenario_RubyThreads1, Scenario_YieldCodeGen, diff --git a/Src/IronRuby.Tests/Runtime/MiscTests.cs b/Src/IronRuby.Tests/Runtime/MiscTests.cs index 3ba74ef5a..85a03fd70 100644 --- a/Src/IronRuby.Tests/Runtime/MiscTests.cs +++ b/Src/IronRuby.Tests/Runtime/MiscTests.cs @@ -813,6 +813,60 @@ puts ArrayList }, @"System::Collections::ArrayList"); } + /// + /// With TZ unset the zone is the machine's, daylight saving time included. Windows has no /etc/localtime, + /// and the zone used to be TimeZoneInfo.Local's base offset alone, so Time.now, Time.local and File.mtime + /// were an hour off all summer. Compared with .NET's own answer, so it holds in any machine zone. + /// + public void Time_MachineZone1() { + TestOutput(@" +ENV.delete('TZ') +local = System::TimeZoneInfo.Local +# 2026-01-15 and 2026-07-15, 10:00 UTC +[1768471200, 1784109600].each do |s| + t = Time.at(s) + expected = local.GetUtcOffset(System::DateTimeOffset.FromUnixTimeSeconds(s)).TotalSeconds.to_i + dst = local.IsDaylightSavingTime(System::DateTimeOffset.FromUnixTimeSeconds(s)) + w = Time.local(t.year, t.month, t.day, t.hour, t.min, t.sec) + p [t.utc_offset == expected, t.isdst == dst, w.to_i == s, w.utc_offset == expected] +end +p Time.now.utc_offset == local.GetUtcOffset(System::DateTimeOffset.UtcNow).TotalSeconds.to_i + +# the zone name is ASCII and survives Marshal (a German Windows used to name it 'Mitteleuropäische Zeit') +t = Time.at(1784109600) +p t.zone.ascii_only?, Marshal.load(Marshal.dump(t)).zone == t.zone +", @" +[true, true, true, true] +[true, true, true, true] +true +true +true +"); + } + + /// + /// An Olson TZ name resolves on Windows too, where there is no zoneinfo file to read it from. + /// + public void Time_OlsonZone1() { + TestOutput(@" +saved = ENV['TZ'] +begin + ENV['TZ'] = 'Europe/Zurich' + w = Time.at(1768471200) # 2026-01-15 10:00 UTC + s = Time.at(1784109600) # 2026-07-15 10:00 UTC + p [w.hour, w.utc_offset, w.isdst], [s.hour, s.utc_offset, s.isdst] + p Time.local(2026, 7, 15, 12).to_i, Time.local(2026, 1, 15, 11).to_i +ensure + ENV['TZ'] = saved +end +", @" +[11, 3600, false] +[12, 7200, true] +1784109600 +1768471200 +"); + } + /// /// Time._load hands a dumped zone name to the class's find_timezone. As in MRI, a StandardError from the /// lookup leaves the name and anything else goes through; only bytes that are not a time are a TypeError. diff --git a/Src/Libraries/Builtins/RubyTimeSupport.cs b/Src/Libraries/Builtins/RubyTimeSupport.cs index 4e0aef0a8..33cfe52ae 100644 --- a/Src/Libraries/Builtins/RubyTimeSupport.cs +++ b/Src/Libraries/Builtins/RubyTimeSupport.cs @@ -476,14 +476,20 @@ namespace IronRuby.Builtins { /// /// A time zone as Ruby sees it. Backed by the zoneinfo file when one exists, because that - /// carries the DST transitions and the POSIX abbreviations that Ruby reports; otherwise a - /// plain fixed offset parsed out of a POSIX TZ string. + /// carries the DST transitions and the POSIX abbreviations that Ruby reports; where there is + /// none (Windows) by .NET's TimeZoneInfo, which has the same transitions but no abbreviations; + /// otherwise a plain fixed offset parsed out of a POSIX TZ string. /// public sealed class RubyTimeZone { - private readonly TzFile _file; // null for a fixed-offset zone + private readonly TzFile _file; // null unless the zone has a zoneinfo file + private readonly TimeZoneInfo _system; // null unless the zone is a .NET one without a zoneinfo file private readonly long _fixedOffset; // seconds east of UTC private readonly string/*!*/ _name; + // the range of seconds since the epoch a DateTimeOffset can hold + private const long MinSystemSeconds = -62135596800L; + private const long MaxSystemSeconds = 253402300799L; + public static readonly RubyTimeZone/*!*/ Utc = new RubyTimeZone(null, 0, "UTC"); private RubyTimeZone(TzFile file, long fixedOffset, string/*!*/ name) { @@ -492,6 +498,12 @@ private RubyTimeZone(TzFile file, long fixedOffset, string/*!*/ name) { _name = name; } + private RubyTimeZone(TimeZoneInfo/*!*/ system) { + _system = system; + _fixedOffset = (long)system.BaseUtcOffset.TotalSeconds; + _name = system.Id; + } + internal static RubyTimeZone/*!*/ MakeFixed(long offsetSeconds, string/*!*/ name) { return new RubyTimeZone(null, offsetSeconds, name); } @@ -504,7 +516,19 @@ private RubyTimeZone(TzFile file, long fixedOffset, string/*!*/ name) { internal static RubyTimeZone FromId(string/*!*/ id) { TzFile file = TzFile.TryLoad(id); - return (file != null) ? new RubyTimeZone(file, 0, id) : null; + if (file != null) { + return new RubyTimeZone(file, 0, id); + } + + // No zoneinfo file (Windows): .NET knows the Olson names too. Only an Area/City name is + // looked up, so that a POSIX TZ string such as "EST5EDT" or "UTC" keeps its own meaning. + if (id.IndexOf('/') > 0) { + TimeZoneInfo system; + if (TimeZoneInfo.TryFindSystemTimeZoneById(id, out system)) { + return new RubyTimeZone(system); + } + } + return null; } /// The machine's zone, used when TZ is unset. @@ -513,12 +537,23 @@ internal static RubyTimeZone FromId(string/*!*/ id) { if (file != null) { return new RubyTimeZone(file, 0, System.TimeZoneInfo.Local.Id); } - var local = System.TimeZoneInfo.Local; - return MakeFixed((long)local.BaseUtcOffset.TotalSeconds, local.StandardName); + // Windows: the zone's DST rules are in TimeZoneInfo.Local; its base offset alone would + // put every summer time an hour off. + return new RubyTimeZone(System.TimeZoneInfo.Local); + } + + private static DateTimeOffset ToSystemInstant(long unixSeconds) { + return DateTimeOffset.FromUnixTimeSeconds(Math.Max(MinSystemSeconds, Math.Min(MaxSystemSeconds, unixSeconds))); } internal long GetOffset(long unixSeconds) { - return (_file != null) ? _file.GetOffset(unixSeconds) : _fixedOffset; + if (_file != null) { + return _file.GetOffset(unixSeconds); + } + if (_system != null) { + return (long)_system.GetUtcOffset(ToSystemInstant(unixSeconds)).TotalSeconds; + } + return _fixedOffset; } /// @@ -529,13 +564,13 @@ internal long GetOffset(long unixSeconds) { /// never occurs (the clocks went forward) is taken with the offset from before the change. /// internal long GetOffsetForWallClock(long wallSeconds, bool preferDst = false) { - if (_file == null) { + if (_file == null && _system == null) { return _fixedOffset; } - long before = _file.GetOffset(wallSeconds - 86400); - long after = _file.GetOffset(wallSeconds + 86400); - bool beforeFits = _file.GetOffset(wallSeconds - before) == before; - bool afterFits = _file.GetOffset(wallSeconds - after) == after; + long before = GetOffset(wallSeconds - 86400); + long after = GetOffset(wallSeconds + 86400); + bool beforeFits = GetOffset(wallSeconds - before) == before; + bool afterFits = GetOffset(wallSeconds - after) == after; if (beforeFits && afterFits) { return preferDst ? Math.Max(before, after) : Math.Min(before, after); } @@ -546,9 +581,9 @@ internal long GetOffsetForWallClock(long wallSeconds, bool preferDst = false) { return before; } // neither fits: a gap, or more than one change within the day - long guess = _file.GetOffset(wallSeconds); - long second = _file.GetOffset(wallSeconds - guess); - return (_file.GetOffset(wallSeconds - second) == second) ? second : before; + long guess = GetOffset(wallSeconds); + long second = GetOffset(wallSeconds - guess); + return (GetOffset(wallSeconds - second) == second) ? second : before; } internal string/*!*/ GetAbbreviation(long unixSeconds) { @@ -558,10 +593,16 @@ internal long GetOffsetForWallClock(long wallSeconds, bool preferDst = false) { return result; } } + // A TimeZoneInfo zone is named by its id, summer and winter alike, as CRuby on Windows names + // it ("W. Europe Standard Time"): StandardName and DaylightName are in the language of the + // Windows installation, and Ruby takes a zone name to be ASCII. return _name; } internal bool IsDaylightSavingTime(long unixSeconds) { + if (_system != null) { + return _system.IsDaylightSavingTime(ToSystemInstant(unixSeconds)); + } return _file != null && _file.IsDaylightSavingTime(unixSeconds); } From d7d23adf92b6f0d80aa043b13dbc1e78230f121b Mon Sep 17 00:00:00 2001 From: Largo Date: Fri, 23 Oct 2026 16:11:09 +0200 Subject: [PATCH 3/9] Windows: zlib on the zlib .NET ships require "zlib" was a LoadError on Windows: there is no libz there, and the binding's z_stream is laid out for LP64. Every .NET runtime carries zlib in System.IO.Compression.Native, though (zlib-ng since .NET 9, Intel's zlib in .NET 8), behind CompressionNative_* exports over its own PAL_ZStream. ClrZlib runs LibZ's entry points on those exports, so ZStream, Inflate, Deflate and the gzip classes in zlib.rb work unchanged: the z_stream record is only managed code's on Windows; next_in/avail_in/next_out/avail_out go to the PAL stream and back, and total_in, total_out and adler (the running adler32/crc32, or the dictionary id on Z_NEED_DICT) are kept as libz keeps them. adler32, crc32, their _combine and crc_table are computed as zlib does. A reset begins the stream again with its parameters (.NET 8 exports no reset). What the exports leave out raises NotImplementedError: set_dictionary, Deflate#params once data has gone in, Inflate#sync_point?. Linux and macOS keep calling libz exactly as before. ruby/spec library/zlib on Windows: 148 examples, 2 failures (they compare classic zlib's exact compressed bytes), 3 errors (the NotImplementedErrors); before, all 42 files were the LoadError. Zlib_Streams1 inflates input CRuby compressed and checks round trips, totals, adler and the checksums, so it holds on libz and on .NET's zlib alike. --- README.md | 17 +- Src/IronRuby.Tests/RubyTests.cs | 1 + Src/IronRuby.Tests/Runtime/MiscTests.cs | 83 ++++++ Src/Libraries/Zlib/ClrZlib.cs | 367 ++++++++++++++++++++++++ Src/Libraries/Zlib/zlib.cs | 140 +++++++-- Src/StdLib/ironruby/zlib.rb | 10 +- 6 files changed, 579 insertions(+), 39 deletions(-) create mode 100644 Src/Libraries/Zlib/ClrZlib.cs diff --git a/README.md b/README.md index 13231e383..457e59b5c 100644 --- a/README.md +++ b/README.md @@ -417,7 +417,7 @@ Linux is the primary target and the one the numbers above are measured on. **Win `ir.cmd` and `irb.cmd` run, and `spec/language` (2920 examples) and `spec/security` pass with **0 failures**. `spec/core` and `spec/library` are rougher there — symlinks/chmod/umask in `core/file`, fork and signals in `core/process`, and `IO.select`/`IO#wait` on pipes (which is -`poll(2)`, so `core/io` and the socket suites hang rather than fail). `zlib`, Win32OLE and +`poll(2)`, so `core/io` and the socket suites hang rather than fail). Win32OLE and readline are not implemented on Windows; `IO.console` is nil, so irb falls back to its ANSI input path. Windows Forms and WPF (`require "System.Windows.Forms"`, `"PresentationFramework"`) come from the Windows Desktop runtime, which `ir` references whenever it is built for Windows @@ -535,12 +535,17 @@ Where the Windows errors are: `core/file` (113) and `core/filetest` (8) are syml `chmod`/`umask` and the other Unix file metadata; `core/process` (36 failures, 15 errors) is `fork`, process groups, uid/gid and signals; `library/win32ole` (114) and `library/readline` (25) are libraries IronRuby does not implement and whose specs only run on Windows; -`library/zlib` (42) is the `LoadError` below. `core/objectspace` needs `-X:ObjectSpace`, as -on Linux. +`library/zlib` (2 failures, 3 errors) is the zlib below. `core/objectspace` needs +`-X:ObjectSpace`, as on Linux. -What Windows does not have yet: **`zlib`** (`require "zlib"` is a clean `LoadError` — there -is no libz to bind to, and the `z_stream` binding is laid out for an LP64 C compiler, so a -stray `zlib1.dll` would be read through the wrong struct), **`io/console`** (`IO.console` is +**`zlib`** on Windows runs on the zlib inside .NET itself (`System.IO.Compression.Native`: +zlib-ng from .NET 9 on, Intel's zlib in .NET 8), since there is no libz to bind to. It +inflates and deflates, gzip included, but its compressed bytes are that compressor's, not +classic zlib's (the 2 `library/zlib` failures compare exact bytes), and what .NET does not +export raises `NotImplementedError`: `set_dictionary`, `Deflate#params` once data has gone in, +and `Inflate#sync_point?` (the 3 errors). + +What Windows does not have yet: **`io/console`** (`IO.console` is `nil`, the termios binding being Unix-only by construction; irb and reline fall back to their ANSI path and start fine — `Src/Libraries/Termios` would need a Win32 console-API twin), **`IO#wait`/`IO.select` on a pipe** (they are `poll(2)`, which is why `io-wait`, diff --git a/Src/IronRuby.Tests/RubyTests.cs b/Src/IronRuby.Tests/RubyTests.cs index 3a8b1f589..6565fd130 100644 --- a/Src/IronRuby.Tests/RubyTests.cs +++ b/Src/IronRuby.Tests/RubyTests.cs @@ -702,6 +702,7 @@ public Tests(Driver/*!*/ driver) { Time_DumpLoadedZone1, Time_MachineZone1, Time_OlsonZone1, + Zlib_Streams1, Scenario_RubyThreads1, Scenario_YieldCodeGen, diff --git a/Src/IronRuby.Tests/Runtime/MiscTests.cs b/Src/IronRuby.Tests/Runtime/MiscTests.cs index 85a03fd70..a04c4c56c 100644 --- a/Src/IronRuby.Tests/Runtime/MiscTests.cs +++ b/Src/IronRuby.Tests/Runtime/MiscTests.cs @@ -867,6 +867,89 @@ p Time.local(2026, 7, 15, 12).to_i, Time.local(2026, 1, 15, 11).to_i "); } + /// + /// Zlib's streams and checksums. Windows has no libz; there they run on the zlib .NET ships + /// (ClrZlib), so everything here holds on both: input CRuby compressed, round trips, and + /// the values libz keeps in the z_stream (total_in, total_out, adler) rather than bytes a + /// particular compressor produces. + /// + public void Zlib_Streams1() { + TestOutput(@" +load_assembly 'IronRuby.Libraries', 'IronRuby.StandardLibrary.Zlib' + +hex = lambda { |s| [s].pack('H*') } +text = 'hello hello hello hello' + +# from CRuby: Zlib::Deflate.deflate(text), and Zlib.gzip(text) +p Zlib::Inflate.inflate(hex['789ccb48cdc9c957c8402701680308b1']) +p Zlib.gunzip(hex['1f8b0800486adb6a0003cb48cdc9c957c8402701e3513d8d17000000']) + +# fed a few bytes at a time, as a PNG decoder does +data = 'IronRuby zlib ' * 2000 +z = Zlib::Deflate.deflate(data) +inf = Zlib::Inflate.new +out = '' +z.bytes.each_slice(7) { |s| out << inf.inflate(s.pack('C*')) } +out << inf.finish +p [out == data, inf.finished?, inf.total_in == z.bytesize, inf.total_out, inf.adler == Zlib.adler32(data)] +inf.close + +d = Zlib::Deflate.new +d << data[0, 10000] +d << data[10000..-1] +z = d.finish +p [d.total_in, d.total_out == z.bytesize, d.adler == Zlib.adler32(data), Zlib::Inflate.inflate(z) == data] +d.close + +p Zlib.gunzip(Zlib.gzip(data)) == data +raw = Zlib::Deflate.new(Zlib::BEST_SPEED, -Zlib::MAX_WBITS).deflate(data, Zlib::FINISH) +p Zlib::Inflate.new(-Zlib::MAX_WBITS).inflate(raw) == data +p Zlib::Inflate.new(Zlib::MAX_WBITS + 32).inflate(Zlib.gzip(data)) == data + +# a stream reset is a fresh one +d = Zlib::Deflate.new +d.deflate('discarded', Zlib::SYNC_FLUSH) +d.reset +z = d.deflate(text, Zlib::FINISH) +p [Zlib::Inflate.inflate(z), d.total_in] + +# deflated with the preset dictionary 'hello': inflate asks for it by its adler32 +inf = Zlib::Inflate.new +begin + inf.inflate(hex['78bb062c0215cb00110ae5f9453929001a0b045d']) +rescue Zlib::NeedDict + p [:need_dict, inf.adler == Zlib.adler32('hello')] +end + +p [Zlib.crc32(text), Zlib.adler32(text), Zlib.crc32, Zlib.adler32, Zlib.crc32('lo', Zlib.crc32('hel'))] +p [Zlib.crc32_combine(Zlib.crc32('hel'), Zlib.crc32('lo'), 2) == Zlib.crc32('hello'), + Zlib.adler32_combine(Zlib.adler32('hel'), Zlib.adler32('lo'), 2) == Zlib.adler32('hello')] +p Zlib.crc_table.size, Zlib.crc_table[1], Zlib.crc_table[255] + +begin + Zlib::Inflate.inflate('not zlib') +rescue Zlib::DataError => e + p e.message +end +", @" +""hello hello hello hello"" +""hello hello hello hello"" +[true, true, true, 28000, true] +[28000, true, true, true] +true +true +true +[""hello hello hello hello"", 23] +[:need_dict, true] +[2369606115, 1745029297, 0, 1, 907060870] +[true, true] +256 +1996959894 +755167117 +""incorrect header check"" +"); + } + /// /// Time._load hands a dumped zone name to the class's find_timezone. As in MRI, a StandardError from the /// lookup leaves the name and anything else goes through; only bytes that are not a time are a TypeError. diff --git a/Src/Libraries/Zlib/ClrZlib.cs b/Src/Libraries/Zlib/ClrZlib.cs new file mode 100644 index 000000000..7b37c9459 --- /dev/null +++ b/Src/Libraries/Zlib/ClrZlib.cs @@ -0,0 +1,367 @@ +/* **************************************************************************** + * + * This source code is subject to terms and conditions of the Apache License, Version 2.0. A + * copy of the license can be found in the License.html file at the root of this distribution. + * + * ***************************************************************************/ + +using System; +using System.Runtime.InteropServices; + +namespace IronRuby.StandardLibrary.Zlib { + + /// + /// zlib on Windows. There is no libz there, but every .NET runtime carries zlib in + /// System.IO.Compression.Native, the one DeflateStream runs on (zlib-ng in zlib-compat mode + /// since .NET 9, Intel's fork of zlib 1.2 in .NET 8). What it exports is narrower than libz: + /// init, deflate/inflate and end over its own PAL_ZStream, plus crc32. + /// + /// This runs LibZ's z_stream-shaped record over those exports, so ZStream cannot tell the + /// difference: next_in/avail_in/next_out/avail_out go to the PAL stream and back, total_in, + /// total_out and adler (the running adler32 or crc32 libz keeps) are kept here. What the + /// exports leave out - the preset dictionaries, deflateParams once data has gone in, and + /// inflateSyncPoint - raises NotImplementedError. + /// + /// The record's opaque field, which libz would hand to zalloc/zfree, holds the GCHandle of + /// the stream's ; nothing native ever reads the record. + /// + internal static class ClrZlib { + private const string Lib = "System.IO.Compression.Native"; + + /// The zlib API version behind the exports; libz's would come from zlibVersion(). + internal static string/*!*/ Version { + get { return Environment.Version.Major >= 9 ? "1.3.1.zlib-ng" : "1.2.13"; } + } + + /// PAL_ZStream from System.IO.Compression.Native's pal_zlib.h. + [StructLayout(LayoutKind.Sequential)] + private struct PalZStream { + public IntPtr nextIn; + public IntPtr nextOut; + public IntPtr msg; + public IntPtr internalState; + public uint availIn; + public uint availOut; + } + + [DllImport(Lib, EntryPoint = "CompressionNative_DeflateInit2_", CallingConvention = CallingConvention.Cdecl)] + private static extern int DeflateInit2_(ref PalZStream stream, int level, int method, int windowBits, int memLevel, int strategy); + + [DllImport(Lib, EntryPoint = "CompressionNative_Deflate", CallingConvention = CallingConvention.Cdecl)] + private static extern int Deflate(ref PalZStream stream, int flush); + + [DllImport(Lib, EntryPoint = "CompressionNative_DeflateEnd", CallingConvention = CallingConvention.Cdecl)] + private static extern int DeflateEnd(ref PalZStream stream); + + [DllImport(Lib, EntryPoint = "CompressionNative_InflateInit2_", CallingConvention = CallingConvention.Cdecl)] + private static extern int InflateInit2_(ref PalZStream stream, int windowBits); + + [DllImport(Lib, EntryPoint = "CompressionNative_Inflate", CallingConvention = CallingConvention.Cdecl)] + private static extern int Inflate(ref PalZStream stream, int flush); + + [DllImport(Lib, EntryPoint = "CompressionNative_InflateEnd", CallingConvention = CallingConvention.Cdecl)] + private static extern int InflateEnd(ref PalZStream stream); + + private const int Z_UNKNOWN = 2; + + /// Which checksum libz would keep in strm->adler for the stream's wrapper. + private enum Check { None, Adler32, Crc32, Detect } + + private sealed class Stream { + public PalZStream Pal; + public bool IsInflate; + public int Level, Method, WindowBits, MemLevel, Strategy; + public Check Check; + public uint Sum; + + // the first bytes of a zlib stream, for the dictionary id Z_NEED_DICT reports + public readonly byte[]/*!*/ Header = new byte[6]; + public int HeaderLength; + + public int Init() { + Pal = default(PalZStream); + Sum = 0; + HeaderLength = 0; + if (IsInflate) { + // inflateReset: strm->adler = state->wrap & 1 + Check = (WindowBits < 0) ? Check.None : (WindowBits >= 32) ? Check.Detect : (WindowBits >= 16) ? Check.Crc32 : Check.Adler32; + Sum = (Check == Check.Adler32 || Check == Check.Detect) ? 1u : 0u; + return InflateInit2_(ref Pal, WindowBits); + } + // deflateReset: strm->adler = wrap == 2 ? crc32(0, NULL, 0) : adler32(0, NULL, 0) + Check = (WindowBits < 0) ? Check.None : (WindowBits >= 16) ? Check.Crc32 : Check.Adler32; + Sum = (Check == Check.Crc32) ? 0u : 1u; + return DeflateInit2_(ref Pal, Level, Method, WindowBits, MemLevel, Strategy); + } + + public int End() { + return IsInflate ? InflateEnd(ref Pal) : DeflateEnd(ref Pal); + } + } + + private static LibZ.ZStreamRec Read(IntPtr strm) { + return (LibZ.ZStreamRec)Marshal.PtrToStructure(strm, typeof(LibZ.ZStreamRec)); + } + + private static void Write(IntPtr strm, LibZ.ZStreamRec rec) { + Marshal.StructureToPtr(rec, strm, false); + } + + private static Stream GetStream(LibZ.ZStreamRec rec) { + return (rec.opaque != IntPtr.Zero) ? (Stream)GCHandle.FromIntPtr(rec.opaque).Target : null; + } + + internal static int DeflateInit(IntPtr strm, int level, int method, int windowBits, int memLevel, int strategy) { + return Init(strm, new Stream { Level = level, Method = method, WindowBits = windowBits, MemLevel = memLevel, Strategy = strategy }); + } + + internal static int InflateInit(IntPtr strm, int windowBits) { + return Init(strm, new Stream { IsInflate = true, WindowBits = windowBits }); + } + + private static int Init(IntPtr strm, Stream/*!*/ s) { + int err = s.Init(); + var rec = Read(strm); + rec.msg = s.Pal.msg; + if (err == LibZ.Z_OK) { + rec.opaque = GCHandle.ToIntPtr(GCHandle.Alloc(s)); + rec.adler = (UIntPtr)s.Sum; + rec.total_in = rec.total_out = UIntPtr.Zero; + rec.data_type = Z_UNKNOWN; + } + Write(strm, rec); + return err; + } + + internal static int End(IntPtr strm) { + var rec = Read(strm); + Stream s = GetStream(rec); + if (s == null) { + return LibZ.Z_STREAM_ERROR; + } + int err = s.End(); + GCHandle.FromIntPtr(rec.opaque).Free(); + rec.opaque = IntPtr.Zero; + rec.msg = IntPtr.Zero; + Write(strm, rec); + return err; + } + + internal static int Reset(IntPtr strm) { + var rec = Read(strm); + Stream s = GetStream(rec); + if (s == null) { + return LibZ.Z_STREAM_ERROR; + } + // .NET 8 exports no inflateReset and no runtime exports deflateReset; a stream begun + // again with the same parameters is what a reset leaves. + s.End(); + int err = s.Init(); + rec.msg = s.Pal.msg; + rec.adler = (UIntPtr)s.Sum; + rec.total_in = rec.total_out = UIntPtr.Zero; + rec.data_type = Z_UNKNOWN; + Write(strm, rec); + return err; + } + + internal static int Run(IntPtr strm, int flush) { + var rec = Read(strm); + Stream s = GetStream(rec); + if (s == null) { + return LibZ.Z_STREAM_ERROR; + } + + IntPtr inStart = rec.next_in, outStart = rec.next_out; + uint availIn = rec.avail_in, availOut = rec.avail_out; + s.Pal.nextIn = inStart; + s.Pal.availIn = availIn; + s.Pal.nextOut = outStart; + s.Pal.availOut = availOut; + + int err = s.IsInflate ? Inflate(ref s.Pal, flush) : Deflate(ref s.Pal, flush); + + int consumed = (int)(availIn - s.Pal.availIn); + int produced = (int)(availOut - s.Pal.availOut); + rec.next_in = s.Pal.nextIn; + rec.avail_in = s.Pal.availIn; + rec.next_out = s.Pal.nextOut; + rec.avail_out = s.Pal.availOut; + rec.msg = s.Pal.msg; + rec.total_in = (UIntPtr)((ulong)rec.total_in + (ulong)consumed); + rec.total_out = (UIntPtr)((ulong)rec.total_out + (ulong)produced); + + if (s.IsInflate) { + if (consumed > 0 && s.HeaderLength < s.Header.Length) { + int n = Math.Min(consumed, s.Header.Length - s.HeaderLength); + Marshal.Copy(inStart, s.Header, s.HeaderLength, n); + s.HeaderLength += n; + } + if (s.Check == Check.Detect && s.HeaderLength > 0) { + s.Check = (s.Header[0] == 0x1f) ? Check.Crc32 : Check.Adler32; + s.Sum = (s.Check == Check.Crc32) ? 0u : 1u; + } + // the checksum covers what comes out of inflate and what goes into deflate + Update(s, outStart, produced); + if (err == LibZ.Z_NEED_DICT && s.HeaderLength >= 6) { + // inflate reports the dictionary it wants in strm->adler (RFC 1950's DICTID) + s.Sum = (uint)(s.Header[2] << 24 | s.Header[3] << 16 | s.Header[4] << 8 | s.Header[5]); + } + } else { + Update(s, inStart, consumed); + } + rec.adler = (UIntPtr)s.Sum; + + Write(strm, rec); + return err; + } + + private static void Update(Stream/*!*/ s, IntPtr data, int length) { + if (length <= 0 || (s.Check != Check.Adler32 && s.Check != Check.Crc32)) { + return; + } + var bytes = new byte[length]; + Marshal.Copy(data, bytes, 0, length); + s.Sum = (s.Check == Check.Adler32) ? Checksums.Adler32(s.Sum, bytes, 0, length) : Checksums.Crc32(s.Sum, bytes, 0, length); + } + + /// + /// deflateParams. Until anything has gone in the stream can simply begin again with the new + /// level and strategy, which is all deflateParams does then; after that the exports have + /// nothing that changes them. + /// + internal static int Params(IntPtr strm, int level, int strategy) { + var rec = Read(strm); + Stream s = GetStream(rec); + if (s == null) { + return LibZ.Z_STREAM_ERROR; + } + if (level == s.Level && strategy == s.Strategy) { + return LibZ.Z_OK; + } + if ((ulong)rec.total_in != 0 || (ulong)rec.total_out != 0) { + throw Unavailable("Zlib::Deflate#params after data has been deflated", "deflateParams"); + } + s.Level = level; + s.Strategy = strategy; + return Reset(strm); + } + + internal static Exception/*!*/ Unavailable(string/*!*/ what, string/*!*/ function) { + return new NotImplementedException(what + " is not available on Windows: the zlib .NET ships there (System.IO.Compression.Native) does not export " + function); + } + } + + /// adler32 and crc32 as libz computes them, for the platform without libz. + internal static class Checksums { + private const uint AdlerBase = 65521; + private const uint CrcPolynomial = 0xedb88320; + + internal static readonly uint[]/*!*/ CrcTable = MakeCrcTable(); + + private static uint[]/*!*/ MakeCrcTable() { + var table = new uint[256]; + for (uint n = 0; n < 256; n++) { + uint c = n; + for (int k = 0; k < 8; k++) { + c = ((c & 1) != 0) ? CrcPolynomial ^ (c >> 1) : c >> 1; + } + table[n] = c; + } + return table; + } + + internal static uint Adler32(uint adler, byte[] buffer, int offset, int length) { + if (buffer == null) { + return 1; + } + uint a = adler & 0xffff, b = adler >> 16; + while (length > 0) { + // 5552 is the most bytes that cannot overflow b before the modulo (zlib's NMAX) + int n = Math.Min(length, 5552); + length -= n; + while (n-- > 0) { + a += buffer[offset++]; + b += a; + } + a %= AdlerBase; + b %= AdlerBase; + } + return b << 16 | a; + } + + internal static uint Crc32(uint crc, byte[] buffer, int offset, int length) { + if (buffer == null) { + return 0; + } + uint c = ~crc; + for (int i = 0; i < length; i++) { + c = CrcTable[(c ^ buffer[offset + i]) & 0xff] ^ (c >> 8); + } + return ~c; + } + + /// zlib's adler32_combine. + internal static uint Adler32Combine(uint adler1, uint adler2, long length2) { + if (length2 < 0) { + return 0xffffffff; + } + uint rem = (uint)(length2 % AdlerBase); + ulong sum1 = adler1 & 0xffff; + ulong sum2 = (rem * sum1) % AdlerBase; + sum1 += (adler2 & 0xffff) + AdlerBase - 1; + sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + AdlerBase - rem; + if (sum1 >= AdlerBase) sum1 -= AdlerBase; + if (sum1 >= AdlerBase) sum1 -= AdlerBase; + if (sum2 >= ((ulong)AdlerBase << 1)) sum2 -= ((ulong)AdlerBase << 1); + if (sum2 >= AdlerBase) sum2 -= AdlerBase; + return (uint)(sum1 | (sum2 << 16)); + } + + /// zlib's crc32_combine: crc1 shifted by length2 zero bytes, then crc2. + internal static uint Crc32Combine(uint crc1, uint crc2, long length2) { + return MultiplyModP(PowerOfXModP(length2, 3), crc1) ^ crc2; + } + + // a(x) * b(x) modulo the CRC polynomial, bits reflected as in zlib's multmodp + private static uint MultiplyModP(uint a, uint b) { + uint m = 1u << 31, p = 0; + while (m != 0) { + if ((a & m) != 0) { + p ^= b; + if ((a & (m - 1)) == 0) { + break; + } + } + m >>= 1; + b = ((b & 1) != 0) ? (b >> 1) ^ CrcPolynomial : b >> 1; + } + return p; + } + + private static readonly uint[]/*!*/ _x2n = MakeX2nTable(); + + private static uint[]/*!*/ MakeX2nTable() { + var table = new uint[32]; + uint p = 1u << 30; // x^1 + table[0] = p; + for (int n = 1; n < 32; n++) { + table[n] = p = MultiplyModP(p, p); + } + return table; + } + + // x^(n * 2^k) modulo the CRC polynomial, as zlib's x2nmodp + private static uint PowerOfXModP(long n, int k) { + uint p = 1u << 31; // x^0 + while (n > 0) { + if ((n & 1) != 0) { + p = MultiplyModP(_x2n[k & 31], p); + } + n >>= 1; + k++; + } + return p; + } + } +} diff --git a/Src/Libraries/Zlib/zlib.cs b/Src/Libraries/Zlib/zlib.cs index fb3f4ab9c..d7d59c4b2 100644 --- a/Src/Libraries/Zlib/zlib.cs +++ b/Src/Libraries/Zlib/zlib.cs @@ -30,10 +30,15 @@ namespace IronRuby.StandardLibrary.Zlib { /// /// Compressed output has to be byte-for-byte what CRuby produces - the specs compare exact /// bytes - so the compressor itself is the system's, not a reimplementation. + /// + /// Windows has no libz; there the same entry points run on the zlib inside .NET itself + /// (), and the z_stream record below is only ever read by managed code. /// internal static class LibZ { private const string Lib = "libz"; + internal static readonly bool UseClrZlib = RuntimeInformation.IsOSPlatform(OSPlatform.Windows); + internal const int Z_NO_FLUSH = 0; internal const int Z_SYNC_FLUSH = 2; internal const int Z_FINISH = 4; @@ -84,7 +89,7 @@ internal struct ZStreamRec { internal static string Version { get { if (_version == null) { - _version = Marshal.PtrToStringAnsi(sys_zlibVersion()) ?? "1.2.11"; + _version = UseClrZlib ? ClrZlib.Version : (Marshal.PtrToStringAnsi(sys_zlibVersion()) ?? "1.2.11"); } return _version; } @@ -92,57 +97,148 @@ internal static string Version { internal static readonly int StreamSize = Marshal.SizeOf(typeof(ZStreamRec)); + internal static int deflateInit2_(IntPtr strm, int level, int method, int windowBits, + int memLevel, int strategy, string/*!*/ version, int stream_size) { + return UseClrZlib + ? ClrZlib.DeflateInit(strm, level, method, windowBits, memLevel, strategy) + : sys_deflateInit2_(strm, level, method, windowBits, memLevel, strategy, version, stream_size); + } + + internal static int deflate(IntPtr strm, int flush) { + return UseClrZlib ? ClrZlib.Run(strm, flush) : sys_deflate(strm, flush); + } + + internal static int deflateEnd(IntPtr strm) { + return UseClrZlib ? ClrZlib.End(strm) : sys_deflateEnd(strm); + } + + internal static int deflateReset(IntPtr strm) { + return UseClrZlib ? ClrZlib.Reset(strm) : sys_deflateReset(strm); + } + + internal static int deflateParams(IntPtr strm, int level, int strategy) { + return UseClrZlib ? ClrZlib.Params(strm, level, strategy) : sys_deflateParams(strm, level, strategy); + } + + internal static int deflateSetDictionary(IntPtr strm, byte[]/*!*/ dictionary, uint dictLength) { + if (UseClrZlib) { + throw ClrZlib.Unavailable("Zlib::Deflate#set_dictionary", "deflateSetDictionary"); + } + return sys_deflateSetDictionary(strm, dictionary, dictLength); + } + + internal static int inflateInit2_(IntPtr strm, int windowBits, string/*!*/ version, int stream_size) { + return UseClrZlib ? ClrZlib.InflateInit(strm, windowBits) : sys_inflateInit2_(strm, windowBits, version, stream_size); + } + + internal static int inflate(IntPtr strm, int flush) { + return UseClrZlib ? ClrZlib.Run(strm, flush) : sys_inflate(strm, flush); + } + + internal static int inflateEnd(IntPtr strm) { + return UseClrZlib ? ClrZlib.End(strm) : sys_inflateEnd(strm); + } + + internal static int inflateReset(IntPtr strm) { + return UseClrZlib ? ClrZlib.Reset(strm) : sys_inflateReset(strm); + } + + internal static int inflateSetDictionary(IntPtr strm, byte[]/*!*/ dictionary, uint dictLength) { + if (UseClrZlib) { + throw ClrZlib.Unavailable("Zlib::Inflate#set_dictionary", "inflateSetDictionary"); + } + return sys_inflateSetDictionary(strm, dictionary, dictLength); + } + + internal static int inflateSyncPoint(IntPtr strm) { + if (UseClrZlib) { + throw ClrZlib.Unavailable("Zlib::Inflate#sync_point?", "inflateSyncPoint"); + } + return sys_inflateSyncPoint(strm); + } + + internal static UIntPtr adler32(UIntPtr adler, byte[] buf, uint len) { + return UseClrZlib ? (UIntPtr)Checksums.Adler32((uint)adler, buf, 0, (int)len) : sys_adler32(adler, buf, len); + } + + internal static UIntPtr crc32(UIntPtr crc, byte[] buf, uint len) { + return UseClrZlib ? (UIntPtr)Checksums.Crc32((uint)crc, buf, 0, (int)len) : sys_crc32(crc, buf, len); + } + + internal static UIntPtr adler32_combine(UIntPtr adler1, UIntPtr adler2, long len2) { + return UseClrZlib ? (UIntPtr)Checksums.Adler32Combine((uint)adler1, (uint)adler2, len2) : sys_adler32_combine(adler1, adler2, len2); + } + + internal static UIntPtr crc32_combine(UIntPtr crc1, UIntPtr crc2, long len2) { + return UseClrZlib ? (UIntPtr)Checksums.Crc32Combine((uint)crc1, (uint)crc2, len2) : sys_crc32_combine(crc1, crc2, len2); + } + + /// The 256 entries of zlib's CRC-32 table. + internal static uint[]/*!*/ GetCrcTable() { + if (UseClrZlib) { + return (uint[])Checksums.CrcTable.Clone(); + } + // get_crc_table() hands back 256 z_crc_t (uint32 since zlib 1.2.7) entries. + var entries = new int[256]; + Marshal.Copy(sys_get_crc_table(), entries, 0, 256); + var result = new uint[256]; + for (int i = 0; i < entries.Length; i++) { + result[i] = unchecked((uint)entries[i]); + } + return result; + } + [DllImport(Lib, EntryPoint = "deflateInit2_", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] - internal static extern int deflateInit2_(IntPtr strm, int level, int method, int windowBits, + private static extern int sys_deflateInit2_(IntPtr strm, int level, int method, int windowBits, int memLevel, int strategy, string/*!*/ version, int stream_size); [DllImport(Lib, EntryPoint = "deflate", CallingConvention = CallingConvention.Cdecl)] - internal static extern int deflate(IntPtr strm, int flush); + private static extern int sys_deflate(IntPtr strm, int flush); [DllImport(Lib, EntryPoint = "deflateEnd", CallingConvention = CallingConvention.Cdecl)] - internal static extern int deflateEnd(IntPtr strm); + private static extern int sys_deflateEnd(IntPtr strm); [DllImport(Lib, EntryPoint = "deflateReset", CallingConvention = CallingConvention.Cdecl)] - internal static extern int deflateReset(IntPtr strm); + private static extern int sys_deflateReset(IntPtr strm); [DllImport(Lib, EntryPoint = "deflateParams", CallingConvention = CallingConvention.Cdecl)] - internal static extern int deflateParams(IntPtr strm, int level, int strategy); + private static extern int sys_deflateParams(IntPtr strm, int level, int strategy); [DllImport(Lib, EntryPoint = "deflateSetDictionary", CallingConvention = CallingConvention.Cdecl)] - internal static extern int deflateSetDictionary(IntPtr strm, byte[]/*!*/ dictionary, uint dictLength); + private static extern int sys_deflateSetDictionary(IntPtr strm, byte[]/*!*/ dictionary, uint dictLength); [DllImport(Lib, EntryPoint = "inflateInit2_", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] - internal static extern int inflateInit2_(IntPtr strm, int windowBits, string/*!*/ version, int stream_size); + private static extern int sys_inflateInit2_(IntPtr strm, int windowBits, string/*!*/ version, int stream_size); [DllImport(Lib, EntryPoint = "inflate", CallingConvention = CallingConvention.Cdecl)] - internal static extern int inflate(IntPtr strm, int flush); + private static extern int sys_inflate(IntPtr strm, int flush); [DllImport(Lib, EntryPoint = "inflateEnd", CallingConvention = CallingConvention.Cdecl)] - internal static extern int inflateEnd(IntPtr strm); + private static extern int sys_inflateEnd(IntPtr strm); [DllImport(Lib, EntryPoint = "inflateReset", CallingConvention = CallingConvention.Cdecl)] - internal static extern int inflateReset(IntPtr strm); + private static extern int sys_inflateReset(IntPtr strm); [DllImport(Lib, EntryPoint = "inflateSetDictionary", CallingConvention = CallingConvention.Cdecl)] - internal static extern int inflateSetDictionary(IntPtr strm, byte[]/*!*/ dictionary, uint dictLength); + private static extern int sys_inflateSetDictionary(IntPtr strm, byte[]/*!*/ dictionary, uint dictLength); [DllImport(Lib, EntryPoint = "inflateSyncPoint", CallingConvention = CallingConvention.Cdecl)] - internal static extern int inflateSyncPoint(IntPtr strm); + private static extern int sys_inflateSyncPoint(IntPtr strm); [DllImport(Lib, EntryPoint = "adler32", CallingConvention = CallingConvention.Cdecl)] - internal static extern UIntPtr adler32(UIntPtr adler, byte[] buf, uint len); + private static extern UIntPtr sys_adler32(UIntPtr adler, byte[] buf, uint len); [DllImport(Lib, EntryPoint = "crc32", CallingConvention = CallingConvention.Cdecl)] - internal static extern UIntPtr crc32(UIntPtr crc, byte[] buf, uint len); + private static extern UIntPtr sys_crc32(UIntPtr crc, byte[] buf, uint len); [DllImport(Lib, EntryPoint = "adler32_combine", CallingConvention = CallingConvention.Cdecl)] - internal static extern UIntPtr adler32_combine(UIntPtr adler1, UIntPtr adler2, long len2); + private static extern UIntPtr sys_adler32_combine(UIntPtr adler1, UIntPtr adler2, long len2); [DllImport(Lib, EntryPoint = "crc32_combine", CallingConvention = CallingConvention.Cdecl)] - internal static extern UIntPtr crc32_combine(UIntPtr crc1, UIntPtr crc2, long len2); + private static extern UIntPtr sys_crc32_combine(UIntPtr crc1, UIntPtr crc2, long len2); [DllImport(Lib, EntryPoint = "get_crc_table", CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr get_crc_table(); + private static extern IntPtr sys_get_crc_table(); } [RubyModule("Zlib")] @@ -355,13 +451,9 @@ public static object AdlerCombine(ConversionStorage/*!*/ integerCo [RubyMethod("crc_table", RubyMethodAttributes.PublicSingleton)] [RubyMethod("crc_table", RubyMethodAttributes.PrivateInstance)] public static RubyArray/*!*/ CrcTable(object self) { - // get_crc_table() hands back 256 z_crc_t (uint32 since zlib 1.2.7) entries. - IntPtr table = LibZ.get_crc_table(); var result = new RubyArray(256); - var entries = new int[256]; - Marshal.Copy(table, entries, 0, 256); - for (int i = 0; i < entries.Length; i++) { - result.Add(Protocols.Normalize(unchecked((uint)entries[i]))); + foreach (uint entry in LibZ.GetCrcTable()) { + result.Add(Protocols.Normalize(entry)); } return result; } diff --git a/Src/StdLib/ironruby/zlib.rb b/Src/StdLib/ironruby/zlib.rb index 0d20114c4..0450f4935 100644 --- a/Src/StdLib/ironruby/zlib.rb +++ b/Src/StdLib/ironruby/zlib.rb @@ -13,18 +13,10 @@ # # **************************************************************************** -# There is no libz to bind to on Windows, and the z_stream this binds to is laid out for -# an LP64 C compiler - `unsigned long` is 8 bytes there and 4 under MSVC - so even a -# zlib1.dll that happens to be on PATH would be read through the wrong struct. Refusing -# here is a LoadError the caller can rescue; letting it through was a -# TypeInitializationException from the first constant the class defines. -if ::File::ALT_SEPARATOR == "\\" - raise LoadError, "cannot load such file -- zlib (no libz on this platform)" -end - load_assembly 'IronRuby.Libraries', 'IronRuby.StandardLibrary.Zlib' # Zlib::ZStream, Inflate and Deflate are the libz binding in Src/Libraries/Zlib/zlib.cs. +# Windows has no libz; there they run on the zlib .NET itself ships (Src/Libraries/Zlib/ClrZlib.cs). # The gzip family below is written on top of them: a gzip member is a 10-byte header, a # raw deflate stream and an 8-byte footer, none of which needs libz directly. From ae23dd9bfb59168e9845b570db83e9438f328890 Mon Sep 17 00:00:00 2001 From: Largo Date: Fri, 23 Oct 2026 16:27:29 +0200 Subject: [PATCH 4/9] Windows: File::NULL is NUL, and Process.kill without libc Process.spawn(cmd, out: File::NULL) failed on Windows with ENOENT, and Process.kill raised System::DllNotFoundException. IO::NULL (and File::NULL) came from the prelude as "/dev/null" everywhere; Windows has no such file, so the redirect could not be opened. It is "NUL" there, as in CRuby. The error itself named the program, not the file: WindowsSpawn handed back only -errno and the prelude filled in the command. A redirection that cannot be opened now raises with its own path - ENOENT, EACCES, or EISDIR for a directory - as CRuby does, which opens it in the parent. Process.kill P/Invoked libc's kill(), which Windows does not have. WindowsSpawn.Kill does what CRuby's win32 kill() does: KILL is TerminateProcess (exit code 0, as there), 0 reports whether the process still runs (ESRCH once it has exited), INT is a console Ctrl+C - Ctrl+Break aimed at a process group - and every other signal is EINVAL. ruby/spec on Windows: core/process/kill 2 errors -> 0; core/process/spawn, core/kernel/spawn and core/kernel/system unchanged otherwise. Process_SpawnKill1 spawns a child that blocks on a pipe, signals 0 and KILL, waits, and checks a missing redirection is named. --- Src/IronRuby.Tests/RubyTests.cs | 1 + Src/IronRuby.Tests/Runtime/MiscTests.cs | 43 ++++++++++ Src/Libraries/Builtins/PosixSignals.cs | 3 + Src/Libraries/Builtins/WindowsSpawn.cs | 105 +++++++++++++++++++++++- Src/StdLib/ironruby/ruby4.rb | 5 +- 5 files changed, 152 insertions(+), 5 deletions(-) diff --git a/Src/IronRuby.Tests/RubyTests.cs b/Src/IronRuby.Tests/RubyTests.cs index 6565fd130..66c2fbeda 100644 --- a/Src/IronRuby.Tests/RubyTests.cs +++ b/Src/IronRuby.Tests/RubyTests.cs @@ -703,6 +703,7 @@ public Tests(Driver/*!*/ driver) { Time_MachineZone1, Time_OlsonZone1, Zlib_Streams1, + Process_SpawnKill1, Scenario_RubyThreads1, Scenario_YieldCodeGen, diff --git a/Src/IronRuby.Tests/Runtime/MiscTests.cs b/Src/IronRuby.Tests/Runtime/MiscTests.cs index a04c4c56c..562f1e2fe 100644 --- a/Src/IronRuby.Tests/Runtime/MiscTests.cs +++ b/Src/IronRuby.Tests/Runtime/MiscTests.cs @@ -867,6 +867,49 @@ p Time.local(2026, 7, 15, 12).to_i, Time.local(2026, 1, 15, 11).to_i "); } + /// + /// Process.spawn redirected to File::NULL, and Process.kill. On Windows File::NULL was "/dev/null", + /// so the redirect failed with an ENOENT that named the program; Process.kill P/Invoked libc's + /// kill() and raised DllNotFoundException. The child reads a pipe nobody writes to, so it runs + /// until it is killed. File::NULL and Process.spawn are the prelude's (ruby4.rb), which needs prism. + /// + [Options(Prism = true)] + public void Process_SpawnKill1() { + TestOutput(@" +require 'ruby4' +windows = File::ALT_SEPARATOR == '\\' +p File::NULL == (windows ? 'NUL' : '/dev/null'), IO::NULL == File::NULL + +command = windows ? ['cmd.exe', '/c', 'more'] : ['cat'] +r, w = IO.pipe +pid = Process.spawn(*(command + [{:in => r, :out => File::NULL, :err => File::NULL}])) +r.close +p Process.kill(0, pid), Process.kill(:KILL, pid) +p Process.wait(pid) == pid +w.close +begin + Process.kill(0, pid) +rescue Errno::ESRCH + p :gone +end + +# a redirection that cannot be opened is what the error names (Windows; posix_spawn cannot tell) +begin + Process.spawn(*(command + [{:out => 'no/such/dir/out.txt'}])) +rescue Errno::ENOENT => e + p(!windows || e.message.include?('no/such/dir/out.txt')) +end +", @" +true +true +1 +1 +true +:gone +true +"); + } + /// /// Zlib's streams and checksums. Windows has no libz; there they run on the zlib .NET ships /// (ClrZlib), so everything here holds on both: input CRuby compressed, round trips, and diff --git a/Src/Libraries/Builtins/PosixSignals.cs b/Src/Libraries/Builtins/PosixSignals.cs index be5f720c9..8140953dc 100644 --- a/Src/Libraries/Builtins/PosixSignals.cs +++ b/Src/Libraries/Builtins/PosixSignals.cs @@ -186,6 +186,9 @@ internal static bool HasHandler(int signal) { /// to the prelude, which knows how to turn it into the right class. /// internal static int Kill(int pid, int signal) { + if (RubyProcess.IsWindows) { + return WindowsSpawn.Kill(pid, signal); + } if (SysKill(pid, signal) == 0) { return 0; } diff --git a/Src/Libraries/Builtins/WindowsSpawn.cs b/Src/Libraries/Builtins/WindowsSpawn.cs index 925b22b3e..e9d2d65a1 100644 --- a/Src/Libraries/Builtins/WindowsSpawn.cs +++ b/Src/Libraries/Builtins/WindowsSpawn.cs @@ -143,6 +143,15 @@ private static extern bool DuplicateHandle(IntPtr sourceProcess, IntPtr source, private static extern IntPtr CreateFileW(string name, uint access, uint share, IntPtr security, uint creation, uint flags, IntPtr template); + [DllImport("kernel32", SetLastError = true)] + private static extern IntPtr OpenProcess(uint access, bool inheritHandle, int processId); + + [DllImport("kernel32", SetLastError = true)] + private static extern bool TerminateProcess(IntPtr handle, uint exitCode); + + [DllImport("kernel32", SetLastError = true)] + private static extern bool GenerateConsoleCtrlEvent(uint ctrlEvent, int processGroupId); + #endregion #region children @@ -176,6 +185,12 @@ private static bool Forget(int pid, out IntPtr handle) { } } + private static bool TryGetChild(int pid, out IntPtr handle) { + lock (_children) { + return _children.TryGetValue(pid, out handle); + } + } + private static KeyValuePair[] Children() { lock (_children) { var result = new KeyValuePair[_children.Count]; @@ -438,10 +453,12 @@ private static int ToInt(object value) { break; default: { - IntPtr opened = OpenFile(ToStr(action[2]), ToInt(action[3])); + string path = ToStr(action[2]); + IntPtr opened = OpenFile(path, ToInt(action[3])); if (opened == new IntPtr(-1)) { - plan.Error = -Errno(Marshal.GetLastWin32Error()); - return plan; + int error = Marshal.GetLastWin32Error(); + plan.Dispose(); + throw RedirectionError(error, path); } plan.Opened.Add(opened); Assign(plan, target, opened); @@ -504,6 +521,19 @@ private static IntPtr OpenFile(string/*!*/ path, int flags) { FILE_ATTRIBUTE_NORMAL, IntPtr.Zero); } + /// + /// MRI opens a redirection's file in the parent before it starts the child, so a file that + /// cannot be opened is what the error names. Handing back only -errno made the prelude name + /// the program instead: `out: "C:/no/dir/x"` read as "No such file or directory - ruby.exe". + /// + private static Exception/*!*/ RedirectionError(int win32Error, string/*!*/ path) { + switch (Errno(win32Error)) { + case ENOENT: return new FileNotFoundException(path); + case EACCES: return Directory.Exists(path) ? RubyExceptions.CreateEISDIR(path) : new UnauthorizedAccessException(path); + default: return new InvalidError(path); + } + } + private static int Errno(int win32Error) { switch (win32Error) { case ERROR_FILE_NOT_FOUND: @@ -598,6 +628,75 @@ internal static int Exec(RubyContext/*!*/ context, MutableString/*!*/ file, Ruby #endregion + #region kill + + private const int SIGINT = 2; + private const int SIGKILL = 9; + private const int EPERM = 1; + private const int ESRCH = 3; + private const uint STILL_ACTIVE = 259; + private const uint PROCESS_TERMINATE = 0x0001; + private const uint PROCESS_QUERY_INFORMATION = 0x0400; + private const int ERROR_INVALID_PARAMETER = 87; + private const uint CTRL_C_EVENT = 0; + private const uint CTRL_BREAK_EVENT = 1; + + /// + /// kill(2) as MRI's win32 kill() does it, since there is no kill(2) to call - the libc one + /// Process.kill used to P/Invoke is not there (DllNotFoundException). Returns 0, or -errno. + /// KILL is TerminateProcess (with exit code 0, as in MRI), 0 asks whether the process still + /// runs, INT is a console Ctrl+C - Ctrl+Break for a pid, which has to be a process group + /// (spawn's pgroup: true). Windows has no other signals to send: EINVAL, as in MRI. + /// + internal static int Kill(int pid, int signal) { + if (pid < 0 || (pid == 0 && signal != SIGINT)) { + return -EINVAL; + } + + switch (signal) { + case SIGINT: + // a console's Ctrl+C cannot be aimed at one process group, so a pid gets Ctrl+Break + if (!GenerateConsoleCtrlEvent(pid != 0 ? CTRL_BREAK_EVENT : CTRL_C_EVENT, pid)) { + int error = Marshal.GetLastWin32Error(); + return -(error == 0 ? EPERM : Errno(error)); + } + return 0; + + case 0: + case SIGKILL: + IntPtr handle; + bool child = TryGetChild(pid, out handle); + if (!child) { + handle = OpenProcess(PROCESS_TERMINATE | PROCESS_QUERY_INFORMATION, false, pid); + if (handle == IntPtr.Zero) { + return (Marshal.GetLastWin32Error() == ERROR_INVALID_PARAMETER) ? -ESRCH : -EPERM; + } + } + try { + uint status; + if (!GetExitCodeProcess(handle, out status)) { + return -Errno(Marshal.GetLastWin32Error()); + } + if (status != STILL_ACTIVE) { + return -ESRCH; + } + if (signal == SIGKILL && !TerminateProcess(handle, 0)) { + return -EPERM; + } + return 0; + } finally { + if (!child) { + CloseHandle(handle); + } + } + + default: + return -EINVAL; + } + } + + #endregion + #region __waitpid__ private const int WNOHANG = 1; diff --git a/Src/StdLib/ironruby/ruby4.rb b/Src/StdLib/ironruby/ruby4.rb index 40ab1c477..64c9bb7f2 100644 --- a/Src/StdLib/ironruby/ruby4.rb +++ b/Src/StdLib/ironruby/ruby4.rb @@ -5545,8 +5545,9 @@ class ClosedQueueError < StopIteration; end unless defined?(ClosedQueueError) class IO # Ruby defines NULL on IO; File inherits it. Defining it on File alone left - # IO::NULL undefined, which several specs and helpers reference. - NULL = "/dev/null" unless const_defined?(:NULL, false) + # IO::NULL undefined, which several specs and helpers reference. Windows has + # no /dev/null: there it is the NUL device, as in CRuby. + NULL = (File::ALT_SEPARATOR == "\\" ? "NUL" : "/dev/null") unless const_defined?(:NULL, false) end class << Dir From 4348f6cc582edfe25e91bd7285f9d5bcad3b6a76 Mon Sep 17 00:00:00 2001 From: Largo Date: Fri, 23 Oct 2026 16:29:57 +0200 Subject: [PATCH 5/9] JSON.parse: a raw control character in a string is a ParserError RFC 8259 has U+0000-U+001F escaped inside a string, and the json gem raises "invalid ASCII control character in string" for an unescaped one. IronRuby's parser took them as they were, so a document with a literal line break in a value parsed here and failed on CRuby - code that falls back on a ParserError for exactly that case never ran its fallback. JSON.parse(source, allow_control_characters: true), the gem's option since 2.18.0 (the API version this JSON reports), lets them through. DEL and escaped control characters stay fine. --- Src/IronRuby.Tests/RubyTests.cs | 1 + Src/IronRuby.Tests/Runtime/MiscTests.cs | 32 +++++++++++++++++++++++++ Src/Libraries/Json/Json.cs | 15 +++++++++++- 3 files changed, 47 insertions(+), 1 deletion(-) diff --git a/Src/IronRuby.Tests/RubyTests.cs b/Src/IronRuby.Tests/RubyTests.cs index 66c2fbeda..bac7f7bc9 100644 --- a/Src/IronRuby.Tests/RubyTests.cs +++ b/Src/IronRuby.Tests/RubyTests.cs @@ -704,6 +704,7 @@ public Tests(Driver/*!*/ driver) { Time_OlsonZone1, Zlib_Streams1, Process_SpawnKill1, + Json_ControlCharacters1, Scenario_RubyThreads1, Scenario_YieldCodeGen, diff --git a/Src/IronRuby.Tests/Runtime/MiscTests.cs b/Src/IronRuby.Tests/Runtime/MiscTests.cs index 562f1e2fe..73745e074 100644 --- a/Src/IronRuby.Tests/Runtime/MiscTests.cs +++ b/Src/IronRuby.Tests/Runtime/MiscTests.cs @@ -910,6 +910,38 @@ p Process.wait(pid) == pid "); } + /// + /// A raw control character (U+0000-U+001F) inside a JSON string is a ParserError, as in the json gem; + /// JSON.parse took a model's answer with a literal line break in a value as it was. The gem's + /// allow_control_characters option (2.18.0) lets them through. + /// + public void Json_ControlCharacters1() { + TestOutput(@" +load_assembly 'IronRuby.Libraries', 'IronRuby.StandardLibrary.Json' + +[10, 9, 1, 0, 31].each do |code| + src = '{""k"": ""a' + code.chr + 'b""}' + begin + JSON.parse(src) + p [code, :accepted] + rescue JSON::ParserError => e + p [code, e.message.start_with?('invalid ASCII control character in string')] + end +end +p JSON.parse('[""a' + 10.chr + 'b""]', :allow_control_characters => true) +# an escaped one, and DEL, are fine +p JSON.parse('[""a\nb"", ""' + 127.chr + '""]') == ['a' + 10.chr + 'b', 127.chr] +", @" +[10, true] +[9, true] +[1, true] +[0, true] +[31, true] +[""a\nb""] +true +"); + } + /// /// Zlib's streams and checksums. Windows has no libz; there they run on the zlib .NET ships /// (ClrZlib), so everything here holds on both: input CRuby compressed, round trips, and diff --git a/Src/Libraries/Json/Json.cs b/Src/Libraries/Json/Json.cs index f36d8ee36..0f62872af 100644 --- a/Src/Libraries/Json/Json.cs +++ b/Src/Libraries/Json/Json.cs @@ -291,6 +291,7 @@ public static object Parse(RubyContext/*!*/ context, object self, [DefaultProtoc var parser = new JsonParser(source.ConvertToString(), context); parser.SymbolizeNames = TruthyOption(context, options, "symbolize_names"); + parser.AllowControlCharacters = TruthyOption(context, options, "allow_control_characters"); object result = parser.ParseValue(0); parser.SkipWhitespace(); if (!parser.AtEnd) { @@ -301,7 +302,7 @@ public static object Parse(RubyContext/*!*/ context, object self, [DefaultProtoc /// /// One keyword of the options Hash JSON.parse takes. Only the options this parser - /// can honour are read: symbolize_names, and allow_comments, which needs no flag + /// can honour are read: symbolize_names, allow_control_characters, and allow_comments, which needs no flag /// because this parser has always skipped comments. An option it does not know is /// ignored rather than rejected, the way the json gem ignores unknown keys. /// @@ -352,6 +353,12 @@ internal sealed class JsonParser { /// internal bool SymbolizeNames { get; set; } + /// + /// JSON.parse(source, allow_control_characters: true) takes a raw newline, tab, ... inside + /// a string as it is. + /// + internal bool AllowControlCharacters { get; set; } + internal JsonParser(string/*!*/ source, RubyContext/*!*/ context) { _source = source; _context = context; @@ -494,6 +501,12 @@ private object ParseArray(int depth) { return builder.ToString(); } if (c != '\\') { + // RFC 8259: U+0000 through U+001F must be escaped inside a string. The json gem + // rejects them unless asked not to (2.18.0's allow_control_characters). + if (c < ' ' && !AllowControlCharacters) { + _position--; + throw new JsonParserError("invalid ASCII control character in string: '" + Rest + "'"); + } builder.Append(c); continue; } From 0c3b9a55b97b8cb51196122bb3b364568f7315c0 Mon Sep 17 00:00:00 2001 From: Largo Date: Fri, 23 Oct 2026 16:37:10 +0200 Subject: [PATCH 6/9] net/http over TLS: diagnosis and proposed fix (not fixed) net/http was reported "not dependable on Windows, where IO.select on a socket is poll(2)". Measured: plain sockets are fine (Socket.Select on Windows, and read_timeout fires); over TLS nothing times out - SSLSocket's read_nonblock, write_nonblock and connect_nonblock block in SslStream and never return :wait_readable, which is the only path net/protocol applies read_timeout on - and ca_file/cert_store/verify_callback are not consulted. Docs/net-http-over-tls.md has the diagnosis and a two-stage proposal: timeouts on the blocking SslStream calls plus the context's CAs first (small), real non-blocking reads through IoReadiness later. Util/net-http-tls-server.rb (CRuby) and Util/net-http-tls-check.rb reproduce both findings. --- Docs/net-http-over-tls.md | 132 ++++++++++++++++++++++++++++++++++++ Util/net-http-tls-check.rb | 55 +++++++++++++++ Util/net-http-tls-server.rb | 67 ++++++++++++++++++ 3 files changed, 254 insertions(+) create mode 100644 Docs/net-http-over-tls.md create mode 100644 Util/net-http-tls-check.rb create mode 100644 Util/net-http-tls-server.rb diff --git a/Docs/net-http-over-tls.md b/Docs/net-http-over-tls.md new file mode 100644 index 000000000..5eaa3a280 --- /dev/null +++ b/Docs/net-http-over-tls.md @@ -0,0 +1,132 @@ +# net/http over TLS: diagnosis and proposed fix + +Status: diagnosed, not fixed. Measured on IronRuby 4.0.1 and on `fix/llm-port-quirks`, +Windows 11, .NET 10.0.12, 2026-10-23. + +## What was reported + +An application ported to IronRuby (a JobRouter system activity calling Google's +Gemini API) replaced `net/http` with a transport over .NET's `HttpClient`, because +"`net/http` is not dependable on Windows, where `IO.select` on a socket is `poll(2)`". + +## What is actually the case + +`Util/net-http-tls-check.rb` against `Util/net-http-tls-server.rb` (CRuby) runs keep-alive +GETs and POSTs from 10 bytes to 300 KB, chunked bodies, a fresh connection per request, +and one request that has to end in `Net::ReadTimeout`: + +| | plain HTTP | HTTPS, `VERIFY_NONE` | HTTPS, `ca_file:` | +|---|---|---|---| +| CRuby 4.0 | no failures | no failures | no failures | +| IronRuby | no failures | **`read_timeout` never fires** | **every connection refused** | + +- **Plain sockets are fine.** `IO.select`, `IO#wait_readable` and + `read_nonblock` on a socket go through `Socket.Select` on Windows + (`Src/Libraries/Builtins/IoReadiness.cs`, `BlockWindows`), not `poll(2)`, and + `net/http`'s read timeout works. What *is* `poll(2)` on Windows is a pipe + (README, "What Windows does not have yet"). The report mixed the two up. +- **Over TLS nothing times out.** A server that stops answering leaves the caller + blocked for ever: no `read_timeout`, no `write_timeout`, and no `open_timeout` + for the TLS handshake. For a service that calls an API in a loop, that is a hang. +- **`ca_file`, `ca_path`, `cert_store` and `verify_callback` are ignored.** Only the + system trust store counts, so a private CA or a self-signed test server cannot be + verified, only switched off with `VERIFY_NONE`. + +The data itself arrives intact over TLS: no corruption and no short reads were seen. + +## Why + +`OpenSSL::SSL::SSLSocket` (`Src/StdLib/ironruby/openssl/ssl.rb`) runs on +`OpenSSL::SSL::Transport__` (`Src/Libraries/OpenSSL/OpenSSL.cs`), an `SslStream` over +the TCP socket, which `Transport__.Create` switches to blocking mode. The header of +`ssl.rb` says what follows from that: `#read_nonblock`, `#write_nonblock` and +`#connect_nonblock` block, and never return `:wait_readable`/`:wait_writable`. + +`Net::BufferedIO#rbuf_fill` (`net/protocol.rb`) applies `read_timeout` only on the +`:wait_readable` path: + +```ruby +case rv = @io.read_nonblock(BUFSIZE, tmp, exception: false) +when String then ... +when :wait_readable + (io = @io.to_io).wait_readable(@read_timeout) or raise Net::ReadTimeout.new(io) +``` + +An `SSLSocket` never takes that path, so `read_nonblock` sits in `SslStream.Read` until +data comes. `ssl_socket_connect` (handshake under `open_timeout`) and `write_nonblock` +(under `write_timeout`) have the same shape. `Transport__.Validate` returns +`errors == SslPolicyErrors.None` and never looks at the context's CA settings. + +## Proposed fix + +There are two stages. The first is small and covers what a client needs; the second +gives real non-blocking I/O. + +### Stage 1: timeouts on the blocking calls, and the context's CAs (recommended next) + +1. **Read and write timeouts.** `Transport__` gets `read_timeout=` and `write_timeout=` + (milliseconds, -1 for none), which set `SslStream.ReadTimeout`/`WriteTimeout`. + They delegate to the inner `NetworkStream`, which means `Socket.ReceiveTimeout`/ + `SendTimeout`. A read that times out throws an `IOException` whose inner + `SocketException` is `TimedOut`. `Transport__.read`/`write` turn that into + `IO::TimeoutError`. An `SslStream` is unusable after a timed-out read, so the + transport marks itself broken and every later call raises. +2. **Where the timeout comes from.** IronRuby keeps a small override of + `Net::BufferedIO` in its own stdlib layer (`Src/StdLib/ironruby/`, loaded after + `net/protocol`). When `@io` is an IronRuby `SSLSocket`, `rbuf_fill` sets the + transport's read timeout from `@read_timeout` before the read and maps + `IO::TimeoutError` to `Net::ReadTimeout`. `write0` does the same with + `@write_timeout` and `Net::WriteTimeout`. The upstream file stays untouched, as + with the other stdlib shims. +3. **Handshake timeout.** `Transport__.connect` takes an optional timeout and calls + `AuthenticateAsClientAsync(options, cancellationToken)` with a + `CancellationTokenSource(timeout)`, waiting on the task. `ssl_socket_connect`'s + timeout reaches it through an override of `SSLSocket#connect_nonblock`, or through + `net/http` passing `open_timeout` (the override above can do that in `connect`). +4. **CA settings.** `Validate` builds the chain itself when the context has + `ca_file`, `ca_path` or `cert_store`: `X509ChainPolicy.TrustMode = + X509ChainTrustMode.CustomRootTrust` with those certificates in `CustomTrustStore`, + then `chain.Build`, plus the name check SslStream reported (`RemoteCertificateNameMismatch`). + `verify_callback`, when set, is called with the result and an `X509StoreContext` + holding the chain, and it has the last word, as in MRI. + +Risk: small. Blocking I/O stays as it is, only bounded. What it does not give is real +non-blocking `read_nonblock`, so `IO.select([ssl_socket])` still says "readable" only +when the TCP socket is. A reader that selects first and then reads can block in the +middle of a TLS record. `net/http` doesn't work that way. + +### Stage 2: non-blocking reads over SslStream + +- `Transport__.read_nonblock(length)` keeps at most one `ReadAsync` in flight. If none is + in flight, it starts one. If that completes at once (the plaintext was already + decrypted), it returns the data. Otherwise it returns `:wait_readable` and keeps the + task. The next call returns the task's result once it has completed. +- Readiness has to see that task: the in-flight read may already have drained the TCP + socket, so `Socket.Select` would wait although the data is there. `IoReadiness` + gets a per-`RubyIO` hook ("a pending read has completed") that `Block` checks + before it selects. It then waits on the task's handle together with the sockets, + the way `ReadinessWaiter` already stands in for pipes. `SSLSocket#to_io` keeps + returning the TCP socket, which carries the hook. +- `write_nonblock` and `connect_nonblock` follow the same pattern with `WriteAsync` and + `AuthenticateAsClientAsync`. + +Risk: medium. It touches `IO.select` for every caller, and the in-flight task has to be +cancelled cleanly on `close`. It is worth doing for servers and event loops (nio4r, +puma over TLS), not for a client. + +## How to test it + +- `Util/net-http-tls-check.rb` (needs CRuby for the server): after stage 1 the + `no_timeout` entry and, with `CA=1`, the refused connections are gone. +- For CI without CRuby: `IronRuby.Tests` can host the TLS server itself. Create a + certificate with `CertificateRequest` + `CreateSelfSigned`, accept on a loopback + `TcpListener`, `SslStream.AuthenticateAsServer`, and stall after the headers for the + timeout case. The Ruby side then runs `Net::HTTP` with `ca_file:` pointing at the + exported certificate and `read_timeout: 1` (the test needs `[Options(Prism = true)]` + to load `net/http`). + +## For the application that reported it + +Its .NET `HttpClient` transport stays the right choice until stage 1 lands. Change the +reason it gives: it is not `IO.select` being `poll(2)`. It is that `net/http` over TLS +has no timeouts and ignores `ca_file`. diff --git a/Util/net-http-tls-check.rb b/Util/net-http-tls-check.rb new file mode 100644 index 000000000..70e143b98 --- /dev/null +++ b/Util/net-http-tls-check.rb @@ -0,0 +1,55 @@ +# Net::HTTP over plain TCP and over TLS against Util/net-http-tls-server.rb: keep-alive +# GETs and POSTs of several sizes, chunked bodies, fresh connections, and a read_timeout +# that has to fire. See Docs/net-http-over-tls.md. +# +# ruby Util/net-http-tls-server.rb 18080 18443 # CRuby, in another terminal +# ir.cmd Util/net-http-tls-check.rb 18080 18443 40 # or ./ir.sh +# +# CA=1 verifies against the server's certificate (ca_file) instead of VERIFY_NONE. +# IronRuby 4.0.1: http has no failures; https reports no_timeout (the read_timeout never +# fires), and with CA=1 every connection is refused (ca_file is not consulted). +require "net/http" +require "openssl" +require "tmpdir" +http_port, https_port, rounds = ARGV.map(&:to_i) +rounds = 20 if rounds.zero? +cert = File.join(Dir.tmpdir, "net-http-tls-check-cert.pem") +[[:http, http_port, false], [:https, https_port, true]].each do |label, port, tls| + fails = Hash.new(0) + t0 = Time.now + begin + Net::HTTP.start("127.0.0.1", port, use_ssl: tls, **(tls ? (ENV["CA"] ? {ca_file: cert} : {verify_mode: OpenSSL::SSL::VERIFY_NONE}) : {}), open_timeout: 5, read_timeout: 10) do |h| + rounds.times do |i| + size = [10, 1000, 20_000, 300_000][i % 4] + path = (i % 3 == 0) ? "/chunked?size=#{size}" : "/data?size=#{size}" + begin + r = h.get(path) + fails[:size] += 1 unless r.body.bytesize == size + r = h.post("/echo", "y" * size) + fails[:echo] += 1 unless r.body.bytesize == size + rescue Exception => e + fails["#{e.class}: #{e.message[0, 60]}"] += 1 + end + end + end + rescue Exception => e + fails["start #{e.class}: #{e.message[0, 80]}"] += 1 + end + # one fresh connection per request too + rounds.times do + begin + Net::HTTP.start("127.0.0.1", port, use_ssl: tls, **(tls ? (ENV["CA"] ? {ca_file: cert} : {verify_mode: OpenSSL::SSL::VERIFY_NONE}) : {}), open_timeout: 5, read_timeout: 10) { |h| h.get("/data?size=5000") } + rescue Exception => e + fails["fresh #{e.class}: #{e.message[0, 60]}"] += 1 + end + end + # a read timeout must fire + begin + Net::HTTP.start("127.0.0.1", port, use_ssl: tls, **(tls ? (ENV["CA"] ? {ca_file: cert} : {verify_mode: OpenSSL::SSL::VERIFY_NONE}) : {}), read_timeout: 1) { |h| h.get("/data?delay=3") } + fails[:no_timeout] += 1 + rescue Net::ReadTimeout + rescue Exception => e + fails["timeout #{e.class}"] += 1 + end + puts "#{label}: #{rounds} rounds in #{(Time.now - t0).round(1)}s, failures #{fails.inspect}" +end diff --git a/Util/net-http-tls-server.rb b/Util/net-http-tls-server.rb new file mode 100644 index 000000000..44b2a8856 --- /dev/null +++ b/Util/net-http-tls-server.rb @@ -0,0 +1,67 @@ +# Test server for Util/net-http-tls-check.rb: HTTP/1.1 on one port, HTTPS on another, +# with a throwaway self-signed certificate for 127.0.0.1 written to Dir.tmpdir +# (net-http-tls-check-cert.pem). Run it with CRuby: IronRuby has no SSLServer. +# +# ruby Util/net-http-tls-server.rb 18080 18443 +# +# GET /data?size=N[&delay=S] answers N bytes after S seconds; /chunked?size=N the same, +# chunked; POST /echo sends the body back. +require "socket" +require "openssl" +require "tmpdir" + +http_port, https_port = ARGV.map(&:to_i) + +key = OpenSSL::PKey::RSA.new(2048) +cert = OpenSSL::X509::Certificate.new +cert.version = 2 +cert.serial = 1 +cert.subject = cert.issuer = OpenSSL::X509::Name.parse("/CN=127.0.0.1") +cert.public_key = key.public_key +cert.not_before = Time.now - 60 +cert.not_after = Time.now + 86400 +ef = OpenSSL::X509::ExtensionFactory.new(cert, cert) +cert.add_extension(ef.create_extension("subjectAltName", "IP:127.0.0.1")) +cert.sign(key, OpenSSL::Digest::SHA256.new) +File.write(File.join(Dir.tmpdir, "net-http-tls-check-cert.pem"), cert.to_pem) + +def serve(sock) + loop do + request = sock.gets("\r\n\r\n") or break + path = request[/\A\S+ (\S+)/, 1] + length = request[/^content-length: *(\d+)/i, 1].to_i + body_in = length > 0 ? sock.read(length) : "" + size = path[/size=(\d+)/, 1].to_i + sleep(path[/delay=([\d.]+)/, 1].to_f) + body = path.include?("echo") ? body_in : ("x" * (size > 0 ? size : 100)) + if path.include?("chunked") + sock.write "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\nTransfer-Encoding: chunked\r\n\r\n" + body.scan(/.{1,1000}/m) { |c| sock.write "#{c.bytesize.to_s(16)}\r\n#{c}\r\n"; sock.flush } + sock.write "0\r\n\r\n" + else + sock.write "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\nContent-Length: #{body.bytesize}\r\n\r\n#{body}" + end + sock.flush + break if request =~ /^connection: *close/i + end +rescue StandardError +ensure + sock.close rescue nil +end + +ctx = OpenSSL::SSL::SSLContext.new +ctx.cert = cert +ctx.key = key +plain = TCPServer.new("127.0.0.1", http_port) +tls = TCPServer.new("127.0.0.1", https_port) +ssl = OpenSSL::SSL::SSLServer.new(tls, ctx) +ssl.start_immediately = true +$stdout.puts "listening #{http_port} #{https_port}"; $stdout.flush +Thread.new { loop { s = plain.accept; Thread.new(s) { |c| serve(c) } } } +loop do + begin + s = ssl.accept + Thread.new(s) { |c| serve(c) } + rescue StandardError + end +end From 9a16336f56623e026299fdc5c557e6796ceb6e9a Mon Sep 17 00:00:00 2001 From: Largo Date: Wed, 28 Oct 2026 09:04:01 +0100 Subject: [PATCH 7/9] Remove the legacy parser; run Rails 8.1 + SQLite and popular gems on Windows Prism is now IronRuby's only parser, and a default `rails new` app runs on Windows: scaffold, migrations, importmap/Turbo/Stimulus and `bin/rails server` through Puma and sqlite3. Docs/rails-on-windows.md has the details. Legacy parser: - Delete the gppg grammar and runtime (Parser.y, Parser.Generated.cs, GPPG.cs, ParserStack.cs, ...), the lexer half of Tokenizer.cs, RubyContext.LegacyParser, the legacy -n/-p wrapping and the DLR TokenizerService. - -X:UsePrism is accepted and ignored; the launchers no longer pass it. - The C# suite runs every test on prism: tests of 1.8/1.9-only control flow are removed, the rest expect CRuby 4's output and parse warnings, and the parser tests become NumberLiteralTests. Rails and RubyGems on Windows: - File#flock via LockFileEx; no RLIMIT_/PRIO_ constants and NotImplemented getrlimit & co, as in CRuby; IO readiness without libc poll; IO#ioctl a not-implemented stub; invalid path characters raise Errno::EINVAL. - Binstubs whose #! names ir.exe count as Ruby. - Bundler answers `platforms:` for the dotnet platform; bindex's Exception#bindings; no bundled_gems warning for IronRuby's own fiddle. - attr_* applies the scope's visibility only when self is the module. - File.dirname/basename of drive-relative and UNC paths, realpath ENOENT, Dir.pwd keeps 8.3 short names, Dir.home with forward slashes, and UTF-8 filesystem/locale/default external encodings, ENV and ARGV. Gems: - A requirement for prism 1.x or bigdecimal 2.x/3.x is read with its upper bound lifted where the built-in version then satisfies it: rubocop, rubocop-ast, standard, minitest 6 and prawn activate, under Bundler too. - Ripper reads a Symbol's name from prism 2.0's content_loc (rspec). - Method#source_location is nil for prelude methods that are C in MRI, from a list generated by Util/gen-internal-methods.rb (method_source, pry). - New prawn exercise; listen's exercise no longer races listen's first snapshot. ruby/spec language: - Interpolated symbols with invalid bytes raise EncodingError. - Lazy empty-iteration loops are counted, so .NET 10 stops them as Onigmo does. - defined?(A::B::C) never calls const_missing; nested BEGIN runs first; eval("__FILE__") takes the first frame that names a file. --- Docs/rails-on-windows.md | 219 + README.md | 3 +- Samples/Notepad/notepad.cmd | 2 +- Src/Console/Program.cs | 4 +- Src/IronRuby.Tests/Driver.cs | 65 +- Src/IronRuby.Tests/Helpers.cs | 101 +- Src/IronRuby.Tests/Manual.cs | 1 - Src/IronRuby.Tests/Parser/AssertTokenizer.cs | 238 - .../Parser/CoverageParserLogger.cs | 72 - .../Parser/DefaultParserLogger.cs | 95 - Src/IronRuby.Tests/Parser/ParserTests.cs | 1645 ----- Src/IronRuby.Tests/Parser/Sources.txt | 1 - .../Parser/TokenizerTestDriver.cs | 442 -- Src/IronRuby.Tests/RubyTests.cs | 44 +- Src/IronRuby.Tests/Runtime/AliasTests.cs | 2 +- Src/IronRuby.Tests/Runtime/BlockTests.cs | 497 +- .../Runtime/BoolAndConditionalTests.cs | 6 +- Src/IronRuby.Tests/Runtime/CloningTests.cs | 2 +- Src/IronRuby.Tests/Runtime/ClrBinderTests.cs | 9 - .../Runtime/ClrProtocolTests.cs | 6 - .../Runtime/ClrSubclassingTests.cs | 1 - Src/IronRuby.Tests/Runtime/ClrTests.cs | 6 +- Src/IronRuby.Tests/Runtime/ConstantTests.cs | 27 +- Src/IronRuby.Tests/Runtime/DefinedTests.cs | 11 +- Src/IronRuby.Tests/Runtime/EvalTests.cs | 34 +- Src/IronRuby.Tests/Runtime/ExceptionTests.cs | 4 +- Src/IronRuby.Tests/Runtime/HashTests.cs | 2 +- .../Runtime/InitializerTests.cs | 53 +- Src/IronRuby.Tests/Runtime/LoopTests.cs | 34 - Src/IronRuby.Tests/Runtime/MethodTests.cs | 45 +- Src/IronRuby.Tests/Runtime/MiscTests.cs | 78 +- Src/IronRuby.Tests/Runtime/ModuleTests.cs | 1 - Src/IronRuby.Tests/Runtime/NetHttpTlsTests.cs | 5 - .../Runtime/NumberLiteralTests.cs | 247 + Src/IronRuby.Tests/Runtime/PumaTlsTests.cs | 1 - Src/IronRuby.Tests/Runtime/RegexTests.cs | 6 +- Src/IronRuby.Tests/Runtime/RubyUtilsTests.cs | 17 + Src/IronRuby.Tests/Runtime/StringTests.cs | 6 +- Src/IronRuby.Tests/Runtime/SuperTests.cs | 2 +- Src/IronRuby.Tests/Runtime/UndefTests.cs | 4 +- Src/Libraries/Builtins/FileOps.cs | 116 +- .../Builtins/InternalMethods.Generated.cs | 324 + Src/Libraries/Builtins/IoOps.cs | 11 +- Src/Libraries/Builtins/IoReadiness.cs | 27 + Src/Libraries/Builtins/ModuleOps.cs | 9 +- Src/Libraries/Builtins/UnboundMethod.cs | 21 +- .../ParseTree/IronRubyParseTreeOps.cs | 2 +- Src/Libraries/Socket/Socket.cs | 21 +- Src/Prism/PrismAstBridge.cs | 38 +- Src/Prism/Program.cs | 2 +- Src/Prism/README.md | 35 +- Src/Ruby/Builtins/RegexpTransformer.cs | 11 +- Src/Ruby/Builtins/RubyFile.cs | 7 + .../Ast/Definitions/MethodDefinition.cs | 4 +- Src/Ruby/Compiler/Parser/GPPG.cs | 717 -- Src/Ruby/Compiler/Parser/Generate.cmd | 2 - Src/Ruby/Compiler/Parser/Parser.Generated.cs | 6062 ----------------- Src/Ruby/Compiler/Parser/Parser.cs | 693 -- Src/Ruby/Compiler/Parser/Parser.y | 2323 ------- Src/Ruby/Compiler/Parser/ParserStack.cs | 65 - .../Compiler/Parser/TokenSequenceState.cs | 307 - Src/Ruby/Compiler/Parser/Tokenizer.cs | 4247 +----------- Src/Ruby/Compiler/Parser/VariableFactory.cs | 120 - Src/Ruby/GlobalSuppressions.cs | 1 - Src/Ruby/Hosting/RubyCommandLine.cs | 54 +- Src/Ruby/Hosting/RubyConsoleHost.cs | 39 + Src/Ruby/Runtime/Attributes.cs | 9 + .../Runtime/Calls/RubyLibraryMethodInfo.cs | 3 +- Src/Ruby/Runtime/RubyContext.cs | 89 +- Src/Ruby/Runtime/RubyOps.cs | 33 +- Src/Ruby/Runtime/RubyUtils.cs | 22 + Src/StdLib/ironruby/ironruby/gem_compat.rb | 56 + Src/StdLib/ironruby/ripper/sexp_builder.rb | 8 +- Src/StdLib/ironruby/ruby4.rb | 35 +- Src/StdLib/ruby/4.0/bundled_gems.rb | 9 + .../ruby/4.0/rubygems/defaults/ironruby.rb | 49 +- Util/aot/NativeAot/Program.cs | 3 +- Util/aot/NativeAot/ir-native.sh | 2 +- Util/gems/POPULAR.md | 2 +- Util/gems/catalog.rb | 4 +- Util/gems/exercises/listen.rb | 12 +- Util/gems/exercises/prawn.rb | 26 + Util/gen-internal-methods.rb | 55 + default.mspec | 3 +- ir.cmd | 2 +- ir.sh | 2 +- 86 files changed, 1741 insertions(+), 17979 deletions(-) create mode 100644 Docs/rails-on-windows.md delete mode 100644 Src/IronRuby.Tests/Parser/AssertTokenizer.cs delete mode 100644 Src/IronRuby.Tests/Parser/CoverageParserLogger.cs delete mode 100644 Src/IronRuby.Tests/Parser/DefaultParserLogger.cs delete mode 100644 Src/IronRuby.Tests/Parser/ParserTests.cs delete mode 100644 Src/IronRuby.Tests/Parser/Sources.txt delete mode 100644 Src/IronRuby.Tests/Parser/TokenizerTestDriver.cs create mode 100644 Src/IronRuby.Tests/Runtime/NumberLiteralTests.cs create mode 100644 Src/Libraries/Builtins/InternalMethods.Generated.cs delete mode 100644 Src/Ruby/Compiler/Parser/GPPG.cs delete mode 100644 Src/Ruby/Compiler/Parser/Generate.cmd delete mode 100644 Src/Ruby/Compiler/Parser/Parser.Generated.cs delete mode 100644 Src/Ruby/Compiler/Parser/Parser.cs delete mode 100644 Src/Ruby/Compiler/Parser/Parser.y delete mode 100644 Src/Ruby/Compiler/Parser/ParserStack.cs delete mode 100644 Src/Ruby/Compiler/Parser/TokenSequenceState.cs delete mode 100644 Src/Ruby/Compiler/Parser/VariableFactory.cs create mode 100644 Util/gems/exercises/prawn.rb create mode 100644 Util/gen-internal-methods.rb diff --git a/Docs/rails-on-windows.md b/Docs/rails-on-windows.md new file mode 100644 index 000000000..4b024dc00 --- /dev/null +++ b/Docs/rails-on-windows.md @@ -0,0 +1,219 @@ +# Rails 8.1 + SQLite and popular gems on IronRuby, on Windows + +Measured on `fix/llm-port-quirks` merged up to `origin/master` (`b34a4df9`), Windows 11, +.NET 10.0.12, Debug build, 2026-10-27, with a repo-local `GEM_HOME` (`.gems`) and +`IRONRUBY_NO_HOST_GEMS=1`. The legacy parser was removed in the same piece of work (see the +last section); everything below was re-checked on the prism-only build. + +## Rails + +The path a Windows user would take: + +``` +gem install rails # 8.1.3.1, 43 gems +rails new blog # default Gemfile, untouched +bundle install # 97 gems: Puma, sqlite3, nokogiri, bootsnap, ... as resolved +bin/rails generate scaffold Post title:string body:text published:boolean +bin/rails db:migrate +bin/rails importmap:install turbo:install stimulus:install +bin/rails server +``` + +The app serves the scaffold through IronRuby's Puma, against SQLite through IronRuby's +sqlite3, with Turbo and Stimulus loaded through importmap and propshaft. Index, new, create +(with a CSRF token), show, JSON, edit, update, destroy and the development 404 page answer as on +CRuby, the CSRF meta tags are there, and a POST without a token is refused with 422. + +### Fixed here + +1. **`gem install rails` died writing the first binstub: `File#flock` raised + `NotImplementedError` on Windows.** RubyGems locks every binstub it writes. Now + `LockFileEx`/`UnlockFileEx` over the whole file, as CRuby's win32.c does it, polled for a + blocking lock like the Unix path. `Src/Libraries/Builtins/FileOps.cs`. +2. **`bundle install` died on load: `Process.getrlimit` P/Invoked libc.** net-http-persistent + (vendored by Bundler) calls it whenever `Process::RLIMIT_NOFILE` is defined. On Windows CRuby + has neither the `RLIMIT_*`/`RLIM_*`/`PRIO_*` constants nor working `getrlimit`/`setrlimit`/ + `getpriority`/`setpriority` (they raise `NotImplementedError`; `respond_to?` says false). + IronRuby now matches. `Src/StdLib/ironruby/ruby4.rb`. +3. **`bundle install` died checksumming the first `.gem`: `IO#readpartial` after `IO#eof?` + P/Invoked libc `poll`.** New `IoReadiness.IsReadableNow`: poll on Unix; on Windows + `Socket.Poll`, `PeekNamedPipe` for a pipe, and a disk file is always readable. + `Src/Libraries/Builtins/IoReadiness.cs`, `IoOps.cs`. +4. **`bin/rails` refused to run: "no Ruby script found in input".** Rails writes binstubs from + `ruby_install_name`, which is `ir`, so they start `#!/usr/bin/env ir.exe"`; like MRI, the + command line and prism skip a `#!` line without "ruby" in it. A `#!` line naming IronRuby's + own launcher now counts as Ruby. `RubyUtils.ShebangNamesIronRuby`, `RubyCommandLine.cs`, + `PrismAstBridge.cs`. +5. **`TZInfo::DataSourceNotFound` in the first initializer.** Windows has no zoneinfo, so the + Gemfile has `gem "tzinfo-data", platforms: %i[windows jruby]`; Bundler filters such gems by the + *generic* platform, and IronRuby's `universal-dotnet` is generic `ruby`. For the dotnet + platform the restriction is now answered by the running Ruby. `ironruby/gem_compat.rb`. +6. **`private method 'importmap=' called`.** importmap-rails runs + `Rails::Application.send(:attr_accessor, :importmap)` at a file's top level, where the default + visibility is private; MRI applies the scope's visibility only when the caller's `self` is the + module itself. `Src/Libraries/Builtins/ModuleOps.cs`. +7. **Every development error page was a 500**: web-console calls `Exception#bindings`, which + bindex defines for CRuby, JRuby and Rubinius only. It now answers `[]` as it does there for an + exception nobody captured bindings for, so the page renders. `ironruby/gem_compat.rb`. +8. **"fiddle used to be loaded from the standard library" on every boot**, from IronRuby's own + `ffi.rb`. fiddle (like syslog, nkf, win32ole) is IronRuby's own, in its archdir, and is not + leaving. `Src/StdLib/ruby/4.0/bundled_gems.rb`. + +Found here and already fixed on master: `Pathname#binwrite` missing (master now ships CRuby +4.0's `pathname_builtin.rb`), and a `Hash` subclass's `super() { |h, k| ... }` losing the default +proc - which made `ActiveSupport::InheritableOptions` return `nil` for inherited config, so +**CSRF protection was silently off** in every controller. + +### Not IronRuby's to fix: a checkout path with spaces + +The checkout these measurements come from lives in a path with spaces, and two things break there exactly as +they would for CRuby installed in such a path: Bundler sets `RUBYOPT=-r/bundler/setup` +unquoted, so a child Ruby started from a bundled process splits it (`invalid switch in RUBYOPT: +-A`; this stops `turbo:install`/`stimulus:install`), and Rails runs `"#{Gem.ruby}" bundle +install` around a `Gem.ruby` that is already quoted. Run those install templates with +`bin/rails app:template LOCATION=...`, or keep IronRuby in a path without spaces. mspec's +`ruby_exe` has the same problem: it joins the interpreter, temp files and fixtures into a shell +command unquoted, so from a path with spaces most child-interpreter specs fail. Running with every +path in its 8.3 short form (`RUBY_EXE`, `SPEC_TEMP_DIR` and the spec files) avoids it. + +## Popular gems + +`tmp/rails-try/gem_sweep.rb` (not committed) runs the popular tier of `Util/gems/catalog.rb` +the way `Util/gems/run.sh` does on Linux: each `Util/gems/exercises/.rb` under IronRuby +and under CRuby 4.0.1 with the same gem versions, byte-identical stdout being the pass. + +- **81 work, identical to CRuby**, among them railties, activesupport, activerecord, + actionpack, actionview, activejob, activemodel, sqlite3, nokogiri, rack, sinatra, roda, sidekiq, + faraday, excon, httpclient, webmock, vcr, aws-sdk-core, jwt, mail, parser, concurrent-ruby, + zeitwerk, i18n, thor, tzinfo, kramdown, asciidoctor, octokit, chunky_png, listen, and - after + the fixes below - rspec, pry, sprockets, method_source, tty-prompt, rubocop, rubocop-ast, + standard and prawn. (The CRuby side needs `tzinfo-data` on Windows, `webrick`, and for pry `readline` + with CRuby's own `fiddle`.) +- **19 load** and have no exercise (puma, nio4r, ffi, oj, bcrypt, msgpack, websocket-driver, + yard, googleauth, rails-dom-testing, ...). +- Fixed here: **tty-prompt** - `IO#ioctl` on Windows raised .NET's `NotSupportedException`; + CRuby defines it as a not-implemented stub (`NotImplementedError`, `respond_to?` false), which + tty-screen asks about. `[RubyNotImplemented(OnWindowsOnly = true)]`, `IoOps.cs`. + And opening a path with characters Windows forbids (`<`, `|`, `?`) raised a bare `IOError`; + it is `Errno::EINVAL` now, as in CRuby. `RubyFile.cs`. +- Fixed here: **rspec** - its failure report goes through Ripper, and IronRuby's Ripper read a + Symbol's name from `value_loc`, which prism 2.0 calls `content_loc`; every Symbol raised. + `Src/StdLib/ironruby/ripper/sexp_builder.rb`. +- Fixed here: **sprockets** - `Pathname#absolute?` was false for every `C:/...` path. + `pathname_builtin.rb` (CRuby 4.0's own) recognises drive letters by + `File.dirname("A:") == "A:."`, and IronRuby answered `"A:"`: `File.dirname`/`basename` of + a drive-relative name (`C:`, `C:x`) now give MRI's `C:.` and `x`. Also from ruby/spec: three + or more leading separators are a UNC prefix (`File.dirname("\\\\\\foo")` is `\\foo`), and a + UNC root's base name keeps the separator it ends with. `FileOps.cs`. +- Fixed here: **method_source** - `Method#source_location` of a method IronRuby's prelude + defines was `` even where MRI's is C (`Kernel#puts`), and method_source then + tried to open the file. It is now `nil` there, and MRI's `` name where MRI + writes the method in Ruby too; `Util/gen-internal-methods.rb` generates that list from + CRuby (`InternalMethods.Generated.cs`, 314 methods). +- Fixed here: **pry** - `File.realpath` did not raise `Errno::ENOENT` for a path that is not + there (nor `realdirpath` for a missing parent) where there is no realpath(3) - Windows, macOS - + so pry tried to load a `./.pryrc` that does not exist. `FileOps.cs`. +- Fixed here: **rubocop, rubocop-ast, standard, and minitest 6** (which a Bundler-less + `require "rails-dom-testing"` picks) could not activate: they ask for `prism ~> 1.x`, and + IronRuby's built-in prism is 2.0.0 (the honest version of the ruby/prism `main` it pins), the + only one it can have - the gem is a C extension. They use prism through its Ruby API, which 2.0 + kept for what they call, so RubyGems now reads a requirement *on prism only* for 1.x with its + upper bound lifted (`~> 1.7` as `>= 1.7`), and only where the built-in prism then satisfies + it; a 0.x requirement is left alone. Bundler goes through the same `Gem::Dependency`: a + Gemfile with `minitest` and `rubocop` resolves to minitest 6.0.6 and rubocop 1.92.1 on + prism 2.0.0. `rubygems/defaults/ironruby.rb`. +- Fixed here: **prawn**, the same way: ttfunk, which prawn depends on, asks for + `bigdecimal ~> 3.1`, and IronRuby's bigdecimal is its own C# one at 4.0.1. The rule above + now covers bigdecimal from 2.x on (2.0 removed `BigDecimal.new`), so prawn activates with the + built-in one, under Bundler too, and renders the same PDF bytes as CRuby with the C gem 3.3.1. + Substituting bigdecimal-pure was looked at and is not needed here: IronRuby's C# BigDecimal + passes ruby/spec's `library/bigdecimal` at CI's revision but for two examples that start a + child interpreter and fail from a path with spaces (bigdecimal-pure on IronRuby fails 7 + more), and what ttfunk lacked was a version it accepts, not an implementation. New + exercise `Util/gems/exercises/prawn.rb`. +- Fixed here: **rubocop showed every file by its absolute path.** `Dir.pwd` expanded 8.3 short + names (`C:\Users\ABCDEF~1`), so after `Dir.chdir(Dir.tmpdir)` it was not the directory just + changed into, and no file path built from the one started with the other. `Dir.pwd` is now + `GetCurrentDirectory`, and `Dir.chdir` sets the path as given, as MRI does. + `RubyConsoleHost.cs`. +- Fixed here: **listen's exercise was flaky** (1 run in 3): listen builds its first snapshot on a + thread of its own after `#start`, so a file written at once can land in it and no "added" + event comes, on any Ruby. The exercise now writes the file again until an event names it. + `Util/gems/exercises/listen.rb`. +- **Expected**: pg, mysql2, sassc, google-protobuf (native code), rb-inotify (Linux only). + +## Open + +- **NameError/NoMethodError messages quote names the 3.3 way**, `` `b' ``, where Ruby 3.4+ + writes `'b'`. +- **The "block passed to 'y' may be ignored" warning** says `'y'` where CRuby says + `'Object#y'`, and is sometimes reported at line 0. +- **web-console's console has no bindings to evaluate in** (fix 7): real `Exception#bindings` + needs the runtime to capture a Binding per frame at raise time. +- **`File.write` in text mode returns the byte count after CRLF conversion** (CRuby: before). +- **`Pathname` methods report `pathname_builtin.rb`'s real path** as their `source_location`, + where CRuby says ``. +- **`IO#read_nonblock` on an empty pipe blocks** on Windows (the README's pipe-readiness gap). +- **concurrent-ruby warns "Possibly unsupported Ruby implementation"** on every Rails command: + it knows MRI, JRuby and TruffleRuby only; `Concurrent::Array`/`Hash` are then plain + `Array`/`Hash` on a runtime with parallel threads. +- **Every `bin/rails` command takes 40-70 s** to boot on the Debug build. +- One `bundle install` once locked `irb 1.16.0` from rubygems.org instead of IronRuby's pinned + default gem (`Bundler::GemNotFound` afterwards); three later resolutions pinned correctly. + +## The legacy parser is gone + +Prism is IronRuby's only parser. Removed: the gppg grammar (`Parser.y`, `Parser.Generated.cs`, +`GPPG.cs`, `ParserStack.cs`), the lexer half of `Tokenizer.cs` (its static helpers for names, +number literals and the encoding magic comment stay), `RubyContext.LegacyParser` and the +fallback to it, the legacy `-n`/`-p` wrapping, the DLR `TokenizerService` (the colouring +tokenizer was that lexer), and the test suite's parser/tokenizer tests and `/tokenizer` mode. +`-X:UsePrism` is still accepted and ignored; the launchers no longer pass it. 17,939 lines go. + +The C# test suite now runs every test on prism and passes (before, most ran on the legacy +parser). Of the ~70 tests that failed when switched over: + +- 15 tested 1.8/1.9-only control flow (`retry` outside `rescue`, `break`/`next`/`redo`/`retry` + escaping an `eval`) that is a SyntaxError in CRuby 4; they were removed. +- About 45 now expect what CRuby 4 does: the suite runs with warnings on, so each expects the + parse warnings `ruby -wc` gives, and a handful of outputs changed to CRuby's (a `BEGIN` block + sees top-level locals as `nil`; `defined?` never calls `const_missing`; a regexp literal calls + a redefined `Regexp#=~`; Ruby 3.4 rejects keywords in an index assignment). +- Two were IronRuby bugs on the prism path, fixed: a `BEGIN` nested in a `BEGIN` ran after the + outer one's first statement (MRI runs it first; `PrismAstBridge.HoistPreExecution`), and + `defined?(A::B::C)` called `const_missing` for a missing name in the middle of the path + (`RubyOps.ResolveQualifiedConstant`). + +## ruby/spec `spec/language` + +Run at CI's pinned revisions (`SPEC_REF`/`MSPEC_REF` in `.github/workflows/ci.yml`), checked +out with LF line endings as CI does (`core.autocrlf input`; a CRLF checkout moves the `DATA` +offsets three specs compare), the language suite now passes on Windows: every one of its 2,921 +examples passes, run once with short paths for the child-interpreter specs and once from the +long path for the three that compare `__FILE__` and `$:` with paths resolved from the current +directory. CI on master had two left, both fixed here: + +- **`:"#{...}"` and `%I[#{...}]` made a Symbol of invalid bytes** where MRI raises + `EncodingError` (as `String#to_sym` already did). `RubyOps.CreateInterpolatedSymbol`. +- **`/^(()|a)*?$/` overflowed the backtracking stack on .NET 10** (an error on the net10.0 spec + job): the loop Onigmo's empty-iteration rule is emulated with is now a counted lazy loop, + `{0,N}?`, which .NET 10 stops as Onigmo does. `RegexpTransformer.RewriteLoop`. + +And one that only showed in a long run: **`eval("__FILE__")` said `(eval at :0)`** once a +library frame stood first in the backtrace; the eval's location is now the first frame that +names a file. `RubyContext.TryGetCurrentSourceLocation`. + +## Paths and encodings on Windows + +The `File`, `Dir` and `Encoding` specs that failed on Windows before (6 failures, 2 errors) pass: + +- **Paths were Windows-1252.** The filesystem and locale encodings, `Encoding.default_external`, + and with them `ENV`, `ARGV`, `Dir.home` and every path IronRuby hands out, are UTF-8 on + Windows, as in CRuby 3.0+. `RubyContext.cs`. +- **`Dir.home` and `File.expand_path("~")` had backslashes** (`C:\Users\...` straight from + `USERPROFILE`); CRuby gives `/` and looks at `HOME`, then `USERPROFILE`, then + `HOMEDRIVE`+`HOMEPATH`, then the profile folder. `Dir.home` no longer modifies the `HOME` + string it was given. `ironruby/ruby4.rb`. + +Noted: `RbConfig::CONFIG["ruby_version"]` is still `1.9.1` (and `sitelibdir` ends in +`site_ruby/1.9.1`), where CRuby 4 says `4.0.0`. diff --git a/README.md b/README.md index 6f905354f..68dd06745 100644 --- a/README.md +++ b/README.md @@ -191,7 +191,8 @@ version (`4.0.0`). Ruby source is parsed by `libprism.so` through P/Invoke, decoded from prism's binary serialization by a **generated** C# loader, and mapped onto IronRuby's existing AST — so the -whole AstGenerator/DLR compilation pipeline works unchanged. This is the same architecture +whole AstGenerator/DLR compilation pipeline works unchanged. It is the only parser: the +hand-ported 1.9 grammar and its lexer have been removed. This is the same architecture JRuby uses for its Java loader: ``` diff --git a/Samples/Notepad/notepad.cmd b/Samples/Notepad/notepad.cmd index d191dd400..2ea5459c6 100644 --- a/Samples/Notepad/notepad.cmd +++ b/Samples/Notepad/notepad.cmd @@ -13,4 +13,4 @@ if "%IR_TFM%"=="" set "IR_TFM=net8.0" set "IR_BIN=%IR_ROOT%\Src\Console\bin\%IR_CONFIG%\%IR_TFM%\win-x64\ir.exe" if not exist "%IR_BIN%" set "IR_BIN=%IR_ROOT%\Src\Console\bin\%IR_CONFIG%\%IR_TFM%\ir.exe" set "S=%IR_ROOT%\Src\StdLib" -start "" /b "%IR_BIN%" -X:UsePrism "-X:StdLib=%S%\ironruby;%S%\ruby\4.0" "%~dp0notepad.rb" %* +start "" /b "%IR_BIN%" "-X:StdLib=%S%\ironruby;%S%\ruby\4.0" "%~dp0notepad.rb" %* diff --git a/Src/Console/Program.cs b/Src/Console/Program.cs index e416178ba..9f10fb9ab 100644 --- a/Src/Console/Program.cs +++ b/Src/Console/Program.cs @@ -82,10 +82,12 @@ protected override void ReportInvalidOption(InvalidOptionException e) { [STAThread] [RubyStackTraceHidden] static int Main(string[] args) { + // -X:UsePrism chose prism over the legacy parser. Prism is the only parser now; the switch + // is still accepted, and ignored, so that scripts and older launchers that pass it work. if (Array.IndexOf(args, "-X:UsePrism") >= 0) { args = Array.FindAll(args, a => a != "-X:UsePrism"); - RubyContext.AlternativeParser = IronRuby.Prism.PrismAstBridge.Parse; } + RubyContext.AlternativeParser = IronRuby.Prism.PrismAstBridge.Parse; return new Host().Run(args); } } diff --git a/Src/IronRuby.Tests/Driver.cs b/Src/IronRuby.Tests/Driver.cs index bc159c5fa..d74cfdb01 100644 --- a/Src/IronRuby.Tests/Driver.cs +++ b/Src/IronRuby.Tests/Driver.cs @@ -49,14 +49,6 @@ public sealed class OptionsAttribute : Attribute { public bool PrivateBinding { get; set; } public bool NoRuntime { get; set; } public Type Pal { get; set; } - - /// - /// Parse with the prism front end, which ir and irubyc always use, instead of the legacy - /// parser the rest of the suite runs on. The legacy grammar stops at Ruby 1.9: it cannot - /// parse keyword parameters, so a test that loads today's standard library (psych 5.3.1, - /// ruby4.rb) needs this. IR_USE_PRISM=1 runs every test this way. - /// - public bool Prism { get; set; } } public class TestRuntime { @@ -75,11 +67,8 @@ public TestRuntime(Driver/*!*/ driver, TestCase/*!*/ testCase) { _driver = driver; _testName = testCase.Name; - // The front end is a process-wide static, so every test sets it, back to the legacy - // parser as well, rather than inherit whatever the previous test chose. - RubyContext.AlternativeParser = (Driver.UsePrism || testCase.Options != null && testCase.Options.Prism) - ? IronRuby.Prism.PrismAstBridge.Parse - : RubyContext.LegacyParser; + // The front end is a process-wide static; every test parses with prism, as ir does. + RubyContext.AlternativeParser = IronRuby.Prism.PrismAstBridge.Parse; if (testCase.Options.NoRuntime) { return; @@ -152,14 +141,12 @@ public class Driver { private static bool _verbose; private static bool _isDebug; private static bool _saveToAssemblies; - private static bool _runTokenizerDriver; private static bool _displayList; private static bool _partialTrust; private static bool _noAdaptiveCompilation; private static int _compilationThreshold; private static bool _runPython = true; private static bool? _isPythonConfigured; - private static bool _usePrism; private readonly string/*!*/ _baseDirectory; public Driver(string/*!*/ baseDirectory) { @@ -230,14 +217,6 @@ private static bool IsPythonConfigured { } } - /// - /// IR_USE_PRISM=1: every test parses with the prism front end, not only those marked - /// [Options(Prism = true)]. - /// - public static bool UsePrism { - get { return _usePrism; } - } - public string BaseDirectory { get { return _baseDirectory; } } @@ -255,9 +234,6 @@ private static bool ParseArguments(List/*!*/ args) { Console.WriteLine("Disable Python interop tests : /py-"); Console.WriteLine("Run Specific Tests : [/exclude] [test_to_run ...]"); Console.WriteLine("List Tests : /list"); - Console.WriteLine("Tokenizer baseline : /tokenizer "); - Console.WriteLine("Productions dump : /tokenizer /prod "); - Console.WriteLine("Benchmark : /tokenizer /bm "); } if (args.Contains("/list")) { @@ -330,11 +306,6 @@ private static bool ParseArguments(List/*!*/ args) { args.Remove("/exclude"); } - if (args.Contains("/tokenizer")) { - args.Remove("/tokenizer"); - _runTokenizerDriver = true; - } - return true; } @@ -342,11 +313,6 @@ public static void Main(string[]/*!*/ arguments) { List args = new List(arguments); string culture = Environment.GetEnvironmentVariable("IR_CULTURE"); - if (Environment.GetEnvironmentVariable("IR_USE_PRISM") == "1") { - Console.WriteLine("Using prism front end"); - _usePrism = true; - } - if (args.Contains("/partial")) { // partial trust requires CAS + secondary AppDomains, neither exists on .NET Core Console.Error.WriteLine("/partial (partial trust) is not supported on .NET Core"); @@ -385,25 +351,16 @@ public static int Run(List/*!*/ args, string/*!*/ baseDirectory) { int status = 0; - if (_runTokenizerDriver) { - TokenizerTestDriver driver = new TokenizerTestDriver((RubyContext)HostingHelpers.GetLanguageContext(Ruby.CreateEngine())); - if (!driver.ParseArgs(args)) { - return -3; - } + InitializeDomain(); + Driver driver = new Driver(baseDirectory); - status = driver.RunTests(); + if (Manual.TestCode.Trim().Length == 0) { + status = driver.RunUnitTests(args); } else { - InitializeDomain(); - Driver driver = new Driver(baseDirectory); - - if (Manual.TestCode.Trim().Length == 0) { - status = driver.RunUnitTests(args); - } else { - driver.RunManualTest(); + driver.RunManualTest(); - // for case the test is forgotten, this would fail the test suite: - status = -2; - } + // for case the test is forgotten, this would fail the test suite: + status = -2; } // return failure on bad filter (any real failures throw) @@ -433,7 +390,9 @@ private void RunManualTest() { if (Manual.ParseOnly) { _testRuntime = new TestRuntime(this, new TestCase { Name = "" }); - Tests.GetRubyTokens(_testRuntime.Context, new LoggingErrorSink(false), Manual.TestCode, !Manual.DumpReductions, Manual.DumpReductions); + var log = new LoggingErrorSink(false); + RubyContext.EffectiveParser(_testRuntime.Context.CreateSnippet(Manual.TestCode, SourceCodeKind.File), new IronRuby.Compiler.RubyCompilerOptions(), log); + Console.WriteLine("{0} error(s), {1} warning(s)", log.ErrorCount, log.WarningCount); } else { try { diff --git a/Src/IronRuby.Tests/Helpers.cs b/Src/IronRuby.Tests/Helpers.cs index 457328bd3..ed02cfb59 100644 --- a/Src/IronRuby.Tests/Helpers.cs +++ b/Src/IronRuby.Tests/Helpers.cs @@ -108,11 +108,21 @@ public void CompilerTest(string/*!*/ code) { public void CompilerTest(string/*!*/ code, int expectedCompilerWarningCount, int expectedRuntimeWarningCount) { LoggingErrorSink log = new LoggingErrorSink(true); CompilerTest(code, log); - Assert(log.ErrorCount == 0 && log.FatalErrorCount == 0, "Compile time error"); - Assert(log.WarningCount == expectedCompilerWarningCount, "Wrong number of compile time errors/warnings"); + Assert(log.ErrorCount == 0 && log.FatalErrorCount == 0, "Compile time error: " + DescribeLog(log)); + Assert(log.WarningCount == expectedCompilerWarningCount, String.Format( + "Wrong number of compile time errors/warnings: expected {0}, got {1}: {2}", + expectedCompilerWarningCount, log.WarningCount, DescribeLog(log))); Assert(Context.RuntimeErrorSink.WarningCount == expectedRuntimeWarningCount, "Wrong number of runtime warnings"); } + private static string/*!*/ DescribeLog(LoggingErrorSink/*!*/ log) { + var parts = new List(); + foreach (var e in log.Errors) { + parts.Add(String.Format("{0} at {1}: {2}", e.Severity, e.Span.Start.Line, e.Message)); + } + return String.Join("; ", parts); + } + public void CompilerTest(string/*!*/ code, ErrorSink/*!*/ sink) { Debug.Assert(code != null && sink != null); SourceUnit source; @@ -134,43 +144,6 @@ public void CompilerTest(string/*!*/ code, ErrorSink/*!*/ sink) { } } - public List GetRubyTokens(ErrorSink log, string source) { - return GetRubyTokens(log, source, false); - } - - public List GetRubyTokens(ErrorSink log, string source, bool dumpTokens) { - return GetRubyTokens(Context, log, source, dumpTokens, false); - } - - public static List GetRubyTokens(RubyContext context, ErrorSink log, string source, bool dumpTokens, bool dumpReductions) { - Parser parser = new Parser(); - List tokens = new List(); - - if (dumpTokens) { - parser.Tokenizer.EnableLogging(1, Console.Out); - } - - parser.TokenSink = delegate(Tokens token, SourceSpan span) { - tokens.Add(token); - }; - -#if DEBUG - if (dumpReductions) { - DefaultParserLogger.Attach(parser, Console.Out); - } -#endif - parser.Parse(context.CreateSnippet(source, SourceCodeKind.File), new RubyCompilerOptions(), log); - - //tokenizer.Initialize(SourceUnit.CreateSnippet(RB, source)); - //List tokens = new List(); - //Tokens token; - //while ((token = tokenizer.GetNextToken()) != Tokens.EOF) { - // tokens.Add(token); - //} - - return tokens; - } - [Flags] enum OutputFlags { None = 0, @@ -202,6 +175,20 @@ private void TestOutput(string code, string expectedOutput) { AssertOutput(() => CompilerTest(code), expectedOutput); } + /// + /// The tests run with warnings on (Verbosity 2, ruby -w), so the parse warnings are the ones + /// `ruby -wc` reports for the same code. + /// + [DebuggerHiddenAttribute] + private void TestOutput(string code, string expectedOutput, int expectedCompilerWarningCount) { + AssertOutput(() => CompilerTest(code, expectedCompilerWarningCount, 0), expectedOutput); + } + + [DebuggerHiddenAttribute] + private void TestOutput(string code, string expectedOutput, int expectedCompilerWarningCount, int expectedRuntimeWarningCount) { + AssertOutput(() => CompilerTest(code, expectedCompilerWarningCount, expectedRuntimeWarningCount), expectedOutput); + } + [DebuggerHiddenAttribute] private void XTestOutput(string code, string expectedOutput) { XAssertOutput(() => CompilerTest(code), expectedOutput); @@ -212,6 +199,11 @@ private void TestOutputWithEval(string code, string expectedOutput) { UsingEval((eval) => AssertOutput(() => CompilerTest(Eval(eval, code)), expectedOutput)); } + [DebuggerHiddenAttribute] + private void TestOutputWithEval(string code, string expectedOutput, int expectedCompilerWarningCount) { + UsingEval((eval) => AssertOutput(() => CompilerTest(Eval(eval, code), expectedCompilerWarningCount, 0), expectedOutput)); + } + [DebuggerHiddenAttribute] private void XTestOutputWithEval(string code, string expectedOutput) { UsingEval((eval) => XAssertOutput(() => CompilerTest(Eval(eval, code)), expectedOutput)); @@ -389,37 +381,6 @@ internal void AssertBreak() { } } - #region Parser, Tokenizer - - public object TestCategorizer(ScriptEngine engine, object state, string/*!*/ src, params TokenInfo[]/*!*/ expected) { - return TestCategorizer(engine, state, src, SourceLocation.MinValue, expected); - } - - public object TestCategorizer(ScriptEngine engine, object state, string/*!*/ src, SourceLocation initial, params TokenInfo[]/*!*/ expected) { - TokenCategorizer categorizer = engine.GetService(); - - categorizer.Initialize(state, engine.CreateScriptSourceFromString(src), initial); - IEnumerable actual = categorizer.ReadTokens(Int32.MaxValue); - - int i = 0; - foreach (TokenInfo info in actual) { - Assert(i < expected.Length); - if (!info.Equals(expected[i])) { - Assert(false); - } - i++; - } - Assert(i == expected.Length); - - TokenInfo t = categorizer.ReadToken(); - SourceLocation end = expected[expected.Length - 1].SourceSpan.End; - Assert(t.Equals(new TokenInfo(new SourceSpan(end, end), TokenCategory.EndOfStream, TokenTriggers.None))); - - return categorizer.CurrentState; - } - - #endregion - #region Bugs // Helpers for tests which are currently failing. Using these helpers will ensure that when the bug is fixed, diff --git a/Src/IronRuby.Tests/Manual.cs b/Src/IronRuby.Tests/Manual.cs index 8a24c7191..cc6565e7d 100644 --- a/Src/IronRuby.Tests/Manual.cs +++ b/Src/IronRuby.Tests/Manual.cs @@ -22,6 +22,5 @@ public static class Manual { }; public static bool ParseOnly = false; - public static bool DumpReductions = false; } } diff --git a/Src/IronRuby.Tests/Parser/AssertTokenizer.cs b/Src/IronRuby.Tests/Parser/AssertTokenizer.cs deleted file mode 100644 index 674a3b0e1..000000000 --- a/Src/IronRuby.Tests/Parser/AssertTokenizer.cs +++ /dev/null @@ -1,238 +0,0 @@ -/* **************************************************************************** - * - * Copyright (c) Microsoft Corporation. - * - * This source code is subject to terms and conditions of the Apache License, Version 2.0. A - * copy of the license can be found in the License.html file at the root of this distribution. If - * you cannot locate the Apache License, Version 2.0, please send an email to - * ironruby@microsoft.com. By using this source code in any fashion, you are agreeing to be bound - * by the terms of the Apache License, Version 2.0. - * - * You must not remove this notice, or any other, from this software. - * - * - * ***************************************************************************/ - -using System; -using System.Diagnostics; -using System.Dynamic; -using Microsoft.Scripting; -using IronRuby.Builtins; -using IronRuby.Compiler; -using IronRuby.Runtime; -using System.IO; -using System.Text; -using System.Collections.Generic; -using Microsoft.Scripting.Utils; - -namespace IronRuby.Tests { - internal class AssertTokenizer { - private readonly RubyContext/*!*/ _context; - private readonly Tests/*!*/ _tests; - private Tokenizer _tokenizer; - private Tokens _actualToken; - private TokenValue _actualValue; - private SourceSpan _actualSpan; - private LoggingErrorSink _log; - private List/*!*/ _allTokens; - private List/*!*/ _allValues; - public RubyCompatibility Compatibility { get; set; } - public bool Verbatim { get; set; } - - public AssertTokenizer(Tests/*!*/ tests) { - _log = new LoggingErrorSink(); - _tests = tests; - _context = tests.Context; - DefaultEncoding = RubyEncoding.UTF8; - Compatibility = tests.Context.RubyOptions.Compatibility; - } - - public Tokenizer Tokenizer { - get { return _tokenizer; } - } - - public List/*!*/ AllTokens { - get { return _allTokens; } - } - - public List/*!*/ AllValues { - get { return _allValues; } - } - - public AssertTokenizer/*!*/ B { - get { if (Debugger.IsAttached) Debugger.Break(); return this; } - } - - public RubyEncoding/*!*/ DefaultEncoding { get; set; } - - public void EOF() { - Read(Tokens.EndOfFile); - Expect(); - } - - public AssertTokenizer/*!*/ Load(object/*!*/ source, Action/*!*/ tokenizerInit) { // source: byte[] or string - var result = Load(source); - tokenizerInit(result.Tokenizer); - return result; - } - - public AssertTokenizer/*!*/ Load(object/*!*/ source) { // source: byte[] or string - _tests.Assert(_log.Errors.Count == 0, "Previous test case reported unexpected error/warning(s)"); - - SourceUnit sourceUnit; - RubyEncoding encoding; - byte[] binarySource = source as byte[]; - if (binarySource != null) { - encoding = RubyEncoding.Binary; - sourceUnit = _context.CreateSourceUnit(new BinaryContentProvider(binarySource), null, encoding.Encoding, SourceCodeKind.File); - } else { - encoding = DefaultEncoding; - sourceUnit = _context.CreateSnippet((string)source, SourceCodeKind.File); - } - - _tokenizer = new Tokenizer(false, DummyVariableResolver.AllMethodNames) { - ErrorSink = _log, - Compatibility = Compatibility, - Encoding = encoding, - Verbatim = Verbatim, - }; - - _tokenizer.Initialize(sourceUnit); - _allTokens = new List(); - _allValues = new List(); - return this; - } - - public AssertTokenizer/*!*/ Skip(int count) { - while (count-- > 0) { - Next(); - } - return this; - } - - public AssertTokenizer/*!*/ Next() { - _actualToken = _tokenizer.GetNextToken(); - _actualValue = _tokenizer.TokenValue; - _actualSpan = _tokenizer.TokenSpan; - _allTokens.Add(_actualToken); - _allValues.Add(_actualValue); - return this; - } - - public AssertTokenizer/*!*/ Read(Tokens token) { - Next(); - _tests.Assert(_actualToken == token); - return this; - } - - public AssertTokenizer/*!*/ Read(int expected) { - Next(); - _tests.Assert(_actualToken == Tokens.Integer); - _tests.Assert(expected == _actualValue.Integer1); - return this; - } - - public AssertTokenizer/*!*/ Read(string/*!*/ expected) { - Next(); - _tests.Assert(_actualToken == Tokens.StringContent); - _tests.Assert(_actualValue.StringContent is string); - _tests.Assert(expected == (string)_actualValue.StringContent); - return this; - } - - public AssertTokenizer/*!*/ Read(byte[]/*!*/ expected) { - Next(); - _tests.Assert(_actualToken == Tokens.StringContent); - _tests.Assert(_actualValue.StringContent is byte[]); - _tests.Assert(expected.ValueCompareTo(expected.Length, (byte[])_actualValue.StringContent) == 0); - return this; - } - - public AssertTokenizer/*!*/ ReadSymbol(Tokens token, string expected) { - Next(); - _tests.Assert(_actualToken == token); - _tests.Assert(expected == _actualValue.String); - return this; - } - - public AssertTokenizer/*!*/ Read(RubyRegexOptions expected) { - Next(); - _tests.Assert(_actualToken == Tokens.RegexpEnd); - _tests.Assert(expected == _actualValue.RegExOptions); - return this; - } - - public AssertTokenizer/*!*/ ReadBigInteger(string/*!*/ expected, int @base) { - Next(); - _tests.Assert(_actualToken == Tokens.BigInteger); - _tests.Assert(StringComparer.OrdinalIgnoreCase.Compare(_actualValue.BigInteger.ToString(@base), expected) == 0); - return this; - } - - public AssertTokenizer/*!*/ Read(double expected) { - Next(); - _tests.Assert(_actualToken == Tokens.Float); - - if (Double.IsNaN(expected)) { - _tests.Assert(Double.IsNaN(_actualValue.Double)); - } else if (Double.IsNegativeInfinity(expected)) { - _tests.Assert(Double.IsNegativeInfinity(_actualValue.Double)); - } else if (Double.IsPositiveInfinity(expected)) { - _tests.Assert(Double.IsPositiveInfinity(_actualValue.Double)); - } else { - // TODO: is this correct? - _tests.Assert(System.Math.Abs(_actualValue.Double - expected) < Double.Epsilon); - } - return this; - } - - public AssertTokenizer/*!*/ Expect(params ErrorInfo[] errors) { - if (errors == null || errors.Length == 0) { - _tests.Assert(_log.Errors.Count == 0, "Unexpected error/warning(s)"); - } else { - _tests.Assert(_log.Errors.Count == errors.Length, String.Format("Expected {0} error/warning(s)", errors.Length)); - for (int i = 0; i < errors.Length; i++) { - _tests.Assert(_log.Errors[i].Code == errors[i].Code); - } - } - _log.Errors.Clear(); - return this; - } - - public AssertTokenizer/*!*/ State(LexicalState expected) { - _tests.Assert(Tokenizer.LexicalState == expected); - return this; - } - - public AssertTokenizer/*!*/ this[Tokens expected] { - get { return Read(expected); } - } - - public AssertTokenizer/*!*/ this[string/*!*/ expected] { - get { return Read(expected); } - } - - public AssertTokenizer/*!*/ this[string/*!*/ expected, Encoding/*!*/ encoding] { - get { return Read(encoding.GetBytes(expected)); } - } - - public AssertTokenizer/*!*/ this[byte[]/*!*/ expected] { - get { return Read(expected); } - } - - public AssertTokenizer/*!*/ this[int expected] { - get { return Read(expected); } - } - - public AssertTokenizer/*!*/ this[Tokens token, string/*!*/ expected] { - get { - Next(); - _tests.Assert(_actualToken == token); - _tests.Assert(_actualValue.StringContent is string); - _tests.Assert(expected == (string)_actualValue.StringContent); - return this; - } - } - - } -} diff --git a/Src/IronRuby.Tests/Parser/CoverageParserLogger.cs b/Src/IronRuby.Tests/Parser/CoverageParserLogger.cs deleted file mode 100644 index 1485f5b93..000000000 --- a/Src/IronRuby.Tests/Parser/CoverageParserLogger.cs +++ /dev/null @@ -1,72 +0,0 @@ -/* **************************************************************************** - * - * Copyright (c) Microsoft Corporation. - * - * This source code is subject to terms and conditions of the Apache License, Version 2.0. A - * copy of the license can be found in the License.html file at the root of this distribution. If - * you cannot locate the Apache License, Version 2.0, please send an email to - * ironruby@microsoft.com. By using this source code in any fashion, you are agreeing to be bound - * by the terms of the Apache License, Version 2.0. - * - * You must not remove this notice, or any other, from this software. - * - * - * ***************************************************************************/ -#if DEBUG -using System.Collections.Generic; -using System.IO; -using Microsoft.Scripting.Utils; -using IronRuby.Compiler; - -namespace IronRuby.Tests { - /// - /// Create a shadow stack, similar to the one used to keep track of which LALR state you are in - /// - /// Whenever you encounter a 'shift' action push 0 on the shadow stack. Since you shift terimal symbols, we can ignore them. - /// - /// Whenever you encounter a 'reduction' action, pop the top n elements off the shadow stack and log them. So, for example - /// if you encounter a production which is a sequence of four terminals you get "[ 0 0 0 0 ]". - /// - /// Whenever you encounter a 'goto' action (typically immediately after a reduction), push the production ID on the shadow stack. - /// This way, the next time you reduce a production where the non terminal token was you have a production ID instead of 0. - /// - public class CoverageParserLogger : IParserLogger { - private readonly Parser/*!*/ _parser; - private readonly TextWriter/*!*/ _output; - private readonly Stack/*!*/ _rules; - - public CoverageParserLogger(Parser/*!*/ parser, TextWriter/*!*/ output) { - Assert.NotNull(parser, output); - _parser = parser; - _output = output; - _rules = new Stack(); - } - - public void BeforeReduction(int ruleId, int rhsLength) { - _output.Write(ruleId); - _output.Write(" ["); - - for (int i = 0; i < rhsLength; i++) { - if (i > 0) _output.Write(' '); - _output.Write(_rules.Pop()); - } - - _output.WriteLine("]"); - } - - public void BeforeShift(int stateId, int tokenId, bool isErrorShift) { - _rules.Push(0); - } - - public void BeforeGoto(int stateId, int ruleId) { - _rules.Push(ruleId); - } - - public void StateEntered() { - } - - public void NextToken(int tokenId) { - } - } -} -#endif \ No newline at end of file diff --git a/Src/IronRuby.Tests/Parser/DefaultParserLogger.cs b/Src/IronRuby.Tests/Parser/DefaultParserLogger.cs deleted file mode 100644 index c332168de..000000000 --- a/Src/IronRuby.Tests/Parser/DefaultParserLogger.cs +++ /dev/null @@ -1,95 +0,0 @@ -/* **************************************************************************** - * - * Copyright (c) Microsoft Corporation. - * - * This source code is subject to terms and conditions of the Apache License, Version 2.0. A - * copy of the license can be found in the License.html file at the root of this distribution. If - * you cannot locate the Apache License, Version 2.0, please send an email to - * ironruby@microsoft.com. By using this source code in any fashion, you are agreeing to be bound - * by the terms of the Apache License, Version 2.0. - * - * You must not remove this notice, or any other, from this software. - * - * - * ***************************************************************************/ - -#if DEBUG -using System; -using System.Diagnostics; -using System.IO; -using Microsoft.Scripting.Utils; -using IronRuby.Compiler; - -namespace IronRuby.Tests { - internal class DefaultParserLogger : IParserLogger { - private readonly Parser/*!*/ _parser; - private int _logVerbosity; // 0 means logging disabled - private TextWriter _log; - - public DefaultParserLogger(Parser/*!*/ parser, int verbosity, TextWriter/*!*/ output) { - Assert.NotNull(parser, output); - Debug.Assert(verbosity > 0 && verbosity <= 2); - - _parser = parser; - _logVerbosity = verbosity; - _log = output; - } - - public void BeforeReduction(int ruleId, int rhsLength) { - LogRule("Reducing by rule", ruleId); - } - - public void BeforeShift(int stateId, int tokenId, bool isErrorShift) { - LogToken(isErrorShift ? "Error shift" : "Shifting token", tokenId); - } - - public void BeforeGoto(int stateId, int ruleId) { - } - - public void StateEntered() { - LogState("Entering state", _parser.CurrentState.Id); - } - - public void NextToken(int tokenId) { - LogToken("Next token", tokenId); - } - - - private void LogRule(string message, int ruleId) { - Log("{0} {1}: {2}", message, ruleId, _parser.RuleToString(ruleId)); - } - - private void LogToken(string message, int tokenId) { - Log("{0}: {1}", message, Parser.GetTerminalName(tokenId)); - } - - private void LogState(string/*!*/ action, int stateId) { - Log("{0} {1} ", action, stateId); - } - - private void Log(string/*!*/ format, params object[] args) { - if (_logVerbosity > 0) { - _log.WriteLine(format, args); - } - } - - private void DumpStack() { - if (_logVerbosity > 1) { - _log.WriteLine("State stack:"); - foreach (State state in _parser.Stack.GetStates()) { - _log.WriteLine(state.Id); - } - _log.WriteLine(); - } - } - - public static void Attach(Parser/*!*/ parser) { - Attach(parser, Console.Out); - } - - public static void Attach(Parser/*!*/ parser, TextWriter/*!*/ output) { - parser.EnableLogging(new DefaultParserLogger(parser, 1, output)); - } - } -} -#endif \ No newline at end of file diff --git a/Src/IronRuby.Tests/Parser/ParserTests.cs b/Src/IronRuby.Tests/Parser/ParserTests.cs deleted file mode 100644 index 6700a34bf..000000000 --- a/Src/IronRuby.Tests/Parser/ParserTests.cs +++ /dev/null @@ -1,1645 +0,0 @@ -/* **************************************************************************** - * - * Copyright (c) Microsoft Corporation. - * - * This source code is subject to terms and conditions of the Apache License, Version 2.0. A - * copy of the license can be found in the License.html file at the root of this distribution. If - * you cannot locate the Apache License, Version 2.0, please send an email to - * ironruby@microsoft.com. By using this source code in any fashion, you are agreeing to be bound - * by the terms of the Apache License, Version 2.0. - * - * You must not remove this notice, or any other, from this software. - * - * - * ***************************************************************************/ - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Text; -using IronRuby.Builtins; -using IronRuby.Compiler; -using IronRuby.Runtime; -using IronRuby.Runtime.Calls; -using Microsoft.Scripting; -using Microsoft.Scripting.Hosting; -using System.Numerics; -using Microsoft.Scripting.Runtime; -using Microsoft.Scripting.Utils; - -namespace IronRuby.Tests { - public partial class Tests { - - // manual test, measures initialization and JIT times (hence it must be the first run) - public void Scenario_Startup() { - Stopwatch w = new Stopwatch(); - w.Start(); - Engine.CreateScriptSourceFromString("def foo; puts 2 + 2; end").Execute(Engine.CreateScope()); - w.Stop(); - Console.WriteLine("> total time: {0}ms", w.ElapsedMilliseconds); - } - - // manual test - public void Scenario_ParserLogging() { - if (!_driver.PartialTrust) { - ParserLoggingTest(); - } - } - - private void ParserLoggingTest() { -#if DEBUG - string source = "def foo(a); end"; - var sourceUnit = Context.CreateSnippet(source, SourceCodeKind.Statements); - var options = new RubyCompilerOptions(); - - string temp = Path.Combine(Path.GetTempPath(), "RubyParser"); - Console.WriteLine("> see {0}", temp); - Directory.CreateDirectory(temp); - - Parser parser = new Parser(); - using (TextWriter writer = File.CreateText(Path.Combine(temp, "default.log"))) { - DefaultParserLogger.Attach(parser, writer); - parser.Parse(sourceUnit, options, ErrorSink.Null); - } - - using (TextWriter writer = File.CreateText(Path.Combine(temp, "tables.csv"))) { - parser.DumpTables(writer); - } - - using (TextWriter writer = File.CreateText(Path.Combine(temp, "productions.txt"))) { - for (int i = 0; i < parser.Rules.Length; i++) { - writer.WriteLine("{0}\t{1}", i, parser.RuleToString(i)); - } - } - - parser = new Parser(); - using (TextWriter writer = File.CreateText(Path.Combine(temp, "productions.txt"))) { - for (int i = 0; i < parser.Rules.Length; i++) { - writer.WriteLine("{0}\t{1}", i, parser.RuleToString(i)); - } - } - - using (TextWriter writer = File.CreateText(Path.Combine(temp, "second_order.log"))) { - parser.EnableLogging(new CoverageParserLogger(parser, writer)); - parser.Parse(sourceUnit, options, ErrorSink.Null); - } -#endif - } - - public void Parser1() { - LoggingErrorSink log = new LoggingErrorSink(); - - List tokens; - - tokens = GetRubyTokens(log, "foo (while (f do end) do end) do end"); - - Assert(tokens.Count == 14); - Assert(tokens[0] == Tokens.Identifier); - Assert(tokens[1] == Tokens.LeftArgParenthesis); - Assert(tokens[2] == Tokens.While); - Assert(tokens[3] == Tokens.LeftExprParenthesis); - Assert(tokens[4] == Tokens.Identifier); - Assert(tokens[5] == Tokens.Do); - Assert(tokens[6] == Tokens.End); - Assert(tokens[7] == Tokens.RightParenthesis); - Assert(tokens[8] == Tokens.LoopDo); - Assert(tokens[9] == Tokens.End); - Assert(tokens[10] == Tokens.RightParenthesis); - Assert(tokens[11] == Tokens.BlockDo); - Assert(tokens[12] == Tokens.End); - Assert(tokens[13] == Tokens.EndOfFile); - - log.Errors.Clear(); - - tokens = GetRubyTokens(log, "print 'foo'"); - - Assert(log.Errors.Count == 0); - - Assert(tokens.Count == 5 && - tokens[0] == Tokens.Identifier && - tokens[1] == Tokens.StringBegin && - tokens[2] == Tokens.StringContent && - tokens[3] == Tokens.StringEnd && - tokens[4] == Tokens.EndOfFile); - - Assert(log.Errors.Count == 0); - - tokens = GetRubyTokens(log, "print '"); - - Assert(log.Errors.Count == 1 && - log.Errors[0].Severity == Severity.Error - ); - - Assert(tokens.Count == 4 && - tokens[0] == Tokens.Identifier && - tokens[1] == Tokens.StringBegin && - tokens[2] == Tokens.StringEnd && - tokens[3] == Tokens.EndOfFile); - - log.Errors.Clear(); - - tokens = GetRubyTokens(log, "f \"a#{g.h /x/}\" do\nend"); - - Assert(tokens.ToArray().ValueEquals(new[] { - Tokens.Identifier, - Tokens.StringBegin, - Tokens.StringContent, - Tokens.StringEmbeddedCodeBegin, - Tokens.Identifier, - Tokens.Dot, - Tokens.Identifier, - Tokens.RegexpBegin, - Tokens.StringContent, - Tokens.RegexpEnd, - Tokens.StringEmbeddedCodeEnd, - Tokens.StringEnd, - Tokens.BlockDo, - Tokens.End, - Tokens.EndOfFile - })); - - Assert(log.Errors.Count == 1 && - log.Errors[0].Severity == Severity.Warning - ); - - log.Errors.Clear(); - - // 1.9: - tokens = GetRubyTokens(log, "def !@\nend"); - - Assert(tokens.ToArray().ValueEquals(new[] { - Tokens.Def, - Tokens.Bang, - Tokens.NewLine, - Tokens.End, - Tokens.EndOfFile - })); - - Assert(log.Errors.Count == 0); - - // 1.9: - tokens = GetRubyTokens(log, "puts <(){} }"); - Assert(tokens.ToArray().ValueEquals(new[] { - Tokens.Identifier, - Tokens.LeftBlockBrace, - Tokens.Lambda, - Tokens.LeftParenthesis, - Tokens.RightParenthesis, - Tokens.LeftLambdaBrace, - Tokens.RightBrace, - Tokens.RightBrace, - Tokens.EndOfFile, - })); - - Assert(log.Errors.Count == 0); - - tokens = GetRubyTokens(log, "\"#{->{ }}\"\n-> do\nend"); - - Assert(tokens.ToArray().ValueEquals(new[] { - Tokens.StringBegin, - Tokens.StringEmbeddedCodeBegin, - Tokens.Lambda, - Tokens.LeftLambdaBrace, - Tokens.RightBrace, - Tokens.StringEmbeddedCodeEnd, - Tokens.StringEnd, - Tokens.NewLine, - Tokens.Lambda, - Tokens.LambdaDo, - Tokens.NewLine, - Tokens.End, - Tokens.EndOfFile, - })); - - Assert(log.Errors.Count == 0); - } - - private void ParserErrors1() { - LoggingErrorSink log = new LoggingErrorSink(); - - var tokens = GetRubyTokens(log, "def ["); - - Assert(tokens.ToArray().ValueEquals(new[] { - Tokens.Def, - Tokens.LeftIndexingBracket, - })); - - Assert(log.Errors.Count == 1 && - log.Errors[0].Severity == Severity.FatalError - ); - - log.Errors.Clear(); - - tokens = GetRubyTokens(log, "${"); - - Assert(tokens.ToArray().ValueEquals(new[] { - Tokens.Dollar, - })); - - Assert(log.Errors.Count == 1 && - log.Errors[0].Severity == Severity.FatalError - ); - - log.Errors.Clear(); - - // Error: block argument should not be given (yield as a command): - tokens = GetRubyTokens(log, "a[yield 1, &x]"); - Assert(tokens.ToArray().ValueEquals(new[] { - Tokens.Identifier, - Tokens.LeftIndexingBracket, - Tokens.Yield, - Tokens.Integer, - Tokens.Comma, - Tokens.BlockReference, - Tokens.Identifier, - Tokens.RightBracket, - Tokens.EndOfFile, - })); - - Assert(log.Errors.Count == 1 && - log.Errors[0].Severity == Severity.Error - ); - - log.Errors.Clear(); - - // restrictions on jump statements: - foreach (var src in new[] { - "a[return 1, &x]", - "puts if return 1", - "1 && return 1", - "(a ? return 1 : 1) while true", - "a while return", - "1 + return", - "return / 1", - "a = return", - "return.foo = bar", - "a = 1 rescue return 2", - }) { - tokens = GetRubyTokens(log, src); - Assert(log.Errors.Count > 0 && log.Errors.Exists((e) => e.Severity == Severity.FatalError)); - log.Errors.Clear(); - } - - // Error: Duplicate parameter name: - tokens = GetRubyTokens(log, "lambda { |x,x| }"); - Assert(log.Errors.Count == 1 && log.Errors[0].Severity == Severity.Error); - log.Errors.Clear(); - - // Underscore may be duplicated: - tokens = GetRubyTokens(log, "lambda { |_,_| }"); - Assert(log.Errors.Count == 0); - log.Errors.Clear(); - } - - [Options(NoRuntime = true)] - public void TokenCategorizer1() { - var allTokens = Enum.GetValues(typeof(Tokens)); - foreach (Tokens token in allTokens) { - if (token != Tokens.None && token != Tokens.Lowest && token != Tokens.LastToken) { - var info = Tokenizer.GetTokenInfo(token); - Assert(info.Category != TokenCategory.None); - } - } - foreach (Tokens token in allTokens) { - if (token != Tokens.None && token != Tokens.Lowest && token != Tokens.LastToken) { - Assert(!String.IsNullOrEmpty(Tokenizer.GetTokenDescription(token))); - } - } - } - - public void TokenCategorizer2() { - // initial position: - TestCategorizer(Engine, null, "1\n2", new SourceLocation(10, 2, 5), - // 1 - new TokenInfo(new SourceSpan(new SourceLocation(10, 2, 5), new SourceLocation(11, 2, 6)), TokenCategory.NumericLiteral, TokenTriggers.None), - // \n - new TokenInfo(new SourceSpan(new SourceLocation(11, 2, 6), new SourceLocation(12, 3, 1)), TokenCategory.WhiteSpace, TokenTriggers.None), - // 2 - new TokenInfo(new SourceSpan(new SourceLocation(12, 3, 1), new SourceLocation(13, 3, 2)), TokenCategory.NumericLiteral, TokenTriggers.None) - ); - - // regexes: - TestCategorizer(Engine, null, "/x/", - // / - new TokenInfo(new SourceSpan(new SourceLocation(0, 1, 1), new SourceLocation(1, 1, 2)), TokenCategory.StringLiteral, TokenTriggers.None), - // hello - new TokenInfo(new SourceSpan(new SourceLocation(1, 1, 2), new SourceLocation(2, 1, 3)), TokenCategory.StringLiteral, TokenTriggers.None), - // / - new TokenInfo(new SourceSpan(new SourceLocation(2, 1, 3), new SourceLocation(3, 1, 4)), TokenCategory.StringLiteral, TokenTriggers.None) - ); - - // whitespace: - TestCategorizer(Engine, null, "print 'foo' #bar", - // print - new TokenInfo(new SourceSpan(new SourceLocation(0, 1, 1), new SourceLocation(5, 1, 6)), TokenCategory.Identifier, TokenTriggers.None), - // ' ' - new TokenInfo(new SourceSpan(new SourceLocation(5, 1, 6), new SourceLocation(6, 1, 7)), TokenCategory.WhiteSpace, TokenTriggers.None), - // ' - new TokenInfo(new SourceSpan(new SourceLocation(6, 1, 7), new SourceLocation(7, 1, 8)), TokenCategory.StringLiteral, TokenTriggers.None), - // foo - new TokenInfo(new SourceSpan(new SourceLocation(7, 1, 8), new SourceLocation(10, 1, 11)), TokenCategory.StringLiteral, TokenTriggers.None), - // ' - new TokenInfo(new SourceSpan(new SourceLocation(10, 1, 11), new SourceLocation(11, 1, 12)), TokenCategory.StringLiteral, TokenTriggers.None), - // ' ' - new TokenInfo(new SourceSpan(new SourceLocation(11, 1, 12), new SourceLocation(12, 1, 13)), TokenCategory.WhiteSpace, TokenTriggers.None), - // #bar - new TokenInfo(new SourceSpan(new SourceLocation(12, 1, 13), new SourceLocation(16, 1, 17)), TokenCategory.LineComment, TokenTriggers.None) - ); - - // eolns: - TestCategorizer(Engine, null, "a\r\nb", - // a - new TokenInfo(new SourceSpan(new SourceLocation(0, 1, 1), new SourceLocation(1, 1, 2)), TokenCategory.Identifier, TokenTriggers.None), - // \r\n - new TokenInfo(new SourceSpan(new SourceLocation(1, 1, 2), new SourceLocation(3, 2, 1)), TokenCategory.WhiteSpace, TokenTriggers.None), - // b - new TokenInfo(new SourceSpan(new SourceLocation(3, 2, 1), new SourceLocation(4, 2, 2)), TokenCategory.Identifier, TokenTriggers.None) - ); - - // 11111111 11222222222233 333 - // 012345678901234567 89012345678901 234 - TestCategorizer(Engine, null, "canvas.Event { |x|\nputs 'string'\n}", - // 1234567890123456789 12345678901234 12 - // 1111111111 11111 - // line 1 - new TokenInfo(new SourceSpan(new SourceLocation(0, 1, 1), new SourceLocation(6, 1, 7)), TokenCategory.Identifier, TokenTriggers.None), // canvas - new TokenInfo(new SourceSpan(new SourceLocation(6, 1, 7), new SourceLocation(7, 1, 8)), TokenCategory.Delimiter, TokenTriggers.MemberSelect), // . - new TokenInfo(new SourceSpan(new SourceLocation(7, 1, 8), new SourceLocation(12, 1, 13)), TokenCategory.Identifier, TokenTriggers.None), // Event - new TokenInfo(new SourceSpan(new SourceLocation(12, 1, 13), new SourceLocation(13, 1, 14)), TokenCategory.WhiteSpace, TokenTriggers.None), // - new TokenInfo(new SourceSpan(new SourceLocation(13, 1, 14), new SourceLocation(14, 1, 15)), TokenCategory.Grouping, TokenTriggers.MatchBraces), // { - new TokenInfo(new SourceSpan(new SourceLocation(14, 1, 15), new SourceLocation(15, 1, 16)), TokenCategory.WhiteSpace, TokenTriggers.None), // - new TokenInfo(new SourceSpan(new SourceLocation(15, 1, 16), new SourceLocation(16, 1, 17)), TokenCategory.Grouping, TokenTriggers.MatchBraces), // | - new TokenInfo(new SourceSpan(new SourceLocation(16, 1, 17), new SourceLocation(17, 1, 18)), TokenCategory.Identifier, TokenTriggers.None), // x - new TokenInfo(new SourceSpan(new SourceLocation(17, 1, 18), new SourceLocation(18, 1, 19)), TokenCategory.Grouping, TokenTriggers.MatchBraces), // | - new TokenInfo(new SourceSpan(new SourceLocation(18, 1, 19), new SourceLocation(19, 2, 1)), TokenCategory.WhiteSpace, TokenTriggers.None), // \n - // line 2 - new TokenInfo(new SourceSpan(new SourceLocation(19, 2, 1), new SourceLocation(23, 2, 5)), TokenCategory.Identifier, TokenTriggers.None), // puts - new TokenInfo(new SourceSpan(new SourceLocation(23, 2, 5), new SourceLocation(24, 2, 6)), TokenCategory.WhiteSpace, TokenTriggers.None), // - new TokenInfo(new SourceSpan(new SourceLocation(24, 2, 6), new SourceLocation(25, 2, 7)), TokenCategory.StringLiteral, TokenTriggers.None), // ' - new TokenInfo(new SourceSpan(new SourceLocation(25, 2, 7), new SourceLocation(31, 2, 13)), TokenCategory.StringLiteral, TokenTriggers.None), // string - new TokenInfo(new SourceSpan(new SourceLocation(31, 2, 13), new SourceLocation(32, 2, 14)), TokenCategory.StringLiteral, TokenTriggers.None), // ' - new TokenInfo(new SourceSpan(new SourceLocation(32, 2, 14), new SourceLocation(33, 3, 1)), TokenCategory.WhiteSpace, TokenTriggers.None), // \n (significant) - // line 3 - new TokenInfo(new SourceSpan(new SourceLocation(33, 3, 1), new SourceLocation(34, 3, 2)), TokenCategory.Grouping, TokenTriggers.MatchBraces) // } - ); - - // state transfer: strings // - - object state = null; - state = TestCategorizer(Engine, state, "\"a\n", - new TokenInfo(new SourceSpan(new SourceLocation(0, 1, 1), new SourceLocation(1, 1, 2)), TokenCategory.StringLiteral, TokenTriggers.None), // " - new TokenInfo(new SourceSpan(new SourceLocation(1, 1, 2), new SourceLocation(3, 2, 1)), TokenCategory.StringLiteral, TokenTriggers.None) // a\n - ); - - state = TestCategorizer(Engine, state, "b\n", - new TokenInfo(new SourceSpan(new SourceLocation(0, 1, 1), new SourceLocation(2, 2, 1)), TokenCategory.StringLiteral, TokenTriggers.None) // b\n - ); - - state = TestCategorizer(Engine, state, "\"", - new TokenInfo(new SourceSpan(new SourceLocation(0, 1, 1), new SourceLocation(1, 1, 2)), TokenCategory.StringLiteral, TokenTriggers.None) // "" - ); - - // state transfer: multi-line comments // - - state = null; - state = TestCategorizer(Engine, state, "=begin\n", - new TokenInfo(new SourceSpan(new SourceLocation(0, 1, 1), new SourceLocation(7, 2, 1)), TokenCategory.Comment, TokenTriggers.None) - ); - - for (int i = 0; i < 3; i++) { - state = TestCategorizer(Engine, state, "foo\n", - new TokenInfo(new SourceSpan(new SourceLocation(0, 1, 1), new SourceLocation(4, 2, 1)), TokenCategory.Comment, TokenTriggers.None) - ); - } - - state = TestCategorizer(Engine, state, "a\nb\n", - new TokenInfo(new SourceSpan(new SourceLocation(0, 1, 1), new SourceLocation(4, 3, 1)), TokenCategory.Comment, TokenTriggers.None) - ); - - state = TestCategorizer(Engine, state, "=end", - new TokenInfo(new SourceSpan(new SourceLocation(0, 1, 1), new SourceLocation(4, 1, 5)), TokenCategory.Comment, TokenTriggers.None) - ); - - Assert(((Tokenizer.State)state).CurrentSequence == TokenSequenceState.None); - - // state transfer: nested strings // - - state = null; - state = TestCategorizer(Engine, state, "\"a", - new TokenInfo(new SourceSpan(new SourceLocation(0, 1, 1), new SourceLocation(1, 1, 2)), TokenCategory.StringLiteral, TokenTriggers.None), - new TokenInfo(new SourceSpan(new SourceLocation(1, 1, 2), new SourceLocation(2, 1, 3)), TokenCategory.StringLiteral, TokenTriggers.None) - ); - - state = TestCategorizer(Engine, state, "#{", - new TokenInfo(new SourceSpan(new SourceLocation(0, 1, 1), new SourceLocation(2, 1, 3)), TokenCategory.Grouping, TokenTriggers.MatchBraces) - ); - - state = TestCategorizer(Engine, state, "1", - new TokenInfo(new SourceSpan(new SourceLocation(0, 1, 1), new SourceLocation(1, 1, 2)), TokenCategory.NumericLiteral, TokenTriggers.None) - ); - - state = TestCategorizer(Engine, state, "}", - new TokenInfo(new SourceSpan(new SourceLocation(0, 1, 1), new SourceLocation(1, 1, 2)), TokenCategory.Grouping, TokenTriggers.MatchBraces) - ); - - state = TestCategorizer(Engine, state, "\"", - new TokenInfo(new SourceSpan(new SourceLocation(0, 1, 1), new SourceLocation(1, 1, 2)), TokenCategory.StringLiteral, TokenTriggers.None) - ); - - Assert(((Tokenizer.State)state).CurrentSequence == TokenSequenceState.None); - } - - public void TokenizeIdentifiers1() { - string surrogate = "\ud800\udc00"; - - Assert(Tokenizer.IsConstantName("C")); - Assert(Tokenizer.IsConstantName("Cx")); - Assert(Tokenizer.IsConstantName("C9")); - Assert(Tokenizer.IsConstantName("CazAZ0123456789_")); - Assert(Tokenizer.IsConstantName("C_")); - Assert(!Tokenizer.IsConstantName(null)); - Assert(!Tokenizer.IsConstantName("")); - Assert(!Tokenizer.IsConstantName("C=")); - Assert(!Tokenizer.IsConstantName("C?")); - Assert(!Tokenizer.IsConstantName("C!")); - Assert(!Tokenizer.IsConstantName("_")); - Assert(!Tokenizer.IsConstantName("0")); - Assert(!Tokenizer.IsConstantName("c")); - Assert(Tokenizer.IsConstantName("Σ")); // an uppercase letter, so a constant (as in CRuby) - Assert(Tokenizer.IsConstantName("CΣ")); - - Assert(Tokenizer.IsMethodName("C")); - Assert(Tokenizer.IsMethodName("Cx")); - Assert(Tokenizer.IsMethodName("CazAZ0123456789_")); - Assert(Tokenizer.IsMethodName("f=")); - Assert(Tokenizer.IsMethodName("f?")); - Assert(Tokenizer.IsMethodName("f!")); - Assert(Tokenizer.IsMethodName("_")); - Assert(Tokenizer.IsMethodName("c")); - Assert(!Tokenizer.IsMethodName("=")); - Assert(!Tokenizer.IsMethodName("?")); - Assert(!Tokenizer.IsMethodName("!")); - Assert(!Tokenizer.IsMethodName(null)); - Assert(!Tokenizer.IsMethodName("")); - Assert(Tokenizer.IsMethodName("Σ")); - Assert(Tokenizer.IsMethodName(surrogate)); - - Assert(Tokenizer.IsGlobalVariableName("$x")); - Assert(Tokenizer.IsGlobalVariableName("$XazAZ0123456789_")); - Assert(!Tokenizer.IsGlobalVariableName("$f=")); - Assert(!Tokenizer.IsGlobalVariableName("$f?")); - Assert(!Tokenizer.IsGlobalVariableName("$f!")); - Assert(!Tokenizer.IsGlobalVariableName("$f$")); - Assert(!Tokenizer.IsGlobalVariableName(null)); - Assert(!Tokenizer.IsGlobalVariableName("$")); - Assert(!Tokenizer.IsGlobalVariableName("$$")); - Assert(!Tokenizer.IsGlobalVariableName("f")); - Assert(!Tokenizer.IsGlobalVariableName("ff")); - Assert(!Tokenizer.IsGlobalVariableName("fff")); - Assert(Tokenizer.IsGlobalVariableName("$Σ")); - Assert(Tokenizer.IsGlobalVariableName("$" + surrogate)); - - Assert(Tokenizer.IsInstanceVariableName("@x")); - Assert(Tokenizer.IsInstanceVariableName("@XazAZ0123456789_")); - Assert(!Tokenizer.IsInstanceVariableName("@f=")); - Assert(!Tokenizer.IsInstanceVariableName("@f?")); - Assert(!Tokenizer.IsInstanceVariableName("@f!")); - Assert(!Tokenizer.IsInstanceVariableName("@f@")); - Assert(!Tokenizer.IsInstanceVariableName(null)); - Assert(!Tokenizer.IsInstanceVariableName("@")); - Assert(!Tokenizer.IsInstanceVariableName("@@")); - Assert(!Tokenizer.IsInstanceVariableName("@@@")); - Assert(!Tokenizer.IsInstanceVariableName("f")); - Assert(!Tokenizer.IsInstanceVariableName("ff")); - Assert(!Tokenizer.IsInstanceVariableName("fff")); - Assert(Tokenizer.IsInstanceVariableName("@Σ")); - Assert(Tokenizer.IsInstanceVariableName("@" + surrogate)); - - Assert(Tokenizer.IsClassVariableName("@@x")); - Assert(Tokenizer.IsClassVariableName("@@XazAZ0123456789_")); - Assert(!Tokenizer.IsClassVariableName("@@f=")); - Assert(!Tokenizer.IsClassVariableName("@@f?")); - Assert(!Tokenizer.IsClassVariableName("@@f!")); - Assert(!Tokenizer.IsClassVariableName("@@f@")); - Assert(!Tokenizer.IsClassVariableName(null)); - Assert(!Tokenizer.IsClassVariableName("@")); - Assert(!Tokenizer.IsClassVariableName("@@")); - Assert(!Tokenizer.IsClassVariableName("@@@")); - Assert(!Tokenizer.IsClassVariableName("f")); - Assert(!Tokenizer.IsClassVariableName("ff")); - Assert(!Tokenizer.IsClassVariableName("fff")); - Assert(Tokenizer.IsClassVariableName("@@Σ")); - Assert(Tokenizer.IsClassVariableName("@@" + surrogate)); - } - - private void Identifiers2() { - AssertTokenizer t = NewAssertTokenizer(); - - // 'variable' non-terminal needs to set $$ even for keywords, - // otherwise the content of previous token is stored in token value and is interpreted as string. - t.Load("//\ntrue")[Tokens.RegexpBegin][Tokens.RegexpEnd][Tokens.NewLine][Tokens.True].EOF(); - - t.Load("Σ = CΣ", (tok) => tok.AllowNonAsciiIdentifiers = true). - ReadSymbol(Tokens.Identifier, "Σ")[Tokens.Assignment].ReadSymbol(Tokens.ConstantIdentifier, "CΣ").EOF(); - - t.Load("Σ = CΣ")[Tokens.InvalidCharacter].Expect(Errors.InvalidCharacterInExpression); - - t.Load("@Σ=@@Σ=$Σ", (tok) => tok.AllowNonAsciiIdentifiers = true) - [Tokens.InstanceVariable][Tokens.Assignment] - [Tokens.ClassVariable][Tokens.Assignment] - [Tokens.GlobalVariable].EOF(); - - t.Load("def Σ;end", (tok) => tok.AllowNonAsciiIdentifiers = true) - [Tokens.Def][Tokens.Identifier][Tokens.Semicolon][Tokens.End].EOF(); - -#if OBSOLETE // ??? - // we should report a warning if -KU is used and treat BOM as whitespace (MRI 1.8 treats the BOM as identifier): - t.Load(new byte[] { - 0xEF, 0xBB, 0xBF, (byte)'x' - }, (tok) => { - tok.Compatibility = RubyCompatibility.Ruby186; - tok.Encoding = RubyEncoding.KCodeUTF8; - tok.Verbatim = true; - }) - [Tokens.Whitespace][Tokens.Identifier].Expect(Errors.ByteOrderMarkIgnored); - - // we should report a warning if -KCODE is not used and treat BOM as whitespace (MRI 1.8 reports an error): - t.Load(new byte[] { - 0xEF, 0xBB, 0xBF, (byte)'=', (byte)'1' - }, (tok) => { - tok.Compatibility = RubyCompatibility.Ruby186; - tok.AllowNonAsciiIdentifiers = false; - tok.Verbatim = true; - }) - [Tokens.Whitespace][Tokens.Assignment][1].Expect(Errors.ByteOrderMarkIgnored); -#endif - t.Expect(); - } - - public void ParseBigInts1() { - TestBigInt("00010010000_00100000_01001000_00010000_00000010_01001000_11111111_00010000_00100000_00000011", 2); - TestBigInt("000100_afe1_1231_4980_6FEA_1470_5100_afe1_1231_4980_6FEA_1471", 16); - TestBigInt("65_6465477756_5454111111_1112365414_65_4365414564_5463215467_3215456713", 8); - TestBigInt("645456600_000798789_789798798_798789798_798765461_237676891_968734198_467346797", 10); - TestBigInt("hhs15489231dfu89765460z", 36); - TestBigInt("lafkhalkdhflkghalgAKD12", 28); - - for (int i = 3; i <= 36; i++) { - TestBigInt("00010010000_00100000_01001000_00010000_00000010_01001000_11111111_00010000_00100000_00000011", i, 0); - } - } - - public void ParseIntegers1() { - IntegerValue x; - Assert((x = Tokenizer.ParseInteger("", 0)).Equals(0)); - Assert((x = Tokenizer.ParseInteger("", 16)).Equals(0)); - Assert((x = Tokenizer.ParseInteger(" ", 0)).Equals(0)); - Assert((x = Tokenizer.ParseInteger("-", 0)).Equals(0)); - Assert((x = Tokenizer.ParseInteger("+", 0)).Equals(0)); - Assert((x = Tokenizer.ParseInteger("0", 0)).Equals(0)); - Assert((x = Tokenizer.ParseInteger("00", 0)).Equals(0)); - Assert((x = Tokenizer.ParseInteger("0x", 0)).Equals(0)); - Assert((x = Tokenizer.ParseInteger("0x", 0)).Equals(0)); - Assert((x = Tokenizer.ParseInteger("-0x", 0)).Equals(0)); - Assert((x = Tokenizer.ParseInteger("+0x", 0)).Equals(0)); - Assert((x = Tokenizer.ParseInteger(" 1234 ", 0)).Equals(1234)); - Assert((x = Tokenizer.ParseInteger(" 1_2_3_4 ", 0)).Equals(1234)); - Assert((x = Tokenizer.ParseInteger(" _1234 ", 0)).Equals(0)); - Assert((x = Tokenizer.ParseInteger(" 12a34 ", 0)).Equals(12)); - Assert((x = Tokenizer.ParseInteger(" 1_2__34 ", 0)).Equals(12)); - Assert((x = Tokenizer.ParseInteger(" -1_2", 0)).Equals(-12)); - Assert((x = Tokenizer.ParseInteger("0x1234", 0)).Equals(0x1234)); - Assert((x = Tokenizer.ParseInteger("0x1234", 10)).Equals(0)); - Assert((x = Tokenizer.ParseInteger("0b102", 0)).Equals(2)); - Assert((x = Tokenizer.ParseInteger("1000_000000_0000000000", 0)).Bignum.ToString() == "10000000000000000000"); - Assert((x = Tokenizer.ParseInteger("1000000_000000_0000000", 16)).Bignum.ToString() == "75557863725914323419136"); - Assert((x = Tokenizer.ParseInteger("0x1000000_000000_0000000", 0)).Bignum.ToString() == "75557863725914323419136"); - Assert((x = Tokenizer.ParseInteger("0b1000000_000000_0000000", 0)).Equals(524288)); - Assert((x = Tokenizer.ParseInteger("-0b1000000_000000_0000000", 0)).Equals(-524288)); - } - - private void TokenizeNumbers1() { - AssertTokenizer t = NewAssertTokenizer(); - - t.Load("0").Read(0); - t.Load("0000").Read(0); - t.Load("0_0_00000_0_0_00000000000000000000_00_00000000000000000000000000000").Read(0); - - t.Load("0777").Read(Convert.ToInt32("777", 8)); - t.Load("000000000000000000000000000000000000076541").Read(Convert.ToInt32("76541", 8)); - AssertTokenBigInteger("0100000000000000_000000000000000000000076541", 8); - - t.Load("0x0").Read(0); - t.Load("0xa_F").Read(Convert.ToInt32("af", 16)); - t.Load("0x000000_0000000000000000000aF").Read(Convert.ToInt32("af", 16)); - t.Load("0x10000000000_00000000000000aF").ReadBigInteger("1000000000000000000000000aF", 16); - - t.Load("0b0").Read(0); - t.Load("0b000000000000_000000000000000000000000000101").Read(Convert.ToInt32("101", 2)); - t.Load("0b10000000_0000000000000000000000000000000101").ReadBigInteger("100000000000000000000000000000000000000101", 2); - - t.Load("0d0").Read(0); - t.Load("0d00000000_0000000000000000000000000000000101").Read(101); - t.Load("0d10000000_0000000000000000000000_000000000101").ReadBigInteger("100000000000000000000000000000000000000101", 10); - - t.Load("0o0").Read(0); - t.Load("0o000_000000000000000000000000000000000076541").Read(Convert.ToInt32("76541", 8)); - t.Load("0o100000000_000000000000000000000000000076541").ReadBigInteger("100000000000000000000000000000000000076541", 8); - t.Load("0.0").Read(0.0D); - - t.Load("0e-000").Read(0.0D); - t.Load("0e2").Read(0.0D); - t.Load("0e+2").Read(0.0D); - t.Load("1e2").Read(100.0D); - t.Load("1e+2").Read(100.0D); - t.Load("1e-2").Read(0.01D); - - t.Load("3_1_3_2_1_3_2_1_3_5_4_6_5_3_1_3_2.0").Read(31321321354653132.0D); - t.Load("1_3_2.3_1_3_2_1_3").Read(132.313213D); - - t.Load("1.1e-0").Read(1.1D); - t.Load("1.1e+0").Read(1.1D); - t.Load("1.1e0").Read(1.1D); - t.Load("1.1e-1").Read(0.11D); - - t.Load("1.1e-1020").Read(0.0D); - t.Load("1.1e-1021").Read(0.0D).Expect(Errors.FloatOutOfRange); - - t.Load("1.1e1024").Read(Double.PositiveInfinity); - t.Load("1.1e1025").Read(Double.PositiveInfinity).Expect(Errors.FloatOutOfRange); - - t.Load("1.1e-30000").Read(0.0D).Expect(Errors.FloatOutOfRange); - t.Load("1.1e3_1_3_2_1_3_2_1_3_5_4_6_5_3_1_3_2").Read(Double.PositiveInfinity).Expect(Errors.FloatOutOfRange); - t.Load("4.94065645841247e-324").Read(Double.Epsilon); - t.Load("1_2.4_5e2_2").Read(12.45e22); - t.Load("1._1").Read(1); - t.Load("1.").Read(1); - - t.Load("122312. 1212").Read(122312); - t.Load("01234e12").Read(Convert.ToInt32("1234", 8)); - t.Load("12__1212").Read(12).Expect(Errors.TrailingUnderscoreInNumber); - t.Load("123_.123").Read(123).Expect(Errors.TrailingUnderscoreInNumber); - t.Load("08").Read(8).Expect(Errors.IllegalOctalDigit); - t.Load("0_8").Read(0).Expect(Errors.TrailingUnderscoreInNumber); - t.Load("0_x").Read(0).Expect(Errors.TrailingUnderscoreInNumber); - t.Load("0_").Read(0).Expect(Errors.TrailingUnderscoreInNumber); - t.Load("0x_").Read(0).Expect(Errors.NumericLiteralWithoutDigits); - t.Load("0x").Read(0).Expect(Errors.NumericLiteralWithoutDigits); - t.Load("0x_1").Read(0).Expect(Errors.NumericLiteralWithoutDigits); - - t.Load(".20").Read(Tokens.Dot).Expect(Errors.NoFloatingLiteral); - t.Load("1.e").Read(1); - t.Load("1.2e").Read(1.2D).Expect(Errors.TrailingEInNumber); - t.Load("1e").Read(1).Expect(Errors.TrailingEInNumber); - t.Load("1e-").Read(1).Expect(Errors.TrailingMinusInNumber); - t.Load("1e+").Read(1).Expect(Errors.TrailingPlusInNumber); - - t.Load("00.0").Read(0).Expect(Errors.NoFloatingLiteral); - t.Load("00.foo").Read(0); - t.Load("00.e-1").Read(0); - t.Load("00.foo").Read(0); - t.Load("0x.0").Read(0).Expect(Errors.NumericLiteralWithoutDigits, Errors.NoFloatingLiteral); - t.Load("0x.foo").Read(0).Expect(Errors.NumericLiteralWithoutDigits); - - t.Expect(); - } - - private void TokenizeInstanceClassVariables1() { - AssertTokenizer t = NewAssertTokenizer(); - - t.Load("@").Read(Tokens.At); - t.Load("@@").Read(Tokens.At); - t.Load("@1").Read(Tokens.At).Expect(Errors.InvalidInstanceVariableName); - t.Load("@@1").Read(Tokens.At).Expect(Errors.InvalidClassVariableName); - t.Load("@_").ReadSymbol(Tokens.InstanceVariable, "@_"); - t.Load("@@_").ReadSymbol(Tokens.ClassVariable, "@@_"); - t.Load("@aA1_").ReadSymbol(Tokens.InstanceVariable, "@aA1_"); - t.Load("@@aA1_").ReadSymbol(Tokens.ClassVariable, "@@aA1_"); - - t.Expect(); - } - - private void TokenizeGlobalVariables1() { - AssertTokenizer t = NewAssertTokenizer(); - - t.Load("$")[Tokens.Dollar].EOF(); - t.Load("$_")[Tokens.GlobalVariable, "_"].EOF(); - t.Load("$_1")[Tokens.GlobalVariable, "_1"].EOF(); - t.Load("$_-1")[Tokens.GlobalVariable, "_"][Tokens.Minus][1].EOF(); - t.Load("$!")[Tokens.GlobalVariable, "!"].EOF(); - t.Load("$@")[Tokens.GlobalVariable, "@"].EOF(); - t.Load("$-")[Tokens.GlobalVariable, "-"].EOF(); - t.Load("$--1")[Tokens.GlobalVariable, "-"][Tokens.Minus][1].EOF(); - t.Load("$-x")[Tokens.GlobalVariable, "-x"].EOF(); - - t.Expect(); - } - - private void TokenizeEolns1() { - AssertTokenizer t = NewAssertTokenizer(); - - // empty source: - t.Load("").EOF(); - - // escaped eoln: - t.Load("[\\\r\n]")[Tokens.LeftBracket][Tokens.RightBracket].EOF(); - t.Load("[\\\n]")[Tokens.LeftBracket][Tokens.RightBracket].EOF(); - t.Load("[\\\r]")[Tokens.LeftBracket][Tokens.Backslash][Tokens.RightBracket].EOF(); - - // 1.9 dot: - t.Load("foo\n\t .bar")[Tokens.Identifier][Tokens.Dot][Tokens.Identifier].EOF(); - t.Load("foo\n\t ..bar")[Tokens.Identifier][Tokens.NewLine][Tokens.DoubleDot][Tokens.Identifier].EOF(); - t.Load("foo\n\t \nbar")[Tokens.Identifier][Tokens.NewLine][Tokens.Identifier].EOF(); - - // eoln used to quote a string: - t.Load("x = %\r\nhello\r\n")[Tokens.Identifier][Tokens.Assignment][Tokens.StringBegin][Tokens.StringContent, "hello"][Tokens.StringEnd].EOF(); - t.Load("x = %\nhello\r\n")[Tokens.Identifier][Tokens.Assignment][Tokens.StringBegin][Tokens.StringContent, "hello"][Tokens.StringEnd].EOF(); - t.Load("x = %\rhello\r\n\r")[Tokens.Identifier][Tokens.Assignment][Tokens.StringBegin][Tokens.StringContent, "hello\n"][Tokens.StringEnd].EOF(); - - t.Load("%Q\r\nhello\n")[Tokens.StringBegin][Tokens.StringContent, "hello"][Tokens.StringEnd].EOF(); - t.Load("%Q\nhello\n")[Tokens.StringBegin][Tokens.StringContent, "hello"][Tokens.StringEnd].EOF(); - t.Load("%Q\rhello\r\n\r")[Tokens.StringBegin][Tokens.StringContent, "hello\n"][Tokens.StringEnd].EOF(); - - t.Load("%w[ ]")[Tokens.VerbatimWordsBegin][Tokens.StringEnd].EOF(); - t.Load("%w[ foo]")[Tokens.VerbatimWordsBegin][Tokens.StringContent, "foo"][Tokens.StringEnd].EOF(); - t.Load("%w[\n foo]")[Tokens.VerbatimWordsBegin][Tokens.StringContent, "foo"][Tokens.StringEnd].EOF(); - t.Load("%w(\rx\n \r\n \nz\n)")[Tokens.VerbatimWordsBegin][Tokens.StringContent, "x"][Tokens.WordSeparator][Tokens.StringContent, "z"][Tokens.StringEnd].EOF(); - - t.Load("%1")[Tokens.Percent].Expect(Errors.UnknownQuotedStringType)[1].EOF(); - - // heredoc: - t.Load("p <""c""}}""=>""#{2}""}=>""#{3}""}}a""") - [Tokens.StringBegin] - [Tokens.StringContent] - [Tokens.StringEmbeddedCodeBegin] - [Tokens.LeftBrace] - [Tokens.LeftBrace] - [Tokens.StringBegin] - [Tokens.StringEmbeddedCodeBegin] - [Tokens.LeftBrace] - [Tokens.StringBegin] - [Tokens.StringEmbeddedCodeBegin] - [1] - [Tokens.StringEmbeddedCodeEnd] - [Tokens.StringEnd] - [Tokens.DoubleArrow] - [Tokens.StringBegin] - [Tokens.StringContent] - [Tokens.StringEnd] - [Tokens.RightBrace] - [Tokens.StringEmbeddedCodeEnd] - [Tokens.StringEnd] - [Tokens.DoubleArrow] - [Tokens.StringBegin] - [Tokens.StringEmbeddedCodeBegin] - [2] - [Tokens.StringEmbeddedCodeEnd] - [Tokens.StringEnd] - [Tokens.RightBrace] - [Tokens.DoubleArrow] - [Tokens.StringBegin] - [Tokens.StringEmbeddedCodeBegin] - [3] - [Tokens.StringEmbeddedCodeEnd] - [Tokens.StringEnd] - [Tokens.RightBrace] - [Tokens.StringEmbeddedCodeEnd] - [Tokens.StringContent] - [Tokens.StringEnd]. - EOF(); - - // =begin .. =end nested in a string: - t.Load("\"hello#{\n=begin\nxxx\n=end\nidf\n}world\"") - [Tokens.StringBegin] - [Tokens.StringContent] - [Tokens.StringEmbeddedCodeBegin] - [Tokens.EndOfLine] - [Tokens.MultiLineComment] - [Tokens.Identifier, "idf"] - [Tokens.NewLine] - [Tokens.StringEmbeddedCodeEnd] - [Tokens.StringContent] - [Tokens.StringEnd]. - EOF(); - - // braces nesting in word array: - t.Load("%w{#$a #{b + 1} c}") - [Tokens.VerbatimWordsBegin] - [Tokens.StringContent, "#$a"][Tokens.WordSeparator] - [Tokens.StringContent, "#{b"][Tokens.WordSeparator] - [Tokens.StringContent, "+"][Tokens.WordSeparator] - [Tokens.StringContent, "1}"][Tokens.WordSeparator] - [Tokens.StringContent, "c"] - [Tokens.StringEnd]. - EOF(); - } - - private void TokenizeEscapes2() { - AssertTokenizer t = NewAssertTokenizer(); - - // hexa: - t.Load("\"\\x\n20\"")[Tokens.StringBegin]["?\n20"][Tokens.StringEnd].Expect(Errors.InvalidEscapeCharacter); - t.Load("\"\\x2\n0\"")[Tokens.StringBegin]["\u0002\n0"][Tokens.StringEnd].EOF(); - t.Load("\"\\x20\n\"")[Tokens.StringBegin][" \n"][Tokens.StringEnd].EOF(); - - // octal: - t.Load("\"\\0\n40\"")[Tokens.StringBegin]["\0\n40"][Tokens.StringEnd].EOF(); - t.Load("\"\\04\n0\"")[Tokens.StringBegin]["\u0004\n0"][Tokens.StringEnd].EOF(); - t.Load("\"\\040\n\"")[Tokens.StringBegin][" \n"][Tokens.StringEnd].EOF(); - t.Load("\"\\123\"")[Tokens.StringBegin]["S"][Tokens.StringEnd].EOF(); - - // multi-byte characters: - t.Load(@"""abΣ\xce\xa3cd\xce\xa3e""")[Tokens.StringBegin]["abΣΣcdΣe", Encoding.UTF8][Tokens.StringEnd].EOF(); - - // an incomplete character: - t.Load(@"""ab\xce""")[Tokens.StringBegin][new byte[] { (byte)'a', (byte)'b', 0xce }][Tokens.StringEnd].EOF(); - - t.Expect(); - } - - private void UnicodeEscapes1() { - AssertTokenizer t = NewAssertTokenizer(); - - int[] values = new[] { 0x20, 0x102020, 0x20, 0x20, 0 }; - int[] width = new[] { 2, 6, 6, 5, 1 }; - - t.Load(@":""\u111""")[Tokens.SymbolBegin][Tokens.StringContent].Expect(Errors.InvalidEscapeCharacter); - t.Load(@":""\u""")[Tokens.SymbolBegin][Tokens.StringContent].Expect(Errors.InvalidEscapeCharacter); - - // regex: - t.Load(@"/\x20/")[Tokens.RegexpBegin][@"\x20"][Tokens.RegexpEnd].EOF(); - t.Load(@"/\u1234/")[Tokens.RegexpBegin][@"\u1234"][Tokens.RegexpEnd].EOF(); - t.Load(@"/\u{101234}/")[Tokens.RegexpBegin][@"\u{101234}"][Tokens.RegexpEnd].EOF(); - - // braces: - t.Load(@":""\u{123456}""")[Tokens.SymbolBegin][Tokens.StringContent].Expect(Errors.TooLargeUnicodeCodePoint); - t.Load(@"%[{\u{05d0}}]")[Tokens.StringBegin]["{\u05d0}"][Tokens.StringEnd].EOF(); - t.Load(@"%[\u{1 2 3 4}]")[Tokens.StringBegin]["\u0001\u0002\u0003\u0004"][Tokens.StringEnd].EOF(); - t.Load(@"%[\u{}]")[Tokens.StringBegin][""][Tokens.StringEnd].Expect(Errors.InvalidUnicodeEscape); - t.Load(@"%[\u{1 }]")[Tokens.StringBegin]["\u0001"][Tokens.StringEnd].Expect(Errors.InvalidUnicodeEscape); - t.Load(@"%[\u{1 }]")[Tokens.StringBegin]["\u0001"][Tokens.StringEnd].Expect(Errors.InvalidUnicodeEscape); - t.Load(@"%[\u{FFFFFF FFFFFFFFFFFFFFFF 3 4}]")[Tokens.StringBegin]["??\u0003\u0004"][Tokens.StringEnd].Expect(Errors.TooLargeUnicodeCodePoint, Errors.TooLargeUnicodeCodePoint); - t.Load(@"%[\u{]")[Tokens.StringBegin][""][Tokens.StringEnd].Expect(Errors.UntermintedUnicodeEscape); - t.Load(@"%[\u{1]")[Tokens.StringBegin]["\u0001"][Tokens.StringEnd].Expect(Errors.UntermintedUnicodeEscape); - t.Load(@"%[\u{")[Tokens.StringBegin][""][Tokens.StringEnd].Expect(Errors.UntermintedUnicodeEscape, Errors.UnterminatedString); - - for (int i = 0; i < values.Length; i++) { - t.Load(@"""\u{" + i.ToString("x" + width[i]) + @"}""")[Tokens.StringBegin][Char.ConvertFromUtf32(i)][Tokens.StringEnd].EOF(); - } - - // eoln in the middle of \u escape: - t.Load("\"\\u0020\n\"")[Tokens.StringBegin][" \n"][Tokens.StringEnd].EOF(); - t.Load("\"\\u002\n0\"")[Tokens.StringBegin]["?002\n0"][Tokens.StringEnd].Expect(Errors.InvalidEscapeCharacter).EOF(); - t.Load("\"\\u00\n20\"")[Tokens.StringBegin]["?00\n20"][Tokens.StringEnd].Expect(Errors.InvalidEscapeCharacter).EOF(); - t.Load("\"\\u0\n020\"")[Tokens.StringBegin]["?0\n020"][Tokens.StringEnd].Expect(Errors.InvalidEscapeCharacter).EOF(); - t.Load("\"\\u\n0020\"")[Tokens.StringBegin]["?\n0020"][Tokens.StringEnd].Expect(Errors.InvalidEscapeCharacter).EOF(); - - // TODO: -#if TODO - t.DefaultEncoding = RubyEncoding.Binary; - t.Load(@"""\u{5d0}""")[Tokens.StringBegin][@"\u{5d0}"][Tokens.StringEnd].Expect(Errors.EncodingsMixed).EOF(); -#endif - t.Expect(); - } - - private void CharacterToken1() { - AssertTokenizer t = NewAssertTokenizer(); - t.Load("?a")[Tokens.Character, "a"].EOF(); - t.Load("?Σ")[Tokens.Character, "Σ"].EOF(); - - // surrogate: - string u12345 = Char.ConvertFromUtf32(0x12345); - t.Load("?" + u12345)[Tokens.Character, u12345].EOF(); - - // escapes: - t.Load(@"?\u{1}")[Tokens.Character, "\u0001"].EOF(); - t.Load(@"?\u{}")[Tokens.Character, "\0"].Expect(Errors.InvalidUnicodeEscape); - t.Load(@"?\u{")[Tokens.Character, "\0"].Expect(Errors.UntermintedUnicodeEscape); - t.Load(@"?\u{1")[Tokens.Character, "\u0001"].Expect(Errors.UntermintedUnicodeEscape); - t.Load(@"?\u{1 2}")[Tokens.Character, "\u0001"].Expect(Errors.UntermintedUnicodeEscape); - t.Load(@"?\u{1123455}")[Tokens.Character, "?"].Expect(Errors.TooLargeUnicodeCodePoint); - } - - private void LexicalState1() { - AssertTokenizer t = NewAssertTokenizer(); - - // command mode: - t.Load("a")[Tokens.Identifier, "a"].State(LexicalState.EXPR_CMDARG).EOF(); - t.Load("1;a")[1][Tokens.Semicolon][Tokens.Identifier, "a"].State(LexicalState.EXPR_CMDARG).EOF(); - - // 1.8 specific - //t.Load("a(b c)"); - //t[Tokens.Identifier, "a"].State(LexicalState.EXPR_CMDARG); - //t[Tokens.LeftParenthesis].State(LexicalState.EXPR_BEG); // switches to command mode for the next non-whitespace token - //t[Tokens.Identifier, "b"].State(LexicalState.EXPR_CMDARG); - //t[Tokens.Identifier, "c"].State(LexicalState.EXPR_ARG); // command mode switched off - //t[Tokens.RightParenthesis].State(LexicalState.EXPR_END).EOF(); - - t.Load("a\nb"); - t[Tokens.Identifier, "a"].State(LexicalState.EXPR_CMDARG); - t[Tokens.NewLine].State(LexicalState.EXPR_BEG); // switches to command mode for the next non-whitespace token - t[Tokens.Identifier, "b"].State(LexicalState.EXPR_CMDARG).EOF(); - - t.Load("foo do a end"); - t[Tokens.Identifier, "foo"].State(LexicalState.EXPR_CMDARG); - t[Tokens.Do].State(LexicalState.EXPR_BEG); // switches to command mode for the next non-whitespace token - t[Tokens.Identifier, "a"].State(LexicalState.EXPR_CMDARG); - t[Tokens.End].State(LexicalState.EXPR_END); - t.EOF(); - } - - private void Heredoc1() { - AssertTokenizer t = new AssertTokenizer(this) { Verbatim = false }; - - t.Load("< - new TokenInfo(new SourceSpan(new SourceLocation(13, 2, 4), new SourceLocation(13, 2, 4)), TokenCategory.StringLiteral, TokenTriggers.None) - ); - - // index: 1 1111 11111 - // 01234567890 1234 56789 - TestCategorizer(Engine, null, "puts <<-L1\naaa\n L1", - // column: 12345678901 1234 12345 - // line: 11111111111 2222 33333 - // - // puts - new TokenInfo(new SourceSpan(new SourceLocation(0, 1, 1), new SourceLocation(4, 1, 5)), TokenCategory.Identifier, TokenTriggers.None), - // ' ' - new TokenInfo(new SourceSpan(new SourceLocation(4, 1, 5), new SourceLocation(5, 1, 6)), TokenCategory.WhiteSpace, TokenTriggers.None), - // <<-L1 - new TokenInfo(new SourceSpan(new SourceLocation(5, 1, 6), new SourceLocation(10, 1, 11)), TokenCategory.StringLiteral, TokenTriggers.None), - // \n - new TokenInfo(new SourceSpan(new SourceLocation(10, 1, 11), new SourceLocation(11, 2, 1)), TokenCategory.WhiteSpace, TokenTriggers.None), - // aaa\n - new TokenInfo(new SourceSpan(new SourceLocation(11, 2, 1), new SourceLocation(15, 3, 1)), TokenCategory.StringLiteral, TokenTriggers.None), - // L1 - new TokenInfo(new SourceSpan(new SourceLocation(17, 3, 3), new SourceLocation(19, 3, 5)), TokenCategory.StringLiteral, TokenTriggers.None) - ); - } - - public void ParseSymbols1() { - AssertTokens(":''", Tokens.SymbolBegin, Tokens.StringEnd, Tokens.EndOfFile); - AssertTokens(":do", Tokens.SymbolBegin, Tokens.Do, Tokens.EndOfFile); - AssertTokens("foo :do", Tokens.Identifier, Tokens.SymbolBegin, Tokens.BlockDo, Tokens.EndOfFile); - } - - private void AssertTokens(string/*!*/ source, params Tokens[] expected) { - var tokens = new List(); - var parser = new Parser() { - TokenSink = (token, span) => tokens.Add(token) - }; - - parser.Parse(Context.CreateSnippet(source, SourceCodeKind.AutoDetect), new RubyCompilerOptions(), ErrorSink.Null); - Assert(tokens.ToArray().ValueEquals(expected)); - } - - // encodings suported in preamble: - private static readonly string[] preambleEncodingNames = - new[] { "ASCII-8BIT", "ASCII", "BINARY", "US-ASCII", "UTF-8", "EUC-JP", "SJIS", "SHIFT_JIS", "LOCALE", "FILESYSTEM" }; - - private void Encoding1() { - foreach (var name in preambleEncodingNames) { - var encoding = Context.GetEncodingByRubyName(name); - Assert(encoding != null); - - // the encoding must be an identity on ASCII characters: - Assert(RubyEncoding.AsciiIdentity(encoding)); - } - - foreach (var info in Encoding.GetEncodings()) { - var encoding = info.GetEncoding(); - - // doesn't blow up (the method checks itself): - RubyEncoding.AsciiIdentity(encoding); - - //Console.WriteLine("case " + info.CodePage + ": // " + encoding.EncodingName); - } - - } - - private void Encoding2() { - var source1 = Context.CreateSourceUnit(new BinaryContentProvider(BinaryEncoding.Instance.GetBytes( -@"#! foo bar -# enCoding = ascii-8BIT - -p __ENCODING__ -")), null, Encoding.UTF8, SourceCodeKind.File); - - using (var reader = source1.GetReader()) { - Assert(reader.Encoding == BinaryEncoding.Instance); - } - - // The test used to expect "#", which no Ruby since 3.4 prints. - // Ruby 3.4 renamed the encoding to BINARY and made #inspect - and only #inspect, - // #name still answers "ASCII-8BIT" - show both spellings: - // - // $ ruby -v - // ruby 4.0.6 (2026-07-14 revision 03b6d3f889) +PRISM [x86_64-linux] - // $ printf '#!/usr/bin/env ruby\n# enCoding = ascii-8BIT\n\np __ENCODING__\n' > /tmp/e.rb - // $ ruby /tmp/e.rb - // # - // - // ruby/spec asserts the same thing - spec/core/encoding/inspect_spec.rb, under - // ruby_version_is "3.4", special-cases ASCII-8BIT to "#". - AssertOutput(() => source1.Execute(), @"#"); - - // default hosted encoding is UTF8: - var source2 = Context.CreateSnippet("p __ENCODING__", SourceCodeKind.Expression); - AssertOutput(() => source2.Execute(), @"#"); - } - - private void Encoding4() { - var enc = Engine.Execute(@"eval('# encoding: SJIS -__ENCODING__ -')"); - Assert(enc == RubyEncoding.SJIS); - } - - private void Encoding_Host1() { - Encoding_HostHelper(Encoding.UTF8, "\u0394", true); - Encoding_HostHelper(Encoding.UTF32, "\u0394", false); - } - - private void Encoding_HostHelper(Encoding/*!*/ encoding, string/*!*/ specialChars, bool shouldSucceed) { - var preamble = "# coding = " + encoding.WebName + "\r\n"; - var src = "$X = '" + specialChars + "'"; - - var content = new List(); - content.AddRange(BinaryEncoding.Instance.GetBytes(preamble)); - content.AddRange(encoding.GetBytes(src)); - - var source = Engine.CreateScriptSource(new BinaryContentProvider(content.ToArray()), null); - - // test encoding: - try { - var detectedEncoding = source.DetectEncoding(); - Assert(encoding.WebName == detectedEncoding.WebName); - } catch (IOException) { - Assert(!shouldSucceed); - } - - // test content: - try { - var code = source.GetCode(); - Assert(StringComparer.Ordinal.Equals(code, preamble + src)); - } catch (IOException) { - Assert(!shouldSucceed); - } - } - - // Ruby preamble overrides the encoding's preamble (BOM) - public void Encoding_Host2() { - var src = "# encoding: ASCII-8BIT\r\n$X = '\u0394'"; - var binsrc = Encoding.UTF8.GetBytes(src); - - var content = new List(); - content.AddRange(Encoding.UTF8.GetPreamble()); - content.AddRange(binsrc); - var source = Engine.CreateScriptSource(new BinaryContentProvider(content.ToArray()), null); - var encoding = source.DetectEncoding(); - Assert(encoding == BinaryEncoding.Instance); - var actualCode = source.GetCode(); - - // \u0394 is encoded in 2 bytes, which are represented by 2 characters in binary encoding: - Assert(actualCode.Length == src.Length + 1); - Assert(actualCode.Length == binsrc.Length); - } - - public void NamesEncoding1() { - // TODO: - XTestOutput(@"#encoding: SJIS -class Cホ - def initialize - @ホ = 1 - @@ホ = 2 - end - - def ホ - end - - Xホ = 5 -end - -$Xホ = 3 -ホ = 4 - -puts Cホ.name -puts Cホ.name.encoding -puts Cホ.new.inspect - -Cホ.instance_methods(false).each { |x| puts x,x.encoding } -Cホ.new.instance_variables.each { |x| puts x,x.encoding } -Cホ.class_variables.each { |x| puts x,x.encoding } -Cホ.constants.each { |x| puts x,x.encoding } -local_variables.each { |x| puts x,x.encoding } -global_variables.each { |x| puts x,x.encoding if x[0] == 'X' } -", @" -Cホ -# -# -ホ -# -@ホ -# -@@ホ -# -Xホ -# -ホ -# -$ホ -# -"); - } - - // TODO: - public void BlockParameterSyntax1() { - // "yield(&p)" -> block argument should not be given - // "yield &p" -> block argument should not be given - // "yield 1=>2, &p" -> block argument should not be given - } - - private void AstLocations1() { -#if FEATURE_CALL_SITE_TRACER - // DumpExpression uses private reflection: - if (_driver.PartialTrust) return; - - var sourceUnit = Context.CreateSnippet(@" -def add a,b - a + b -end - -add 1, 1 -add 'foo', 'bar' -", SourceCodeKind.Expression); - - var options = new RubyCompilerOptions(); - var parser = new Parser(); - var tokens = new List>(); - - parser.TokenSink = (token, span) => { tokens.Add(new KeyValuePair(span, token)); }; - var ast = parser.Parse(sourceUnit, options, Context.RuntimeErrorSink); - - const int Id = 0x12345678; - - var lambda = CallSiteTracer.Transform>(ast, sourceUnit, options, Id); - var code = new RubyScriptCode(lambda, sourceUnit, TopScopeFactoryKind.Hosted); - - var locations = new List(); - CallSiteTracer.Register((context, args, result, id, location) => { - locations.Add(location); - Debug.Assert(id == Id); - Debug.Assert(location > 0); - - //Console.WriteLine("-- {0} ---------", location); - //Console.WriteLine(this); - //Console.WriteLine(AstUtils.DumpExpression(result.Restrictions.ToExpression())); - //Console.WriteLine(); - //Console.WriteLine(AstUtils.DumpExpression(result.Expression)); - //Console.WriteLine("----------------"); - }); - - code.Run(); - - // TODO: doesn't include method body since its is lazily compiled: - Debug.Assert(locations.Count == 2 && locations[0] == 31 && locations[1] == 41); - // Debug.Assert(locations.Count == 4 && locations[0] == 31 && locations[1] == 19 && locations[2] == 41 && locations[3] == 19); -#endif - } - - #region Helpers - - private void TestBigInt(string/*!*/ number, int @base) { - TestBigInt(number, @base, 10); - } - - private void TestBigInt(string/*!*/ number, int @base, int repeat) { - Stopwatch optimizedTime = new Stopwatch(); - Stopwatch universalTime = new Stopwatch(); - - StringBuilder n = new StringBuilder(number); - for (int j = 0; j < repeat; j++) { - n.Append(number); - } - number = n.ToString(); - - for (int i = 0; i < number.Length - 1; i++) { - string sub = number.Substring(i); - string s = sub.Replace("_", "").ToUpper(); - BigInteger b; - Tokenizer.BignumParser p = new Tokenizer.BignumParser(); - p.Position = 0; - p.Buffer = s.ToCharArray(); - - optimizedTime.Start(); - b = p.Parse(s.Length, @base); - optimizedTime.Stop(); - - Assert(b.ToString(@base) == s.TrimStart('0')); - - p.Position = 0; - - universalTime.Start(); - b = p.ParseDefault(s.Length, (uint)@base); - universalTime.Stop(); - - Assert(b.ToString(@base) == s.TrimStart('0')); - } - - if (repeat != 0) { - Console.WriteLine("{0}: optimized = {1}ms, universal = {2}ms", - @base, - optimizedTime.ElapsedMilliseconds, - universalTime.ElapsedMilliseconds); - } - } - - private AssertTokenizer/*!*/ AssertTokenBigInteger(string/*!*/ source, int @base) { - return new AssertTokenizer(this).Load(source).ReadBigInteger(source.Replace("_", "").TrimStart('0'), @base); - } - - private AssertTokenizer/*!*/ NewAssertTokenizer() { - return new AssertTokenizer(this); - } - - #endregion - } -} \ No newline at end of file diff --git a/Src/IronRuby.Tests/Parser/Sources.txt b/Src/IronRuby.Tests/Parser/Sources.txt deleted file mode 100644 index ecd9e2f35..000000000 --- a/Src/IronRuby.Tests/Parser/Sources.txt +++ /dev/null @@ -1 +0,0 @@ -%DLR_ROOT%\Languages\Ruby diff --git a/Src/IronRuby.Tests/Parser/TokenizerTestDriver.cs b/Src/IronRuby.Tests/Parser/TokenizerTestDriver.cs deleted file mode 100644 index e745d2cca..000000000 --- a/Src/IronRuby.Tests/Parser/TokenizerTestDriver.cs +++ /dev/null @@ -1,442 +0,0 @@ -/* **************************************************************************** - * - * Copyright (c) Microsoft Corporation. - * - * This source code is subject to terms and conditions of the Apache License, Version 2.0. A - * copy of the license can be found in the License.html file at the root of this distribution. If - * you cannot locate the Apache License, Version 2.0, please send an email to - * ironruby@microsoft.com. By using this source code in any fashion, you are agreeing to be bound - * by the terms of the Apache License, Version 2.0. - * - * You must not remove this notice, or any other, from this software. - * - * - * ***************************************************************************/ - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Dynamic; -using System.Text; -using Microsoft.Scripting; -using Microsoft.Scripting.Runtime; -using IronRuby.Builtins; -using IronRuby.Compiler; -using IronRuby.Compiler.Ast; -using IronRuby.Runtime; -using Microsoft.Scripting.Utils; - -namespace IronRuby.Tests { - public class TokenizerTestDriver { - private readonly RubyContext/*!*/ _context; - private string _targetDir; - private string _sources; - private TextWriter _log; - private TextWriter _exceptions; - private TextWriter _regexLog; - private TextWriter _parserLog; - private string _currentSourceFile; - private bool _logProductions; - private bool _benchmark; - - public TokenizerTestDriver(RubyContext/*!*/ context) { - _context = context; - _log = Console.Out; - } - - // /tokenizer - public bool ParseArgs(List/*!*/ args) { - int argIndex; - if ((argIndex = args.IndexOf("/prod")) != -1) { - _logProductions = true; - args.RemoveAt(argIndex); - } else { - _logProductions = false; - } - - if ((argIndex = args.IndexOf("/bm")) != -1) { - _benchmark = true; - args.RemoveAt(argIndex); - } else { - _benchmark = false; - } - - _targetDir = (args.Count > 0) ? args[0] : @"C:\RubyTokens"; - _sources = (args.Count > 1) ? args[1] : @"..\..\Languages\Ruby\IronRuby.Tests\Parser\Sources.txt"; - return true; - } - - private class AssertLog : TraceListener { - private readonly TokenizerTestDriver/*!*/ _driver; - - public AssertLog(TokenizerTestDriver/*!*/ driver) { - _driver = driver; - } - - public override void Fail(string message, string detail) { - _driver.WriteException("ASSERTION FAILED:\n" + message + "\n" + detail); - } - - public override void Write(string message) { - _driver._exceptions.Write(message); - } - - public override void WriteLine(string message) { - _driver._exceptions.WriteLine(message); - } - } - - public int RunTests() { - - try { - Directory.Delete(_targetDir, true); - } catch (DirectoryNotFoundException) { - } catch (Exception e) { - Console.WriteLine("Output directory cannot be deleted: {0}", e); - return -1; - } - - Directory.CreateDirectory(_targetDir); - _exceptions = File.CreateText(Path.Combine(_targetDir, "Exceptions.log")); - _regexLog = File.CreateText(Path.Combine(_targetDir, "Regex.log")); - _parserLog = File.CreateText(Path.Combine(_targetDir, "Parser.log")); - - // redirect failed assertions to the _exceptions file - Trace.Listeners.Clear(); - Trace.Listeners.Add(new AssertLog(this)); - - string[] lines; - - try { - lines = File.ReadAllLines(_sources); - } catch (Exception e) { - Console.WriteLine("Source file not found: {0}", e); - return -1; - } - - _log.WriteLine("Scanning files ..."); - - var files = new List(); - var exclude = new Dictionary(StringComparer.OrdinalIgnoreCase); - var envVars = Environment.GetEnvironmentVariables(); - - for (int i = 0; i < lines.Length; i++) { - string path = lines[i]; - - bool excluding = false; - if (path.StartsWith("!")) { - path = path.Substring(1); - excluding = true; - } - - int comment = path.IndexOf('#'); - if (comment >= 0) { - path = path.Substring(0, comment); - } - - StringBuilder sb = new StringBuilder(path); - foreach (DictionaryEntry envVar in envVars) { - sb.Replace("%" + (string)envVar.Key + "%", (string)envVar.Value); - } - - path = sb.ToString().Trim(); - - if (path.Length > 0) { - if (File.Exists(path)) { - path = Path.GetFullPath(path); - if (excluding) { - exclude[path] = true; - } else { - files.Add(path); - } - } else if (Directory.Exists(path)) { - ScanDirs(files, path); - } else { - Console.Error.WriteLine("Error: {0}({1}): {2} doesn't exist", _sources, i + 1, path); - } - } - } - - _log.WriteLine(); - _log.WriteLine(); - - var filteredFiles = new List(); - foreach (var file in files) { - if (!exclude.ContainsKey(file)) { - filteredFiles.Add(file); - } - } - - filteredFiles.Sort(); - if (_benchmark) { - Benchmark(filteredFiles); - } else { - Dump(filteredFiles); - } - - return 0; - } - - private void ScanDirs(List/*!*/ files, string/*!*/ dir) { - //_log.Write(dir); - //_log.Write(' '); - - foreach (string file in Directory.GetFiles(dir, "*.rb")) { - files.Add(Path.GetFullPath(Path.Combine(dir, file))); - //_log.Write('.'); - } - - //_log.WriteLine(); - - foreach (string subdir in Directory.GetDirectories(dir)) { - ScanDirs(files, Path.Combine(dir, subdir)); - } - } - - #region Dump - - internal class ErrorLog : ErrorCounter { - private List/*!*/ _errors = new List(); - - public List/*!*/ Errors { get { return _errors; } } - - public override void Add(SourceUnit source, string message, SourceSpan span, int errorCode, Severity severity) { - CountError(severity); - _errors.Add(String.Format("{0}: {1}", severity, message)); - } - } - - private void Dump(List/*!*/ files) { - foreach (string file in files) { - DumpFile(file); - } - } - - private void DumpFile(string/*!*/ path) { - _log.WriteLine(path); - - try { - string fullPath = Path.GetFullPath(path); - string root = Path.GetPathRoot(fullPath); - string outputPath = Path.ChangeExtension(Path.Combine(_targetDir, fullPath.Substring(root.Length).TrimEnd('\'', '/')), ".txt"); - Directory.CreateDirectory(Path.GetDirectoryName(outputPath)); - - using (TextWriter output = File.CreateText(outputPath)) { - - output.WriteLine(fullPath); - output.WriteLine(); - output.WriteLine("Tokens:"); - output.WriteLine(); - - ErrorLog errors = new ErrorLog(); - Parser parser = new Parser(); - - parser.TokenSink = delegate(Tokens token, SourceSpan span) { - DumpTokenDetail(output, parser.Tokenizer, token); - }; - - if (_logProductions) { -#if DEBUG - parser.EnableLogging(new CoverageParserLogger(parser, _parserLog)); -#endif - } - - _currentSourceFile = path; - - SourceUnitTree ast = null; - try { - ast = parser.Parse(_context.CreateFileUnit(path), new RubyCompilerOptions(), errors); - } catch (Exception e) { - WriteException(e.ToString()); - } - - output.WriteLine(); - - if (errors.ErrorCount + errors.FatalErrorCount + errors.WarningCount > 0) { - output.WriteLine(); - output.WriteLine("Errors:"); - - foreach (string error in errors.Errors) { - output.WriteLine(error); - } - } else { - Debug.Assert(ast != null); - DumpRegularExpressions(ast); - } - - output.WriteLine("."); - } - } catch (Exception e) { - _log.WriteLine("!{0}", e.Message); - } finally { - _currentSourceFile = null; - _regexLog.Flush(); - _parserLog.Flush(); - } - } - - public void DumpTokenDetail(TextWriter/*!*/ output, Tokenizer/*!*/ tokenizer, Tokens token) { - TokenValue value = tokenizer.TokenValue; - - output.Write("{0}: ", Parser.GetTerminalName((int)token)); - - switch (token) { - default: - break; - - case Tokens.Identifier: - output.Write(value.String); - break; - - case Tokens.Float: - output.Write("{0}D", value.Double); - break; - - case Tokens.Integer: - output.Write(value.Integer1); - break; - - case Tokens.BigInteger: - output.Write("{0}BI", value.BigInteger.ToString(10)); - break; - - case Tokens.RegexpEnd: - output.Write("RegexOptions({0})", (RubyRegexOptions)value.Integer1); - break; - - case Tokens.StringContent: - if (value.StringContent is string) { - output.Write("String(\"{0}\", {1})", Parser.EscapeString((string)value.StringContent), value.Encoding); - } else { - output.Write("String({0}), {1}", BitConverter.ToString((byte[])value.StringContent), value.Encoding); - } - break; - - case Tokens.StringBegin: - case Tokens.RegexpBegin: - case Tokens.ShellStringBegin: - case Tokens.SymbolBegin: - output.Write(((Tokenizer.State)tokenizer.CurrentState).CurrentSequence); - break; - } - - output.Write(' '); - output.Write(tokenizer.LexicalState); - output.WriteLine(); - } - - private void WriteException(string/*!*/ str) { - _exceptions.WriteLine(); - _exceptions.WriteLine(_currentSourceFile); - _exceptions.WriteLine(); - _exceptions.WriteLine(str); - _exceptions.WriteLine(new String('-', 50)); - _exceptions.Flush(); - } - - private void DumpRegularExpressions(SourceUnitTree/*!*/ ast) { - new RegexDumper(_regexLog).Walk(ast); - } - - private class RegexDumper : Walker { - private readonly TextWriter/*!*/ _regexLog; - - public RegexDumper(TextWriter/*!*/ regexLog) { - _regexLog = regexLog; - } - - public override bool Enter(RegularExpression/*!*/ node) { - if (node.Pattern.Count == 1) { - var literal = node.Pattern[0] as StringLiteral; - if (literal != null) { - _regexLog.WriteLine("/{0}/{{{1}}}", literal.Value, node.Options); - } - } - return true; - } - } - - #endregion - - #region Benchmarks - - private void Benchmark(List/*!*/ files) { - - var sources = new List(); - Stopwatch readTime = new Stopwatch(); - long totalSize = 0; - readTime.Start(); - foreach (string path in files) { - try { - byte[] data = File.ReadAllBytes(path); - sources.Add(_context.CreateSourceUnit(new BinaryContentProvider(data), path, Encoding.Default, SourceCodeKind.File)); - totalSize += data.Length; - } catch (Exception) { - Console.WriteLine("Error: {0}", path); - } - } - readTime.Stop(); - - Console.WriteLine("Read: {0} kB in {1}", totalSize / 1024, readTime.Elapsed); - -#if F - Stopwatch tokenizeTime = new Stopwatch(); - tokenizeTime.Start(); - foreach (var source in sources) { - try { - var tokenizer = new Tokenizer(); - tokenizer.Initialize(source); - - Tokens token; - do { - token = tokenizer.GetNextToken(); - } while (token != Tokens.EndOfFile); - } catch (Exception) { - Console.WriteLine("Tokenization error: {0}", source.Path); - break; - } - } - tokenizeTime.Stop(); -#endif - //var stackSizes = new Dictionary(); - - var options = new RubyCompilerOptions(); - Stopwatch parseTime = new Stopwatch(); - Stopwatch transformTime = new Stopwatch(); - foreach (var source in sources) { - try { - parseTime.Start(); - var parser = new Parser(); - parser.Parse(source, options, ErrorSink.Null); - //int mt; - //stackSizes[parser.StackMaxTop] = stackSizes.TryGetValue(parser.StackMaxTop, out mt) ? mt + 1 : 1; - parseTime.Stop(); -#if F - if (rubyTree != null) { - transformTime.Start(); - var lambda = _context.TransformTree(rubyTree, source, options); - transformTime.Stop(); - } else { - Console.WriteLine("SyntaxError: {0}", source.Path); - } -#endif - } catch (Exception e) { - Console.WriteLine("{0}: {1}: {2}", e.GetType().Name, source.Path, e.Message); - break; - } - } - - // Console.WriteLine("Tokenize: {0}", tokenizeTime.Elapsed); - Console.WriteLine("Parse: {0}", parseTime.Elapsed); - //Console.WriteLine("Idf/Kwd/Loc: {0}/{1}/{2}", Tokenizer.IdfLength, Tokenizer.KwdLength, Tokenizer.LocLength); - // Console.WriteLine("Transform: {0}", transformTime.Elapsed); - - //PerfTrack.DumpHistogram(Parser.Reductions); - //PerfTrack.DumpHistogram(stackSizes); - } - - #endregion - } -} diff --git a/Src/IronRuby.Tests/RubyTests.cs b/Src/IronRuby.Tests/RubyTests.cs index 41bc8c8fe..f245e49c9 100644 --- a/Src/IronRuby.Tests/RubyTests.cs +++ b/Src/IronRuby.Tests/RubyTests.cs @@ -63,28 +63,10 @@ public Tests(Driver/*!*/ driver) { TypeMemberCache, ReflectionUtils_GetMembers, - Scenario_ParserLogging, - Parser1, - ParserErrors1, - TokenizeIdentifiers1, - Identifiers2, ParseBigInts1, ParseIntegers1, - TokenizeNumbers1, - TokenizeInstanceClassVariables1, - TokenizeGlobalVariables1, - TokenizeEscapes1, - TokenizeEolns1, - TokenizeRegex1, - TokenizeStrings1, - TokenizeStrings2, - TokenizeEscapes2, - Heredoc1, - LexicalState1, - ParseSymbols1, - - TokenCategorizer1, - TokenCategorizer2, + + ShebangNamesIronRuby1, NameMangling1, NameMangling2, DelegateChainClone1, @@ -135,8 +117,6 @@ public Tests(Driver/*!*/ driver) { NumericLiterals1, NumericOps1, - UnicodeEscapes1, - CharacterToken1, Encoding1, Encoding2, @@ -144,7 +124,6 @@ public Tests(Driver/*!*/ driver) { Encoding_Host1, Encoding_Host2, - AstLocations1, Scenario_Globals1, @@ -272,21 +251,16 @@ public Tests(Driver/*!*/ driver) { RubyBlocks2, RubyBlocks3, RubyBlocks5, - RubyBlocks6, RubyBlocks7, RubyBlocks8, RubyBlocks9, - RubyBlocks10A, - RubyBlocks10B, RubyBlocks11, RubyBlocks12, RubyBlocks13, RubyBlocks14A, RubyBlocks14B, RubyBlocks14C, - RubyBlocks15, RubyBlocks16, - RubyBlocks17, RubyBlocks18, BlockReturnOptimization1, @@ -324,7 +298,6 @@ public Tests(Driver/*!*/ driver) { RubyProcArgConversion4, ProcNew1, ProcNew2, - ProcNew3, ProcNew4, MethodToProc1, DefineMethod1, @@ -335,8 +308,6 @@ public Tests(Driver/*!*/ driver) { Scenario_RubyInitializers1, Scenario_RubyInitializers2A, Scenario_RubyInitializers2B, - Scenario_RubyInitializers3, - Scenario_RubyInitializers4A, Scenario_RubyInitializers4B, Scenario_RubyInitializers4C, Scenario_RubyInitializers5, @@ -354,7 +325,6 @@ public Tests(Driver/*!*/ driver) { LoopBreak3, LoopRedo1, LoopNext1, - MethodBreakRetryRedoNext1, Scenario_RubyUntilLoop1, Scenario_WhileLoopCondition1, PostTestWhile1, @@ -687,6 +657,7 @@ public Tests(Driver/*!*/ driver) { DefineMethodVisibility2B, AliasedMethodVisibility1, AttributeAccessorsVisibility1, + AttributeAccessorsVisibility2, ModuleFunctionVisibility1, ModuleFunctionVisibility2, @@ -758,6 +729,8 @@ public Tests(Driver/*!*/ driver) { Time_OlsonZone1, Zlib_Streams1, Process_SpawnKill1, + File_DriveLetters1, + File_FlockReadpartialRlimit1, Json_ControlCharacters1, NetHttp_Tls1, NetHttp_TlsVerifyCallback1, @@ -840,13 +813,7 @@ public Tests(Driver/*!*/ driver) { EvalReturn2, EvalReturn3, EvalReturn4, - EvalBreak1, EvalBreak2, - EvalBreak3, - EvalRetry1, - EvalRetry2, - EvalRedo1, - EvalNext1, LocalNames1, LocalNames2, LocalNames3, @@ -875,7 +842,6 @@ public Tests(Driver/*!*/ driver) { // TODO: SuperParameterlessEval1, // TODO: SuperParameterlessEval2, SuperInDefineMethodEval1, - // TODO: NamesEncoding1, BEGIN1, BEGIN2, SymbolToProc1, diff --git a/Src/IronRuby.Tests/Runtime/AliasTests.cs b/Src/IronRuby.Tests/Runtime/AliasTests.cs index 24294302e..b6e38cb59 100644 --- a/Src/IronRuby.Tests/Runtime/AliasTests.cs +++ b/Src/IronRuby.Tests/Runtime/AliasTests.cs @@ -262,7 +262,7 @@ public void MethodAliasExpression() { CompilerTest(@" def b; end p ((alias a b)) -", 1, 0); +", 0, 0); }, "nil"); } diff --git a/Src/IronRuby.Tests/Runtime/BlockTests.cs b/Src/IronRuby.Tests/Runtime/BlockTests.cs index 58db9d402..576856a77 100644 --- a/Src/IronRuby.Tests/Runtime/BlockTests.cs +++ b/Src/IronRuby.Tests/Runtime/BlockTests.cs @@ -164,39 +164,13 @@ puts block_given? C.new.foo { puts 'goo' } C.new.foo - "); + ", 0, 1); }, @" true false "); } - /// - /// Return, yield and retry in a method. - /// - public void RubyBlocks6() { - TestOutputWithEval(@" -def do_until(cond) - if cond then # end - # - # -end - -i = 0 -do_until(i > 4) do - puts i - i = i + 1 -end -", @" -0 -1 -2 -3 -4 -" - ); - } - /// /// Break in a block. /// @@ -249,7 +223,7 @@ puts x if i < 3 then next end puts 'bar' } -"); +", 1, 0); }, @" 0 1 @@ -262,39 +236,6 @@ puts x "); } - /// - /// Retry in a block. - /// - public void RubyBlocks10A() { - AssertOutput(delegate() { - CompilerTest(@" -i = 0 -3.times { |x| - puts x - i = i + 1 - if i == 2 then retry end -} -"); - }, @" -0 -1 -0 -1 -2 -"); - } - - /// - /// Retry in a block called via Proc#call. - /// - public void RubyBlocks10B() { - TestOutput(@" -proc { retry rescue puts 'not caught here' }.call rescue p $! # TODO: bug (should not be caught by the inner rescue) -", @" -not caught here -"); - } - /// /// Return with stack unwinding. /// @@ -357,7 +298,9 @@ def foo /// Nested yielding. /// public void RubyBlocks14A() { - TestOutputWithEval(@" + // The eval variant (run first) gives foo no yield of its own: ruby -w warns that the + // block passed to it may be ignored, and the count is shared by both variants. + UsingEval((eval) => AssertOutput(() => CompilerTest(Eval(eval, @" def bar yield yield # shouldn't be called @@ -367,13 +310,13 @@ def foo bar { print 'x' # - } + } end foo { break } -", @" +"), 0, 1), @" x -"); +")); } /// @@ -400,7 +343,10 @@ def foo /// Covers RubyOps.YieldBlockBreak error path. /// public void RubyBlocks14C() { - TestOutputWithEval(@" + // With `eval %q{yield}` the method has no yield of its own, and ruby -w warns that the + // block passed to it may be ignored. The eval variant runs first and the warning count + // belongs to the runtime both variants share, so both see that one warning. + UsingEval((eval) => AssertOutput(() => CompilerTest(Eval(eval, @" def proc_conv(&b) $x = b end @@ -415,43 +361,9 @@ def foo end foo -", @" +"), 0, 1), @" # -"); - } - - /// - /// Retry for-loop: for-loop should behave like x.each { } method call with a block, that is x is reevaluted on retry. - /// - public void RubyBlocks15() { - TestOutput(@" -def foo x - puts ""foo(#{x})"" - x * ($i + 1) -end - -$i = 0 - -for i in [foo(1), foo(2), foo(3)] do - puts ""i = #{i}"" - - if $i == 0 then - $i = 1 - retry - end -end -", @" -foo(1) -foo(2) -foo(3) -i = 1 -foo(1) -foo(2) -foo(3) -i = 2 -i = 4 -i = 6 -"); +")); } /// @@ -484,48 +396,10 @@ def foo break 1 end puts x -"); +", 2, 0); }, @"1"); } - /// - /// Retry is propagated to the 'each' call. - /// - public void RubyBlocks17() { - TestOutputWithEval(@" -def foo - for i in [1, 2, 3] - puts ""i = #{i}"" - x = # - end - puts x -end - -def bar - $c = 0 - foo do - puts $c - $c += 1 - retry if $c < 3 - 'done' - end -end - -bar -", @" -i = 1 -0 -i = 1 -1 -i = 1 -2 -i = 2 -3 -i = 3 -4 -done"); - } - public void RubyBlocks18() { TestOutput(@" class C @@ -574,7 +448,7 @@ def foo puts foo ", @" 123 -"); +", 1); Assert(StackUnwinder.InstanceCount == 1); } @@ -627,7 +501,7 @@ def f3 puts f0 ", @" 123 -"); +", 0, 2); Assert(StackUnwinder.InstanceCount == 0); } @@ -657,7 +531,7 @@ def f3 puts f0 ", @" 123 -"); +", 0, 1); Assert(StackUnwinder.InstanceCount == 1); } @@ -1664,7 +1538,7 @@ public void Scenario_RubyBlockArgs5() { [1, 2, 3, 4, 5] [1, [2, 3]] [1, [2, 3, 4, 5, 6, 7]] -"); +", 2); } public void Scenario_RubyBlockArgs6() { @@ -1847,7 +1721,7 @@ puts e.message end ", @" tried to create Proc object without a block -"); +", 0, 1); } public void ProcNew2() { @@ -1867,44 +1741,7 @@ puts e.message end ", @" tried to create Proc object without a block -"); - } - - public void ProcNew3() { - TestOutput(@" -$x = 0 - -class P < Proc - def initialize *args, &b - p args, b.class, self.class, block_given? - $x += 1 - retry if $x < 2 - 123 - end -end - -def arg - puts 'arg' - [] -end - -def foo - P.new(*arg) { puts 2 } -end - -foo { puts 1 } -", @" -arg -[] -Proc -P -true -arg -[] -Proc -P -true -"); +", 0, 1); } public void ProcNew4() { @@ -1933,7 +1770,7 @@ puts e.message ", @" arg tried to create Proc object without a block -"); +", 0, 1); } /// @@ -1962,7 +1799,7 @@ p q[] rescue p $! eval('puts x, self', q.binding) p D.new.instance_eval(&q) -"), @" +", 1, 0), @" # 1 :b @@ -2205,50 +2042,6 @@ public void Block_ProcParams1() { "); } - public void EvalBreak1() { - AssertOutput(() => CompilerTest(@" -x = 10.times do - puts 'in 1st loop' - eval('break 1') -end -p x - -x = while true - puts 'in 2nd loop' - eval('break 2') -end -p x - -x = Array.new(10) do - eval('break 3') -end -p x - -class C - define_method(:foo) do - eval('break 4') - end -end -p C.new.foo - -x = Kernel.module_eval do - eval('break 5') -end -p x - -p 10.times { break eval('while true do eval(""break 6""); end') } -"), @" -in 1st loop -1 -in 2nd loop -2 -3 -4 -5 -6 -"); - } - /// /// Break from a block called via Proc#call. /// @@ -2263,240 +2056,6 @@ p f { break 123 } "); } - public void EvalBreak3() { - AssertOutput(() => CompilerTest(@" -def foo - eval('break') -rescue - p $!.class -end - -foo - -class C - eval('break') -rescue - p $!.class -end - -begin - eval('break') -rescue - p $!.class -end -"), @" -LocalJumpError -LocalJumpError -LocalJumpError -"); - } - - /// - /// Block needs to set InLoop and InRescue flags on RFC to "false". - /// - public void EvalRetry1() { - AssertOutput(() => CompilerTest(@" -def foo &p - p[] -end - -$x = 0 - -begin - begin - puts 'in body' - raise - rescue - foo do - puts 'in block' - eval('retry') if ($x += 1) < 3 - end - end -rescue - p $! -end -"), @" -in body -in block -# -"); - } - - public void EvalRetry2() { - // retry in block: - AssertOutput(() => CompilerTest(@" -$x = 0 -1.times do |i| - puts 'in block' - module M - eval('retry') if ($x += 1) < 2 - end -end -"), @" -in block -in block -"); - - // retry in rescue: - AssertOutput(() => CompilerTest(@" -$x = 0 -1.times do - begin - raise - rescue - puts 'in rescue' - module M - eval('retry') if ($x += 1) < 2 - end - end -end -"), @" -in rescue -in rescue -"); - // TODO: - // retry in a define_method block: - AssertOutput(() => CompilerTest(@" -$x = 0 -class C - define_method :foo do - puts 'define_method' - begin - eval('module M; retry; end') if ($x += 1) < 3 - -# TODO: should not catch here -# rescue -# p 'unreachable' - end - end -end - -begin - C.new.foo -rescue - p $! -end"), @" -define_method -# -"); - - // retry in a method taking a block: - AssertOutput(() => CompilerTest(@" -$x = 0 -def foo *a - yield - eval('module M; retry; end') if ($x += 1) < 2 -end - -foo(puts('in arg')) { puts 'in block' } -"), @" -in arg -in block -in arg -in block -"); - } - - public void EvalRedo1() { - // redo in loop: - AssertOutput(() => CompilerTest(@" -$x = 0 -while (puts('in condition'); true) - puts 'in loop' - eval('module M; redo; end') if ($x += 1) < 2 - break -end -"), @" -in condition -in loop -in loop -"); - - // redo in block: - AssertOutput(() => CompilerTest(@" -$x = 0 -2.times do |i| - puts 'in block ' + i.to_s - eval('module M; redo; end') if ($x += 1) < 2 -end -"), @" -in block 0 -in block 0 -in block 1 -"); - - // redo in define_method block: - AssertOutput(() => CompilerTest(@" -$x = 0 -class C - define_method :foo do - puts 'in block' - eval('module M; redo; end') if ($x += 1) < 2 - end -end -C.new.foo -"), @" -in block -in block -"); - } - - public void EvalNext1() { - // next in loop: - AssertOutput(() => CompilerTest(@" -$x = 0 -while (puts('in condition'); true) - puts 'in loop' - eval('module M; next; end') if ($x += 1) < 2 - break -end -"), @" -in condition -in loop -in condition -in loop -"); - - // next in block: - AssertOutput(() => CompilerTest(@" -$x = 0 -2.times do |i| - puts 'in block ' + i.to_s - eval('module M; next; end') if ($x += 1) < 2 -end -"), @" -in block 0 -in block 1 -"); - - // next in define_method block: - AssertOutput(() => CompilerTest(@" -$x = 0 -class C - define_method :foo do - puts 'in block' - eval('module M; next; end') if ($x += 1) < 2 - puts 'unreachable' - end -end -C.new.foo -"), @" -in block -"); - // next returning a value: - AssertOutput(() => CompilerTest(@" -class C - define_method :foo do - eval('next 123') - end -end - -p C.new.foo -"), @" -123 -"); - } - public void EvalReturn1() { TestOutputWithEval(@" def y @@ -2583,6 +2142,10 @@ puts foo "); } + /// + /// A BEGIN block shares the top-level scope (MRI 1.9+): x is already a local there, nil + /// until the assignment after BEGIN has run, and the block's binding sees it afterwards. + /// public void BEGIN1() { TestOutput(@" x = 1 @@ -2590,16 +2153,16 @@ public void BEGIN1() { p x rescue p $! y = 1 z = 2 - 1.times { p y + z } + 1.times { p y + z } $binding = binding } p eval('x', $binding) rescue p $! p eval('y+z', $binding) ", @" -# +nil 3 -# +1 3 "); } diff --git a/Src/IronRuby.Tests/Runtime/BoolAndConditionalTests.cs b/Src/IronRuby.Tests/Runtime/BoolAndConditionalTests.cs index 704e3541c..4c886acbe 100644 --- a/Src/IronRuby.Tests/Runtime/BoolAndConditionalTests.cs +++ b/Src/IronRuby.Tests/Runtime/BoolAndConditionalTests.cs @@ -286,7 +286,7 @@ public void Scenario_RubyIfExpression1() { puts(if nil then 1 elsif 1 then 2 end) puts(if nil then 1 elsif nil then 2 else 3 end) puts(if nil then 1 elsif 1 then 2 else 3 end) -"); +", 4, 0); }, @" 1 @@ -309,7 +309,7 @@ public void Scenario_RubyIfExpression2() { puts(if 1 then end) puts(if 1 then 1;11;111 end) puts(if nil then 1 else 2;22 end) -"); +", 5, 0); }, @" @@ -323,7 +323,7 @@ public void Scenario_RubyUnlessExpression1() { CompilerTest(@" puts(unless nil then 1 end) puts(unless 1 then 1 end) -"); +", 1, 0); }, @" 1 diff --git a/Src/IronRuby.Tests/Runtime/CloningTests.cs b/Src/IronRuby.Tests/Runtime/CloningTests.cs index ffd6c1ad6..3b0679749 100644 --- a/Src/IronRuby.Tests/Runtime/CloningTests.cs +++ b/Src/IronRuby.Tests/Runtime/CloningTests.cs @@ -88,7 +88,7 @@ class << y raise unless ((y.foo;false) rescue true) # methods NOT copied raise unless y.instance_variable_get(:@iv_x) == 4 # instance variables copied end -"); +", 1, 0); }, @" Hash Array diff --git a/Src/IronRuby.Tests/Runtime/ClrBinderTests.cs b/Src/IronRuby.Tests/Runtime/ClrBinderTests.cs index 0e2d242a5..a1361ffef 100644 --- a/Src/IronRuby.Tests/Runtime/ClrBinderTests.cs +++ b/Src/IronRuby.Tests/Runtime/ClrBinderTests.cs @@ -53,7 +53,6 @@ public struct BinderPoint2 { public override string ToString() { return X + "," + Y; } } - [Options(Prism = true)] public void ClrKeywordArguments1() { Context.ObjectClass.SetConstant("N", Context.GetClass(typeof(BinderNamed))); TestOutput(@" @@ -118,7 +117,6 @@ puts e.class /// /// Keywords passed to new set what no constructor parameter takes, like a C# object initializer. /// - [Options(Prism = true)] public void ClrKeywordArguments2() { Context.ObjectClass.SetConstant("W", Context.GetClass(typeof(BinderWidget))); Context.ObjectClass.SetConstant("P", Context.GetClass(typeof(BinderPoint))); @@ -171,7 +169,6 @@ public class BinderCallbacks { public static void Each(IEnumerable items, Action action) { foreach (var item in items) action(item); } } - [Options(Prism = true)] public void ClrBlockToDelegate1() { Context.ObjectClass.SetConstant("CB", Context.GetClass(typeof(BinderCallbacks))); TestOutput(@" @@ -235,7 +232,6 @@ no delegate 1 /// /// break, next and exceptions in a block that a CLR method calls back as a delegate. /// - [Options(Prism = true)] public void ClrBlockToDelegate2() { Context.ObjectClass.SetConstant("CB", Context.GetClass(typeof(BinderCallbacks))); TestOutput(@" @@ -282,7 +278,6 @@ puts CB.pick(System::Func[Integer, Integer].new { |x| x }) "); } - [Options(Prism = true)] public void ClrMethodToDelegate1() { Context.ObjectClass.SetConstant("CB", Context.GetClass(typeof(BinderCallbacks))); TestOutput(@" @@ -380,7 +375,6 @@ public static class BinderGenerics { /// A block passed for a delegate whose parameters use a type parameter leaves the type parameter to the other /// arguments: Filter<T>(List<int>, Func<T, bool>) infers T = int, not Object. /// - [Options(Prism = true)] public void ClrGenericDelegateInference1() { Context.ObjectClass.SetConstant("G", Context.GetClass(typeof(BinderGenerics))); TestOutput(@" @@ -421,7 +415,6 @@ public static class BinderRanges { /// A Ruby Range of Integers passes for a System.Range and a negative index for one counted from the end, /// with Ruby's meaning: an inclusive end unless excluded, -1 the last element. /// - [Options(Prism = true)] public void ClrRangeIndexArguments1() { Context.ObjectClass.SetConstant("R", Context.GetClass(typeof(BinderRanges))); TestOutput(@" @@ -566,7 +559,6 @@ public class BinderPair { /// /// Out and ref parameters come back as a Ruby Array, so a C# Deconstruct method makes array patterns match. /// - [Options(Prism = true)] public void ClrOutParameters1() { Context.ObjectClass.SetConstant("O", Context.GetClass(typeof(BinderOut))); Context.ObjectClass.SetConstant("Pair", Context.GetClass(typeof(BinderPair))); @@ -613,7 +605,6 @@ public static string Keys(Dictionary map) { /// /// A Ruby Array or Hash passed where a CLR method takes a typed collection is copied into one. /// - [Options(Prism = true)] public void ClrCollectionArguments1() { Context.ObjectClass.SetConstant("C", Context.GetClass(typeof(BinderCollections))); TestOutput(@" diff --git a/Src/IronRuby.Tests/Runtime/ClrProtocolTests.cs b/Src/IronRuby.Tests/Runtime/ClrProtocolTests.cs index 4a8892d93..437cffd0f 100644 --- a/Src/IronRuby.Tests/Runtime/ClrProtocolTests.cs +++ b/Src/IronRuby.Tests/Runtime/ClrProtocolTests.cs @@ -358,7 +358,6 @@ p T.ref_pair.to_a /// /// Array patterns go through #deconstruct, which hands CLR strings over as Ruby strings so that String matches them. /// - [Options(Prism = true)] public void ClrTuplePatterns1() { Context.ObjectClass.SetConstant("T", Context.GetClass(typeof(ProtocolTuples1))); TestOutput(@" @@ -437,7 +436,6 @@ p d.inject(0) { |sum, (k, v)| sum + v } /// deconstruct_keys of a pair: {key:, value:}, with the keys asked for (the CLR names Key/Value included), or /// all of them for nil. /// - [Options(Prism = true)] public void ClrKeyValuePairPatterns1() { Context.ObjectClass.SetConstant("T", Context.GetClass(typeof(ProtocolTuples1))); TestOutput(@" @@ -523,7 +521,6 @@ public struct ProtocolMoney1 { /// What a hash pattern passes to #deconstruct_keys, as MRI compiles it: the keys it names, or nil when it needs /// every key - for a **rest or **nil, and for `in {}`, which only matches when there are no keys at all. /// - [Options(Prism = true)] public void HashPatternKeyList1() { TestOutput(@" class Recorder @@ -574,7 +571,6 @@ private void DefineHashPatternTypes() { /// A hash pattern matches a CLR object's public readable instance properties and fields, by CLR name or by /// Ruby (mangled) name. /// - [Options(Prism = true)] public void ClrHashPatterns1() { DefineHashPatternTypes(); TestOutput(@" @@ -675,7 +671,6 @@ p Throws.new.deconstruct_keys([:ok]) /// Only CLR classes that no library defines get #deconstruct_keys this way: Ruby objects and the built-in /// classes do not, and a Ruby definition (in the class or in a module included into it) takes precedence. /// - [Options(Prism = true)] public void ClrHashPatternScope1() { DefineHashPatternTypes(); TestOutput(@" @@ -770,7 +765,6 @@ public int CompareTo(object other) { /// A type implementing only IComparable<T> is Comparable: <=> calls CompareTo, and everything Comparable /// and Array build on it works. /// - [Options(Prism = true)] public void ClrGenericComparable1() { Context.ObjectClass.SetConstant("V", Context.GetClass(typeof(ProtocolVersion1))); TestOutput(@" diff --git a/Src/IronRuby.Tests/Runtime/ClrSubclassingTests.cs b/Src/IronRuby.Tests/Runtime/ClrSubclassingTests.cs index cb92d685c..fff4a1da7 100644 --- a/Src/IronRuby.Tests/Runtime/ClrSubclassingTests.cs +++ b/Src/IronRuby.Tests/Runtime/ClrSubclassingTests.cs @@ -121,7 +121,6 @@ Dr. Nested /// A base class with a parameterless constructor is constructed with it when allocated, as before; super with /// arguments then runs the matching constructor, super without arguments does nothing more. /// - [Options(Prism = true)] public void ClrSuperConstructor2() { Context.ObjectClass.SetConstant("Widget", Context.GetClass(typeof(SubclassingWidget))); Context.ObjectClass.SetConstant("Shape", Context.GetClass(typeof(SubclassingShape))); diff --git a/Src/IronRuby.Tests/Runtime/ClrTests.cs b/Src/IronRuby.Tests/Runtime/ClrTests.cs index 75e5242f5..0a9454417 100644 --- a/Src/IronRuby.Tests/Runtime/ClrTests.cs +++ b/Src/IronRuby.Tests/Runtime/ClrTests.cs @@ -354,7 +354,7 @@ puts c.prop1 puts c.prop2 (b.prop2 = 10) rescue p $! puts b.prop2 -"); +", 1, 0); }, @" 1 2 @@ -391,7 +391,7 @@ puts b.prop2 Bar(O): 7 Baz(I): 1 10 -"); +", 1); } public delegate void TestDelegate(string a); @@ -471,7 +471,7 @@ private mangled ", @" method called: + method called: compare_to -"); +", 1); } public class ClassWithGeneratedMembers1 : I1 { diff --git a/Src/IronRuby.Tests/Runtime/ConstantTests.cs b/Src/IronRuby.Tests/Runtime/ConstantTests.cs index 0d34ee843..7a9a7f36d 100644 --- a/Src/IronRuby.Tests/Runtime/ConstantTests.cs +++ b/Src/IronRuby.Tests/Runtime/ConstantTests.cs @@ -454,15 +454,24 @@ public void ConstantCaching_Unqualified7() { Assert(ReferenceEquals(result[3], null)); } + /// + /// The cached answer of defined? is a frozen string (MRI 3.0+), so a caller cannot change + /// what the next evaluation answers. + /// public void ConstantCaching_Unqualified_IsDefined1() { TestOutput(@" a = [] 2.times { a << defined?(Object) } -a[0][0] = ?x -puts a +p a, a.map(&:frozen?) +begin + a[0][0] = ?x +rescue => e + p e.class +end ", @" -xonstant -constant +[""constant"", ""constant""] +[true, true] +FrozenError "); } @@ -544,6 +553,10 @@ module E "); } + /// + /// defined? of a constant path never calls const_missing, for a missing name in the middle of + /// the path either (MRI 1.9+): A::B::C is gone after the remove_const, and the path is undefined. + /// public void ConstantCaching_Qualified_IsDefined1() { TestOutput(@" module A @@ -585,10 +598,8 @@ module D ", @" -missing: C -constant -missing: C -constant + + constant constant "); diff --git a/Src/IronRuby.Tests/Runtime/DefinedTests.cs b/Src/IronRuby.Tests/Runtime/DefinedTests.cs index 5aa300cf9..bb40f9118 100644 --- a/Src/IronRuby.Tests/Runtime/DefinedTests.cs +++ b/Src/IronRuby.Tests/Runtime/DefinedTests.cs @@ -162,12 +162,11 @@ def const_missing name end end -puts defined?(X::C) +puts defined?(X::C) # defined? never calls const_missing (MRI 1.9+) puts defined?(raise::C) puts defined?(foo::C) ", @" -missing X -constant + constant "); @@ -183,7 +182,7 @@ public void DefinedOperator_Constants3() { print '.' if defined? FOO print '7' if not (defined? Object and defined? FOO) print '8' if defined? FOO or defined? Object -", 2, 0), @" +", 0, 0), @" 1278 "); } @@ -202,7 +201,7 @@ puts defined? 'foo' puts defined? x = 1 puts defined? x &= 1 -puts defined? x &&= 1 +puts defined? x &&= 1 # an assignment too (MRI 1.9+) "); }, @" true @@ -213,7 +212,7 @@ puts defined? 'foo' method assignment assignment -expression +assignment "); } diff --git a/Src/IronRuby.Tests/Runtime/EvalTests.cs b/Src/IronRuby.Tests/Runtime/EvalTests.cs index 53bc3e0e4..64d946841 100644 --- a/Src/IronRuby.Tests/Runtime/EvalTests.cs +++ b/Src/IronRuby.Tests/Runtime/EvalTests.cs @@ -25,7 +25,7 @@ def foo() end foo -"); +", 1, 0); }, "1"); } @@ -79,8 +79,10 @@ puts b rescue p $! END "; // Locals an eval defines are its own: neither the frame nor the next eval sees them (MRI 1.9+). - // MRI raises NameError for a bare name; only the prism front end tells a bare name apart, - // so under this parser it is still NoMethodError, its subclass. + // A bare name that is neither is a NameError under ir, as in MRI; this test runs hosted, in a + // ScriptScope whose variables a bare name may also mean, and there it is NoMethodError, its + // subclass. `a`, assigned in the block and read only inside eval strings, is the one parse + // warning `ruby -wc` gives for each wrapping. string output = @" # N*Error @@ -91,11 +93,11 @@ puts b rescue p $! # "; - AssertOutput(() => CompilerTest(String.Format(@"def foo; {0}; end; foo", body)), output, OutputFlags.Match); - AssertOutput(() => CompilerTest(String.Format(@"module M; {0}; end", body)), output, OutputFlags.Match); - AssertOutput(() => CompilerTest(String.Format(@"class C; {0}; end", body)), output, OutputFlags.Match); - AssertOutput(() => CompilerTest(String.Format(@"class << Object.new; {0}; end", body)), output, OutputFlags.Match); - AssertOutput(() => CompilerTest(body), output, OutputFlags.Match); + AssertOutput(() => CompilerTest(String.Format(@"def foo; {0}; end; foo", body), 1, 0), output, OutputFlags.Match); + AssertOutput(() => CompilerTest(String.Format(@"module M; {0}; end", body), 1, 0), output, OutputFlags.Match); + AssertOutput(() => CompilerTest(String.Format(@"class C; {0}; end", body), 1, 0), output, OutputFlags.Match); + AssertOutput(() => CompilerTest(String.Format(@"class << Object.new; {0}; end", body), 1, 0), output, OutputFlags.Match); + AssertOutput(() => CompilerTest(body, 1, 0), output, OutputFlags.Match); } /// @@ -173,7 +175,7 @@ public void Eval6() { [1, 2, 3, nil, nil] [1, 2, 3, 4, nil] [1, 2, 3, 4, 5] -"); +", 2); } public void LocalNames1() { @@ -186,7 +188,7 @@ puts local_variables.sort end f -"); +", 2, 0); }, @" a b"); @@ -207,7 +209,7 @@ def bar bar eval('puts local_variables.sort', $b) -"); +", 1, 0); }, @" x y @@ -231,7 +233,7 @@ module M eval('puts x', $p[0]) eval('puts x', $p[1]) -"); +", 1, 0); }, @" 0 1 @@ -258,7 +260,7 @@ module M bar eval('puts local_variables.sort', $b) -"); +", 0, 1); }, @" y z @@ -291,7 +293,7 @@ def foo foo p eval('x+y', $b) -"); +", 2, 0); }, "3"); } @@ -336,7 +338,7 @@ def z end p eval('x+y+z', goo) rescue p $! -"); +", 3, 0); }, @"#"); } @@ -599,7 +601,7 @@ def foo end foo -"); +", 1, 0); }, @" 1 1"); diff --git a/Src/IronRuby.Tests/Runtime/ExceptionTests.cs b/Src/IronRuby.Tests/Runtime/ExceptionTests.cs index 589608e14..52b72c243 100644 --- a/Src/IronRuby.Tests/Runtime/ExceptionTests.cs +++ b/Src/IronRuby.Tests/Runtime/ExceptionTests.cs @@ -202,7 +202,7 @@ rescue IOError end puts x puts 'End' -"); +", 2, 0); }, @" Begin Raise @@ -577,7 +577,7 @@ def bazz bar baz bazz -", @""); +", @"", 1); } public void ExceptionArg1() { diff --git a/Src/IronRuby.Tests/Runtime/HashTests.cs b/Src/IronRuby.Tests/Runtime/HashTests.cs index b339b8af8..8e4022d73 100644 --- a/Src/IronRuby.Tests/Runtime/HashTests.cs +++ b/Src/IronRuby.Tests/Runtime/HashTests.cs @@ -78,7 +78,7 @@ class C end end -C.new[1 => 'a', 2 => 'b'] = 'c' +C.new[{1 => 'a', 2 => 'b'}] = 'c' # Ruby 3.4+: without braces they are keywords, not allowed here "); }, @"abc"); } diff --git a/Src/IronRuby.Tests/Runtime/InitializerTests.cs b/Src/IronRuby.Tests/Runtime/InitializerTests.cs index 05d819a8e..6a6bbc96d 100644 --- a/Src/IronRuby.Tests/Runtime/InitializerTests.cs +++ b/Src/IronRuby.Tests/Runtime/InitializerTests.cs @@ -74,61 +74,10 @@ def initialize &b x = A.new { break 'foo' } 1.times(&$b) rescue p $! -"); +", 1, 0); }, @"#"); } - /// - /// Retry returns from the 'new' frame (skipping initialize frame) as that frame is its proc-converter. - /// The block is not redefined however. Only the proc-converter frame is updated to the new instance of the 'new' frame. - /// - public void Scenario_RubyInitializers3() { - AssertOutput(delegate() { - CompilerTest(@" -class A - def initialize *a - yield - end -end - -$i = 0 -y = A.new($i += 1) { - puts $i - if $i < 3 then - retry - end -} -"); - }, @" -1 -2 -3"); - } - - /// - /// The same case as Scenario_RubyInitializers3, but with initializer defined in library. - /// - public void Scenario_RubyInitializers4A() { - AssertOutput(delegate() { - CompilerTest(@" -$i = 0 -y = Array.new($i += 1) { - puts $i - if $i < 3 then - retry - end -} -puts y.inspect -"); - }, @" -1 -2 -3 -3 -3 -[nil, nil, nil]"); - } - /// /// A block is yielded to from "initialize", not from the factory. /// diff --git a/Src/IronRuby.Tests/Runtime/LoopTests.cs b/Src/IronRuby.Tests/Runtime/LoopTests.cs index 3ca51f022..59dfd3d49 100644 --- a/Src/IronRuby.Tests/Runtime/LoopTests.cs +++ b/Src/IronRuby.Tests/Runtime/LoopTests.cs @@ -170,40 +170,6 @@ puts x 2 1 -"); - } - - /// - /// Break, retry, redo and next in a method, out of loop/rescue. - /// - public void MethodBreakRetryRedoNext1() { - TestOutput(@" -def _break; break rescue p $!; end -def _redo; redo rescue puts 'not caught here'; end -def _retry; retry rescue puts 'not caught here'; end -def _next; next rescue puts 'not caught here'; end -def e_break; eval('break') rescue p $!; end -def e_redo; eval('redo') rescue puts 'not caught here'; end -def e_retry; eval('retry') rescue puts 'not caught here'; end # // TODO: bug -def e_next; eval('next') rescue puts 'not caught here'; end # // TODO: bug - -_break -_retry rescue p $! -_redo rescue p $! -_next rescue p $! -e_break -e_retry rescue p $! -e_redo rescue p $! -e_next rescue p $! -", @" -# -# -# -# -# -# -not caught here -not caught here "); } diff --git a/Src/IronRuby.Tests/Runtime/MethodTests.cs b/Src/IronRuby.Tests/Runtime/MethodTests.cs index 9e1df1084..2f7278dc9 100644 --- a/Src/IronRuby.Tests/Runtime/MethodTests.cs +++ b/Src/IronRuby.Tests/Runtime/MethodTests.cs @@ -1050,7 +1050,49 @@ class C true "); } - + + /// + /// The scope's default visibility applies only where the calling frame's self is the + /// module itself (MRI's rb_vm_cref_in_context). importmap-rails sends attr_accessor to + /// Rails::Application from the top level of a file, whose default is private. + /// + public void AttributeAccessorsVisibility2() { + TestOutput(@" +class Box; end +Box.send(:attr_accessor, :a) + +class Box + private + Box.send(:attr_reader, :c) +end + +class Other + private + Box.send(:attr_writer, :d) +end + +Box.class_eval { private; attr_reader :f } + +module Helper + def self.define(klass) + klass.send(:attr_reader, :g) + end +end +Helper.define(Box) + +[:a, :a=, :c, :d=, :f, :g].each do |m| + puts ""#{m} #{Box.public_method_defined?(m) ? 'public' : 'private'}"" +end +", @" +a public +a= public +c private +d= public +f private +g public +"); + } + private string MethodDefinitionInDefineMethodCode1 = @" class A $p = lambda { def foo; end } @@ -1247,7 +1289,6 @@ p Foo.method(:new).arity, Foo.method(:new).parameters, 1.method(:send).arity, Fo /// so every node after a symbol in a method body was read from the wrong offset ("Unknown prism /// node type", IndexOutOfRangeException) - mspec, for one, could not start. /// - [Options(Prism = true)] public void MethodDef_SymbolInBody1() { TestOutput(@" def sym = :start diff --git a/Src/IronRuby.Tests/Runtime/MiscTests.cs b/Src/IronRuby.Tests/Runtime/MiscTests.cs index eeb6f8e83..d18b78205 100644 --- a/Src/IronRuby.Tests/Runtime/MiscTests.cs +++ b/Src/IronRuby.Tests/Runtime/MiscTests.cs @@ -189,8 +189,10 @@ class c << G end ", SourceCodeKind.File); - p = new Parser().Parse(unit, new RubyCompilerOptions(), log); - Assert(p == null && log.FatalErrorCount == 1); + // the three errors `ruby -c` reports: the class name (twice, as prism gives it), and the << + p = RubyContext.EffectiveParser(unit, new RubyCompilerOptions(), log); + Assert(p == null && log.FatalErrorCount == 3, String.Format("tree: {0}, fatal errors: {1}, errors: {2}", + p != null, log.FatalErrorCount, log.ErrorCount)); log.ClearCounters(); unit = Context.CreateSnippet(@" @@ -216,7 +218,7 @@ def bar() END { goo2() { } } ", SourceCodeKind.File); - p = new Parser().Parse(unit, new RubyCompilerOptions(), ErrorSink.Null); + p = RubyContext.EffectiveParser(unit, new RubyCompilerOptions(), ErrorSink.Null); Assert(p != null && !log.AnyError); log.ClearCounters(); @@ -226,7 +228,7 @@ def bar() end ", SourceCodeKind.File); - p = new Parser().Parse(unit, new RubyCompilerOptions(), ErrorSink.Null); + p = RubyContext.EffectiveParser(unit, new RubyCompilerOptions(), ErrorSink.Null); Assert(p != null && !log.AnyError); log.ClearCounters(); } @@ -293,7 +295,7 @@ class C puts x puts y -"); +", 1, 0); }, @" method var"); @@ -348,7 +350,7 @@ module N end end } -"); +", 1, 0); } public void NumericLiterals1() { @@ -518,7 +520,7 @@ puts begin x = ('E'; 'F') puts x -"); +", 1, 0); }, @" A bar @@ -872,7 +874,6 @@ p Time.local(2026, 7, 15, 12).to_i, Time.local(2026, 1, 15, 11).to_i /// kill() and raised DllNotFoundException. The child reads a pipe nobody writes to, so it runs /// until it is killed. File::NULL and Process.spawn are the prelude's (ruby4.rb), which needs prism. /// - [Options(Prism = true)] public void Process_SpawnKill1() { TestOutput(@" require 'ruby4' @@ -923,6 +924,63 @@ p got "); } + /// + /// What RubyGems and Bundler need from the file system on Windows, where each of these + /// used to P/Invoke libc or raise: File#flock (RubyGems locks every binstub it writes), + /// IO#readpartial after IO#eof? has filled the buffer (Bundler checksums every .gem that + /// way), and Process's resource limits, which MRI does not define on Windows at all - + /// net-http-persistent calls getrlimit whenever RLIMIT_NOFILE is defined. + /// + public void File_DriveLetters1() { + TestOutput(@" +require 'ruby4' +require 'pathname' +windows = File::ALT_SEPARATOR == '\\' +p File.dirname('A:') == (windows ? 'A:.' : '.') +p File.dirname('C:x') == (windows ? 'C:.' : '.'), File.basename('C:x') == (windows ? 'x' : 'C:x') +p Pathname.new('C:/x/y').absolute? == windows, Pathname.new('/x').absolute? +", @" +true +true +true +true +true +"); + } + + public void File_FlockReadpartialRlimit1() { + TestOutput(@" +require 'ruby4' +require 'tmpdir' +windows = File::ALT_SEPARATOR == '\\' +path = File.join(Dir.tmpdir, ""ir-flock-#{Process.pid}.lock"") + +a = File.open(path, 'w') +b = File.open(path, 'r') +p a.flock(File::LOCK_EX), b.flock(File::LOCK_SH | File::LOCK_NB) +p a.flock(File::LOCK_UN), b.flock(File::LOCK_SH | File::LOCK_NB), b.flock(File::LOCK_UN) +a.close +b.close + +File.binwrite(path, 'x' * 100_000) +total = 0 +File.open(path, 'rb') { |io| total += io.readpartial(16384).bytesize until io.eof? } +p total +File.delete(path) + +p Process.const_defined?(:RLIMIT_NOFILE) == !windows, Process.respond_to?(:getrlimit) == !windows +", @" +0 +false +0 +0 +0 +100000 +true +true +"); + } + /// /// A raw control character (U+0000-U+001F) inside a JSON string is a ParserError, as in the json gem; /// JSON.parse took a document with a literal line break in a value as it was. The gem's @@ -1275,7 +1333,7 @@ public void Numeric_BignumFloatOverflow1() { 1 true false -"); +", 1); } public void Numeric_BignumExponent1() { @@ -1904,7 +1962,6 @@ public void ManyLocals1() { /// A safe navigation call (a&.b) is lowered to a temporary local each, so a chain of 200 needs a scope of more /// than 128 locals (see ManyLocals1); the legacy parser cannot read the syntax. /// - [Options(Prism = true)] public void ManyLocals2() { TestOutput("p 1" + new System.Text.StringBuilder().Insert(0, "&.to_i", 200) + "\n", @" 1 @@ -1919,7 +1976,6 @@ public void ManyLocals2() { /// runs on a thread with the 1 MB stack of a Windows main thread, so every one of those overflowed at these /// depths before; lambdas and procs are made but not called, as calling them nests calls just as deep. /// - [Options(Prism = true)] public void DeepNesting1() { Func times = (str, n) => new System.Text.StringBuilder().Insert(0, str, n).ToString(); var code = new System.Text.StringBuilder(); diff --git a/Src/IronRuby.Tests/Runtime/ModuleTests.cs b/Src/IronRuby.Tests/Runtime/ModuleTests.cs index e862a5543..d73e709fb 100644 --- a/Src/IronRuby.Tests/Runtime/ModuleTests.cs +++ b/Src/IronRuby.Tests/Runtime/ModuleTests.cs @@ -349,7 +349,6 @@ p X /// first keyword parameter ("syntax error, unexpected label") - the require failed that /// way before it could touch the frozen Object. CRuby 4.0.6 prints the same three lines. /// - [Options(Prism = true)] public void ModuleFreezing1() { if (_driver.PartialTrust) return; diff --git a/Src/IronRuby.Tests/Runtime/NetHttpTlsTests.cs b/Src/IronRuby.Tests/Runtime/NetHttpTlsTests.cs index 2cee7d923..99982bfe7 100644 --- a/Src/IronRuby.Tests/Runtime/NetHttpTlsTests.cs +++ b/Src/IronRuby.Tests/Runtime/NetHttpTlsTests.cs @@ -54,7 +54,6 @@ def http(**opts) /// SSLSocket is a blocking SslStream; before Docs/net-http-over-tls.md stage 1 none of /// those timeouts fired and only the system trust store counted. net/http needs prism. /// - [Options(Prism = true)] public void NetHttp_Tls1() { using (var server = new TlsTestServer()) { TestOutput(NetHttpPrelude(server, true) + @" @@ -197,7 +196,6 @@ p s.post_connection_check('10.0.0.5') /// is a rejection with a warning. The error codes are OpenSSL's: 18 for a lone untrusted /// self-signed certificate, 10 expired, 9 not yet valid, 26 the wrong purpose. /// - [Options(Prism = true)] public void NetHttp_TlsVerifyCallback1() { using (var server = new TlsTestServer()) { TestOutput(NetHttpPrelude(server, true) + @" @@ -264,7 +262,6 @@ p s.verify_result /// and IO.select on #to_io and NIO::Selector see it finish. Bytes SslStream has already /// decrypted make the socket readable although the TCP socket under it is empty. /// - [Options(Prism = true)] public void Ssl_NonBlocking1() { using (var server = new TlsTestServer()) { TestOutput(@" @@ -382,7 +379,6 @@ p IO.select(nil, [s.to_io], nil, 0.2) /// its own Gem::Net errors. Nothing of it is patched: SSLSocket's non-blocking calls are /// what upstream's timeouts wait on. /// - [Options(Prism = true)] public void NetHttp_GemNetTls1() { using (var server = new TlsTestServer()) { TestOutput(@" @@ -429,7 +425,6 @@ p gem_http(:self).start { |h| h.get('/data?size=5').body } /// A plain HTTP request does not load openssl: IronRuby's net/protocol checks for its own /// SSLSocket without naming OpenSSL, which would run net/http's autoload. /// - [Options(Prism = true)] public void NetHttp_PlainNoOpenSsl1() { using (var server = new TlsTestServer()) { TestOutput(NetHttpPrelude(server, false) + @" diff --git a/Src/IronRuby.Tests/Runtime/NumberLiteralTests.cs b/Src/IronRuby.Tests/Runtime/NumberLiteralTests.cs new file mode 100644 index 000000000..814c32f44 --- /dev/null +++ b/Src/IronRuby.Tests/Runtime/NumberLiteralTests.cs @@ -0,0 +1,247 @@ +/* **************************************************************************** + * + * Copyright (c) Microsoft Corporation. + * + * This source code is subject to terms and conditions of the Apache License, Version 2.0. A + * copy of the license can be found in the License.html file at the root of this distribution. If + * you cannot locate the Apache License, Version 2.0, please send an email to + * ironruby@microsoft.com. By using this source code in any fashion, you are agreeing to be bound + * by the terms of the Apache License, Version 2.0. + * + * You must not remove this notice, or any other, from this software. + * + * + * ***************************************************************************/ + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Text; +using IronRuby.Builtins; +using IronRuby.Compiler; +using IronRuby.Runtime; +using IronRuby.Runtime.Calls; +using Microsoft.Scripting; +using Microsoft.Scripting.Hosting; +using System.Numerics; +using Microsoft.Scripting.Runtime; +using Microsoft.Scripting.Utils; + +namespace IronRuby.Tests { + /// + /// Integer and Bignum literals as the runtime parses them (String#to_i, Integer()), how a source's encoding is detected from its magic comment and preamble, and a first-run timing. Kept from the legacy parser's tests when that parser was removed. + /// + public partial class Tests { + // manual test, measures initialization and JIT times (hence it must be the first run) + public void Scenario_Startup() { + Stopwatch w = new Stopwatch(); + w.Start(); + Engine.CreateScriptSourceFromString("def foo; puts 2 + 2; end").Execute(Engine.CreateScope()); + w.Stop(); + Console.WriteLine("> total time: {0}ms", w.ElapsedMilliseconds); + } + + public void ParseBigInts1() { + TestBigInt("00010010000_00100000_01001000_00010000_00000010_01001000_11111111_00010000_00100000_00000011", 2); + TestBigInt("000100_afe1_1231_4980_6FEA_1470_5100_afe1_1231_4980_6FEA_1471", 16); + TestBigInt("65_6465477756_5454111111_1112365414_65_4365414564_5463215467_3215456713", 8); + TestBigInt("645456600_000798789_789798798_798789798_798765461_237676891_968734198_467346797", 10); + TestBigInt("hhs15489231dfu89765460z", 36); + TestBigInt("lafkhalkdhflkghalgAKD12", 28); + + for (int i = 3; i <= 36; i++) { + TestBigInt("00010010000_00100000_01001000_00010000_00000010_01001000_11111111_00010000_00100000_00000011", i, 0); + } + } + + public void ParseIntegers1() { + IntegerValue x; + Assert((x = Tokenizer.ParseInteger("", 0)).Equals(0)); + Assert((x = Tokenizer.ParseInteger("", 16)).Equals(0)); + Assert((x = Tokenizer.ParseInteger(" ", 0)).Equals(0)); + Assert((x = Tokenizer.ParseInteger("-", 0)).Equals(0)); + Assert((x = Tokenizer.ParseInteger("+", 0)).Equals(0)); + Assert((x = Tokenizer.ParseInteger("0", 0)).Equals(0)); + Assert((x = Tokenizer.ParseInteger("00", 0)).Equals(0)); + Assert((x = Tokenizer.ParseInteger("0x", 0)).Equals(0)); + Assert((x = Tokenizer.ParseInteger("0x", 0)).Equals(0)); + Assert((x = Tokenizer.ParseInteger("-0x", 0)).Equals(0)); + Assert((x = Tokenizer.ParseInteger("+0x", 0)).Equals(0)); + Assert((x = Tokenizer.ParseInteger(" 1234 ", 0)).Equals(1234)); + Assert((x = Tokenizer.ParseInteger(" 1_2_3_4 ", 0)).Equals(1234)); + Assert((x = Tokenizer.ParseInteger(" _1234 ", 0)).Equals(0)); + Assert((x = Tokenizer.ParseInteger(" 12a34 ", 0)).Equals(12)); + Assert((x = Tokenizer.ParseInteger(" 1_2__34 ", 0)).Equals(12)); + Assert((x = Tokenizer.ParseInteger(" -1_2", 0)).Equals(-12)); + Assert((x = Tokenizer.ParseInteger("0x1234", 0)).Equals(0x1234)); + Assert((x = Tokenizer.ParseInteger("0x1234", 10)).Equals(0)); + Assert((x = Tokenizer.ParseInteger("0b102", 0)).Equals(2)); + Assert((x = Tokenizer.ParseInteger("1000_000000_0000000000", 0)).Bignum.ToString() == "10000000000000000000"); + Assert((x = Tokenizer.ParseInteger("1000000_000000_0000000", 16)).Bignum.ToString() == "75557863725914323419136"); + Assert((x = Tokenizer.ParseInteger("0x1000000_000000_0000000", 0)).Bignum.ToString() == "75557863725914323419136"); + Assert((x = Tokenizer.ParseInteger("0b1000000_000000_0000000", 0)).Equals(524288)); + Assert((x = Tokenizer.ParseInteger("-0b1000000_000000_0000000", 0)).Equals(-524288)); + } + + // encodings suported in preamble: + private static readonly string[] preambleEncodingNames = + new[] { "ASCII-8BIT", "ASCII", "BINARY", "US-ASCII", "UTF-8", "EUC-JP", "SJIS", "SHIFT_JIS", "LOCALE", "FILESYSTEM" }; + + private void Encoding1() { + foreach (var name in preambleEncodingNames) { + var encoding = Context.GetEncodingByRubyName(name); + Assert(encoding != null); + + // the encoding must be an identity on ASCII characters: + Assert(RubyEncoding.AsciiIdentity(encoding)); + } + + foreach (var info in Encoding.GetEncodings()) { + var encoding = info.GetEncoding(); + + // doesn't blow up (the method checks itself): + RubyEncoding.AsciiIdentity(encoding); + + //Console.WriteLine("case " + info.CodePage + ": // " + encoding.EncodingName); + } + + } + + private void Encoding2() { + // The magic comment may be on the second line after a #! line that runs ruby; after any + // other #! line neither MRI nor prism looks there. + var source1 = Context.CreateSourceUnit(new BinaryContentProvider(BinaryEncoding.Instance.GetBytes( +@"#!/usr/bin/env ruby +# enCoding = ascii-8BIT + +p __ENCODING__ +")), null, Encoding.UTF8, SourceCodeKind.File); + + using (var reader = source1.GetReader()) { + Assert(reader.Encoding == BinaryEncoding.Instance); + } + + // The test used to expect "#", which no Ruby since 3.4 prints. + // Ruby 3.4 renamed the encoding to BINARY and made #inspect - and only #inspect, + // #name still answers "ASCII-8BIT" - show both spellings: + // + // $ ruby -v + // ruby 4.0.6 (2026-07-14 revision 03b6d3f889) +PRISM [x86_64-linux] + // $ printf '#!/usr/bin/env ruby\n# enCoding = ascii-8BIT\n\np __ENCODING__\n' > /tmp/e.rb + // $ ruby /tmp/e.rb + // # + // + // ruby/spec asserts the same thing - spec/core/encoding/inspect_spec.rb, under + // ruby_version_is "3.4", special-cases ASCII-8BIT to "#". + AssertOutput(() => source1.Execute(), @"#"); + + // default hosted encoding is UTF8: + var source2 = Context.CreateSnippet("p __ENCODING__", SourceCodeKind.Expression); + AssertOutput(() => source2.Execute(), @"#"); + } + + private void Encoding4() { + var enc = Engine.Execute(@"eval('# encoding: SJIS +__ENCODING__ +')"); + Assert(enc == RubyEncoding.SJIS); + } + + private void Encoding_Host1() { + Encoding_HostHelper(Encoding.UTF8, "\u0394", true); + Encoding_HostHelper(Encoding.UTF32, "\u0394", false); + } + + private void Encoding_HostHelper(Encoding/*!*/ encoding, string/*!*/ specialChars, bool shouldSucceed) { + var preamble = "# coding = " + encoding.WebName + "\r\n"; + var src = "$X = '" + specialChars + "'"; + + var content = new List(); + content.AddRange(BinaryEncoding.Instance.GetBytes(preamble)); + content.AddRange(encoding.GetBytes(src)); + + var source = Engine.CreateScriptSource(new BinaryContentProvider(content.ToArray()), null); + + // test encoding: + try { + var detectedEncoding = source.DetectEncoding(); + Assert(encoding.WebName == detectedEncoding.WebName); + } catch (IOException) { + Assert(!shouldSucceed); + } + + // test content: + try { + var code = source.GetCode(); + Assert(StringComparer.Ordinal.Equals(code, preamble + src)); + } catch (IOException) { + Assert(!shouldSucceed); + } + } + + // Ruby preamble overrides the encoding's preamble (BOM) + public void Encoding_Host2() { + var src = "# encoding: ASCII-8BIT\r\n$X = '\u0394'"; + var binsrc = Encoding.UTF8.GetBytes(src); + + var content = new List(); + content.AddRange(Encoding.UTF8.GetPreamble()); + content.AddRange(binsrc); + var source = Engine.CreateScriptSource(new BinaryContentProvider(content.ToArray()), null); + var encoding = source.DetectEncoding(); + Assert(encoding == BinaryEncoding.Instance); + var actualCode = source.GetCode(); + + // \u0394 is encoded in 2 bytes, which are represented by 2 characters in binary encoding: + Assert(actualCode.Length == src.Length + 1); + Assert(actualCode.Length == binsrc.Length); + } + + private void TestBigInt(string/*!*/ number, int @base) { + TestBigInt(number, @base, 10); + } + + private void TestBigInt(string/*!*/ number, int @base, int repeat) { + Stopwatch optimizedTime = new Stopwatch(); + Stopwatch universalTime = new Stopwatch(); + + StringBuilder n = new StringBuilder(number); + for (int j = 0; j < repeat; j++) { + n.Append(number); + } + number = n.ToString(); + + for (int i = 0; i < number.Length - 1; i++) { + string sub = number.Substring(i); + string s = sub.Replace("_", "").ToUpper(); + BigInteger b; + Tokenizer.BignumParser p = new Tokenizer.BignumParser(); + p.Position = 0; + p.Buffer = s.ToCharArray(); + + optimizedTime.Start(); + b = p.Parse(s.Length, @base); + optimizedTime.Stop(); + + Assert(b.ToString(@base) == s.TrimStart('0')); + + p.Position = 0; + + universalTime.Start(); + b = p.ParseDefault(s.Length, (uint)@base); + universalTime.Stop(); + + Assert(b.ToString(@base) == s.TrimStart('0')); + } + + if (repeat != 0) { + Console.WriteLine("{0}: optimized = {1}ms, universal = {2}ms", + @base, + optimizedTime.ElapsedMilliseconds, + universalTime.ElapsedMilliseconds); + } + } + } +} diff --git a/Src/IronRuby.Tests/Runtime/PumaTlsTests.cs b/Src/IronRuby.Tests/Runtime/PumaTlsTests.cs index c507181ae..943610ca4 100644 --- a/Src/IronRuby.Tests/Runtime/PumaTlsTests.cs +++ b/Src/IronRuby.Tests/Runtime/PumaTlsTests.cs @@ -34,7 +34,6 @@ public partial class Tests { /// port is turned away and puma serves on. The client certificates are presented by /// PumaTlsClient (.NET's SslStream), as IronRuby's SSLSocket has no client certificates. /// - [Options(Prism = true)] public void Puma_Tls1() { using (var files = new PumaTlsFiles()) { Runtime.Globals.SetVariable("MtlsClient", new PumaTlsClient(files.ClientPfx, files.RoguePfx)); diff --git a/Src/IronRuby.Tests/Runtime/RegexTests.cs b/Src/IronRuby.Tests/Runtime/RegexTests.cs index 6bfac9bfb..7a849f170 100644 --- a/Src/IronRuby.Tests/Runtime/RegexTests.cs +++ b/Src/IronRuby.Tests/Runtime/RegexTests.cs @@ -346,7 +346,7 @@ public void RegexCondition1() { if /(foo)/ then puts $1 end -"); +", 1, 0); }, @" foo "); @@ -367,12 +367,12 @@ class Regexp z = /foo/ puts(z =~ 'foo') -puts(/foo/ =~ 'xxxfoo') +puts(/foo/ =~ 'xxxfoo') # a literal calls a redefined Regexp#=~ too (MRI 1.9+) "); }, @" 3 =~ -3 +=~ "); } diff --git a/Src/IronRuby.Tests/Runtime/RubyUtilsTests.cs b/Src/IronRuby.Tests/Runtime/RubyUtilsTests.cs index 810cf9450..a2d262e63 100644 --- a/Src/IronRuby.Tests/Runtime/RubyUtilsTests.cs +++ b/Src/IronRuby.Tests/Runtime/RubyUtilsTests.cs @@ -21,6 +21,23 @@ namespace IronRuby.Tests { public partial class Tests { + /// + /// A binstub that Rails or RubyGems writes on IronRuby starts "#!/usr/bin/env ir.exe" + /// (from ruby_install_name), which has no "ruby" in it and would otherwise make the + /// command line and prism look for the program further down. + /// + public void ShebangNamesIronRuby1() { + Assert(RubyUtils.ShebangNamesIronRuby("#!/usr/bin/env ir.exe\"\nAPP_PATH = 1\n")); + Assert(RubyUtils.ShebangNamesIronRuby("#!/usr/bin/env ir\r\nputs 1")); + Assert(RubyUtils.ShebangNamesIronRuby("#!C:\\IronRuby\\ir.cmd")); + Assert(RubyUtils.ShebangNamesIronRuby("#!\"C:/Program Files/IronRuby/IR.EXE\" -w")); + Assert(!RubyUtils.ShebangNamesIronRuby("#!/bin/sh\nexec ruby -x \"$0\"")); + Assert(!RubyUtils.ShebangNamesIronRuby("#!/usr/bin/env irb")); + Assert(!RubyUtils.ShebangNamesIronRuby("#!/opt/dir/python")); + Assert(!RubyUtils.ShebangNamesIronRuby("puts 1 #!ir")); + Assert(!RubyUtils.ShebangNamesIronRuby("# !ir")); + } + public void NameMangling1() { Assert(RubyUtils.TryUnmangleName("stack") == "Stack"); Assert(RubyUtils.TryUnmangleName("this_is_my_long_name") == "ThisIsMyLongName"); diff --git a/Src/IronRuby.Tests/Runtime/StringTests.cs b/Src/IronRuby.Tests/Runtime/StringTests.cs index b5b2fbe60..d2e33f41b 100644 --- a/Src/IronRuby.Tests/Runtime/StringTests.cs +++ b/Src/IronRuby.Tests/Runtime/StringTests.cs @@ -59,7 +59,7 @@ public void Strings2() { puts ""foo#{1;2;3}baz"" ", @" foo3baz -"); +", 2); } public void Strings3() { @@ -89,7 +89,7 @@ class Integer; def to_s; 'N'; end; end -N+N -N+N- -bob- -"); +", 1); } public void Strings4() { @@ -128,7 +128,7 @@ class Integer; def to_s; 'N'; end; end puts :""-#{1}+#{1}-"" puts ""-#{x = 'bob'}-"" -"); +", 1, 0); }, @" N N- diff --git a/Src/IronRuby.Tests/Runtime/SuperTests.cs b/Src/IronRuby.Tests/Runtime/SuperTests.cs index b3478a246..c4f250851 100644 --- a/Src/IronRuby.Tests/Runtime/SuperTests.cs +++ b/Src/IronRuby.Tests/Runtime/SuperTests.cs @@ -64,7 +64,7 @@ D.new.foo 0 [] C.foo [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0] -" +", 2 ); } diff --git a/Src/IronRuby.Tests/Runtime/UndefTests.cs b/Src/IronRuby.Tests/Runtime/UndefTests.cs index 6ee31c585..0489d35ea 100644 --- a/Src/IronRuby.Tests/Runtime/UndefTests.cs +++ b/Src/IronRuby.Tests/Runtime/UndefTests.cs @@ -101,7 +101,7 @@ def w d.d2 d.u d.w -"); +", 1, 0); }, @" undefined method `d2' for class `C' M::m1 @@ -137,7 +137,7 @@ public void MethodUndefExpression() { CompilerTest(@" def u; end p ((undef u)) -", 1, 0); +", 0, 0); }, "nil"); } diff --git a/Src/Libraries/Builtins/FileOps.cs b/Src/Libraries/Builtins/FileOps.cs index 164cfe734..d259acbdb 100644 --- a/Src/Libraries/Builtins/FileOps.cs +++ b/Src/Libraries/Builtins/FileOps.cs @@ -582,9 +582,12 @@ public static int Rename(ConversionStorage/*!*/ toPath, RubyClass if (isWindows) { string first = parts[0]; if (strPath.Length >= 2 && IsDirectorySeparator(strPath[0]) && IsDirectorySeparator(strPath[1])) { - // UNC: skip 2 parts + // UNC: skip 2 parts. The root's base name is its trailing separator as written + // ("\\foo\bar\" gives "\"), or "/" when there is none (MRI). if (parts.Length <= 2) { - return MutableString.CreateMutable(path.Encoding).Append(DirectorySeparatorChar).TaintBy(path); + char lastChar = strPath[strPath.Length - 1]; + return MutableString.CreateMutable(path.Encoding) + .Append(IsDirectorySeparator(lastChar) ? lastChar : DirectorySeparatorChar).TaintBy(path); } } else if (first.Length == 2 && Tokenizer.IsLetter(first[0]) && first[1] == ':') { // skip drive letter "X:" @@ -599,6 +602,10 @@ public static int Rename(ConversionStorage/*!*/ toPath, RubyClass } string last = parts[parts.Length - 1]; + // "C:x" is x relative to drive C's current directory: its base name is "x" (MRI). + if (isWindows && parts.Length == 1 && IsDriveRelative(strPath)) { + last = last.Substring(2); + } if (MutableString.IsNullOrEmpty(suffix)) { return MutableString.CreateMutable(last, path.Encoding); } @@ -713,10 +720,37 @@ public static int Rename(ConversionStorage/*!*/ toPath, RubyClass return (rooted ? "/" : "") + rest.Substring(0, slash); } + /// + /// "C:" or "C:name" with no separator after the colon: a name relative to the current + /// directory of drive C. + /// + private static bool IsDriveRelative(string/*!*/ path) { + return path.Length >= 2 && Tokenizer.IsLetter(path[0]) && path[1] == ':' && + path.IndexOfAny(SeparatorChars, 2) < 0; + } + private static MutableString/*!*/ WindowsDirName(MutableString/*!*/ path) { string strPath = path.ConvertToString(); string directoryName = strPath; + // MRI: the directory of "C:" and of "C:x" is "C:.", the current directory of drive C. + // pathname tells a DOS-ish platform by File.dirname("A:") == "A:.", and without it + // Pathname#absolute? was false for every "C:/..." path. + if (IsDriveRelative(strPath)) { + return MutableString.CreateMutable(strPath.Substring(0, 2) + ".", path.Encoding); + } + + // More than two leading separators are a UNC prefix all the same: "\\\foo\bar" is + // \\foo\bar, the root of share bar on server foo (MRI). + int leading = 0; + while (leading < strPath.Length && IsDirectorySeparator(strPath[leading])) { + leading++; + } + if (leading > 2 && leading < strPath.Length) { + strPath = strPath.Substring(leading - 2); + directoryName = strPath; + } + if (IsValidPath(strPath)) { strPath = StripPathCharacters(strPath); @@ -1106,6 +1140,9 @@ internal static int GetNativeFileDescriptor(RubyIO/*!*/ io) { [RubyMethod("flock", BuildConfig = "FEATURE_FILESYSTEM")] public static object FileLock(RubyFile/*!*/ self, [DefaultProtocol]int operation) { self.RequireInitialized(); + if (Path.DirectorySeparatorChar == '\\') { + return WindowsFileLock(self, operation); + } if (!Posix.IsFlockAvailable) { throw new IronRuby.Builtins.NotImplementedError("flock() function is unimplemented on this machine"); } @@ -1137,6 +1174,69 @@ public static object FileLock(RubyFile/*!*/ self, [DefaultProtocol]int operation } } + private const int LOCKFILE_FAIL_IMMEDIATELY = 1; + private const int LOCKFILE_EXCLUSIVE_LOCK = 2; + private const int ERROR_LOCK_VIOLATION = 33; + private const int ERROR_NOT_LOCKED = 158; + private const int ERROR_IO_PENDING = 997; + + [System.Runtime.InteropServices.DllImport("kernel32", SetLastError = true)] + private static extern bool LockFileEx(Microsoft.Win32.SafeHandles.SafeFileHandle handle, int flags, int reserved, + uint lengthLow, uint lengthHigh, ref System.Threading.NativeOverlapped overlapped); + + [System.Runtime.InteropServices.DllImport("kernel32", SetLastError = true)] + private static extern bool UnlockFileEx(Microsoft.Win32.SafeHandles.SafeFileHandle handle, int reserved, + uint lengthLow, uint lengthHigh, ref System.Threading.NativeOverlapped overlapped); + + /// + /// flock on Windows, as CRuby's win32.c does it: LockFileEx/UnlockFileEx over the + /// whole file, shared or exclusive. A blocking lock polls with FAIL_IMMEDIATELY for + /// the reason the Posix path above does. RubyGems takes one for every binstub it + /// writes, so without it `gem install` of any gem with an executable failed. + /// + private static object WindowsFileLock(RubyFile/*!*/ self, int operation) { + var fs = self.GetStream().BaseStream as FileStream; + if (fs == null) { + throw RubyExceptions.CreateEBADF(); + } + // Windows locks are mandatory: what is buffered has to reach the file first. + fs.Flush(); + + var overlapped = new System.Threading.NativeOverlapped(); + if ((operation & Posix.LOCK_UN) != 0) { + if (!UnlockFileEx(fs.SafeFileHandle, 0, UInt32.MaxValue, UInt32.MaxValue, ref overlapped)) { + int error = System.Runtime.InteropServices.Marshal.GetLastWin32Error(); + // Unlocking a file that is not locked is not an error for flock(2). + if (error != ERROR_NOT_LOCKED) { + throw RubyExceptions.CreateEINVAL("{0}", self.Path); + } + } + return 0; + } + + int flags = LOCKFILE_FAIL_IMMEDIATELY; + if ((operation & Posix.LOCK_EX) != 0) { + flags |= LOCKFILE_EXCLUSIVE_LOCK; + } else if ((operation & Posix.LOCK_SH) == 0) { + throw RubyExceptions.CreateEINVAL("{0}", self.Path); + } + + while (true) { + overlapped = new System.Threading.NativeOverlapped(); + if (LockFileEx(fs.SafeFileHandle, flags, 0, UInt32.MaxValue, UInt32.MaxValue, ref overlapped)) { + return 0; + } + int error = System.Runtime.InteropServices.Marshal.GetLastWin32Error(); + if (error != ERROR_LOCK_VIOLATION && error != ERROR_IO_PENDING) { + throw RubyExceptions.CreateEINVAL("{0}", self.Path); + } + if ((operation & Posix.LOCK_NB) != 0) { + return false; + } + System.Threading.Thread.Sleep(10); + } + } + [RubyMethod("readlink", RubyMethodAttributes.PublicSingleton, BuildConfig = "FEATURE_FILESYSTEM")] public static MutableString/*!*/ Readlink(ConversionStorage/*!*/ toPath, RubyClass/*!*/ self, object path) { string strPath = self.Context.DecodePath(Protocols.CastToPath(toPath, path)); @@ -1299,7 +1399,17 @@ public static int MakeFifo(ConversionStorage/*!*/ toPath, RubyCla : self.Context.DecodePath(Protocols.CastToPath(toPath, basedir)); if (!Posix.IsAvailable) { - return ExpandPath(toPath, self, path, basedir == Missing.Value ? null : basedir); + MutableString expanded = ExpandPath(toPath, self, path, basedir == Missing.Value ? null : basedir); + + // No realpath(3) here, so links are not resolved; but what has to exist does, as in + // MRI: the whole path for realpath, all but the last component for realdirpath. + // pry asks Pathname#realpath whether a ./.pryrc is there and expects ENOENT if not. + string full = self.Context.DecodePath(expanded).TrimEnd('/', '\\'); + string mustExist = strict ? full : System.IO.Path.GetDirectoryName(full); + if (!String.IsNullOrEmpty(mustExist) && !System.IO.File.Exists(mustExist) && !System.IO.Directory.Exists(mustExist)) { + throw RubyExceptions.CreateENOENT("{0}", strPath); + } + return expanded; } string resolved = ResolvePath(self.Context, strPath, strBase, strict); diff --git a/Src/Libraries/Builtins/InternalMethods.Generated.cs b/Src/Libraries/Builtins/InternalMethods.Generated.cs new file mode 100644 index 000000000..a0d02ea62 --- /dev/null +++ b/Src/Libraries/Builtins/InternalMethods.Generated.cs @@ -0,0 +1,324 @@ +// Generated by Util/gen-internal-methods.rb from ruby 4.0.1 (2026-01-13 revision e04267a14b) +PRISM [x64-mingw-ucrt]; do not edit. +// The core methods CRuby writes in Ruby, and the file Method#source_location names for each. +using System.Collections.Generic; + +namespace IronRuby.Builtins { + internal static class InternalMethods { + internal static readonly Dictionary/*!*/ SourceFiles = new Dictionary { + { "Array#fetch_values", "" }, + { "Array#first", "" }, + { "Array#last", "" }, + { "Array#pack", "" }, + { "Array#sample", "" }, + { "Array#shuffle", "" }, + { "Array#shuffle!", "" }, + { "Binding#irb", "" }, + { "Dir#initialize", "" }, + { "Dir.[]", "" }, + { "Dir.glob", "" }, + { "Dir.open", "" }, + { "Enumerable#to_set", "" }, + { "Float#-@", "" }, + { "Float#abs", "" }, + { "Float#magnitude", "" }, + { "Float#negative?", "" }, + { "Float#positive?", "" }, + { "Float#to_f", "" }, + { "Float#zero?", "" }, + { "GC#garbage_collect", "" }, + { "GC.config", "" }, + { "GC.count", "" }, + { "GC.disable", "" }, + { "GC.enable", "" }, + { "GC.latest_gc_info", "" }, + { "GC.measure_total_time", "" }, + { "GC.measure_total_time=", "" }, + { "GC.start", "" }, + { "GC.stat", "" }, + { "GC.stat_heap", "" }, + { "GC.stress", "" }, + { "GC.stress=", "" }, + { "GC.total_time", "" }, + { "Hash#initialize", "" }, + { "IO#read_nonblock", "" }, + { "IO#readline", "" }, + { "IO#write_nonblock", "" }, + { "Integer#-@", "" }, + { "Integer#abs", "" }, + { "Integer#bit_length", "" }, + { "Integer#ceildiv", "" }, + { "Integer#denominator", "" }, + { "Integer#even?", "" }, + { "Integer#integer?", "" }, + { "Integer#magnitude", "" }, + { "Integer#numerator", "" }, + { "Integer#odd?", "" }, + { "Integer#ord", "" }, + { "Integer#size", "" }, + { "Integer#times", "" }, + { "Integer#to_i", "" }, + { "Integer#to_int", "" }, + { "Integer#zero?", "" }, + { "Integer#~", "" }, + { "Kernel#Float", "" }, + { "Kernel#Integer", "" }, + { "Kernel#Pathname", "" }, + { "Kernel#class", "" }, + { "Kernel#clone", "" }, + { "Kernel#frozen?", "" }, + { "Kernel#loop", "" }, + { "Kernel#pp", "" }, + { "Kernel#tap", "" }, + { "Kernel#then", "" }, + { "Kernel#warn", "" }, + { "Kernel#yield_self", "" }, + { "Kernel.Float", "" }, + { "Kernel.Integer", "" }, + { "Kernel.Pathname", "" }, + { "Kernel.loop", "" }, + { "Kernel.warn", "" }, + { "Marshal.load", "" }, + { "Marshal.restore", "" }, + { "NilClass#rationalize", "" }, + { "NilClass#to_c", "" }, + { "NilClass#to_f", "" }, + { "NilClass#to_i", "" }, + { "NilClass#to_r", "" }, + { "Numeric#+@", "" }, + { "Numeric#conj", "" }, + { "Numeric#conjugate", "" }, + { "Numeric#dup", "" }, + { "Numeric#finite?", "" }, + { "Numeric#imag", "" }, + { "Numeric#imaginary", "" }, + { "Numeric#infinite?", "" }, + { "Numeric#integer?", "" }, + { "Numeric#real", "" }, + { "Numeric#real?", "" }, + { "ObjectSpace#garbage_collect", "" }, + { "ObjectSpace.garbage_collect", "" }, + { "Pathname#+", "" }, + { "Pathname#/", "" }, + { "Pathname#==", "" }, + { "Pathname#===", "" }, + { "Pathname#absolute?", "" }, + { "Pathname#add_trailing_separator", "" }, + { "Pathname#ascend", "" }, + { "Pathname#atime", "" }, + { "Pathname#basename", "" }, + { "Pathname#binread", "" }, + { "Pathname#binwrite", "" }, + { "Pathname#birthtime", "" }, + { "Pathname#blockdev?", "" }, + { "Pathname#chardev?", "" }, + { "Pathname#children", "" }, + { "Pathname#chmod", "" }, + { "Pathname#chop_basename", "" }, + { "Pathname#chown", "" }, + { "Pathname#cleanpath", "" }, + { "Pathname#cleanpath_aggressive", "" }, + { "Pathname#cleanpath_conservative", "" }, + { "Pathname#ctime", "" }, + { "Pathname#del_trailing_separator", "" }, + { "Pathname#delete", "" }, + { "Pathname#descend", "" }, + { "Pathname#directory?", "" }, + { "Pathname#dirname", "" }, + { "Pathname#each_child", "" }, + { "Pathname#each_entry", "" }, + { "Pathname#each_filename", "" }, + { "Pathname#each_line", "" }, + { "Pathname#empty?", "" }, + { "Pathname#entries", "" }, + { "Pathname#eql?", "" }, + { "Pathname#executable?", "" }, + { "Pathname#executable_real?", "" }, + { "Pathname#exist?", "" }, + { "Pathname#expand_path", "" }, + { "Pathname#extname", "" }, + { "Pathname#file?", "" }, + { "Pathname#fnmatch", "" }, + { "Pathname#fnmatch?", "" }, + { "Pathname#freeze", "" }, + { "Pathname#ftype", "" }, + { "Pathname#glob", "" }, + { "Pathname#grpowned?", "" }, + { "Pathname#has_trailing_separator?", "" }, + { "Pathname#hash", "" }, + { "Pathname#initialize", "" }, + { "Pathname#inspect", "" }, + { "Pathname#join", "" }, + { "Pathname#lchmod", "" }, + { "Pathname#lchown", "" }, + { "Pathname#lstat", "" }, + { "Pathname#lutime", "" }, + { "Pathname#make_link", "" }, + { "Pathname#make_symlink", "" }, + { "Pathname#mkdir", "" }, + { "Pathname#mkpath", "" }, + { "Pathname#mountpoint?", "" }, + { "Pathname#mtime", "" }, + { "Pathname#open", "" }, + { "Pathname#opendir", "" }, + { "Pathname#owned?", "" }, + { "Pathname#parent", "" }, + { "Pathname#path", "" }, + { "Pathname#pipe?", "" }, + { "Pathname#plus", "" }, + { "Pathname#prepend_prefix", "" }, + { "Pathname#read", "" }, + { "Pathname#readable?", "" }, + { "Pathname#readable_real?", "" }, + { "Pathname#readlines", "" }, + { "Pathname#readlink", "" }, + { "Pathname#realdirpath", "" }, + { "Pathname#realpath", "" }, + { "Pathname#relative?", "" }, + { "Pathname#relative_path_from", "" }, + { "Pathname#rename", "" }, + { "Pathname#rmdir", "" }, + { "Pathname#root?", "" }, + { "Pathname#same_paths?", "" }, + { "Pathname#setgid?", "" }, + { "Pathname#setuid?", "" }, + { "Pathname#size", "" }, + { "Pathname#size?", "" }, + { "Pathname#socket?", "" }, + { "Pathname#split", "" }, + { "Pathname#split_names", "" }, + { "Pathname#stat", "" }, + { "Pathname#sticky?", "" }, + { "Pathname#sub_ext", "" }, + { "Pathname#symlink?", "" }, + { "Pathname#sysopen", "" }, + { "Pathname#to_path", "" }, + { "Pathname#to_s", "" }, + { "Pathname#truncate", "" }, + { "Pathname#unlink", "" }, + { "Pathname#utime", "" }, + { "Pathname#world_readable?", "" }, + { "Pathname#world_writable?", "" }, + { "Pathname#writable?", "" }, + { "Pathname#writable_real?", "" }, + { "Pathname#write", "" }, + { "Pathname#zero?", "" }, + { "Pathname.getwd", "" }, + { "Pathname.glob", "" }, + { "Pathname.pwd", "" }, + { "Ractor#<<", "" }, + { "Ractor#[]", "" }, + { "Ractor#[]=", "" }, + { "Ractor#close", "" }, + { "Ractor#default_port", "" }, + { "Ractor#inspect", "" }, + { "Ractor#join", "" }, + { "Ractor#monitor", "" }, + { "Ractor#name", "" }, + { "Ractor#receive", "" }, + { "Ractor#recv", "" }, + { "Ractor#send", "" }, + { "Ractor#to_s", "" }, + { "Ractor#unmonitor", "" }, + { "Ractor#value", "" }, + { "Ractor.[]", "" }, + { "Ractor.[]=", "" }, + { "Ractor._activated", "" }, + { "Ractor._require", "" }, + { "Ractor.count", "" }, + { "Ractor.current", "" }, + { "Ractor.main", "" }, + { "Ractor.main?", "" }, + { "Ractor.make_shareable", "" }, + { "Ractor.new", "" }, + { "Ractor.receive", "" }, + { "Ractor.recv", "" }, + { "Ractor.select", "" }, + { "Ractor.shareable?", "" }, + { "Ractor.shareable_lambda", "" }, + { "Ractor.shareable_proc", "" }, + { "Ractor.store_if_absent", "" }, + { "Ractor::Port#<<", "" }, + { "Ractor::Port#close", "" }, + { "Ractor::Port#closed?", "" }, + { "Ractor::Port#inspect", "" }, + { "Ractor::Port#receive", "" }, + { "Ractor::Port#send", "" }, + { "Ractor::RemoteError#ractor", "" }, + { "RubyVM::AbstractSyntaxTree.node_id_for_backtrace_location", "" }, + { "RubyVM::AbstractSyntaxTree.of", "" }, + { "RubyVM::AbstractSyntaxTree.parse", "" }, + { "RubyVM::AbstractSyntaxTree.parse_file", "" }, + { "RubyVM::AbstractSyntaxTree::Location#first_column", "" }, + { "RubyVM::AbstractSyntaxTree::Location#first_lineno", "" }, + { "RubyVM::AbstractSyntaxTree::Location#inspect", "" }, + { "RubyVM::AbstractSyntaxTree::Location#last_column", "" }, + { "RubyVM::AbstractSyntaxTree::Location#last_lineno", "" }, + { "RubyVM::AbstractSyntaxTree::Node#all_tokens", "" }, + { "RubyVM::AbstractSyntaxTree::Node#children", "" }, + { "RubyVM::AbstractSyntaxTree::Node#first_column", "" }, + { "RubyVM::AbstractSyntaxTree::Node#first_lineno", "" }, + { "RubyVM::AbstractSyntaxTree::Node#inspect", "" }, + { "RubyVM::AbstractSyntaxTree::Node#last_column", "" }, + { "RubyVM::AbstractSyntaxTree::Node#last_lineno", "" }, + { "RubyVM::AbstractSyntaxTree::Node#locations", "" }, + { "RubyVM::AbstractSyntaxTree::Node#node_id", "" }, + { "RubyVM::AbstractSyntaxTree::Node#script_lines", "" }, + { "RubyVM::AbstractSyntaxTree::Node#source", "" }, + { "RubyVM::AbstractSyntaxTree::Node#tokens", "" }, + { "RubyVM::AbstractSyntaxTree::Node#type", "" }, + { "String#unpack", "" }, + { "String#unpack1", "" }, + { "Symbol#id2name", "" }, + { "Symbol#intern", "" }, + { "Symbol#name", "" }, + { "Symbol#to_s", "" }, + { "Symbol#to_sym", "" }, + { "Thread::ConditionVariable#broadcast", "" }, + { "Thread::ConditionVariable#initialize", "" }, + { "Thread::ConditionVariable#marshal_dump", "" }, + { "Thread::ConditionVariable#signal", "" }, + { "Thread::ConditionVariable#wait", "" }, + { "Thread::Mutex#initialize", "" }, + { "Thread::Mutex#lock", "" }, + { "Thread::Mutex#locked?", "" }, + { "Thread::Mutex#owned?", "" }, + { "Thread::Mutex#sleep", "" }, + { "Thread::Mutex#synchronize", "" }, + { "Thread::Mutex#try_lock", "" }, + { "Thread::Mutex#unlock", "" }, + { "Thread::Queue#deq", "" }, + { "Thread::Queue#pop", "" }, + { "Thread::Queue#shift", "" }, + { "Thread::SizedQueue#<<", "" }, + { "Thread::SizedQueue#deq", "" }, + { "Thread::SizedQueue#enq", "" }, + { "Thread::SizedQueue#pop", "" }, + { "Thread::SizedQueue#push", "" }, + { "Thread::SizedQueue#shift", "" }, + { "Time#initialize", "" }, + { "Time.at", "" }, + { "Time.now", "" }, + { "TracePoint#binding", "" }, + { "TracePoint#callee_id", "" }, + { "TracePoint#defined_class", "" }, + { "TracePoint#disable", "" }, + { "TracePoint#enable", "" }, + { "TracePoint#enabled?", "" }, + { "TracePoint#eval_script", "" }, + { "TracePoint#event", "" }, + { "TracePoint#inspect", "" }, + { "TracePoint#instruction_sequence", "" }, + { "TracePoint#lineno", "" }, + { "TracePoint#method_id", "" }, + { "TracePoint#parameters", "" }, + { "TracePoint#path", "" }, + { "TracePoint#raised_exception", "" }, + { "TracePoint#return_value", "" }, + { "TracePoint#self", "" }, + { "TracePoint.allow_reentry", "" }, + { "TracePoint.new", "" }, + { "TracePoint.stat", "" }, + { "TracePoint.trace", "" }, + }; + } +} diff --git a/Src/Libraries/Builtins/IoOps.cs b/Src/Libraries/Builtins/IoOps.cs index 260230e74..be7447bc3 100644 --- a/Src/Libraries/Builtins/IoOps.cs +++ b/Src/Libraries/Builtins/IoOps.cs @@ -1219,12 +1219,19 @@ public static int FileControl(RubyIO/*!*/ self, [DefaultProtocol]int commandId, // 0, true passes 1, an Integer passes itself, and a String is the buffer the call reads // and writes - grown first to the size the request encodes, 256 bytes at least (MRI's // DEFAULT_IOCTL_NARG_LEN), and left at that size. + // + // Windows has no ioctl(2): there MRI defines the method as rb_f_notimplement, so it raises + // NotImplementedError and #respond_to? denies it - tty-screen, for one, asks before it calls. [RubyMethod("ioctl")] + [RubyNotImplemented(OnWindowsOnly = true)] public static int IoControl(CallSiteStorage>/*!*/ newStorage, RubyIO/*!*/ self, [DefaultProtocol]IntegerValue request, [Optional]object arg) { self.GetStream(); + if (!Posix.IsAvailable) { + throw new IronRuby.Builtins.NotImplementedError("ioctl() function is unimplemented on this machine"); + } int fd = self.KernelDescriptor; - if (fd < 0 || !Posix.IsAvailable) { + if (fd < 0) { throw new NotSupportedException(); } @@ -1934,7 +1941,7 @@ private static MutableString ReadOnceWithoutWaiting(RubyIO/*!*/ io, int count, M // for more: an ordinary read that would block raises EAGAIN out of here, and the // bytes taken out of the buffer would go with it and not be in the descriptor to // be read again. - if (buffered > 0 && !DescriptorStream.IsReadableNow(RubyIO.DescriptorOf(stream.BaseStream))) { + if (buffered > 0 && !IoReadiness.IsReadableNow(io, stream.BaseStream)) { return buffer; } int more = io.AppendBytes(buffer, count); diff --git a/Src/Libraries/Builtins/IoReadiness.cs b/Src/Libraries/Builtins/IoReadiness.cs index b12ce7928..429417fab 100644 --- a/Src/Libraries/Builtins/IoReadiness.cs +++ b/Src/Libraries/Builtins/IoReadiness.cs @@ -193,6 +193,7 @@ private static extern bool PeekNamedPipe(Microsoft.Win32.SafeHandles.SafeFileHan [System.Runtime.InteropServices.DllImport("kernel32.dll")] private static extern int GetFileType(Microsoft.Win32.SafeHandles.SafeFileHandle handle); + private const int FILE_TYPE_DISK = 1; private const int FILE_TYPE_PIPE = 3; /// @@ -231,6 +232,32 @@ internal static bool IsWindowsPipeReadable(System.IO.FileStream/*!*/ pipe) { #endregion + /// + /// Whether a read from the IO's stream would return at once. Asked where a read already + /// has bytes in hand and must not risk blocking with them. poll(2) on Unix; on Windows, + /// where there is no libc to poll with, the socket, the pipe or the disk file is asked + /// itself - a disk file is always readable, as poll(2) says of a regular file. + /// + internal static bool IsReadableNow(RubyIO/*!*/ io, System.IO.Stream/*!*/ baseStream) { + if (_isUnix) { + return DescriptorStream.IsReadableNow(RubyIO.DescriptorOf(baseStream)); + } + var socketStream = baseStream as SocketStream; + if (socketStream != null) { + return socketStream.Socket.Poll(0, SelectMode.SelectRead); + } + var pipe = GetWindowsPipe(io); + if (pipe != null) { + return IsWindowsPipeReadable(pipe); + } + var file = baseStream as System.IO.FileStream; + try { + return file != null && GetFileType(file.SafeFileHandle) == FILE_TYPE_DISK; + } catch (Exception) { + return false; + } + } + /// /// Whether any of can only tell the waiter about a change - an /// in-process pipe, or an IO with a readiness hook - so that a wait needs one. diff --git a/Src/Libraries/Builtins/ModuleOps.cs b/Src/Libraries/Builtins/ModuleOps.cs index 23ea46a52..de88a4acf 100644 --- a/Src/Libraries/Builtins/ModuleOps.cs +++ b/Src/Libraries/Builtins/ModuleOps.cs @@ -678,7 +678,14 @@ private static void DefineAccessor(RubyScope/*!*/ scope, RubyModule/*!*/ self, s // top-level `def` is, and taking them left reline's Reline::Core readers private // where MRI's are public. MRI reads the visibility only off a class or module // body; anywhere else attr_reader defines public methods. - var visibility = attributesScope.IsEmpty ? RubyMethodVisibility.Public : attributesScope.Visibility; + // + // The same holds for a frame whose self is some other object: MRI's rb_attr takes the + // scope's visibility only when the caller's self is the module itself + // (rb_vm_cref_in_context). importmap-rails does + // `Rails::Application.send(:attr_accessor, :importmap)` at the top level of a file, + // where the default is private, and Rails then calls `app.importmap = ...`. + var visibility = (attributesScope.IsEmpty || !ReferenceEquals(attributesScope.SelfObject, self)) + ? RubyMethodVisibility.Public : attributesScope.Visibility; if (definedNames != null) { var context = scope.RubyContext; diff --git a/Src/Libraries/Builtins/UnboundMethod.cs b/Src/Libraries/Builtins/UnboundMethod.cs index d0127ace7..795dc5f82 100644 --- a/Src/Libraries/Builtins/UnboundMethod.cs +++ b/Src/Libraries/Builtins/UnboundMethod.cs @@ -342,13 +342,28 @@ public static RubyArray GetSourceLocation(UnboundMethod/*!*/ self) { return self.Info.GetRubyParameterArray(); } + // "Kernel#tap", "Dir.glob": how InternalMethods.SourceFiles names a method. + private static string/*!*/ InternalMethodKey(RubyMethodInfo/*!*/ info) { + RubyModule owner = info.DeclaringModule; + var singleton = owner.IsSingletonClass ? ((RubyClass)owner).SingletonClassOf as RubyModule : null; + return (singleton != null) + ? singleton.Name + "." + info.DefinitionName + : owner.Name + "#" + info.DefinitionName; + } + internal static RubyArray GetSourceLocation(RubyMemberInfo/*!*/ info) { RubyMethodInfo rubyInfo = info as RubyMethodInfo; if (rubyInfo != null) { string file = rubyInfo.Document.FileName; - // a core method written in Ruby is where MRI's are: and the like - if (RubyStackTraceBuilder.IsInternalFile(file) && rubyInfo.DeclaringModule.Name != null) { - file = ""; + // A core method IronRuby writes in Ruby is located where MRI's is when MRI writes it + // in Ruby too ( for Kernel#tap); where MRI's is C, it has no + // location at all, as a C method has none - method_source and pry rely on that. + if (RubyStackTraceBuilder.IsInternalFile(file)) { + string mriFile; + if (!InternalMethods.SourceFiles.TryGetValue(InternalMethodKey(rubyInfo), out mriFile)) { + return null; + } + file = mriFile; } return new RubyArray(2) { rubyInfo.DeclaringModule.Context.EncodePath(file), diff --git a/Src/Libraries/ParseTree/IronRubyParseTreeOps.cs b/Src/Libraries/ParseTree/IronRubyParseTreeOps.cs index b55750640..606787256 100644 --- a/Src/Libraries/ParseTree/IronRubyParseTreeOps.cs +++ b/Src/Libraries/ParseTree/IronRubyParseTreeOps.cs @@ -71,7 +71,7 @@ public static class ParseTreeOps { var options = RubyUtils.CreateCompilerOptionsForEval(scope, line); - SourceUnitTree ast = new Parser().Parse(source, options, scope.RubyContext.RuntimeErrorSink); + SourceUnitTree ast = RubyContext.EffectiveParser(source, options, scope.RubyContext.RuntimeErrorSink); // TODO: // bool includeNewLines = IncludeNewLines(scope.RubyContext, self); var visitor = new AstVisitor(scope.RubyContext, GetNodeNames(scope.RubyContext, self), false); diff --git a/Src/Libraries/Socket/Socket.cs b/Src/Libraries/Socket/Socket.cs index 979306974..970ce56ce 100644 --- a/Src/Libraries/Socket/Socket.cs +++ b/Src/Libraries/Socket/Socket.cs @@ -735,20 +735,19 @@ private static int ParseInteger(RubyContext/*!*/ context, string/*!*/ str) { str = str.Remove(0, 1); } - Tokenizer tokenizer = new Tokenizer(); - tokenizer.Initialize(new StringReader(str)); - Tokens token = tokenizer.GetNextToken(); - TokenValue value = tokenizer.TokenValue; - Tokens nextToken = tokenizer.GetNextToken(); - - // We are only interested in the whole string being a valid Integer - if (token == Tokens.Integer && nextToken == Tokens.Integer) { - return isNegative ? -value.Integer1 : value.Integer1; - } else { - throw RubyExceptions.CreateImplicitConversionError("String", "Integer"); + // The whole string has to be one Ruby integer literal that fits a Fixnum. + if (IntegerLiteral.IsMatch(str)) { + IntegerValue value = Tokenizer.ParseInteger(str, 0); + if (value.IsFixnum) { + return isNegative ? -value.Fixnum : value.Fixnum; + } } + throw RubyExceptions.CreateImplicitConversionError("String", "Integer"); } + private static readonly System.Text.RegularExpressions.Regex IntegerLiteral = new System.Text.RegularExpressions.Regex( + @"\A(?:0[xX][0-9a-fA-F]+(?:_[0-9a-fA-F]+)*|0[bB][01]+(?:_[01]+)*|0[dD][0-9]+(?:_[0-9]+)*|0[oO]?[0-7]+(?:_[0-7]+)*|[1-9][0-9]*(?:_[0-9]+)*|0)\z"); + #endregion } } diff --git a/Src/Prism/PrismAstBridge.cs b/Src/Prism/PrismAstBridge.cs index 2678edd72..e3a26f3f9 100644 --- a/Src/Prism/PrismAstBridge.cs +++ b/Src/Prism/PrismAstBridge.cs @@ -79,7 +79,13 @@ public static SourceUnitTree Parse(SourceUnit/*!*/ sourceUnit, RubyCompilerOptio commandLine = CommandLineFlags(context.RubyOptions, sourceUnit.Path); mainScript = sourceUnit.Path != "-e"; } - return ParseText(sourceUnit.GetCode(), sourceUnit.Path, options.LocalNames, sourceUnit, errorSink, + string code = sourceUnit.GetCode(); + // Prism, told this is the main script, would skip a #! line without "ruby" in it to + // look for one that has; a binstub that names IronRuby's launcher is already Ruby. + if (mainScript && (commandLine & 0x20) == 0 && RubyUtils.ShebangNamesIronRuby(code)) { + mainScript = false; + } + return ParseText(code, sourceUnit.Path, options.LocalNames, sourceUnit, errorSink, options.InitialLocation.Line, options.IsEval && options.TopLevelMethodName == null, options.IsEval, options.EvalSourceEncoding, commandLine, mainScript); } @@ -388,7 +394,11 @@ private static Pm.PmNode HoistPreExecution(Pm.PmNode statementsNode) { var hoisted = new List(); var rest = new List(); foreach (var n in loopBody.Body) { - (n is Pm.PreExecutionNode ? hoisted : rest).Add(n); + if (n is Pm.PreExecutionNode preExec) { + CollectPreExecution(preExec, hoisted); + } else { + rest.Add(n); + } } loop.Statements = new Pm.StatementsNode { Body = rest.ToArray(), StartOffset = loopBody.StartOffset, Length = loopBody.Length, Flags = loopBody.Flags @@ -404,7 +414,7 @@ private static Pm.PmNode HoistPreExecution(Pm.PmNode statementsNode) { } var reordered = new List(); foreach (var n in statements.Body) { - if (n is Pm.PreExecutionNode) reordered.Add(n); + if (n is Pm.PreExecutionNode preExec) CollectPreExecution(preExec, reordered); } foreach (var n in statements.Body) { if (!(n is Pm.PreExecutionNode)) reordered.Add(n); @@ -414,6 +424,28 @@ private static Pm.PmNode HoistPreExecution(Pm.PmNode statementsNode) { }; } + /// + /// Adds a BEGIN block to , after the BEGIN blocks written inside it: + /// MRI's parser registers a BEGIN when it is closed, so `BEGIN { a; BEGIN { b } }` runs b + /// first, and then a without the inner block. + /// + private static void CollectPreExecution(Pm.PreExecutionNode/*!*/ node, List/*!*/ into) { + if (node.Statements is Pm.StatementsNode body && Array.Exists(body.Body, n => n is Pm.PreExecutionNode)) { + var rest = new List(); + foreach (var n in body.Body) { + if (n is Pm.PreExecutionNode inner) { + CollectPreExecution(inner, into); + } else { + rest.Add(n); + } + } + node.Statements = new Pm.StatementsNode { + Body = rest.ToArray(), StartOffset = body.StartOffset, Length = body.Length, Flags = body.Flags + }; + } + into.Add(node); + } + private Statements/*!*/ BuildStatements(Pm.PmNode statementsNode) { var result = new Statements(); if (statementsNode is Pm.StatementsNode statements) { diff --git a/Src/Prism/Program.cs b/Src/Prism/Program.cs index 8c6cacabd..7ec1b2c40 100644 --- a/Src/Prism/Program.cs +++ b/Src/Prism/Program.cs @@ -6,7 +6,7 @@ namespace IronRuby.Prism { internal static class Program { private static int Main(string[] args) { if (args.Length == 2 && args[0] == "--run") { - // execute a Ruby file with prism as the front end (legacy parser bypassed) + // execute a Ruby file with prism as the front end IronRuby.Runtime.RubyContext.AlternativeParser = PrismAstBridge.Parse; var engine = IronRuby.Ruby.CreateEngine(); engine.CreateScriptSourceFromFile(System.IO.Path.GetFullPath(args[1])).Execute(); diff --git a/Src/Prism/README.md b/Src/Prism/README.md index 1f1fa69f8..eedda8068 100644 --- a/Src/Prism/README.md +++ b/Src/Prism/README.md @@ -1,9 +1,12 @@ # IronRuby.Prism — CRuby's parser as an IronRuby front end Binding of [ruby/prism](https://github.com/ruby/prism), the parser CRuby -uses, via P/Invoke to `libprism.so`. Replaces the hand-ported 1.9-era -`Tokenizer.cs` + gppg `Parser.y` front end with the same parser CRuby, -JRuby and TruffleRuby use, targeting current (4.x-level) Ruby syntax. +uses, via P/Invoke to `libprism.so`. It is IronRuby's only parser: it replaced the +hand-ported 1.9-era `Tokenizer.cs` + gppg `Parser.y` front end, which has been +removed, with the same parser CRuby, JRuby and TruffleRuby use, targeting current +(4.x-level) Ruby syntax. Of the old `Tokenizer` only its static helpers remain - the +rules for Ruby names, number literals and the encoding magic comment, which the +runtime asks about at run time. Architecture (the JRuby approach): @@ -35,8 +38,7 @@ Architecture (the JRuby approach): `**rest` extraction), `it`/numbered params become explicit block params, `**` splats in literals/calls become `Hash#merge` chains, `2r`/`2i` become `Rational`/`Complex` calls. -5. Syntax errors from prism are reported through the DLR `ErrorSink` - like the legacy parser's. +5. Syntax errors from prism are reported through the DLR `ErrorSink`. 6. `PrismLex.cs` decodes `pm_serialize_lex` - prism's token stream with the MRI lexer state each token left behind. Ripper is built on it (`Src/Libraries/Ripper/RipperOps.cs`, `Src/StdLib/ironruby/ripper.rb`). @@ -46,9 +48,10 @@ not the other way round, so that the Ripper library can call in here. ## Status -- **`ir -X:UsePrism file.rb` works**: the console flag swaps the front end - for everything, including `require`d stdlib and `eval` (outer eval - locals are passed to prism as a scope via the options blob). +- **Prism parses everything**: the main program, `require`d files and + `eval` (outer eval locals are passed to prism as a scope via the + options blob). `-X:UsePrism`, which once chose it over the legacy + parser, is still accepted and does nothing. - **Modern syntax runs**: keyword arguments (required/optional/`**rest`, correct missing-keyword errors), safe navigation, endless methods, hash shorthand `{x:}`, `it` and numbered block params, lambdas @@ -151,14 +154,11 @@ platform - so a tree holding both can publish for either. patterns (`[*, x, *]` via the __pm_find_index__ prelude helper), `{**nil}` exact matches, pins, alternations, standalone `=>` and `in`. The NoMatchingPatternError message is shorter than MRI's. -- IronRuby.Tests can run under prism: `IR_USE_PRISM=1 IronRuby.Tests`. - Score: 52 distinct failures vs the 16-failure legacy baseline, out of - ~1470 tests. Roughly half the delta is prism being *correct for - Ruby 4* where the 1.9-era tests expect old behavior (retry/redo/break - outside rescue now SyntaxError, keywords in index assignment removed - in 3.4); the rest is niche (flip-flop state in the secondary test - mode, BEGIN hoisting, encoding magic comments, exact compile-error - counts, block-arity corner cases). +- IronRuby.Tests runs every test on prism. The tests that only held for + the 1.9 grammar (retry/redo/break outside rescue, now a SyntaxError) + were removed when the legacy parser was; the rest expect what CRuby 4 + does, warning counts included (the suite runs with warnings on, so a + test expects the parse warnings `ruby -wc` gives). - `...` argument forwarding is lowered to `*?fwd?, &?fwdblk?` (keywords ride along as the trailing hash, consistent with the kwargs lowering). - Keyword-argument lowering is restricted to signatures without optional @@ -167,9 +167,6 @@ platform - so a tree holding both can publish for either. - String literals round-trip through UTF-16; binary string literals with invalid UTF-8 may lose bytes (needs byte[]-based MutableString literals). -- Switchover plan: run the IronRuby.Tests parser suites under - `-X:UsePrism`, then flip the default and keep the legacy parser as - fallback. Line/column info: prism gives byte offsets + a line-offset table (`pm_parser_line_offsets`); IronRuby's `SourceSpan`s are built from the diff --git a/Src/Ruby/Builtins/RegexpTransformer.cs b/Src/Ruby/Builtins/RegexpTransformer.cs index fb821a4ae..1fd1b226d 100644 --- a/Src/Ruby/Builtins/RegexpTransformer.cs +++ b/Src/Ruby/Builtins/RegexpTransformer.cs @@ -982,17 +982,18 @@ private bool RewriteLoop(LoopBody entity, int entityIndex, int min, int max, boo for (int i = 0; i < units; i++) { more = open + stillEmpty + copy + more + close; } + // Lazily the loop of units is a counted one: .NET 10 goes on taking empty units + // of (?:...)*? until its backtracking stack overflows - (()|a)*? and the like - + // where (?:...){0,N}? stops as Onigmo does. + string loop = lazy ? "){0," + (Int32.MaxValue - 1) + "}?" : ")*"; if (min == 0) { _sb.Insert(entityIndex, "(?:" + start); - _sb.Append(more).Append(")*"); + _sb.Append(more).Append(loop); } else { if (min > 1) { _sb.Append('{').Append(min).Append('}'); } - _sb.Append("(?:").Append(start).Append(copy).Append(more).Append(")*"); - } - if (lazy) { - _sb.Append('?'); + _sb.Append("(?:").Append(start).Append(copy).Append(more).Append(loop); } return true; } diff --git a/Src/Ruby/Builtins/RubyFile.cs b/Src/Ruby/Builtins/RubyFile.cs index 5990aac6c..fc03b2b25 100644 --- a/Src/Ruby/Builtins/RubyFile.cs +++ b/Src/Ruby/Builtins/RubyFile.cs @@ -44,6 +44,7 @@ public RubyFile(RubyContext/*!*/ context, Stream/*!*/ stream, int descriptor, IO } private const int ENXIO = 6; + private const int HResultInvalidName = unchecked((int)0x8007007B); // HRESULT of ERROR_INVALID_NAME public static Stream/*!*/ OpenFileStream(RubyContext/*!*/ context, string/*!*/ path, IOMode mode) { ContractUtils.RequiresNotNull(path, "path"); @@ -113,6 +114,12 @@ public RubyFile(RubyContext/*!*/ context, Stream/*!*/ stream, int descriptor, IO if (e.HResult == ENXIO && System.IO.Path.DirectorySeparatorChar == '/') { throw RubyExceptions.CreateENXIO(path); } + // Windows: a name with a character no file name may hold (<, |, ? ...) is + // ERROR_INVALID_NAME, which MRI raises as Errno::EINVAL. method_source opens the + // path of a method defined in "" and expects a SystemCallError. + if (e.HResult == HResultInvalidName) { + throw RubyExceptions.CreateEINVAL(e, "{0}", path); + } throw; } catch (UnauthorizedAccessException) { // .NET reports opening a directory as an access violation; MRI diff --git a/Src/Ruby/Compiler/Ast/Definitions/MethodDefinition.cs b/Src/Ruby/Compiler/Ast/Definitions/MethodDefinition.cs index 86e2f7452..403f167c4 100644 --- a/Src/Ruby/Compiler/Ast/Definitions/MethodDefinition.cs +++ b/Src/Ruby/Compiler/Ast/Definitions/MethodDefinition.cs @@ -62,8 +62,8 @@ public Parameters/*!*/ Parameters { /// MRI's use_block: the method declares a block parameter, yields, or calls super passing /// its block on. A block given to a method without it may be ignored, which MRI warns about. /// - // Only the prism front end works this out; a method from anywhere else (the legacy parser) - // is assumed to use its block, so it is never warned about or given the block-less fast path. + // The prism bridge works this out; a method built any other way is assumed to use its + // block, so it is never warned about or given the block-less fast path. public bool UsesBlock { get; set; } = true; public MethodDefinition(LexicalScope/*!*/ definedScope, Expression target, string/*!*/ name, Parameters parameters, Body/*!*/ body, diff --git a/Src/Ruby/Compiler/Parser/GPPG.cs b/Src/Ruby/Compiler/Parser/GPPG.cs deleted file mode 100644 index 996b7a095..000000000 --- a/Src/Ruby/Compiler/Parser/GPPG.cs +++ /dev/null @@ -1,717 +0,0 @@ -/* **************************************************************************** - * - * Copyright (c) Microsoft Corporation. - * - * This source code is subject to terms and conditions of the Apache License, Version 2.0. A - * copy of the license can be found in the License.html file at the root of this distribution. If - * you cannot locate the Apache License, Version 2.0, please send an email to - * ironruby@microsoft.com. By using this source code in any fashion, you are agreeing to be bound - * by the terms of the Apache License, Version 2.0. - * - * You must not remove this notice, or any other, from this software. - * - * - * ***************************************************************************/ - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using Microsoft.Scripting.Utils; -using System.Text; -using System.Threading; - -using TValue = IronRuby.Compiler.TokenValue; -using TLocation = Microsoft.Scripting.SourceSpan; - -namespace IronRuby.Compiler { - - #region State - - internal sealed class State { -#if DEBUG - private int _id; - public int Id { get { return _id; } set { _id = value; } } -#endif - - // State x Terminal -> ERROR + SHIFT(State) + REDUCE(State) + ACCEPT - // - // SHIFT > 0 - // ERROR == 0 - // REDUCE < 0 - // ACCEPT == -1 - private readonly Dictionary _actions; - - // State x NonTerminal -> State - private readonly Dictionary _gotos; - - // ParseAction - default action if terminal not in _actions dict - private readonly int _defaultAction; - - public int DefaultAction { - get { return _defaultAction; } - } - - public Dictionary GotoStates { - get { return _gotos; } - } - - public Dictionary Actions { - get { return _actions; } - } - - public State(Dictionary actions, Dictionary gotos, int defaultAction) { - _actions = actions; - _gotos = gotos; - _defaultAction = defaultAction; - } - -#if DEBUG - public override string/*!*/ ToString() { - return _id.ToString(); - } -#endif - } - - #endregion - - #region ParserTables - - internal sealed class ParserTables { - public State[] States; - // upper word: LhsNonTerminal - // lower word: RhsLength - public int[] Rules; - public int ErrorToken; - public int EofToken; - -#if DEBUG // Metadata - internal string[] NonTerminalNames; - - // concatenated symbols of rule RHSs; - // symbol < 0 represents a non-terminal - // symbol >= 0 represents a terminal - internal short[] RuleRhsSymbols; - - // rule index -> index in RuleRhsSymbols array (calculated): - internal ushort[] RuleRhsSymbolIndexes; -#endif - } - - #endregion - - #region IParserLogger - - internal interface IParserLogger { - void BeforeReduction(int ruleId, int rhsLength); - void BeforeShift(int stateId, int tokenId, bool isErrorShift); - void BeforeGoto(int stateId, int ruleId); - void StateEntered(); - void NextToken(int tokenId); - } - - #endregion - - #region ShiftReduceParser - - public partial class Parser { - private static ParserTables _tables; - private static readonly object _tablesLock = new object(); - - private TValue yyval; - private TLocation yyloc; - - // Experimental : last yylloc prior to call of yylex() - private TLocation _lastTokenSpan; - - private int _nextToken; - private State _currentState; - - private bool _recovering; - private int _tokensSinceLastError; - - private ParserStack/*!*/ _stack; - private int _errorToken; - private int _eofToken; - - private State[] _states; - private int[] _rules; - -#if DEBUG - // test hooks: - internal State CurrentState { get { return _currentState; } } - internal ParserStack/*!*/ Stack { get { return _stack; } } - internal State[] States { get { return _states; } } - internal int[] Rules { get { return _rules; } } - internal ParserTables Tables { get { return _tables; } } -#endif - // methods that must be implemented by the parser - //private void InitializeGenerated(ParserTables/*!*/ tables); - //private TLocation MergeLocations(TLocation start, TLocation end); - //private TValue GetTokenValue(); // lexical value: set by scanner - //private TLocation GetTokenSpan(); // location value: set by scanner - //private int GetNextToken(); - //private void ReportSyntaxError(string message); - - internal static int GetRuleRhsLength(int ruleDef) { - return ruleDef & 0xffff; - } - - internal static int GetRuleLhsNonterminal(int ruleDef) { - return ruleDef >> 16; - } - - private void InitializeTables() { - _stack = new ParserStack(); - - if (_tables == null) { - lock (_tablesLock) { - if (_tables == null) { - Debug.Assert(typeof(TLocation).IsValueType); - - ParserTables tables = new ParserTables(); - InitializeGeneratedTables(tables); -#if DEBUG - InitializeMetadata(tables); - InitializeRulesMetadata(tables); -#endif - _tables = tables; - } - } - } - - _states = _tables.States; - _rules = _tables.Rules; - _errorToken = _tables.ErrorToken; - _eofToken = _tables.EofToken; - } - - // TODO: possible optimization: build a single dictionary mapping all goto and actions for all states. - // This (custom) dict might be precomputed by generator and allocated in a single array. - // This would safe rellocation of ~650kB of Dictionary.Entry[] since the array would be considered a large object. - private State[]/*!*/ BuildStates(short[]/*!*/ data) { - Debug.Assert(data != null && data.Length > 0); - - // - // serialized structure: - // - // length, - // ( - // (action_count: positive short, goto_count: positive short) | (action_count: negative short), - // (key: short, value: short){action_count} | (defaultAction: short), - // (key: short, value: short){goto_count} - // ){length} - // - // where action_count is - // > 0 ... a number of items in actions hashtable - // == 0 ... there is no action hashtable, but there is a single integer default action id - // < 0 ... there is no action hashtable and no goto table, the value is default action id - // goto_count is a number of items in gotos hashtable, - // zero means there is no goto hashtable - // - - int offset = 0; - State[] states = new State[data[offset++]]; - - for (int i = 0; i < states.Length; i++) { - int actionCount = data[offset++]; - - Dictionary actions = null; - Dictionary gotos = null; - int defaultAction = 0; - - if (actionCount >= 0) { - int gotoCount = data[offset++]; - Debug.Assert(gotoCount >= 0); - - if (actionCount > 0) { - actions = new Dictionary(actionCount); - for (int j = 0; j < actionCount; j++) { - actions.Add(data[offset++], data[offset++]); - } - } else { - defaultAction = data[offset++]; - } - - if (gotoCount > 0) { - gotos = new Dictionary(gotoCount); - for (int j = 0; j < gotoCount; j++) { - Debug.Assert(data[offset] < 0); - gotos.Add(-data[offset++], data[offset++]); - } - } - } else { - defaultAction = actionCount; - } - - states[i] = new State(actions, gotos, defaultAction); -#if DEBUG - states[i].Id = i; -#endif - } - - return states; - } - - private bool Parse() { - - _nextToken = 0; - _currentState = _states[0]; - _lastTokenSpan = GetTokenSpan(); - - _stack.Push(_currentState, yyval, yyloc); - - while (true) { - - LogStateEntered(); - - int action = _currentState.DefaultAction; - - if (_currentState.Actions != null) { - if (_nextToken == 0) { - - // We save the last token span, so that the location span - // of production right hand sides that begin or end with a - // nullable production will be correct. - _lastTokenSpan = GetTokenSpan(); - _nextToken = GetNextToken(); - } - - LogNextToken(_nextToken); - - _currentState.Actions.TryGetValue(_nextToken, out action); - } - - if (action > 0) { - LogBeforeShift(action, _nextToken, false); - Shift(action); - } else if (action < 0) { - Reduce(-action - 1); - - // accept - if (action == -1) { - return true; - } - } else if (action == 0) { - // error - if (!ErrorRecovery()) { - return false; - } - } - } - } - - private void Shift(int stateId) { - _currentState = _states[stateId]; - - _stack.Push(_currentState, GetTokenValue(), GetTokenSpan()); - - if (_recovering) { - if (_nextToken != _errorToken) { - _tokensSinceLastError++; - } - - if (_tokensSinceLastError > 5) { - _recovering = false; - } - } - - if (_nextToken != _eofToken) { - _nextToken = 0; - } - } - - private void Reduce(int ruleId) { - int ruleDef = _rules[ruleId]; - int rhsLength = GetRuleRhsLength(ruleDef); - - LogBeforeReduction(ruleId, rhsLength); - - if (rhsLength == 0) { - // The location span for an empty production will start with the - // beginning of the next lexeme, and end with the finish of the - // previous lexeme. This gives the correct behaviour when this - // nonsense value is used in later Merge operations. - yyloc = MergeLocations(_lastTokenSpan, GetTokenSpan()); - } else if (rhsLength == 1) { - yyloc = _stack.PeekLocation(1); - } else { - TLocation at1 = GetLocation(rhsLength); - TLocation atN = GetLocation(1); - yyloc = MergeLocations(at1, atN); - } - - DoAction(ruleId); - - _stack.Pop(rhsLength); - - var currentState = _stack.PeekState(1); - - int gotoState; - if (currentState.GotoStates.TryGetValue(GetRuleLhsNonterminal(ruleDef), out gotoState)) { - LogBeforeGoto(gotoState, ruleId); - currentState = _states[gotoState]; - } - - _stack.Push(currentState, yyval, yyloc); - - _currentState = currentState; - } - - // Default semantic action used when no action is specified in the rule. - private void DoDefaultAction() { - yyval = _stack.PeekValue(1); - } - - public bool ErrorRecovery() { - bool discard; - - if (!_recovering) { // if not recovering from previous error - ReportSyntaxError(GetSyntaxErrorMessage()); - } - - if (!FindErrorRecoveryState()) - return false; - - // - // The interim fix for the "looping in error recovery" - // artifact involved moving the setting of the recovering - // bool until after invalid tokens have been discarded. - // - ShiftErrorToken(); - discard = DiscardInvalidTokens(); - _recovering = true; - _tokensSinceLastError = 0; - return discard; - } - - private string GetSyntaxErrorMessage() { - StringBuilder errorMsg = new StringBuilder(); - errorMsg.AppendFormat("syntax error, unexpected {0}", Tokenizer.GetTokenDescription((Tokens)_nextToken)); // TODO: actual value? - - if (_currentState.Actions.Count < 7) { - int i = 0; - int last = _currentState.Actions.Keys.Count - 1; - foreach (int terminal in _currentState.Actions.Keys) { - if (i == 0) { - errorMsg.Append(", expecting "); - } else if (i == last) { - errorMsg.Append(", or "); - } else { - errorMsg.Append(", "); - } - - errorMsg.Append(Tokenizer.GetTokenDescription((Tokens)terminal)); - i++; - } - } - return errorMsg.ToString(); - } - - public void ShiftErrorToken() { - int oldNext = _nextToken; - _nextToken = _errorToken; - - int state = _currentState.Actions[_nextToken]; - LogBeforeShift(state, _nextToken, true); - Shift(state); - - _nextToken = oldNext; - } - - - public bool FindErrorRecoveryState() { - // pop states until one found that accepts error token - while (true) { - - // shift - int action; - if (_currentState.Actions != null && _currentState.Actions.TryGetValue(_errorToken, out action) && action > 0) { - return true; - } - - // LogState("Error, popping state", _stateStack.Peek(1)); - - _stack.Pop(); - - if (_stack.IsEmpty) { - // Log("Aborting: didn't find a state that accepts error token"); - return false; - } else { - _currentState = _stack.PeekState(1); - } - } - } - - public bool DiscardInvalidTokens() { - - int action = _currentState.DefaultAction; - - if (_currentState.Actions != null) { - - // Discard tokens until find one that works ... - while (true) { - if (_nextToken == 0) { - _nextToken = GetNextToken(); - } - - LogNextToken(_nextToken); - - if (_nextToken == _eofToken) - return false; - - _currentState.Actions.TryGetValue(_nextToken, out action); - - if (action != 0) { - return true; - } - - // LogToken("Error, discarding token", _nextToken); - _nextToken = 0; - } - - } else if (_recovering && _tokensSinceLastError == 0) { - // - // Boolean recovering is not set until after the first - // error token has been shifted. Thus if we get back - // here with recovering set and no tokens read we are - // looping on the same error recovery action. This - // happens if current_state.parser_table is null because - // the state has an LR(0) reduction, but not all - // lookahead tokens are valid. This only occurs for - // error productions that *end* on "error". - // - // This action discards tokens one at a time until - // the looping stops. Another attack would be to always - // use the LALR(1) table if a production ends on "error" - // - // LogToken("Error, panic discard of {0}", _nextToken); - _nextToken = 0; - return true; - } else { - return true; - } - } - - private TValue GetValue(int depth) { - return _stack.PeekValue(depth); - } - - private TLocation GetLocation(int depth) { - return _stack.PeekLocation(depth); - } - - private void ClearInput() { - // experimental in this version. - _nextToken = 0; - } - - private void StopErrorRecovery() { - _recovering = false; - } - - #region Debug Logging - -#if DEBUG - private IParserLogger _logger; -#endif - - [Conditional("DEBUG")] - internal void EnableLogging(IParserLogger/*!*/ logger) { -#if DEBUG - Assert.NotNull(logger); - _logger = logger; -#endif - } - - [Conditional("DEBUG")] - internal void DisableLogging() { -#if DEBUG - _logger = null; -#endif - } - - [Conditional("DEBUG")] - private void LogStateEntered() { -#if DEBUG - if (_logger != null) _logger.StateEntered(); -#endif - } - - [Conditional("DEBUG")] - private void LogNextToken(int tokenId) { -#if DEBUG - if (_logger != null) _logger.NextToken(tokenId); -#endif - } - - [Conditional("DEBUG")] - private void LogBeforeReduction(int ruleId, int rhsLength) { -#if DEBUG - if (_logger != null) _logger.BeforeReduction(ruleId, rhsLength); -#endif - } - - [Conditional("DEBUG")] - private void LogBeforeShift(int stateId, int tokenId, bool isErrorShift) { -#if DEBUG - if (_logger != null) _logger.BeforeShift(stateId, tokenId, isErrorShift); -#endif - } - - [Conditional("DEBUG")] - private void LogBeforeGoto(int stateId, int ruleId) { -#if DEBUG - if (_logger != null) _logger.BeforeGoto(stateId, ruleId); -#endif - } - - #endregion - - #region Parser Reflection - -#if DEBUG - - private static void InitializeRulesMetadata(ParserTables/*!*/ tables) { - ushort[] indexes = new ushort[tables.Rules.Length]; - ushort index = 0; - for (int i = 0; i < indexes.Length; i++) { - indexes[i] = index; - index += (ushort)(tables.Rules[i] & 0xffff); - } - tables.RuleRhsSymbolIndexes = indexes; - } - - // SHIFT > 0 - // ERROR == 0 - // REDUCE < 0 - // ACCEPT == -1 - internal string ActionToString(int action) { - if (action > 0) return "S(" + action + ")"; - if (action == 0) return ""; - if (action == -1) return "ACCEPT"; - return "R(" + (-action) + ")"; - } - - internal string GetNonTerminalName(int nonTerminal) { - Debug.Assert(nonTerminal > 0); - return _tables.NonTerminalNames[nonTerminal]; - } - - // < 0 -> non-terminal - // > 0 -> terminal - internal string GetSymbolName(int symbol) { - return (symbol < 0) ? GetNonTerminalName(-symbol) : Parser.GetTerminalName(symbol); - } - - internal string RuleToString(int ruleIndex) { - Debug.Assert(ruleIndex >= 0); - StringBuilder sb = new StringBuilder(); - sb.Append(GetNonTerminalName(GetRuleLhsNonterminal(_tables.Rules[ruleIndex]))); - sb.Append(" -> "); - - // index of the first RHS symbol: - int rhsLength = GetRuleRhsLength(_tables.Rules[ruleIndex]); - if (rhsLength > 0) { - int first = _tables.RuleRhsSymbolIndexes[ruleIndex]; - for (int i = 0; i < rhsLength; i++) { - sb.Append(GetSymbolName(_tables.RuleRhsSymbols[first + i])); - sb.Append(" "); - } - } else { - sb.Append(""); - } - - return sb.ToString(); - } -#endif - - [Conditional("DEBUG")] - public void DumpTables(TextWriter/*!*/ output) { -#if DEBUG - Dictionary terminals = new Dictionary(); - Dictionary nonterminals = new Dictionary(); - - int termCount = -1; - int ntermCount = -1; - for (int q = 0; q < _states.Length; q++) { - State s = _states[q]; - if (s.Actions != null) { - foreach (int t in s.Actions.Keys) { - if (t > termCount) { - termCount = t; - } - - terminals[t] = true; - } - } - - if (s.GotoStates != null) { - foreach (int t in s.GotoStates.Keys) { - if (t > ntermCount) { - ntermCount = t; - } - nonterminals[t] = true; - } - } - } - - output.WriteLine("States x (Terms + NonTerms) = {0} x ({1} + {2})", _states.Length, termCount, ntermCount); - - output.Write("State,"); - output.Write("Default,"); - for (int t = 0; t < termCount; t++) { - if (terminals.ContainsKey(t)) { - output.Write(Parser.GetTerminalName(t)); - output.Write(","); - } - } - - for (int t = 0; t < ntermCount; t++) { - if (nonterminals.ContainsKey(t)) { - output.Write(t); // TODO - output.Write(","); - } - } - - for (int q = 0; q < _states.Length; q++) { - State s = _states[q]; - output.Write(q); - output.Write(","); - if (s.Actions == null) { - output.Write(ActionToString(s.DefaultAction)); - } - output.Write(","); - - for (int t = 0; t < termCount; t++) { - if (terminals.ContainsKey(t)) { - int action; - if (s.Actions != null) { - s.Actions.TryGetValue(t, out action); - output.Write(ActionToString(action)); - } - output.Write(","); - } - } - - for (int t = 0; t < ntermCount; t++) { - if (nonterminals.ContainsKey(t)) { - if (s.GotoStates != null) { - int state; - if (s.GotoStates.TryGetValue(t, out state)) { - output.Write(state); - } - } - output.Write(","); - } - } - output.WriteLine(); - } -#endif - } - - #endregion - } - - #endregion -} diff --git a/Src/Ruby/Compiler/Parser/Generate.cmd b/Src/Ruby/Compiler/Parser/Generate.cmd deleted file mode 100644 index 0087a9c0e..000000000 --- a/Src/Ruby/Compiler/Parser/Generate.cmd +++ /dev/null @@ -1,2 +0,0 @@ -@rem tf checkout Parser.Generated.cs -..\..\..\..\..\Util\GPPG\gppg.exe Parser.y > Parser.Generated.cs diff --git a/Src/Ruby/Compiler/Parser/Parser.Generated.cs b/Src/Ruby/Compiler/Parser/Parser.Generated.cs deleted file mode 100644 index 13d7435cb..000000000 --- a/Src/Ruby/Compiler/Parser/Parser.Generated.cs +++ /dev/null @@ -1,6062 +0,0 @@ -/* **************************************************************************** - * - * Copyright (c) Microsoft Corporation. - * - * This source code is subject to terms and conditions of the Apache License, Version 2.0. A - * copy of the license can be found in the License.html file at the root of this distribution. If - * you cannot locate the Apache License, Version 2.0, please send an email to - * ironruby@microsoft.com. By using this source code in any fashion, you are agreeing to be bound - * by the terms of the Apache License, Version 2.0. - * - * You must not remove this notice, or any other, from this software. - * - * - * ***************************************************************************/ - -using System.Collections.Generic; -using System.Diagnostics; -using System.Dynamic; -using Microsoft.Scripting; -using Microsoft.Scripting.Utils; -using IronRuby.Compiler.Ast; - -namespace IronRuby.Compiler -{ -public enum Tokens { - - None = 1, Error = 2, EndOfFile = 3, SingleLineComment = 4, MultiLineComment = 5, Whitespace = 6, EndOfLine = 7, InvalidCharacter = 8, - Pound = 9, At = 10, Dollar = 11, Backslash = 12, WordSeparator = 13, NewLine = 14, Class = 15, Module = 16, - Def = 17, Undef = 18, Begin = 19, Rescue = 20, Ensure = 21, End = 22, If = 23, Unless = 24, - Then = 25, Elsif = 26, Else = 27, Case = 28, When = 29, While = 30, Until = 31, For = 32, - Break = 33, Next = 34, Redo = 35, Retry = 36, In = 37, Do = 38, LoopDo = 39, BlockDo = 40, - LambdaDo = 41, Return = 42, Yield = 43, Super = 44, Self = 45, Nil = 46, True = 47, False = 48, - And = 49, Or = 50, Not = 51, IfMod = 52, UnlessMod = 53, WhileMod = 54, UntilMod = 55, RescueMod = 56, - Alias = 57, Defined = 58, UppercaseBegin = 59, UppercaseEnd = 60, Line = 61, File = 62, Encoding = 63, UnaryPlus = 64, - UnaryMinus = 65, Pow = 66, Cmp = 67, Equal = 68, StrictEqual = 69, NotEqual = 70, GreaterOrEqual = 71, LessOrEqual = 72, - LogicalAnd = 73, LogicalOr = 74, Match = 75, Nmatch = 76, DoubleDot = 77, TripleDot = 78, ItemGetter = 79, ItemSetter = 80, - Lshft = 81, Rshft = 82, SeparatingDoubleColon = 83, LeadingDoubleColon = 84, DoubleArrow = 85, Semicolon = 86, Comma = 87, Dot = 88, - Star = 89, BlockReference = 90, Ampersand = 91, Backtick = 92, Lambda = 93, LeftParenthesis = 94, LeftExprParenthesis = 95, LeftArgParenthesis = 96, - RightParenthesis = 97, LeftBrace = 98, LeftBlockBrace = 99, LeftBlockArgBrace = 100, LeftLambdaBrace = 101, RightBrace = 102, LeftBracket = 103, LeftIndexingBracket = 104, - RightBracket = 105, StringEmbeddedVariableBegin = 106, StringEmbeddedCodeBegin = 107, StringEmbeddedCodeEnd = 108, VerbatimHeredocBegin = 109, VerbatimHeredocEnd = 110, StringBegin = 111, RegexpBegin = 112, - ShellStringBegin = 113, WordsBegin = 114, VerbatimWordsBegin = 115, SymbolBegin = 116, StringEnd = 117, Identifier = 118, FunctionIdentifier = 119, GlobalVariable = 120, - InstanceVariable = 121, ConstantIdentifier = 122, ClassVariable = 123, OpAssignment = 124, Label = 125, Character = 126, StringContent = 127, Integer = 128, - BigInteger = 129, Float = 130, MatchReference = 131, RegexpEnd = 132, Lowest = 133, Assignment = 134, QuestionMark = 135, Colon = 136, - Greater = 137, Less = 138, Pipe = 139, Caret = 140, Plus = 141, Minus = 142, Asterisk = 143, Slash = 144, - Percent = 145, NumberNegation = 146, Bang = 147, Tilde = 148, LastToken = 149}; - -public partial struct TokenValue -#line 27 "Parser.y" - { } -public partial class Parser -{ - private void InitializeGeneratedTables(ParserTables tables) - { - tables.ErrorToken = (int)Tokens.Error; - tables.EofToken = (int)Tokens.EndOfFile; - - tables.States = BuildStates(new short[] { - 938, - 63,42, /* actions: */ 86,27,14,28,57,43,18,142,59,148,60,153,131,136,118,225,122,228,119,286,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,121,226,120,227,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,84,372,103,291,98,300,43,335,58,321,51,342,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,423,19,430,15,440,16,446,17,451,93,457,44,465,147,498,64,501,65,504,148,507,42,525,33,539,34,541,35,544,36,545,89,591,2,598,3,-529, /* gotos: */ -1,1,-4,3,-108,4,-109,5,-132,26,-3,29,-2,31,-10,42,-68,158,-11,352,-14,353,-13,354,-27,18,-29,19,-69,34,-12,355,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-70,371,-25,345,-18,394,-22,415,-23,439,-28,483,-26,484,-19,509,-105,510,-104,520,-7,523,-8,524,-9,543,-99,546,-100,547,-102,589,-103,556, - 1,0, /* actions: */ 3,2, - /* default action: */ -1, - /* default action: */ -2, - /* default action: */ -3, - 71,37, /* actions: */ 86,6,57,43,18,142,59,148,60,153,131,136,118,225,122,228,119,286,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,121,226,120,227,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,84,372,103,291,98,300,43,335,58,321,51,342,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,423,19,430,15,440,16,446,17,451,93,457,44,465,147,498,64,501,65,504,148,507,42,525,33,539,34,541,35,544,36,545,89,591,2,598,3,-530,22,-530,102,-530,108,-530,27,-530,26,-530,21,-530,29,-530,97,-530,20,-530, /* gotos: */ -3,7,-2,31,-10,42,-68,158,-11,352,-14,353,-13,354,-27,18,-29,19,-69,34,-12,355,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-70,371,-25,345,-18,394,-22,415,-23,439,-28,483,-26,484,-19,509,-105,510,-104,520,-7,523,-8,524,-9,543,-99,546,-100,547,-102,589,-103,556, - /* default action: */ -541, - 12,3, /* actions: */ 86,27,14,28,3,-529,22,-529,102,-529,108,-529,27,-529,26,-529,21,-529,29,-529,97,-529,20,-529, /* gotos: */ -108,8,-109,9,-132,26, - /* default action: */ -4, - 70,36, /* actions: */ 86,6,57,43,18,142,59,148,60,153,131,136,118,225,122,228,119,286,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,121,226,120,227,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,84,372,103,291,98,300,43,335,58,321,51,342,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,423,19,430,15,440,16,446,17,451,93,457,44,465,147,498,64,501,65,504,148,507,42,525,33,539,34,541,35,544,36,545,89,591,3,-530,22,-530,102,-530,108,-530,27,-530,26,-530,21,-530,29,-530,97,-530,20,-530, /* gotos: */ -2,10,-10,42,-68,158,-11,352,-14,353,-13,354,-27,18,-29,19,-69,34,-12,355,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-70,371,-25,345,-18,394,-22,415,-23,439,-28,483,-26,484,-19,509,-105,510,-104,520,-7,523,-8,524,-9,543,-99,546,-100,547,-102,589,-103,556, - 17,0, /* actions: */ 52,11,53,32,54,600,55,602,56,604,86,-7,14,-7,3,-7,22,-7,102,-7,108,-7,27,-7,26,-7,21,-7,29,-7,97,-7,20,-7, - 49,25, /* actions: */ 118,225,122,228,119,286,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,121,226,120,227,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,131,136,84,287,103,291,98,300,43,335,58,321,51,342,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,465,147,498,64,501,65,504,148,507, /* gotos: */ -13,12,-27,18,-29,19,-69,34,-12,326,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-70,224,-68,284,-25,345,-18,394,-22,415,-23,439,-28,483,-26,484,-19,509,-105,218,-104,472, - 19,0, /* actions: */ 49,13,50,15,52,-45,53,-45,54,-45,55,-45,56,-45,86,-45,14,-45,3,-45,22,-45,102,-45,108,-45,27,-45,26,-45,21,-45,29,-45,97,-45,20,-45, - 54,28, /* actions: */ 118,225,122,228,119,286,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,121,226,120,227,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,131,136,84,287,103,291,98,300,43,335,58,321,51,342,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,465,147,498,64,501,65,504,148,507,42,525,33,539,34,541,35,544,36,545, /* gotos: */ -13,14,-7,937,-27,18,-29,19,-69,34,-12,326,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-70,224,-68,284,-25,345,-18,394,-22,415,-23,439,-28,483,-26,484,-19,509,-105,218,-104,472,-8,524,-9,543, - /* default action: */ -51, - 54,28, /* actions: */ 118,225,122,228,119,286,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,121,226,120,227,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,131,136,84,287,103,291,98,300,43,335,58,321,51,342,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,465,147,498,64,501,65,504,148,507,42,525,33,539,34,541,35,544,36,545, /* gotos: */ -13,16,-7,17,-27,18,-29,19,-69,34,-12,326,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-70,224,-68,284,-25,345,-18,394,-22,415,-23,439,-28,483,-26,484,-19,509,-105,218,-104,472,-8,524,-9,543, - /* default action: */ -52, - /* default action: */ -54, - /* default action: */ -50, - 22,1, /* actions: */ 40,21,49,-58,50,-58,52,-58,53,-58,54,-58,55,-58,56,-58,86,-58,14,-58,3,-58,22,-58,102,-58,108,-58,27,-58,26,-58,21,-58,29,-58,97,-58,20,-58,25,-58,39,-58, /* gotos: */ -37,20, - /* default action: */ -394, - 0,1, /* default action: */ -392, /* gotos: */ -140,22, - 65,2, /* actions: */ 74,609,139,610,86,-378,14,-378,57,-378,18,-378,59,-378,60,-378,131,-378,118,-378,122,-378,119,-378,128,-378,129,-378,130,-378,146,-378,116,-378,126,-378,111,-378,113,-378,112,-378,114,-378,115,-378,121,-378,120,-378,123,-378,46,-378,45,-378,47,-378,48,-378,62,-378,61,-378,63,-378,84,-378,103,-378,98,-378,43,-378,58,-378,51,-378,23,-378,24,-378,30,-378,31,-378,28,-378,32,-378,96,-378,95,-378,19,-378,15,-378,16,-378,17,-378,93,-378,44,-378,147,-378,64,-378,65,-378,148,-378,42,-378,33,-378,34,-378,35,-378,36,-378,89,-378,2,-378,22,-378, /* gotos: */ -78,23,-77,608, - 63,41, /* actions: */ 86,27,14,28,57,43,18,142,59,148,60,153,131,136,118,225,122,228,119,286,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,121,226,120,227,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,84,372,103,291,98,300,43,335,58,321,51,342,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,423,19,430,15,440,16,446,17,451,93,457,44,465,147,498,64,501,65,504,148,507,42,525,33,539,34,541,35,544,36,545,89,591,2,598,22,-529, /* gotos: */ -4,24,-108,4,-109,5,-132,26,-3,29,-2,31,-10,42,-68,158,-11,352,-14,353,-13,354,-27,18,-29,19,-69,34,-12,355,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-70,371,-25,345,-18,394,-22,415,-23,439,-28,483,-26,484,-19,509,-105,510,-104,520,-7,523,-8,524,-9,543,-99,546,-100,547,-102,589,-103,556, - 1,0, /* actions: */ 22,25, - /* default action: */ -393, - /* default action: */ -540, - /* default action: */ -538, - /* default action: */ -539, - 12,3, /* actions: */ 86,27,14,28,3,-529,22,-529,102,-529,108,-529,27,-529,26,-529,21,-529,29,-529,97,-529,20,-529, /* gotos: */ -108,30,-109,9,-132,26, - /* default action: */ -5, - 17,0, /* actions: */ 52,11,53,32,54,600,55,602,56,604,86,-6,14,-6,3,-6,22,-6,102,-6,108,-6,27,-6,26,-6,21,-6,29,-6,97,-6,20,-6, - 49,25, /* actions: */ 118,225,122,228,119,286,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,121,226,120,227,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,131,136,84,287,103,291,98,300,43,335,58,321,51,342,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,465,147,498,64,501,65,504,148,507, /* gotos: */ -13,33,-27,18,-29,19,-69,34,-12,326,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-70,224,-68,284,-25,345,-18,394,-22,415,-23,439,-28,483,-26,484,-19,509,-105,218,-104,472, - 19,0, /* actions: */ 49,13,50,15,52,-46,53,-46,54,-46,55,-46,56,-46,86,-46,14,-46,3,-46,22,-46,102,-46,108,-46,27,-46,26,-46,21,-46,29,-46,97,-46,20,-46, - 55,4, /* actions: */ 99,347,38,478,94,468,118,-265,121,-265,120,-265,122,-265,123,-265,46,-265,45,-265,47,-265,48,-265,62,-265,61,-265,63,-265,128,-265,129,-265,130,-265,146,-265,116,-265,126,-265,111,-265,113,-265,112,-265,114,-265,115,-265,131,-265,119,-265,84,-265,103,-265,98,-265,43,-265,58,-265,51,-265,23,-265,24,-265,30,-265,31,-265,28,-265,32,-265,96,-265,95,-265,19,-265,15,-265,16,-265,17,-265,93,-265,44,-265,64,-265,65,-265,147,-265,148,-265,89,-265,125,-265,90,-265, /* gotos: */ -44,35,-36,476,-40,477,-120,332, - 24,1, /* actions: */ 100,37,40,-65,49,-65,50,-65,52,-65,53,-65,54,-65,55,-65,56,-65,86,-65,14,-65,3,-65,22,-65,102,-65,108,-65,27,-65,26,-65,21,-65,29,-65,97,-65,20,-65,25,-65,39,-65,105,-65, /* gotos: */ -35,36, - /* default action: */ -66, - 0,1, /* default action: */ -63, /* gotos: */ -115,38, - 65,2, /* actions: */ 74,609,139,610,86,-378,14,-378,57,-378,18,-378,59,-378,60,-378,131,-378,118,-378,122,-378,119,-378,128,-378,129,-378,130,-378,146,-378,116,-378,126,-378,111,-378,113,-378,112,-378,114,-378,115,-378,121,-378,120,-378,123,-378,46,-378,45,-378,47,-378,48,-378,62,-378,61,-378,63,-378,84,-378,103,-378,98,-378,43,-378,58,-378,51,-378,23,-378,24,-378,30,-378,31,-378,28,-378,32,-378,96,-378,95,-378,19,-378,15,-378,16,-378,17,-378,93,-378,44,-378,147,-378,64,-378,65,-378,148,-378,42,-378,33,-378,34,-378,35,-378,36,-378,89,-378,2,-378,102,-378, /* gotos: */ -78,39,-77,608, - 63,41, /* actions: */ 86,27,14,28,57,43,18,142,59,148,60,153,131,136,118,225,122,228,119,286,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,121,226,120,227,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,84,372,103,291,98,300,43,335,58,321,51,342,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,423,19,430,15,440,16,446,17,451,93,457,44,465,147,498,64,501,65,504,148,507,42,525,33,539,34,541,35,544,36,545,89,591,2,598,102,-529, /* gotos: */ -4,40,-108,4,-109,5,-132,26,-3,29,-2,31,-10,42,-68,158,-11,352,-14,353,-13,354,-27,18,-29,19,-69,34,-12,355,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-70,371,-25,345,-18,394,-22,415,-23,439,-28,483,-26,484,-19,509,-105,510,-104,520,-7,523,-8,524,-9,543,-99,546,-100,547,-102,589,-103,556, - 1,0, /* actions: */ 102,41, - /* default action: */ -64, - /* default action: */ -9, - 77,5, /* actions: */ 120,934,118,48,122,49,119,50,139,52,140,53,91,54,67,55,68,56,69,57,75,58,76,59,137,60,71,61,138,62,72,63,70,64,81,65,82,66,141,67,142,68,143,69,89,70,144,71,145,72,66,73,147,74,148,75,64,76,65,77,79,78,80,79,92,80,61,82,62,83,63,84,59,85,60,86,57,87,49,88,19,89,33,90,28,91,15,92,17,93,58,94,38,95,40,96,27,97,26,98,22,99,21,100,48,101,32,102,37,103,16,104,34,105,46,106,51,107,50,108,35,109,20,110,36,111,42,112,45,113,44,114,25,115,47,116,18,117,29,118,43,119,52,120,53,121,54,122,55,123,56,124,116,126, /* gotos: */ -67,44,-76,47,-75,51,-117,81,-66,125, - 0,1, /* default action: */ -18, /* gotos: */ -112,45, - 76,5, /* actions: */ 118,48,122,49,119,50,139,52,140,53,91,54,67,55,68,56,69,57,75,58,76,59,137,60,71,61,138,62,72,63,70,64,81,65,82,66,141,67,142,68,143,69,89,70,144,71,145,72,66,73,147,74,148,75,64,76,65,77,79,78,80,79,92,80,61,82,62,83,63,84,59,85,60,86,57,87,49,88,19,89,33,90,28,91,15,92,17,93,58,94,38,95,40,96,27,97,26,98,22,99,21,100,48,101,32,102,37,103,16,104,34,105,46,106,51,107,50,108,35,109,20,110,36,111,42,112,45,113,44,114,25,115,47,116,18,117,29,118,43,119,52,120,53,121,54,122,55,123,56,124,116,126, /* gotos: */ -67,46,-76,47,-75,51,-117,81,-66,125, - /* default action: */ -19, - /* default action: */ -116, - /* default action: */ -111, - /* default action: */ -112, - /* default action: */ -113, - /* default action: */ -114, - /* default action: */ -128, - /* default action: */ -129, - /* default action: */ -130, - /* default action: */ -131, - /* default action: */ -132, - /* default action: */ -133, - /* default action: */ -134, - /* default action: */ -135, - /* default action: */ -136, - /* default action: */ -137, - /* default action: */ -138, - /* default action: */ -139, - /* default action: */ -140, - /* default action: */ -141, - /* default action: */ -142, - /* default action: */ -143, - /* default action: */ -144, - /* default action: */ -145, - /* default action: */ -146, - /* default action: */ -147, - /* default action: */ -148, - /* default action: */ -149, - /* default action: */ -150, - /* default action: */ -151, - /* default action: */ -152, - /* default action: */ -153, - /* default action: */ -154, - /* default action: */ -155, - /* default action: */ -156, - /* default action: */ -115, - /* default action: */ -157, - /* default action: */ -158, - /* default action: */ -159, - /* default action: */ -160, - /* default action: */ -161, - /* default action: */ -162, - /* default action: */ -163, - /* default action: */ -164, - /* default action: */ -165, - /* default action: */ -166, - /* default action: */ -167, - /* default action: */ -168, - /* default action: */ -169, - /* default action: */ -170, - /* default action: */ -171, - /* default action: */ -172, - /* default action: */ -173, - /* default action: */ -174, - /* default action: */ -175, - /* default action: */ -176, - /* default action: */ -177, - /* default action: */ -178, - /* default action: */ -179, - /* default action: */ -180, - /* default action: */ -181, - /* default action: */ -182, - /* default action: */ -183, - /* default action: */ -184, - /* default action: */ -185, - /* default action: */ -186, - /* default action: */ -187, - /* default action: */ -188, - /* default action: */ -189, - /* default action: */ -190, - /* default action: */ -191, - /* default action: */ -192, - /* default action: */ -193, - /* default action: */ -194, - /* default action: */ -195, - /* default action: */ -196, - /* default action: */ -197, - /* default action: */ -198, - /* default action: */ -199, - /* default action: */ -117, - 83,6, /* actions: */ 118,48,122,49,119,50,139,52,140,53,91,54,67,55,68,56,69,57,75,58,76,59,137,60,71,61,138,62,72,63,70,64,81,65,82,66,141,67,142,68,143,69,89,70,144,71,145,72,66,73,147,74,148,75,64,76,65,77,79,78,80,79,92,80,61,82,62,83,63,84,59,85,60,86,57,87,49,88,19,89,33,90,28,91,15,92,17,93,58,94,38,95,40,96,27,97,26,98,22,99,21,100,48,101,32,102,37,103,16,104,34,105,46,106,51,107,50,108,35,109,20,110,36,111,42,112,45,113,44,114,25,115,47,116,18,117,29,118,43,119,52,120,53,121,54,122,55,123,56,124,121,930,120,931,123,932,131,136,117,-439,127,-439,106,-439,107,-439, /* gotos: */ -71,127,-55,128,-76,929,-75,51,-117,81,-68,933, - /* default action: */ -118, - 4,1, /* actions: */ 117,129,127,131,106,132,107,139, /* gotos: */ -54,130, - /* default action: */ -119, - /* default action: */ -440, - /* default action: */ -441, - 4,2, /* actions: */ 120,134,131,136,121,137,123,138, /* gotos: */ -53,133,-68,135, - /* default action: */ -442, - /* default action: */ -444, - /* default action: */ -445, - /* default action: */ -468, - /* default action: */ -446, - /* default action: */ -447, - 63,41, /* actions: */ 86,27,14,28,57,43,18,142,59,148,60,153,131,136,118,225,122,228,119,286,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,121,226,120,227,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,84,372,103,291,98,300,43,335,58,321,51,342,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,423,19,430,15,440,16,446,17,451,93,457,44,465,147,498,64,501,65,504,148,507,42,525,33,539,34,541,35,544,36,545,89,591,2,598,108,-529, /* gotos: */ -4,140,-108,4,-109,5,-132,26,-3,29,-2,31,-10,42,-68,158,-11,352,-14,353,-13,354,-27,18,-29,19,-69,34,-12,355,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-70,371,-25,345,-18,394,-22,415,-23,439,-28,483,-26,484,-19,509,-105,510,-104,520,-7,523,-8,524,-9,543,-99,546,-100,547,-102,589,-103,556, - 1,0, /* actions: */ 108,141, - /* default action: */ -443, - 76,6, /* actions: */ 118,48,122,49,119,50,139,52,140,53,91,54,67,55,68,56,69,57,75,58,76,59,137,60,71,61,138,62,72,63,70,64,81,65,82,66,141,67,142,68,143,69,89,70,144,71,145,72,66,73,147,74,148,75,64,76,65,77,79,78,80,79,92,80,61,82,62,83,63,84,59,85,60,86,57,87,49,88,19,89,33,90,28,91,15,92,17,93,58,94,38,95,40,96,27,97,26,98,22,99,21,100,48,101,32,102,37,103,16,104,34,105,46,106,51,107,50,108,35,109,20,110,36,111,42,112,45,113,44,114,25,115,47,116,18,117,29,118,43,119,52,120,53,121,54,122,55,123,56,124,116,126, /* gotos: */ -32,143,-67,147,-76,47,-75,51,-117,81,-66,125, - 18,0, /* actions: */ 87,144,52,-10,53,-10,54,-10,55,-10,56,-10,86,-10,14,-10,3,-10,22,-10,102,-10,108,-10,27,-10,26,-10,21,-10,29,-10,97,-10,20,-10, - 0,1, /* default action: */ -126, /* gotos: */ -118,145, - 76,5, /* actions: */ 118,48,122,49,119,50,139,52,140,53,91,54,67,55,68,56,69,57,75,58,76,59,137,60,71,61,138,62,72,63,70,64,81,65,82,66,141,67,142,68,143,69,89,70,144,71,145,72,66,73,147,74,148,75,64,76,65,77,79,78,80,79,92,80,61,82,62,83,63,84,59,85,60,86,57,87,49,88,19,89,33,90,28,91,15,92,17,93,58,94,38,95,40,96,27,97,26,98,22,99,21,100,48,101,32,102,37,103,16,104,34,105,46,106,51,107,50,108,35,109,20,110,36,111,42,112,45,113,44,114,25,115,47,116,18,117,29,118,43,119,52,120,53,121,54,122,55,123,56,124,116,126, /* gotos: */ -67,146,-76,47,-75,51,-117,81,-66,125, - /* default action: */ -127, - /* default action: */ -125, - 0,1, /* default action: */ -11, /* gotos: */ -110,149, - 1,0, /* actions: */ 99,150, - 63,41, /* actions: */ 86,27,14,28,57,43,18,142,59,148,60,153,131,136,118,225,122,228,119,286,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,121,226,120,227,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,84,372,103,291,98,300,43,335,58,321,51,342,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,423,19,430,15,440,16,446,17,451,93,457,44,465,147,498,64,501,65,504,148,507,42,525,33,539,34,541,35,544,36,545,89,591,2,598,102,-529, /* gotos: */ -4,151,-108,4,-109,5,-132,26,-3,29,-2,31,-10,42,-68,158,-11,352,-14,353,-13,354,-27,18,-29,19,-69,34,-12,355,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-70,371,-25,345,-18,394,-22,415,-23,439,-28,483,-26,484,-19,509,-105,510,-104,520,-7,523,-8,524,-9,543,-99,546,-100,547,-102,589,-103,556, - 1,0, /* actions: */ 102,152, - /* default action: */ -12, - 0,1, /* default action: */ -13, /* gotos: */ -111,154, - 1,0, /* actions: */ 99,155, - 63,41, /* actions: */ 86,27,14,28,57,43,18,142,59,148,60,153,131,136,118,225,122,228,119,286,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,121,226,120,227,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,84,372,103,291,98,300,43,335,58,321,51,342,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,423,19,430,15,440,16,446,17,451,93,457,44,465,147,498,64,501,65,504,148,507,42,525,33,539,34,541,35,544,36,545,89,591,2,598,102,-529, /* gotos: */ -4,156,-108,4,-109,5,-132,26,-3,29,-2,31,-10,42,-68,158,-11,352,-14,353,-13,354,-27,18,-29,19,-69,34,-12,355,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-70,371,-25,345,-18,394,-22,415,-23,439,-28,483,-26,484,-19,509,-105,510,-104,520,-7,523,-8,524,-9,543,-99,546,-100,547,-102,589,-103,556, - 1,0, /* actions: */ 102,157, - /* default action: */ -14, - 51,0, /* actions: */ 124,159,88,-284,83,-284,104,-284,141,-284,142,-284,143,-284,144,-284,145,-284,66,-284,139,-284,140,-284,91,-284,67,-284,137,-284,71,-284,138,-284,72,-284,68,-284,69,-284,70,-284,75,-284,76,-284,81,-284,82,-284,73,-284,74,-284,77,-284,78,-284,135,-284,49,-284,50,-284,52,-284,53,-284,54,-284,55,-284,56,-284,86,-284,14,-284,3,-284,22,-284,102,-284,108,-284,27,-284,26,-284,21,-284,29,-284,97,-284,20,-284,134,-105,87,-97, - 49,24, /* actions: */ 118,225,122,228,119,286,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,121,226,120,227,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,131,136,84,287,103,291,98,300,43,335,58,321,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,465,64,501,65,504,147,506,148,507, /* gotos: */ -27,160,-19,161,-29,19,-69,34,-12,326,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-70,224,-68,284,-25,345,-18,394,-22,415,-23,439,-28,483,-26,484,-105,218,-104,472, - /* default action: */ -15, - 55,0, /* actions: */ 141,162,142,164,143,166,144,168,145,170,66,172,139,174,140,176,91,178,67,180,137,182,71,184,138,186,72,188,68,190,69,192,70,194,75,196,76,198,81,200,82,202,73,204,74,206,77,208,78,210,135,212,49,-210,50,-210,52,-210,53,-210,54,-210,55,-210,56,-210,86,-210,14,-210,3,-210,22,-210,102,-210,108,-210,27,-210,26,-210,21,-210,29,-210,97,-210,20,-210,25,-210,39,-210,136,-210,85,-210,87,-210,105,-210,100,-210,40,-210,101,-210,41,-210, - 49,20, /* actions: */ 118,225,121,226,120,227,122,228,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,131,136,119,286,84,287,103,291,98,300,43,308,58,321,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,503,64,501,65,504,147,506,148,507, /* gotos: */ -19,163,-105,218,-70,224,-12,237,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-68,284,-69,475,-25,345,-18,394,-22,415,-23,439,-104,472, - 55,0, /* actions: */ 141,-211,142,-211,143,166,144,168,145,170,66,172,139,-211,140,-211,91,-211,67,-211,137,-211,71,-211,138,-211,72,-211,68,-211,69,-211,70,-211,75,-211,76,-211,81,-211,82,-211,73,-211,74,-211,77,-211,78,-211,135,-211,49,-211,50,-211,52,-211,53,-211,54,-211,55,-211,56,-211,86,-211,14,-211,3,-211,22,-211,102,-211,108,-211,27,-211,26,-211,21,-211,29,-211,97,-211,20,-211,25,-211,39,-211,136,-211,85,-211,87,-211,105,-211,100,-211,40,-211,101,-211,41,-211, - 49,20, /* actions: */ 118,225,121,226,120,227,122,228,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,131,136,119,286,84,287,103,291,98,300,43,308,58,321,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,503,64,501,65,504,147,506,148,507, /* gotos: */ -19,165,-105,218,-70,224,-12,237,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-68,284,-69,475,-25,345,-18,394,-22,415,-23,439,-104,472, - 55,0, /* actions: */ 141,-212,142,-212,143,166,144,168,145,170,66,172,139,-212,140,-212,91,-212,67,-212,137,-212,71,-212,138,-212,72,-212,68,-212,69,-212,70,-212,75,-212,76,-212,81,-212,82,-212,73,-212,74,-212,77,-212,78,-212,135,-212,49,-212,50,-212,52,-212,53,-212,54,-212,55,-212,56,-212,86,-212,14,-212,3,-212,22,-212,102,-212,108,-212,27,-212,26,-212,21,-212,29,-212,97,-212,20,-212,25,-212,39,-212,136,-212,85,-212,87,-212,105,-212,100,-212,40,-212,101,-212,41,-212, - 49,20, /* actions: */ 118,225,121,226,120,227,122,228,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,131,136,119,286,84,287,103,291,98,300,43,308,58,321,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,503,64,501,65,504,147,506,148,507, /* gotos: */ -19,167,-105,218,-70,224,-12,237,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-68,284,-69,475,-25,345,-18,394,-22,415,-23,439,-104,472, - 55,0, /* actions: */ 141,-213,142,-213,143,-213,144,-213,145,-213,66,172,139,-213,140,-213,91,-213,67,-213,137,-213,71,-213,138,-213,72,-213,68,-213,69,-213,70,-213,75,-213,76,-213,81,-213,82,-213,73,-213,74,-213,77,-213,78,-213,135,-213,49,-213,50,-213,52,-213,53,-213,54,-213,55,-213,56,-213,86,-213,14,-213,3,-213,22,-213,102,-213,108,-213,27,-213,26,-213,21,-213,29,-213,97,-213,20,-213,25,-213,39,-213,136,-213,85,-213,87,-213,105,-213,100,-213,40,-213,101,-213,41,-213, - 49,20, /* actions: */ 118,225,121,226,120,227,122,228,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,131,136,119,286,84,287,103,291,98,300,43,308,58,321,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,503,64,501,65,504,147,506,148,507, /* gotos: */ -19,169,-105,218,-70,224,-12,237,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-68,284,-69,475,-25,345,-18,394,-22,415,-23,439,-104,472, - 55,0, /* actions: */ 141,-214,142,-214,143,-214,144,-214,145,-214,66,172,139,-214,140,-214,91,-214,67,-214,137,-214,71,-214,138,-214,72,-214,68,-214,69,-214,70,-214,75,-214,76,-214,81,-214,82,-214,73,-214,74,-214,77,-214,78,-214,135,-214,49,-214,50,-214,52,-214,53,-214,54,-214,55,-214,56,-214,86,-214,14,-214,3,-214,22,-214,102,-214,108,-214,27,-214,26,-214,21,-214,29,-214,97,-214,20,-214,25,-214,39,-214,136,-214,85,-214,87,-214,105,-214,100,-214,40,-214,101,-214,41,-214, - 49,20, /* actions: */ 118,225,121,226,120,227,122,228,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,131,136,119,286,84,287,103,291,98,300,43,308,58,321,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,503,64,501,65,504,147,506,148,507, /* gotos: */ -19,171,-105,218,-70,224,-12,237,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-68,284,-69,475,-25,345,-18,394,-22,415,-23,439,-104,472, - 55,0, /* actions: */ 141,-215,142,-215,143,-215,144,-215,145,-215,66,172,139,-215,140,-215,91,-215,67,-215,137,-215,71,-215,138,-215,72,-215,68,-215,69,-215,70,-215,75,-215,76,-215,81,-215,82,-215,73,-215,74,-215,77,-215,78,-215,135,-215,49,-215,50,-215,52,-215,53,-215,54,-215,55,-215,56,-215,86,-215,14,-215,3,-215,22,-215,102,-215,108,-215,27,-215,26,-215,21,-215,29,-215,97,-215,20,-215,25,-215,39,-215,136,-215,85,-215,87,-215,105,-215,100,-215,40,-215,101,-215,41,-215, - 49,20, /* actions: */ 118,225,121,226,120,227,122,228,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,131,136,119,286,84,287,103,291,98,300,43,308,58,321,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,503,64,501,65,504,147,506,148,507, /* gotos: */ -19,173,-105,218,-70,224,-12,237,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-68,284,-69,475,-25,345,-18,394,-22,415,-23,439,-104,472, - 55,0, /* actions: */ 141,-216,142,-216,143,-216,144,-216,145,-216,66,172,139,-216,140,-216,91,-216,67,-216,137,-216,71,-216,138,-216,72,-216,68,-216,69,-216,70,-216,75,-216,76,-216,81,-216,82,-216,73,-216,74,-216,77,-216,78,-216,135,-216,49,-216,50,-216,52,-216,53,-216,54,-216,55,-216,56,-216,86,-216,14,-216,3,-216,22,-216,102,-216,108,-216,27,-216,26,-216,21,-216,29,-216,97,-216,20,-216,25,-216,39,-216,136,-216,85,-216,87,-216,105,-216,100,-216,40,-216,101,-216,41,-216, - 49,20, /* actions: */ 118,225,121,226,120,227,122,228,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,131,136,119,286,84,287,103,291,98,300,43,308,58,321,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,503,64,501,65,504,147,506,148,507, /* gotos: */ -19,175,-105,218,-70,224,-12,237,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-68,284,-69,475,-25,345,-18,394,-22,415,-23,439,-104,472, - 55,0, /* actions: */ 141,162,142,164,143,166,144,168,145,170,66,172,139,-222,140,-222,91,178,67,-222,137,-222,71,-222,138,-222,72,-222,68,-222,69,-222,70,-222,75,-222,76,-222,81,200,82,202,73,-222,74,-222,77,-222,78,-222,135,-222,49,-222,50,-222,52,-222,53,-222,54,-222,55,-222,56,-222,86,-222,14,-222,3,-222,22,-222,102,-222,108,-222,27,-222,26,-222,21,-222,29,-222,97,-222,20,-222,25,-222,39,-222,136,-222,85,-222,87,-222,105,-222,100,-222,40,-222,101,-222,41,-222, - 49,20, /* actions: */ 118,225,121,226,120,227,122,228,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,131,136,119,286,84,287,103,291,98,300,43,308,58,321,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,503,64,501,65,504,147,506,148,507, /* gotos: */ -19,177,-105,218,-70,224,-12,237,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-68,284,-69,475,-25,345,-18,394,-22,415,-23,439,-104,472, - 55,0, /* actions: */ 141,162,142,164,143,166,144,168,145,170,66,172,139,-223,140,-223,91,178,67,-223,137,-223,71,-223,138,-223,72,-223,68,-223,69,-223,70,-223,75,-223,76,-223,81,200,82,202,73,-223,74,-223,77,-223,78,-223,135,-223,49,-223,50,-223,52,-223,53,-223,54,-223,55,-223,56,-223,86,-223,14,-223,3,-223,22,-223,102,-223,108,-223,27,-223,26,-223,21,-223,29,-223,97,-223,20,-223,25,-223,39,-223,136,-223,85,-223,87,-223,105,-223,100,-223,40,-223,101,-223,41,-223, - 49,20, /* actions: */ 118,225,121,226,120,227,122,228,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,131,136,119,286,84,287,103,291,98,300,43,308,58,321,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,503,64,501,65,504,147,506,148,507, /* gotos: */ -19,179,-105,218,-70,224,-12,237,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-68,284,-69,475,-25,345,-18,394,-22,415,-23,439,-104,472, - 55,0, /* actions: */ 141,162,142,164,143,166,144,168,145,170,66,172,139,-224,140,-224,91,-224,67,-224,137,-224,71,-224,138,-224,72,-224,68,-224,69,-224,70,-224,75,-224,76,-224,81,200,82,202,73,-224,74,-224,77,-224,78,-224,135,-224,49,-224,50,-224,52,-224,53,-224,54,-224,55,-224,56,-224,86,-224,14,-224,3,-224,22,-224,102,-224,108,-224,27,-224,26,-224,21,-224,29,-224,97,-224,20,-224,25,-224,39,-224,136,-224,85,-224,87,-224,105,-224,100,-224,40,-224,101,-224,41,-224, - 49,20, /* actions: */ 118,225,121,226,120,227,122,228,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,131,136,119,286,84,287,103,291,98,300,43,308,58,321,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,503,64,501,65,504,147,506,148,507, /* gotos: */ -19,181,-105,218,-70,224,-12,237,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-68,284,-69,475,-25,345,-18,394,-22,415,-23,439,-104,472, - 55,0, /* actions: */ 141,162,142,164,143,166,144,168,145,170,66,172,139,174,140,176,91,178,67,180,137,182,71,184,138,186,72,188,68,190,69,192,70,194,75,196,76,198,81,200,82,202,73,-225,74,-225,77,-225,78,-225,135,-225,49,-225,50,-225,52,-225,53,-225,54,-225,55,-225,56,-225,86,-225,14,-225,3,-225,22,-225,102,-225,108,-225,27,-225,26,-225,21,-225,29,-225,97,-225,20,-225,25,-225,39,-225,136,-225,85,-225,87,-225,105,-225,100,-225,40,-225,101,-225,41,-225, - 49,20, /* actions: */ 118,225,121,226,120,227,122,228,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,131,136,119,286,84,287,103,291,98,300,43,308,58,321,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,503,64,501,65,504,147,506,148,507, /* gotos: */ -19,183,-105,218,-70,224,-12,237,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-68,284,-69,475,-25,345,-18,394,-22,415,-23,439,-104,472, - 55,0, /* actions: */ 141,162,142,164,143,166,144,168,145,170,66,172,139,174,140,176,91,178,67,-226,137,-226,71,-226,138,-226,72,-226,68,-226,69,-226,70,-226,75,-226,76,-226,81,200,82,202,73,-226,74,-226,77,-226,78,-226,135,-226,49,-226,50,-226,52,-226,53,-226,54,-226,55,-226,56,-226,86,-226,14,-226,3,-226,22,-226,102,-226,108,-226,27,-226,26,-226,21,-226,29,-226,97,-226,20,-226,25,-226,39,-226,136,-226,85,-226,87,-226,105,-226,100,-226,40,-226,101,-226,41,-226, - 49,20, /* actions: */ 118,225,121,226,120,227,122,228,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,131,136,119,286,84,287,103,291,98,300,43,308,58,321,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,503,64,501,65,504,147,506,148,507, /* gotos: */ -19,185,-105,218,-70,224,-12,237,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-68,284,-69,475,-25,345,-18,394,-22,415,-23,439,-104,472, - 55,0, /* actions: */ 141,162,142,164,143,166,144,168,145,170,66,172,139,174,140,176,91,178,67,-227,137,-227,71,-227,138,-227,72,-227,68,-227,69,-227,70,-227,75,-227,76,-227,81,200,82,202,73,-227,74,-227,77,-227,78,-227,135,-227,49,-227,50,-227,52,-227,53,-227,54,-227,55,-227,56,-227,86,-227,14,-227,3,-227,22,-227,102,-227,108,-227,27,-227,26,-227,21,-227,29,-227,97,-227,20,-227,25,-227,39,-227,136,-227,85,-227,87,-227,105,-227,100,-227,40,-227,101,-227,41,-227, - 49,20, /* actions: */ 118,225,121,226,120,227,122,228,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,131,136,119,286,84,287,103,291,98,300,43,308,58,321,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,503,64,501,65,504,147,506,148,507, /* gotos: */ -19,187,-105,218,-70,224,-12,237,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-68,284,-69,475,-25,345,-18,394,-22,415,-23,439,-104,472, - 55,0, /* actions: */ 141,162,142,164,143,166,144,168,145,170,66,172,139,174,140,176,91,178,67,-228,137,-228,71,-228,138,-228,72,-228,68,-228,69,-228,70,-228,75,-228,76,-228,81,200,82,202,73,-228,74,-228,77,-228,78,-228,135,-228,49,-228,50,-228,52,-228,53,-228,54,-228,55,-228,56,-228,86,-228,14,-228,3,-228,22,-228,102,-228,108,-228,27,-228,26,-228,21,-228,29,-228,97,-228,20,-228,25,-228,39,-228,136,-228,85,-228,87,-228,105,-228,100,-228,40,-228,101,-228,41,-228, - 49,20, /* actions: */ 118,225,121,226,120,227,122,228,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,131,136,119,286,84,287,103,291,98,300,43,308,58,321,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,503,64,501,65,504,147,506,148,507, /* gotos: */ -19,189,-105,218,-70,224,-12,237,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-68,284,-69,475,-25,345,-18,394,-22,415,-23,439,-104,472, - 55,0, /* actions: */ 141,162,142,164,143,166,144,168,145,170,66,172,139,174,140,176,91,178,67,-229,137,-229,71,-229,138,-229,72,-229,68,-229,69,-229,70,-229,75,-229,76,-229,81,200,82,202,73,-229,74,-229,77,-229,78,-229,135,-229,49,-229,50,-229,52,-229,53,-229,54,-229,55,-229,56,-229,86,-229,14,-229,3,-229,22,-229,102,-229,108,-229,27,-229,26,-229,21,-229,29,-229,97,-229,20,-229,25,-229,39,-229,136,-229,85,-229,87,-229,105,-229,100,-229,40,-229,101,-229,41,-229, - 49,20, /* actions: */ 118,225,121,226,120,227,122,228,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,131,136,119,286,84,287,103,291,98,300,43,308,58,321,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,503,64,501,65,504,147,506,148,507, /* gotos: */ -19,191,-105,218,-70,224,-12,237,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-68,284,-69,475,-25,345,-18,394,-22,415,-23,439,-104,472, - 55,0, /* actions: */ 141,162,142,164,143,166,144,168,145,170,66,172,139,174,140,176,91,178,67,180,137,182,71,184,138,186,72,188,68,190,69,192,70,194,75,196,76,198,81,200,82,202,73,-230,74,-230,77,-230,78,-230,135,-230,49,-230,50,-230,52,-230,53,-230,54,-230,55,-230,56,-230,86,-230,14,-230,3,-230,22,-230,102,-230,108,-230,27,-230,26,-230,21,-230,29,-230,97,-230,20,-230,25,-230,39,-230,136,-230,85,-230,87,-230,105,-230,100,-230,40,-230,101,-230,41,-230, - 49,20, /* actions: */ 118,225,121,226,120,227,122,228,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,131,136,119,286,84,287,103,291,98,300,43,308,58,321,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,503,64,501,65,504,147,506,148,507, /* gotos: */ -19,193,-105,218,-70,224,-12,237,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-68,284,-69,475,-25,345,-18,394,-22,415,-23,439,-104,472, - 55,0, /* actions: */ 141,162,142,164,143,166,144,168,145,170,66,172,139,174,140,176,91,178,67,180,137,182,71,184,138,186,72,188,68,190,69,192,70,194,75,196,76,198,81,200,82,202,73,-231,74,-231,77,-231,78,-231,135,-231,49,-231,50,-231,52,-231,53,-231,54,-231,55,-231,56,-231,86,-231,14,-231,3,-231,22,-231,102,-231,108,-231,27,-231,26,-231,21,-231,29,-231,97,-231,20,-231,25,-231,39,-231,136,-231,85,-231,87,-231,105,-231,100,-231,40,-231,101,-231,41,-231, - 49,20, /* actions: */ 118,225,121,226,120,227,122,228,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,131,136,119,286,84,287,103,291,98,300,43,308,58,321,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,503,64,501,65,504,147,506,148,507, /* gotos: */ -19,195,-105,218,-70,224,-12,237,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-68,284,-69,475,-25,345,-18,394,-22,415,-23,439,-104,472, - 55,0, /* actions: */ 141,162,142,164,143,166,144,168,145,170,66,172,139,174,140,176,91,178,67,180,137,182,71,184,138,186,72,188,68,190,69,192,70,194,75,196,76,198,81,200,82,202,73,-232,74,-232,77,-232,78,-232,135,-232,49,-232,50,-232,52,-232,53,-232,54,-232,55,-232,56,-232,86,-232,14,-232,3,-232,22,-232,102,-232,108,-232,27,-232,26,-232,21,-232,29,-232,97,-232,20,-232,25,-232,39,-232,136,-232,85,-232,87,-232,105,-232,100,-232,40,-232,101,-232,41,-232, - 49,20, /* actions: */ 118,225,121,226,120,227,122,228,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,131,136,119,286,84,287,103,291,98,300,43,308,58,321,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,503,64,501,65,504,147,506,148,507, /* gotos: */ -19,197,-105,218,-70,224,-12,237,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-68,284,-69,475,-25,345,-18,394,-22,415,-23,439,-104,472, - 55,0, /* actions: */ 141,162,142,164,143,166,144,168,145,170,66,172,139,174,140,176,91,178,67,180,137,182,71,184,138,186,72,188,68,190,69,192,70,194,75,196,76,198,81,200,82,202,73,-233,74,-233,77,-233,78,-233,135,-233,49,-233,50,-233,52,-233,53,-233,54,-233,55,-233,56,-233,86,-233,14,-233,3,-233,22,-233,102,-233,108,-233,27,-233,26,-233,21,-233,29,-233,97,-233,20,-233,25,-233,39,-233,136,-233,85,-233,87,-233,105,-233,100,-233,40,-233,101,-233,41,-233, - 49,20, /* actions: */ 118,225,121,226,120,227,122,228,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,131,136,119,286,84,287,103,291,98,300,43,308,58,321,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,503,64,501,65,504,147,506,148,507, /* gotos: */ -19,199,-105,218,-70,224,-12,237,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-68,284,-69,475,-25,345,-18,394,-22,415,-23,439,-104,472, - 55,0, /* actions: */ 141,162,142,164,143,166,144,168,145,170,66,172,139,174,140,176,91,178,67,180,137,182,71,184,138,186,72,188,68,190,69,192,70,194,75,196,76,198,81,200,82,202,73,-234,74,-234,77,-234,78,-234,135,-234,49,-234,50,-234,52,-234,53,-234,54,-234,55,-234,56,-234,86,-234,14,-234,3,-234,22,-234,102,-234,108,-234,27,-234,26,-234,21,-234,29,-234,97,-234,20,-234,25,-234,39,-234,136,-234,85,-234,87,-234,105,-234,100,-234,40,-234,101,-234,41,-234, - 49,20, /* actions: */ 118,225,121,226,120,227,122,228,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,131,136,119,286,84,287,103,291,98,300,43,308,58,321,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,503,64,501,65,504,147,506,148,507, /* gotos: */ -19,201,-105,218,-70,224,-12,237,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-68,284,-69,475,-25,345,-18,394,-22,415,-23,439,-104,472, - 55,0, /* actions: */ 141,162,142,164,143,166,144,168,145,170,66,172,139,-237,140,-237,91,-237,67,-237,137,-237,71,-237,138,-237,72,-237,68,-237,69,-237,70,-237,75,-237,76,-237,81,-237,82,-237,73,-237,74,-237,77,-237,78,-237,135,-237,49,-237,50,-237,52,-237,53,-237,54,-237,55,-237,56,-237,86,-237,14,-237,3,-237,22,-237,102,-237,108,-237,27,-237,26,-237,21,-237,29,-237,97,-237,20,-237,25,-237,39,-237,136,-237,85,-237,87,-237,105,-237,100,-237,40,-237,101,-237,41,-237, - 49,20, /* actions: */ 118,225,121,226,120,227,122,228,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,131,136,119,286,84,287,103,291,98,300,43,308,58,321,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,503,64,501,65,504,147,506,148,507, /* gotos: */ -19,203,-105,218,-70,224,-12,237,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-68,284,-69,475,-25,345,-18,394,-22,415,-23,439,-104,472, - 55,0, /* actions: */ 141,162,142,164,143,166,144,168,145,170,66,172,139,-238,140,-238,91,-238,67,-238,137,-238,71,-238,138,-238,72,-238,68,-238,69,-238,70,-238,75,-238,76,-238,81,-238,82,-238,73,-238,74,-238,77,-238,78,-238,135,-238,49,-238,50,-238,52,-238,53,-238,54,-238,55,-238,56,-238,86,-238,14,-238,3,-238,22,-238,102,-238,108,-238,27,-238,26,-238,21,-238,29,-238,97,-238,20,-238,25,-238,39,-238,136,-238,85,-238,87,-238,105,-238,100,-238,40,-238,101,-238,41,-238, - 54,21, /* actions: */ 118,225,121,226,120,227,122,228,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,131,136,119,286,84,287,103,291,98,300,43,308,58,321,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,503,64,501,65,504,147,506,148,507,42,919,33,920,34,921,35,544,36,545, /* gotos: */ -19,205,-9,928,-105,218,-70,224,-12,237,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-68,284,-69,475,-25,345,-18,394,-22,415,-23,439,-104,472, - 55,0, /* actions: */ 141,162,142,164,143,166,144,168,145,170,66,172,139,174,140,176,91,178,67,180,137,182,71,184,138,186,72,188,68,190,69,192,70,194,75,196,76,198,81,200,82,202,73,-239,74,-239,77,-239,78,-239,135,-239,49,-239,50,-239,52,-239,53,-239,54,-239,55,-239,56,-239,86,-239,14,-239,3,-239,22,-239,102,-239,108,-239,27,-239,26,-239,21,-239,29,-239,97,-239,20,-239,25,-239,39,-239,136,-239,85,-239,87,-239,105,-239,100,-239,40,-239,101,-239,41,-239, - 54,21, /* actions: */ 118,225,121,226,120,227,122,228,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,131,136,119,286,84,287,103,291,98,300,43,308,58,321,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,503,64,501,65,504,147,506,148,507,42,919,33,920,34,921,35,544,36,545, /* gotos: */ -19,207,-9,927,-105,218,-70,224,-12,237,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-68,284,-69,475,-25,345,-18,394,-22,415,-23,439,-104,472, - 55,0, /* actions: */ 141,162,142,164,143,166,144,168,145,170,66,172,139,174,140,176,91,178,67,180,137,182,71,184,138,186,72,188,68,190,69,192,70,194,75,196,76,198,81,200,82,202,73,204,74,-240,77,-240,78,-240,135,-240,49,-240,50,-240,52,-240,53,-240,54,-240,55,-240,56,-240,86,-240,14,-240,3,-240,22,-240,102,-240,108,-240,27,-240,26,-240,21,-240,29,-240,97,-240,20,-240,25,-240,39,-240,136,-240,85,-240,87,-240,105,-240,100,-240,40,-240,101,-240,41,-240, - 49,20, /* actions: */ 118,225,121,226,120,227,122,228,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,131,136,119,286,84,287,103,291,98,300,43,308,58,321,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,503,64,501,65,504,147,506,148,507, /* gotos: */ -19,209,-105,218,-70,224,-12,237,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-68,284,-69,475,-25,345,-18,394,-22,415,-23,439,-104,472, - 55,0, /* actions: */ 141,162,142,164,143,166,144,168,145,170,66,172,139,174,140,176,91,178,67,180,137,182,71,184,138,186,72,188,68,190,69,192,70,194,75,196,76,198,81,200,82,202,73,204,74,206,77,208,78,210,135,-243,49,-243,50,-243,52,-243,53,-243,54,-243,55,-243,56,-243,86,-243,14,-243,3,-243,22,-243,102,-243,108,-243,27,-243,26,-243,21,-243,29,-243,97,-243,20,-243,25,-243,39,-243,136,-243,85,-243,87,-243,105,-243,100,-243,40,-243,101,-243,41,-243, - 49,20, /* actions: */ 118,225,121,226,120,227,122,228,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,131,136,119,286,84,287,103,291,98,300,43,308,58,321,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,503,64,501,65,504,147,506,148,507, /* gotos: */ -19,211,-105,218,-70,224,-12,237,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-68,284,-69,475,-25,345,-18,394,-22,415,-23,439,-104,472, - 55,0, /* actions: */ 141,162,142,164,143,166,144,168,145,170,66,172,139,174,140,176,91,178,67,180,137,182,71,184,138,186,72,188,68,190,69,192,70,194,75,196,76,198,81,200,82,202,73,204,74,206,77,208,78,210,135,-244,49,-244,50,-244,52,-244,53,-244,54,-244,55,-244,56,-244,86,-244,14,-244,3,-244,22,-244,102,-244,108,-244,27,-244,26,-244,21,-244,29,-244,97,-244,20,-244,25,-244,39,-244,136,-244,85,-244,87,-244,105,-244,100,-244,40,-244,101,-244,41,-244, - 54,21, /* actions: */ 118,225,121,226,120,227,122,228,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,131,136,119,286,84,287,103,291,98,300,43,308,58,321,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,503,64,501,65,504,147,506,148,507,42,919,33,920,34,921,35,544,36,545, /* gotos: */ -19,213,-9,922,-105,218,-70,224,-12,237,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-68,284,-69,475,-25,345,-18,394,-22,415,-23,439,-104,472, - 28,1, /* actions: */ 141,162,142,164,143,166,144,168,145,170,66,172,139,174,140,176,91,178,67,180,137,182,71,184,138,186,72,188,68,190,69,192,70,194,75,196,76,198,81,200,82,202,73,204,74,206,77,208,78,210,135,212,14,314,136,-531, /* gotos: */ -114,214, - 1,0, /* actions: */ 136,215, - 54,21, /* actions: */ 118,225,121,226,120,227,122,228,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,131,136,119,286,84,287,103,291,98,300,43,308,58,321,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,503,64,501,65,504,147,506,148,507,42,919,33,920,34,921,35,544,36,545, /* gotos: */ -19,216,-9,217,-105,218,-70,224,-12,237,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-68,284,-69,475,-25,345,-18,394,-22,415,-23,439,-104,472, - 55,0, /* actions: */ 141,162,142,164,143,166,144,168,145,170,66,172,139,174,140,176,91,178,67,180,137,182,71,184,138,186,72,188,68,190,69,192,70,194,75,196,76,198,81,200,82,202,73,204,74,206,77,208,78,210,135,212,49,-246,50,-246,52,-246,53,-246,54,-246,55,-246,56,-246,86,-246,14,-246,3,-246,22,-246,102,-246,108,-246,27,-246,26,-246,21,-246,29,-246,97,-246,20,-246,25,-246,39,-246,136,-246,85,-246,87,-246,105,-246,100,-246,40,-246,101,-246,41,-246, - /* default action: */ -248, - 1,0, /* actions: */ 134,219, - 49,20, /* actions: */ 118,225,121,226,120,227,122,228,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,131,136,119,286,84,287,103,291,98,300,43,308,58,321,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,503,64,501,65,504,147,506,148,507, /* gotos: */ -19,220,-105,218,-70,224,-12,237,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-68,284,-69,475,-25,345,-18,394,-22,415,-23,439,-104,472, - 55,0, /* actions: */ 56,221,141,162,142,164,143,166,144,168,145,170,66,172,139,174,140,176,91,178,67,180,137,182,71,184,138,186,72,188,68,190,69,192,70,194,75,196,76,198,81,200,82,202,73,204,74,206,77,208,78,210,135,212,49,-200,50,-200,52,-200,53,-200,54,-200,55,-200,86,-200,14,-200,3,-200,22,-200,102,-200,108,-200,27,-200,26,-200,21,-200,29,-200,97,-200,20,-200,25,-200,39,-200,136,-200,85,-200,87,-200,105,-200,100,-200,40,-200,101,-200,41,-200, - 54,21, /* actions: */ 118,225,121,226,120,227,122,228,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,131,136,119,286,84,287,103,291,98,300,43,308,58,321,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,503,64,501,65,504,147,506,148,507,42,919,33,920,34,921,35,544,36,545, /* gotos: */ -19,222,-9,223,-105,218,-70,224,-12,237,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-68,284,-69,475,-25,345,-18,394,-22,415,-23,439,-104,472, - 55,0, /* actions: */ 141,162,142,164,143,166,144,168,145,170,66,172,139,174,140,176,91,178,67,180,137,182,71,184,138,186,72,188,68,190,69,192,70,194,75,196,76,198,81,200,82,202,73,204,74,206,77,208,78,210,135,212,49,-201,50,-201,52,-201,53,-201,54,-201,55,-201,56,-201,86,-201,14,-201,3,-201,22,-201,102,-201,108,-201,27,-201,26,-201,21,-201,29,-201,97,-201,20,-201,25,-201,39,-201,136,-201,85,-201,87,-201,105,-201,100,-201,40,-201,101,-201,41,-201, - /* default action: */ -202, - 60,0, /* actions: */ 134,-98,88,-466,83,-466,104,-466,141,-466,142,-466,143,-466,144,-466,145,-466,66,-466,139,-466,140,-466,91,-466,67,-466,137,-466,71,-466,138,-466,72,-466,68,-466,69,-466,70,-466,75,-466,76,-466,81,-466,82,-466,73,-466,74,-466,77,-466,78,-466,135,-466,49,-466,50,-466,52,-466,53,-466,54,-466,55,-466,56,-466,86,-466,14,-466,3,-466,22,-466,102,-466,108,-466,27,-466,26,-466,21,-466,29,-466,97,-466,20,-466,25,-466,39,-466,136,-466,85,-466,87,-466,105,-466,100,-466,40,-466,101,-466,41,-466,124,-467, - 116,0, /* actions: */ 88,-454,83,-454,104,-454,141,-454,142,-454,143,-454,144,-454,145,-454,66,-454,139,-454,140,-454,91,-454,67,-454,137,-454,71,-454,138,-454,72,-454,68,-454,69,-454,70,-454,75,-454,76,-454,81,-454,82,-454,73,-454,74,-454,77,-454,78,-454,135,-454,49,-454,50,-454,52,-454,53,-454,54,-454,55,-454,56,-454,86,-454,14,-454,3,-454,134,-454,124,-454,87,-454,22,-454,102,-454,108,-454,27,-454,26,-454,21,-454,29,-454,97,-454,20,-454,25,-454,39,-454,136,-454,85,-454,105,-454,100,-454,40,-454,101,-454,41,-454,37,-454,99,-517,38,-517,94,-517,118,-517,121,-517,120,-517,122,-517,123,-517,46,-517,45,-517,47,-517,48,-517,62,-517,61,-517,63,-517,128,-517,129,-517,130,-517,146,-517,116,-517,126,-517,111,-517,113,-517,112,-517,114,-517,115,-517,131,-517,119,-517,84,-517,103,-517,98,-517,43,-517,58,-517,51,-517,23,-517,24,-517,30,-517,31,-517,28,-517,32,-517,96,-517,95,-517,19,-517,15,-517,16,-517,17,-517,93,-517,44,-517,64,-517,65,-517,147,-517,148,-517,89,-517,125,-517,90,-517, - /* default action: */ -455, - /* default action: */ -456, - 116,0, /* actions: */ 88,-457,83,-457,104,-457,141,-457,142,-457,143,-457,144,-457,145,-457,66,-457,139,-457,140,-457,91,-457,67,-457,137,-457,71,-457,138,-457,72,-457,68,-457,69,-457,70,-457,75,-457,76,-457,81,-457,82,-457,73,-457,74,-457,77,-457,78,-457,135,-457,49,-457,50,-457,52,-457,53,-457,54,-457,55,-457,56,-457,86,-457,14,-457,3,-457,134,-457,124,-457,87,-457,22,-457,102,-457,108,-457,27,-457,26,-457,21,-457,29,-457,97,-457,20,-457,25,-457,39,-457,136,-457,85,-457,105,-457,100,-457,40,-457,101,-457,41,-457,37,-457,99,-518,38,-518,94,-518,118,-518,121,-518,120,-518,122,-518,123,-518,46,-518,45,-518,47,-518,48,-518,62,-518,61,-518,63,-518,128,-518,129,-518,130,-518,146,-518,116,-518,126,-518,111,-518,113,-518,112,-518,114,-518,115,-518,131,-518,119,-518,84,-518,103,-518,98,-518,43,-518,58,-518,51,-518,23,-518,24,-518,30,-518,31,-518,28,-518,32,-518,96,-518,95,-518,19,-518,15,-518,16,-518,17,-518,93,-518,44,-518,64,-518,65,-518,147,-518,148,-518,89,-518,125,-518,90,-518, - /* default action: */ -458, - /* default action: */ -459, - /* default action: */ -460, - /* default action: */ -461, - /* default action: */ -462, - /* default action: */ -463, - /* default action: */ -464, - /* default action: */ -465, - 58,0, /* actions: */ 104,238,83,917,88,918,141,-250,142,-250,143,-250,144,-250,145,-250,66,-250,139,-250,140,-250,91,-250,67,-250,137,-250,71,-250,138,-250,72,-250,68,-250,69,-250,70,-250,75,-250,76,-250,81,-250,82,-250,73,-250,74,-250,77,-250,78,-250,135,-250,49,-250,50,-250,52,-250,53,-250,54,-250,55,-250,56,-250,86,-250,14,-250,3,-250,22,-250,102,-250,108,-250,27,-250,26,-250,21,-250,29,-250,97,-250,20,-250,25,-250,39,-250,136,-250,85,-250,87,-250,105,-250,100,-250,40,-250,101,-250,41,-250, - 54,28, /* actions: */ 118,225,121,226,120,227,122,228,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,131,136,119,286,84,287,103,291,98,300,43,335,58,321,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,465,64,501,65,504,147,506,148,507,89,515,125,532,90,534,14,-258,105,-258, /* gotos: */ -43,239,-42,471,-20,316,-19,334,-105,218,-70,224,-12,326,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-68,284,-69,34,-25,345,-18,394,-22,415,-23,439,-104,472,-21,527,-51,528,-52,536,-33,537,-29,538, - 2,2, /* actions: */ 14,314,105,-531, /* gotos: */ -113,240,-114,562, - 62,0, /* actions: */ 124,241,134,-99,99,-403,38,-403,88,-403,83,-403,104,-403,141,-403,142,-403,143,-403,144,-403,145,-403,66,-403,139,-403,140,-403,91,-403,67,-403,137,-403,71,-403,138,-403,72,-403,68,-403,69,-403,70,-403,75,-403,76,-403,81,-403,82,-403,73,-403,74,-403,77,-403,78,-403,135,-403,49,-403,50,-403,52,-403,53,-403,54,-403,55,-403,56,-403,86,-403,14,-403,3,-403,22,-403,102,-403,108,-403,27,-403,26,-403,21,-403,29,-403,97,-403,20,-403,25,-403,39,-403,136,-403,85,-403,87,-403,105,-403,100,-403,40,-403,101,-403,41,-403, - 49,20, /* actions: */ 118,225,121,226,120,227,122,228,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,131,136,119,286,84,287,103,291,98,300,43,308,58,321,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,503,64,501,65,504,147,506,148,507, /* gotos: */ -19,242,-105,218,-70,224,-12,237,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-68,284,-69,475,-25,345,-18,394,-22,415,-23,439,-104,472, - 55,0, /* actions: */ 141,162,142,164,143,166,144,168,145,170,66,172,139,174,140,176,91,178,67,180,137,182,71,184,138,186,72,188,68,190,69,192,70,194,75,196,76,198,81,200,82,202,73,204,74,206,77,208,78,210,135,212,49,-204,50,-204,52,-204,53,-204,54,-204,55,-204,56,-204,86,-204,14,-204,3,-204,22,-204,102,-204,108,-204,27,-204,26,-204,21,-204,29,-204,97,-204,20,-204,25,-204,39,-204,136,-204,85,-204,87,-204,105,-204,100,-204,40,-204,101,-204,41,-204, - /* default action: */ -276, - /* default action: */ -448, - /* default action: */ -449, - /* default action: */ -450, - 3,0, /* actions: */ 128,248,129,911,130,914, - 58,0, /* actions: */ 66,249,88,-451,83,-451,104,-451,141,-451,142,-451,143,-451,144,-451,145,-451,139,-451,140,-451,91,-451,67,-451,137,-451,71,-451,138,-451,72,-451,68,-451,69,-451,70,-451,75,-451,76,-451,81,-451,82,-451,73,-451,74,-451,77,-451,78,-451,135,-451,49,-451,50,-451,52,-451,53,-451,54,-451,55,-451,56,-451,86,-451,14,-451,3,-451,22,-451,102,-451,108,-451,27,-451,26,-451,21,-451,29,-451,97,-451,20,-451,25,-451,39,-451,136,-451,85,-451,87,-451,105,-451,100,-451,40,-451,101,-451,41,-451, - 49,20, /* actions: */ 118,225,121,226,120,227,122,228,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,131,136,119,286,84,287,103,291,98,300,43,308,58,321,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,503,64,501,65,504,147,506,148,507, /* gotos: */ -19,250,-105,218,-70,224,-12,237,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-68,284,-69,475,-25,345,-18,394,-22,415,-23,439,-104,472, - 55,0, /* actions: */ 141,-217,142,-217,143,-217,144,-217,145,-217,66,172,139,-217,140,-217,91,-217,67,-217,137,-217,71,-217,138,-217,72,-217,68,-217,69,-217,70,-217,75,-217,76,-217,81,-217,82,-217,73,-217,74,-217,77,-217,78,-217,135,-217,49,-217,50,-217,52,-217,53,-217,54,-217,55,-217,56,-217,86,-217,14,-217,3,-217,22,-217,102,-217,108,-217,27,-217,26,-217,21,-217,29,-217,97,-217,20,-217,25,-217,39,-217,136,-217,85,-217,87,-217,105,-217,100,-217,40,-217,101,-217,41,-217, - /* default action: */ -277, - 59,1, /* actions: */ 111,254,88,-278,83,-278,104,-278,141,-278,142,-278,143,-278,144,-278,145,-278,66,-278,139,-278,140,-278,91,-278,67,-278,137,-278,71,-278,138,-278,72,-278,68,-278,69,-278,70,-278,75,-278,76,-278,81,-278,82,-278,73,-278,74,-278,77,-278,78,-278,135,-278,49,-278,50,-278,52,-278,53,-278,54,-278,55,-278,56,-278,86,-278,14,-278,3,-278,22,-278,102,-278,108,-278,27,-278,26,-278,21,-278,29,-278,97,-278,20,-278,25,-278,39,-278,136,-278,85,-278,87,-278,105,-278,100,-278,40,-278,101,-278,41,-278, /* gotos: */ -56,253, - /* default action: */ -425, - 0,1, /* default action: */ -439, /* gotos: */ -55,255, - 4,1, /* actions: */ 117,256,127,131,106,132,107,139, /* gotos: */ -54,130, - /* default action: */ -426, - /* default action: */ -423, - /* default action: */ -424, - /* default action: */ -279, - 0,1, /* default action: */ -439, /* gotos: */ -55,261, - 4,1, /* actions: */ 117,262,127,131,106,132,107,139, /* gotos: */ -54,130, - /* default action: */ -427, - /* default action: */ -280, - 0,1, /* default action: */ -439, /* gotos: */ -55,265, - 4,1, /* actions: */ 132,266,127,131,106,132,107,139, /* gotos: */ -54,130, - /* default action: */ -428, - /* default action: */ -281, - 4,1, /* actions: */ 117,269,127,-431,106,-431,107,-431, /* gotos: */ -60,270, - /* default action: */ -429, - 3,2, /* actions: */ 127,131,106,132,107,139, /* gotos: */ -59,271,-54,275, - 5,1, /* actions: */ 117,272,13,273,127,131,106,132,107,139, /* gotos: */ -54,274, - /* default action: */ -430, - /* default action: */ -432, - /* default action: */ -434, - /* default action: */ -433, - /* default action: */ -282, - 2,1, /* actions: */ 117,278,127,-437, /* gotos: */ -61,279, - /* default action: */ -435, - 1,0, /* actions: */ 127,280, - 2,0, /* actions: */ 117,281,13,282, - /* default action: */ -436, - /* default action: */ -438, - /* default action: */ -283, - 60,0, /* actions: */ 124,285,88,-284,83,-284,104,-284,141,-284,142,-284,143,-284,144,-284,145,-284,66,-284,139,-284,140,-284,91,-284,67,-284,137,-284,71,-284,138,-284,72,-284,68,-284,69,-284,70,-284,75,-284,76,-284,81,-284,82,-284,73,-284,74,-284,77,-284,78,-284,135,-284,49,-284,50,-284,52,-284,53,-284,54,-284,55,-284,56,-284,86,-284,14,-284,3,-284,22,-284,102,-284,108,-284,27,-284,26,-284,21,-284,29,-284,97,-284,20,-284,25,-284,39,-284,136,-284,85,-284,87,-284,105,-284,100,-284,40,-284,101,-284,41,-284,134,-105, - 49,20, /* actions: */ 118,225,121,226,120,227,122,228,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,131,136,119,286,84,287,103,291,98,300,43,308,58,321,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,503,64,501,65,504,147,506,148,507, /* gotos: */ -19,161,-105,218,-70,224,-12,237,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-68,284,-69,475,-25,345,-18,394,-22,415,-23,439,-104,472, - 113,0, /* actions: */ 88,-285,83,-285,104,-285,141,-285,142,-285,143,-285,144,-285,145,-285,66,-285,139,-285,140,-285,91,-285,67,-285,137,-285,71,-285,138,-285,72,-285,68,-285,69,-285,70,-285,75,-285,76,-285,81,-285,82,-285,73,-285,74,-285,77,-285,78,-285,135,-285,49,-285,50,-285,52,-285,53,-285,54,-285,55,-285,56,-285,86,-285,14,-285,3,-285,22,-285,102,-285,108,-285,27,-285,26,-285,21,-285,29,-285,97,-285,20,-285,25,-285,39,-285,136,-285,85,-285,87,-285,105,-285,100,-285,40,-285,101,-285,41,-285,99,-519,38,-519,94,-519,118,-519,121,-519,120,-519,122,-519,123,-519,46,-519,45,-519,47,-519,48,-519,62,-519,61,-519,63,-519,128,-519,129,-519,130,-519,146,-519,116,-519,126,-519,111,-519,113,-519,112,-519,114,-519,115,-519,131,-519,119,-519,84,-519,103,-519,98,-519,43,-519,58,-519,51,-519,23,-519,24,-519,30,-519,31,-519,28,-519,32,-519,96,-519,95,-519,19,-519,15,-519,16,-519,17,-519,93,-519,44,-519,64,-519,65,-519,147,-519,148,-519,89,-519,125,-519,90,-519, - 1,0, /* actions: */ 122,288, - 60,0, /* actions: */ 124,289,88,-287,83,-287,104,-287,141,-287,142,-287,143,-287,144,-287,145,-287,66,-287,139,-287,140,-287,91,-287,67,-287,137,-287,71,-287,138,-287,72,-287,68,-287,69,-287,70,-287,75,-287,76,-287,81,-287,82,-287,73,-287,74,-287,77,-287,78,-287,135,-287,49,-287,50,-287,52,-287,53,-287,54,-287,55,-287,56,-287,86,-287,14,-287,3,-287,22,-287,102,-287,108,-287,27,-287,26,-287,21,-287,29,-287,97,-287,20,-287,25,-287,39,-287,136,-287,85,-287,87,-287,105,-287,100,-287,40,-287,101,-287,41,-287,134,-104, - 49,20, /* actions: */ 118,225,121,226,120,227,122,228,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,131,136,119,286,84,287,103,291,98,300,43,308,58,321,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,503,64,501,65,504,147,506,148,507, /* gotos: */ -19,290,-105,218,-70,224,-12,237,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-68,284,-69,475,-25,345,-18,394,-22,415,-23,439,-104,472, - 55,0, /* actions: */ 141,162,142,164,143,166,144,168,145,170,66,172,139,174,140,176,91,178,67,180,137,182,71,184,138,186,72,188,68,190,69,192,70,194,75,196,76,198,81,200,82,202,73,204,74,206,77,208,78,210,135,212,49,-209,50,-209,52,-209,53,-209,54,-209,55,-209,56,-209,86,-209,14,-209,3,-209,22,-209,102,-209,108,-209,27,-209,26,-209,21,-209,29,-209,97,-209,20,-209,25,-209,39,-209,136,-209,85,-209,87,-209,105,-209,100,-209,40,-209,101,-209,41,-209, - 52,25, /* actions: */ 118,225,121,226,120,227,122,228,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,131,136,119,286,84,287,103,291,98,300,43,308,58,321,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,503,64,501,65,504,147,506,148,507,89,515,125,532,105,-251, /* gotos: */ -39,292,-20,294,-19,334,-105,218,-70,224,-12,237,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-68,284,-69,475,-25,345,-18,394,-22,415,-23,439,-104,472,-21,527,-51,909,-52,536, - 1,0, /* actions: */ 105,293, - /* default action: */ -288, - 3,1, /* actions: */ 87,296,14,906,105,-535, /* gotos: */ -119,295, - /* default action: */ -252, - 52,22, /* actions: */ 89,319,118,225,121,226,120,227,122,228,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,131,136,119,286,84,287,103,291,98,300,43,308,58,321,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,503,64,501,65,504,147,506,148,507,125,532,105,-537, /* gotos: */ -19,297,-51,907,-105,218,-70,224,-12,237,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-68,284,-69,475,-25,345,-18,394,-22,415,-23,439,-104,472,-52,536, - 52,0, /* actions: */ 141,162,142,164,143,166,144,168,145,170,66,172,139,174,140,176,91,178,67,180,137,182,71,184,138,186,72,188,68,190,69,192,70,194,75,196,76,198,81,200,82,202,73,204,74,206,77,208,78,210,135,212,85,298,87,-274,14,-274,105,-274,97,-274,100,-274,40,-274,49,-274,50,-274,52,-274,53,-274,54,-274,55,-274,56,-274,86,-274,3,-274,22,-274,102,-274,108,-274,27,-274,26,-274,21,-274,29,-274,20,-274,25,-274,39,-274, - 49,20, /* actions: */ 118,225,121,226,120,227,122,228,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,131,136,119,286,84,287,103,291,98,300,43,308,58,321,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,503,64,501,65,504,147,506,148,507, /* gotos: */ -19,299,-105,218,-70,224,-12,237,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-68,284,-69,475,-25,345,-18,394,-22,415,-23,439,-104,472, - 51,0, /* actions: */ 141,162,142,164,143,166,144,168,145,170,66,172,139,174,140,176,91,178,67,180,137,182,71,184,138,186,72,188,68,190,69,192,70,194,75,196,76,198,81,200,82,202,73,204,74,206,77,208,78,210,135,212,87,-515,14,-515,105,-515,102,-515,97,-515,100,-515,40,-515,49,-515,50,-515,52,-515,53,-515,54,-515,55,-515,56,-515,86,-515,3,-515,22,-515,108,-515,27,-515,26,-515,21,-515,29,-515,20,-515,25,-515,39,-515, - 51,22, /* actions: */ 102,301,118,225,121,226,120,227,122,228,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,131,136,119,286,84,287,103,291,98,300,43,308,58,321,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,503,64,501,65,504,147,506,148,507,125,532, /* gotos: */ -51,302,-52,536,-19,307,-105,218,-70,224,-12,237,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-68,284,-69,475,-25,345,-18,394,-22,415,-23,439,-104,472, - /* default action: */ -289, - 3,1, /* actions: */ 87,305,14,906,102,-535, /* gotos: */ -119,303, - 1,0, /* actions: */ 102,304, - /* default action: */ -290, - 52,21, /* actions: */ 118,225,121,226,120,227,122,228,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,131,136,119,286,84,287,103,291,98,300,43,308,58,321,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,503,64,501,65,504,147,506,148,507,125,532,102,-537,105,-537, /* gotos: */ -52,306,-19,307,-105,218,-70,224,-12,237,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-68,284,-69,475,-25,345,-18,394,-22,415,-23,439,-104,472, - /* default action: */ -514, - 27,0, /* actions: */ 85,298,141,162,142,164,143,166,144,168,145,170,66,172,139,174,140,176,91,178,67,180,137,182,71,184,138,186,72,188,68,190,69,192,70,194,75,196,76,198,81,200,82,202,73,204,74,206,77,208,78,210,135,212, - 59,0, /* actions: */ 94,309,104,-293,83,-293,88,-293,141,-293,142,-293,143,-293,144,-293,145,-293,66,-293,139,-293,140,-293,91,-293,67,-293,137,-293,71,-293,138,-293,72,-293,68,-293,69,-293,70,-293,75,-293,76,-293,81,-293,82,-293,73,-293,74,-293,77,-293,78,-293,135,-293,49,-293,50,-293,52,-293,53,-293,54,-293,55,-293,56,-293,86,-293,14,-293,3,-293,22,-293,102,-293,108,-293,27,-293,26,-293,21,-293,29,-293,97,-293,20,-293,25,-293,39,-293,136,-293,85,-293,87,-293,105,-293,100,-293,40,-293,101,-293,41,-293, - 54,29, /* actions: */ 118,225,121,226,120,227,122,228,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,131,136,119,286,84,287,103,291,98,300,43,335,58,321,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,465,64,501,65,504,147,506,148,507,89,515,125,532,90,534,14,314,97,-531, /* gotos: */ -42,310,-116,315,-20,316,-19,334,-105,218,-70,224,-12,326,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-68,284,-69,34,-25,345,-18,394,-22,415,-23,439,-104,472,-21,527,-51,528,-52,536,-33,537,-29,538,-114,312, - 2,2, /* actions: */ 14,314,97,-531, /* gotos: */ -116,311,-114,312, - /* default action: */ -291, - 1,0, /* actions: */ 97,313, - /* default action: */ -533, - /* default action: */ -532, - /* default action: */ -292, - 25,1, /* actions: */ 87,318,14,-270,105,-270,97,-270,100,-270,40,-270,49,-270,50,-270,52,-270,53,-270,54,-270,55,-270,56,-270,86,-270,3,-270,22,-270,102,-270,108,-270,27,-270,26,-270,21,-270,29,-270,20,-270,25,-270,39,-270, /* gotos: */ -34,317, - /* default action: */ -260, - 76,23, /* actions: */ 89,319,118,225,121,226,120,227,122,228,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,131,136,119,286,84,287,103,291,98,300,43,308,58,321,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,503,64,501,65,504,147,506,148,507,125,532,90,534,14,-269,105,-269,97,-269,100,-269,40,-269,49,-269,50,-269,52,-269,53,-269,54,-269,55,-269,56,-269,86,-269,3,-269,22,-269,102,-269,108,-269,27,-269,26,-269,21,-269,29,-269,20,-269,25,-269,39,-269, /* gotos: */ -19,297,-51,904,-33,531,-105,218,-70,224,-12,237,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-68,284,-69,475,-25,345,-18,394,-22,415,-23,439,-104,472,-52,536, - 49,20, /* actions: */ 118,225,121,226,120,227,122,228,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,131,136,119,286,84,287,103,291,98,300,43,308,58,321,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,503,64,501,65,504,147,506,148,507, /* gotos: */ -19,320,-105,218,-70,224,-12,237,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-68,284,-69,475,-25,345,-18,394,-22,415,-23,439,-104,472, - 52,0, /* actions: */ 141,162,142,164,143,166,144,168,145,170,66,172,139,174,140,176,91,178,67,180,137,182,71,184,138,186,72,188,68,190,69,192,70,194,75,196,76,198,81,200,82,202,73,204,74,206,77,208,78,210,135,212,87,-275,14,-275,105,-275,97,-275,100,-275,40,-275,49,-275,50,-275,52,-275,53,-275,54,-275,55,-275,56,-275,86,-275,3,-275,22,-275,102,-275,108,-275,27,-275,26,-275,21,-275,29,-275,20,-275,25,-275,39,-275,85,-275, - 51,1, /* actions: */ 14,314,94,-531,118,-531,121,-531,120,-531,122,-531,123,-531,46,-531,45,-531,47,-531,48,-531,62,-531,61,-531,63,-531,128,-531,129,-531,130,-531,146,-531,116,-531,126,-531,111,-531,113,-531,112,-531,114,-531,115,-531,131,-531,119,-531,84,-531,103,-531,98,-531,43,-531,58,-531,51,-531,23,-531,24,-531,30,-531,31,-531,28,-531,32,-531,96,-531,95,-531,19,-531,15,-531,16,-531,17,-531,93,-531,44,-531,64,-531,65,-531,147,-531,148,-531, /* gotos: */ -114,322, - 50,20, /* actions: */ 94,323,118,225,121,226,120,227,122,228,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,131,136,119,286,84,287,103,291,98,300,43,308,58,321,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,503,64,501,65,504,147,506,148,507, /* gotos: */ -19,903,-105,218,-70,224,-12,237,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-68,284,-69,475,-25,345,-18,394,-22,415,-23,439,-104,472, - 49,25, /* actions: */ 118,225,122,228,119,286,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,121,226,120,227,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,131,136,84,287,103,291,98,300,43,335,58,321,51,342,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,465,147,498,64,501,65,504,148,507, /* gotos: */ -13,324,-27,18,-29,19,-69,34,-12,326,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-70,224,-68,284,-25,345,-18,394,-22,415,-23,439,-28,483,-26,484,-19,509,-105,218,-104,472, - 4,2, /* actions: */ 49,13,50,15,14,314,97,-531, /* gotos: */ -116,325,-114,312, - /* default action: */ -294, - 55,0, /* actions: */ 88,327,83,898,104,238,141,-250,142,-250,143,-250,144,-250,145,-250,66,-250,139,-250,140,-250,91,-250,67,-250,137,-250,71,-250,138,-250,72,-250,68,-250,69,-250,70,-250,75,-250,76,-250,81,-250,82,-250,73,-250,74,-250,77,-250,78,-250,135,-250,49,-250,50,-250,52,-250,53,-250,54,-250,55,-250,56,-250,86,-250,14,-250,3,-250,22,-250,102,-250,108,-250,27,-250,26,-250,21,-250,29,-250,97,-250,20,-250,25,-250,39,-250,85,-250,87,-250,105,-250,100,-250,40,-250, - 33,3, /* actions: */ 118,894,122,896,119,492,139,52,140,53,91,54,67,55,68,56,69,57,75,58,76,59,137,60,71,61,138,62,72,63,70,64,81,65,82,66,141,67,142,68,143,69,89,70,144,71,145,72,66,73,147,74,148,75,64,76,65,77,79,78,80,79,92,80,94,468, /* gotos: */ -72,328,-40,357,-75,493, - 110,4, /* actions: */ 94,468,118,-265,121,-265,120,-265,122,-265,123,-265,46,-265,45,-265,47,-265,48,-265,62,-265,61,-265,63,-265,128,-265,129,-265,130,-265,146,-265,116,-265,126,-265,111,-265,113,-265,112,-265,114,-265,115,-265,131,-265,119,-265,84,-265,103,-265,98,-265,43,-265,58,-265,51,-265,23,-265,24,-265,30,-265,31,-265,28,-265,32,-265,96,-265,95,-265,19,-265,15,-265,16,-265,17,-265,93,-265,44,-265,64,-265,65,-265,147,-265,148,-265,89,-265,125,-265,90,-265,99,-256,38,-256,88,-256,83,-256,104,-256,141,-256,142,-256,143,-256,144,-256,145,-256,66,-256,139,-256,140,-256,91,-256,67,-256,137,-256,71,-256,138,-256,72,-256,68,-256,69,-256,70,-256,75,-256,76,-256,81,-256,82,-256,73,-256,74,-256,77,-256,78,-256,135,-256,49,-256,50,-256,52,-256,53,-256,54,-256,55,-256,56,-256,86,-256,14,-256,3,-256,22,-256,102,-256,108,-256,27,-256,26,-256,21,-256,29,-256,97,-256,20,-256,25,-256,39,-256,85,-256,87,-256,105,-256,100,-256,40,-256, /* gotos: */ -44,329,-41,331,-120,332,-40,489, - 24,1, /* actions: */ 100,37,40,-67,49,-67,50,-67,52,-67,53,-67,54,-67,55,-67,56,-67,86,-67,14,-67,3,-67,22,-67,102,-67,108,-67,27,-67,26,-67,21,-67,29,-67,97,-67,20,-67,25,-67,39,-67,105,-67, /* gotos: */ -35,330, - /* default action: */ -68, - /* default action: */ -398, - 52,27, /* actions: */ 118,225,121,226,120,227,122,228,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,131,136,119,286,84,287,103,291,98,300,43,335,58,321,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,465,64,501,65,504,147,506,148,507,89,515,125,532,90,534, /* gotos: */ -42,333,-20,316,-19,334,-105,218,-70,224,-12,326,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-68,284,-69,34,-25,345,-18,394,-22,415,-23,439,-104,472,-21,527,-51,528,-52,536,-33,537,-29,538, - /* default action: */ -266, - 52,0, /* actions: */ 141,162,142,164,143,166,144,168,145,170,66,172,139,174,140,176,91,178,67,180,137,182,71,184,138,186,72,188,68,190,69,192,70,194,75,196,76,198,81,200,82,202,73,204,74,206,77,208,78,210,135,212,85,298,87,-271,14,-271,105,-271,97,-271,100,-271,40,-271,49,-271,50,-271,52,-271,53,-271,54,-271,55,-271,56,-271,86,-271,3,-271,22,-271,102,-271,108,-271,27,-271,26,-271,21,-271,29,-271,20,-271,25,-271,39,-271, - 108,2, /* actions: */ 94,309,88,-293,83,-293,104,-293,141,-293,142,-293,143,-293,144,-293,145,-293,66,-293,139,-293,140,-293,91,-293,67,-293,137,-293,71,-293,138,-293,72,-293,68,-293,69,-293,70,-293,75,-293,76,-293,81,-293,82,-293,73,-293,74,-293,77,-293,78,-293,135,-293,49,-293,50,-293,52,-293,53,-293,54,-293,55,-293,56,-293,86,-293,14,-293,3,-293,22,-293,102,-293,108,-293,27,-293,26,-293,21,-293,29,-293,97,-293,20,-293,25,-293,39,-293,85,-293,87,-293,105,-293,100,-293,40,-293,118,-265,121,-265,120,-265,122,-265,123,-265,46,-265,45,-265,47,-265,48,-265,62,-265,61,-265,63,-265,128,-265,129,-265,130,-265,146,-265,116,-265,126,-265,111,-265,113,-265,112,-265,114,-265,115,-265,131,-265,119,-265,84,-265,103,-265,98,-265,43,-265,58,-265,51,-265,23,-265,24,-265,30,-265,31,-265,28,-265,32,-265,96,-265,95,-265,19,-265,15,-265,16,-265,17,-265,93,-265,44,-265,64,-265,65,-265,147,-265,148,-265,89,-265,125,-265,90,-265, /* gotos: */ -44,336,-120,332, - /* default action: */ -72, - 1,0, /* actions: */ 94,338, - 51,27, /* actions: */ 118,225,122,228,119,286,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,121,226,120,227,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,131,136,84,287,103,291,98,300,43,335,58,321,51,342,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,465,147,498,64,501,65,504,148,507,14,314,97,-531, /* gotos: */ -13,339,-116,341,-27,18,-29,19,-69,34,-12,326,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-70,224,-68,284,-25,345,-18,394,-22,415,-23,439,-28,483,-26,484,-19,509,-105,218,-104,472,-114,312, - 4,2, /* actions: */ 49,13,50,15,14,314,97,-531, /* gotos: */ -116,340,-114,312, - /* default action: */ -295, - /* default action: */ -296, - 51,1, /* actions: */ 94,338,14,314,118,-531,122,-531,119,-531,128,-531,129,-531,130,-531,146,-531,116,-531,126,-531,111,-531,113,-531,112,-531,114,-531,115,-531,121,-531,120,-531,123,-531,46,-531,45,-531,47,-531,48,-531,62,-531,61,-531,63,-531,131,-531,84,-531,103,-531,98,-531,43,-531,58,-531,51,-531,23,-531,24,-531,30,-531,31,-531,28,-531,32,-531,96,-531,95,-531,19,-531,15,-531,16,-531,17,-531,93,-531,44,-531,147,-531,64,-531,65,-531,148,-531, /* gotos: */ -114,343, - 49,25, /* actions: */ 118,225,122,228,119,286,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,121,226,120,227,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,131,136,84,287,103,291,98,300,43,335,58,321,51,342,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,465,147,498,64,501,65,504,148,507, /* gotos: */ -13,344,-27,18,-29,19,-69,34,-12,326,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-70,224,-68,284,-25,345,-18,394,-22,415,-23,439,-28,483,-26,484,-19,509,-105,218,-104,472, - /* default action: */ -55, - 60,1, /* actions: */ 99,347,38,478,88,-298,83,-298,104,-298,141,-298,142,-298,143,-298,144,-298,145,-298,66,-298,139,-298,140,-298,91,-298,67,-298,137,-298,71,-298,138,-298,72,-298,68,-298,69,-298,70,-298,75,-298,76,-298,81,-298,82,-298,73,-298,74,-298,77,-298,78,-298,135,-298,49,-298,50,-298,52,-298,53,-298,54,-298,55,-298,56,-298,86,-298,14,-298,3,-298,22,-298,102,-298,108,-298,27,-298,26,-298,21,-298,29,-298,97,-298,20,-298,25,-298,39,-298,136,-298,85,-298,87,-298,105,-298,100,-298,40,-298,101,-298,41,-298, /* gotos: */ -36,346, - /* default action: */ -299, - 0,1, /* default action: */ -406, /* gotos: */ -141,348, - 65,2, /* actions: */ 74,609,139,610,86,-378,14,-378,57,-378,18,-378,59,-378,60,-378,131,-378,118,-378,122,-378,119,-378,128,-378,129,-378,130,-378,146,-378,116,-378,126,-378,111,-378,113,-378,112,-378,114,-378,115,-378,121,-378,120,-378,123,-378,46,-378,45,-378,47,-378,48,-378,62,-378,61,-378,63,-378,84,-378,103,-378,98,-378,43,-378,58,-378,51,-378,23,-378,24,-378,30,-378,31,-378,28,-378,32,-378,96,-378,95,-378,19,-378,15,-378,16,-378,17,-378,93,-378,44,-378,147,-378,64,-378,65,-378,148,-378,42,-378,33,-378,34,-378,35,-378,36,-378,89,-378,2,-378,102,-378, /* gotos: */ -78,349,-77,608, - 63,41, /* actions: */ 86,27,14,28,57,43,18,142,59,148,60,153,131,136,118,225,122,228,119,286,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,121,226,120,227,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,84,372,103,291,98,300,43,335,58,321,51,342,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,423,19,430,15,440,16,446,17,451,93,457,44,465,147,498,64,501,65,504,148,507,42,525,33,539,34,541,35,544,36,545,89,591,2,598,102,-529, /* gotos: */ -4,350,-108,4,-109,5,-132,26,-3,29,-2,31,-10,42,-68,158,-11,352,-14,353,-13,354,-27,18,-29,19,-69,34,-12,355,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-70,371,-25,345,-18,394,-22,415,-23,439,-28,483,-26,484,-19,509,-105,510,-104,520,-7,523,-8,524,-9,543,-99,546,-100,547,-102,589,-103,556, - 1,0, /* actions: */ 102,351, - /* default action: */ -407, - /* default action: */ -16, - /* default action: */ -17, - 19,0, /* actions: */ 49,13,50,15,52,-32,53,-32,54,-32,55,-32,56,-32,86,-32,14,-32,3,-32,22,-32,102,-32,108,-32,27,-32,26,-32,21,-32,29,-32,97,-32,20,-32, - 48,0, /* actions: */ 88,356,83,877,104,889,141,-250,142,-250,143,-250,144,-250,145,-250,66,-250,139,-250,140,-250,91,-250,67,-250,137,-250,71,-250,138,-250,72,-250,68,-250,69,-250,70,-250,75,-250,76,-250,81,-250,82,-250,73,-250,74,-250,77,-250,78,-250,135,-250,49,-250,50,-250,52,-250,53,-250,54,-250,55,-250,56,-250,86,-250,14,-250,3,-250,22,-250,102,-250,108,-250,27,-250,26,-250,21,-250,29,-250,97,-250,20,-250, - 33,3, /* actions: */ 118,358,122,873,119,492,139,52,140,53,91,54,67,55,68,56,69,57,75,58,76,59,137,60,71,61,138,62,72,63,70,64,81,65,82,66,141,67,142,68,143,69,89,70,144,71,145,72,66,73,147,74,148,75,64,76,65,77,79,78,80,79,92,80,94,468, /* gotos: */ -72,328,-40,357,-75,493, - /* default action: */ -401, - 106,0, /* actions: */ 124,359,134,-100,87,-92,94,-520,118,-520,121,-520,120,-520,122,-520,123,-520,46,-520,45,-520,47,-520,48,-520,62,-520,61,-520,63,-520,128,-520,129,-520,130,-520,146,-520,116,-520,126,-520,111,-520,113,-520,112,-520,114,-520,115,-520,131,-520,119,-520,84,-520,103,-520,98,-520,43,-520,58,-520,51,-520,23,-520,24,-520,30,-520,31,-520,28,-520,32,-520,96,-520,95,-520,19,-520,15,-520,16,-520,17,-520,93,-520,44,-520,64,-520,65,-520,147,-520,148,-520,89,-520,125,-520,90,-520,99,-520,38,-520,88,-520,83,-520,104,-520,141,-520,142,-520,143,-520,144,-520,145,-520,66,-520,139,-520,140,-520,91,-520,67,-520,137,-520,71,-520,138,-520,72,-520,68,-520,69,-520,70,-520,75,-520,76,-520,81,-520,82,-520,73,-520,74,-520,77,-520,78,-520,135,-520,49,-520,50,-520,52,-520,53,-520,54,-520,55,-520,56,-520,86,-520,14,-520,3,-520,22,-520,102,-520,108,-520,27,-520,26,-520,21,-520,29,-520,97,-520,20,-520, - 49,24, /* actions: */ 118,225,121,226,120,227,122,228,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,131,136,119,286,84,287,103,291,98,300,43,335,58,321,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,465,64,501,65,504,147,506,148,507, /* gotos: */ -19,360,-27,361,-105,218,-70,224,-12,326,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-68,284,-69,34,-25,345,-18,394,-22,415,-23,439,-104,472,-29,19,-28,483,-26,484, - 55,0, /* actions: */ 141,162,142,164,143,166,144,168,145,170,66,172,139,174,140,176,91,178,67,180,137,182,71,184,138,186,72,188,68,190,69,192,70,194,75,196,76,198,81,200,82,202,73,204,74,206,77,208,78,210,135,212,49,-205,50,-205,52,-205,53,-205,54,-205,55,-205,56,-205,86,-205,14,-205,3,-205,22,-205,102,-205,108,-205,27,-205,26,-205,21,-205,29,-205,97,-205,20,-205,25,-205,39,-205,136,-205,85,-205,87,-205,105,-205,100,-205,40,-205,101,-205,41,-205, - /* default action: */ -38, - 49,25, /* actions: */ 118,225,122,228,119,286,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,121,226,120,227,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,131,136,84,287,103,291,98,300,43,335,58,321,51,342,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,465,147,498,64,501,65,504,148,507, /* gotos: */ -13,363,-27,18,-29,19,-69,34,-12,326,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-70,224,-68,284,-25,345,-18,394,-22,415,-23,439,-28,483,-26,484,-19,509,-105,218,-104,472, - 5,2, /* actions: */ 49,13,50,15,86,27,14,28,25,821, /* gotos: */ -121,364,-132,819, - 65,41, /* actions: */ 86,27,14,28,57,43,18,142,59,148,60,153,131,136,118,225,122,228,119,286,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,121,226,120,227,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,84,372,103,291,98,300,43,335,58,321,51,342,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,423,19,430,15,440,16,446,17,451,93,457,44,465,147,498,64,501,65,504,148,507,42,525,33,539,34,541,35,544,36,545,89,591,2,598,27,-529,26,-529,22,-529, /* gotos: */ -4,365,-108,4,-109,5,-132,26,-3,29,-2,31,-10,42,-68,158,-11,352,-14,353,-13,354,-27,18,-29,19,-69,34,-12,355,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-70,371,-25,345,-18,394,-22,415,-23,439,-28,483,-26,484,-19,509,-105,510,-104,520,-7,523,-8,524,-9,543,-99,546,-100,547,-102,589,-103,556, - 3,2, /* actions: */ 27,369,26,868,22,-341, /* gotos: */ -31,366,-30,368, - 1,0, /* actions: */ 22,367, - /* default action: */ -300, - /* default action: */ -339, - 64,41, /* actions: */ 86,27,14,28,57,43,18,142,59,148,60,153,131,136,118,225,122,228,119,286,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,121,226,120,227,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,84,372,103,291,98,300,43,335,58,321,51,342,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,423,19,430,15,440,16,446,17,451,93,457,44,465,147,498,64,501,65,504,148,507,42,525,33,539,34,541,35,544,36,545,89,591,2,598,22,-529,21,-529, /* gotos: */ -4,370,-108,4,-109,5,-132,26,-3,29,-2,31,-10,42,-68,158,-11,352,-14,353,-13,354,-27,18,-29,19,-69,34,-12,355,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-70,371,-25,345,-18,394,-22,415,-23,439,-28,483,-26,484,-19,509,-105,510,-104,520,-7,523,-8,524,-9,543,-99,546,-100,547,-102,589,-103,556, - /* default action: */ -342, - 51,0, /* actions: */ 88,-466,83,-466,104,-466,141,-466,142,-466,143,-466,144,-466,145,-466,66,-466,139,-466,140,-466,91,-466,67,-466,137,-466,71,-466,138,-466,72,-466,68,-466,69,-466,70,-466,75,-466,76,-466,81,-466,82,-466,73,-466,74,-466,77,-466,78,-466,135,-466,49,-466,50,-466,52,-466,53,-466,54,-466,55,-466,56,-466,86,-466,14,-466,3,-466,22,-466,102,-466,108,-466,27,-466,26,-466,21,-466,29,-466,97,-466,20,-466,134,-98,124,-467,87,-90, - 1,0, /* actions: */ 122,373, - 51,0, /* actions: */ 124,289,88,-287,83,-287,104,-287,141,-287,142,-287,143,-287,144,-287,145,-287,66,-287,139,-287,140,-287,91,-287,67,-287,137,-287,71,-287,138,-287,72,-287,68,-287,69,-287,70,-287,75,-287,76,-287,81,-287,82,-287,73,-287,74,-287,77,-287,78,-287,135,-287,49,-287,50,-287,52,-287,53,-287,54,-287,55,-287,56,-287,86,-287,14,-287,3,-287,22,-287,102,-287,108,-287,27,-287,26,-287,21,-287,29,-287,97,-287,20,-287,134,-104,87,-96, - 49,25, /* actions: */ 118,225,122,228,119,286,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,121,226,120,227,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,131,136,84,287,103,291,98,300,43,335,58,321,51,342,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,465,147,498,64,501,65,504,148,507, /* gotos: */ -13,375,-27,18,-29,19,-69,34,-12,326,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-70,224,-68,284,-25,345,-18,394,-22,415,-23,439,-28,483,-26,484,-19,509,-105,218,-104,472, - 5,2, /* actions: */ 49,13,50,15,86,27,14,28,25,821, /* gotos: */ -121,376,-132,819, - 64,41, /* actions: */ 86,27,14,28,57,43,18,142,59,148,60,153,131,136,118,225,122,228,119,286,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,121,226,120,227,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,84,372,103,291,98,300,43,335,58,321,51,342,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,423,19,430,15,440,16,446,17,451,93,457,44,465,147,498,64,501,65,504,148,507,42,525,33,539,34,541,35,544,36,545,89,591,2,598,27,-529,22,-529, /* gotos: */ -4,377,-108,4,-109,5,-132,26,-3,29,-2,31,-10,42,-68,158,-11,352,-14,353,-13,354,-27,18,-29,19,-69,34,-12,355,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-70,371,-25,345,-18,394,-22,415,-23,439,-28,483,-26,484,-19,509,-105,510,-104,520,-7,523,-8,524,-9,543,-99,546,-100,547,-102,589,-103,556, - 2,1, /* actions: */ 27,369,22,-341, /* gotos: */ -30,378, - 1,0, /* actions: */ 22,379, - /* default action: */ -301, - 0,1, /* default action: */ -302, /* gotos: */ -122,381, - 49,25, /* actions: */ 118,225,122,228,119,286,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,121,226,120,227,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,131,136,84,287,103,291,98,300,43,335,58,321,51,342,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,465,147,498,64,501,65,504,148,507, /* gotos: */ -13,382,-27,18,-29,19,-69,34,-12,326,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-70,224,-68,284,-25,345,-18,394,-22,415,-23,439,-28,483,-26,484,-19,509,-105,218,-104,472, - 5,2, /* actions: */ 49,13,50,15,86,27,14,28,39,845, /* gotos: */ -123,383,-132,844, - 0,1, /* default action: */ -303, /* gotos: */ -124,384, - 63,41, /* actions: */ 86,27,14,28,57,43,18,142,59,148,60,153,131,136,118,225,122,228,119,286,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,121,226,120,227,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,84,372,103,291,98,300,43,335,58,321,51,342,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,423,19,430,15,440,16,446,17,451,93,457,44,465,147,498,64,501,65,504,148,507,42,525,33,539,34,541,35,544,36,545,89,591,2,598,22,-529, /* gotos: */ -4,385,-108,4,-109,5,-132,26,-3,29,-2,31,-10,42,-68,158,-11,352,-14,353,-13,354,-27,18,-29,19,-69,34,-12,355,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-70,371,-25,345,-18,394,-22,415,-23,439,-28,483,-26,484,-19,509,-105,510,-104,520,-7,523,-8,524,-9,543,-99,546,-100,547,-102,589,-103,556, - 1,0, /* actions: */ 22,386, - /* default action: */ -304, - 0,1, /* default action: */ -305, /* gotos: */ -125,388, - 49,25, /* actions: */ 118,225,122,228,119,286,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,121,226,120,227,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,131,136,84,287,103,291,98,300,43,335,58,321,51,342,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,465,147,498,64,501,65,504,148,507, /* gotos: */ -13,389,-27,18,-29,19,-69,34,-12,326,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-70,224,-68,284,-25,345,-18,394,-22,415,-23,439,-28,483,-26,484,-19,509,-105,218,-104,472, - 5,2, /* actions: */ 49,13,50,15,86,27,14,28,39,845, /* gotos: */ -123,390,-132,844, - 0,1, /* default action: */ -306, /* gotos: */ -126,391, - 63,41, /* actions: */ 86,27,14,28,57,43,18,142,59,148,60,153,131,136,118,225,122,228,119,286,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,121,226,120,227,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,84,372,103,291,98,300,43,335,58,321,51,342,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,423,19,430,15,440,16,446,17,451,93,457,44,465,147,498,64,501,65,504,148,507,42,525,33,539,34,541,35,544,36,545,89,591,2,598,22,-529, /* gotos: */ -4,392,-108,4,-109,5,-132,26,-3,29,-2,31,-10,42,-68,158,-11,352,-14,353,-13,354,-27,18,-29,19,-69,34,-12,355,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-70,371,-25,345,-18,394,-22,415,-23,439,-28,483,-26,484,-19,509,-105,510,-104,520,-7,523,-8,524,-9,543,-99,546,-100,547,-102,589,-103,556, - 1,0, /* actions: */ 22,393, - /* default action: */ -307, - /* default action: */ -308, - 52,28, /* actions: */ 118,225,122,228,119,286,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,121,226,120,227,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,131,136,84,287,103,291,98,300,43,335,58,321,51,342,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,465,147,498,64,501,65,504,148,507,86,27,14,28,29,-529, /* gotos: */ -13,396,-108,864,-27,18,-29,19,-69,34,-12,326,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-70,224,-68,284,-25,345,-18,394,-22,415,-23,439,-28,483,-26,484,-19,509,-105,218,-104,472,-109,863,-132,26, - 5,3, /* actions: */ 49,13,50,15,86,27,14,28,29,-529, /* gotos: */ -108,397,-109,863,-132,26, - 1,2, /* actions: */ 29,402, /* gotos: */ -49,398,-50,862, - 3,2, /* actions: */ 27,369,29,402,22,-341, /* gotos: */ -30,399,-50,401, - 1,0, /* actions: */ 22,400, - /* default action: */ -332, - /* default action: */ -411, - 50,22, /* actions: */ 118,225,121,226,120,227,122,228,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,131,136,119,286,84,287,103,291,98,300,43,308,58,321,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,503,64,501,65,504,147,506,148,507,89,515, /* gotos: */ -20,403,-19,842,-105,218,-70,224,-12,237,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-68,284,-69,475,-25,345,-18,394,-22,415,-23,439,-104,472,-21,527, - 4,2, /* actions: */ 87,518,86,27,14,28,25,821, /* gotos: */ -121,404,-132,819, - 65,41, /* actions: */ 86,27,14,28,57,43,18,142,59,148,60,153,131,136,118,225,122,228,119,286,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,121,226,120,227,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,84,372,103,291,98,300,43,335,58,321,51,342,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,423,19,430,15,440,16,446,17,451,93,457,44,465,147,498,64,501,65,504,148,507,42,525,33,539,34,541,35,544,36,545,89,591,2,598,27,-529,29,-529,22,-529, /* gotos: */ -4,405,-108,4,-109,5,-132,26,-3,29,-2,31,-10,42,-68,158,-11,352,-14,353,-13,354,-27,18,-29,19,-69,34,-12,355,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-70,371,-25,345,-18,394,-22,415,-23,439,-28,483,-26,484,-19,509,-105,510,-104,520,-7,523,-8,524,-9,543,-99,546,-100,547,-102,589,-103,556, - /* default action: */ -412, - 46,23, /* actions: */ 118,225,121,226,120,227,122,228,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,128,244,129,245,130,246,146,577,116,126,126,257,111,254,113,260,112,264,114,268,115,277,131,136,119,286,84,859,103,291,98,300,43,308,58,584,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,423,19,430,15,440,16,446,17,451,93,457,44,503,89,591, /* gotos: */ -89,407,-105,846,-70,847,-12,848,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-68,858,-69,475,-25,345,-18,394,-22,415,-23,439,-99,861,-100,547,-102,589,-103,556, - 1,0, /* actions: */ 37,408, - 0,1, /* default action: */ -309, /* gotos: */ -127,409, - 49,25, /* actions: */ 118,225,122,228,119,286,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,121,226,120,227,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,131,136,84,287,103,291,98,300,43,335,58,321,51,342,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,465,147,498,64,501,65,504,148,507, /* gotos: */ -13,410,-27,18,-29,19,-69,34,-12,326,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-70,224,-68,284,-25,345,-18,394,-22,415,-23,439,-28,483,-26,484,-19,509,-105,218,-104,472, - 5,2, /* actions: */ 49,13,50,15,86,27,14,28,39,845, /* gotos: */ -123,411,-132,844, - 0,1, /* default action: */ -310, /* gotos: */ -128,412, - 63,41, /* actions: */ 86,27,14,28,57,43,18,142,59,148,60,153,131,136,118,225,122,228,119,286,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,121,226,120,227,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,84,372,103,291,98,300,43,335,58,321,51,342,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,423,19,430,15,440,16,446,17,451,93,457,44,465,147,498,64,501,65,504,148,507,42,525,33,539,34,541,35,544,36,545,89,591,2,598,22,-529, /* gotos: */ -4,413,-108,4,-109,5,-132,26,-3,29,-2,31,-10,42,-68,158,-11,352,-14,353,-13,354,-27,18,-29,19,-69,34,-12,355,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-70,371,-25,345,-18,394,-22,415,-23,439,-28,483,-26,484,-19,509,-105,510,-104,520,-7,523,-8,524,-9,543,-99,546,-100,547,-102,589,-103,556, - 1,0, /* actions: */ 22,414, - /* default action: */ -311, - /* default action: */ -312, - 49,25, /* actions: */ 118,225,122,228,119,286,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,121,226,120,227,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,131,136,84,287,103,291,98,300,43,335,58,321,51,342,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,465,147,498,64,501,65,504,148,507, /* gotos: */ -13,417,-27,18,-29,19,-69,34,-12,326,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-70,224,-68,284,-25,345,-18,394,-22,415,-23,439,-28,483,-26,484,-19,509,-105,218,-104,472, - 4,1, /* actions: */ 49,13,50,15,14,-314,97,-314, /* gotos: */ -129,418, - 2,2, /* actions: */ 14,314,97,-531, /* gotos: */ -116,419,-114,312, - /* default action: */ -315, - 63,41, /* actions: */ 86,27,14,28,57,43,18,142,59,148,60,153,131,136,118,225,122,228,119,286,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,121,226,120,227,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,84,372,103,291,98,300,43,335,58,321,51,342,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,423,19,430,15,440,16,446,17,451,93,457,44,465,147,498,64,501,65,504,148,507,42,525,33,539,34,541,35,544,36,545,89,591,2,598,97,-529, /* gotos: */ -4,421,-108,4,-109,5,-132,26,-3,29,-2,31,-10,42,-68,158,-11,352,-14,353,-13,354,-27,18,-29,19,-69,34,-12,355,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-70,371,-25,345,-18,394,-22,415,-23,439,-28,483,-26,484,-19,509,-105,510,-104,520,-7,523,-8,524,-9,543,-99,546,-100,547,-102,589,-103,556, - 1,0, /* actions: */ 97,422, - /* default action: */ -316, - 63,41, /* actions: */ 86,27,14,28,57,43,18,142,59,148,60,153,131,136,118,225,122,228,119,286,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,121,226,120,227,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,84,372,103,291,98,300,43,335,58,321,51,342,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,423,19,430,15,440,16,446,17,451,93,457,44,465,147,498,64,501,65,504,148,507,42,525,33,539,34,541,35,544,36,545,89,591,2,598,97,-529, /* gotos: */ -4,421,-99,424,-108,4,-109,5,-132,26,-3,29,-2,31,-10,42,-68,158,-11,352,-14,353,-13,354,-27,18,-29,19,-69,34,-12,355,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-70,371,-25,345,-18,394,-22,415,-23,439,-28,483,-26,484,-19,509,-105,510,-104,520,-7,523,-8,524,-9,543,-100,547,-102,589,-103,556, - 3,2, /* actions: */ 134,426,14,314,97,-531, /* gotos: */ -116,425,-114,312, - 5,0, /* actions: */ 134,-73,37,-73,14,-73,97,-73,87,-89, - 50,26, /* actions: */ 118,225,122,228,119,286,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,121,226,120,227,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,131,136,84,287,103,291,98,300,43,335,58,321,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,465,64,501,65,504,147,506,148,507,89,515, /* gotos: */ -27,427,-19,428,-21,429,-29,19,-69,34,-12,326,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-70,224,-68,284,-25,345,-18,394,-22,415,-23,439,-28,483,-26,484,-105,218,-104,472,-20,517, - /* default action: */ -35, - 44,0, /* actions: */ 141,162,142,164,143,166,144,168,145,170,66,172,139,174,140,176,91,178,67,180,137,182,71,184,138,186,72,188,68,190,69,192,70,194,75,196,76,198,81,200,82,202,73,204,74,206,77,208,78,210,135,212,52,-43,53,-43,54,-43,55,-43,56,-43,86,-43,14,-43,3,-43,22,-43,102,-43,108,-43,27,-43,26,-43,21,-43,29,-43,97,-43,20,-43,87,-271, - 18,0, /* actions: */ 52,-44,53,-44,54,-44,55,-44,56,-44,86,-44,14,-44,3,-44,22,-44,102,-44,108,-44,27,-44,26,-44,21,-44,29,-44,97,-44,20,-44,87,-272, - 66,42, /* actions: */ 86,27,14,28,57,43,18,142,59,148,60,153,131,136,118,225,122,228,119,286,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,121,226,120,227,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,84,372,103,291,98,300,43,335,58,321,51,342,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,423,19,430,15,440,16,446,17,451,93,457,44,465,147,498,64,501,65,504,148,507,42,525,33,539,34,541,35,544,36,545,89,591,2,598,20,-529,27,-529,21,-529,22,-529, /* gotos: */ -24,431,-4,433,-108,4,-109,5,-132,26,-3,29,-2,31,-10,42,-68,158,-11,352,-14,353,-13,354,-27,18,-29,19,-69,34,-12,355,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-70,371,-25,345,-18,394,-22,415,-23,439,-28,483,-26,484,-19,509,-105,510,-104,520,-7,523,-8,524,-9,543,-99,546,-100,547,-102,589,-103,556, - 1,0, /* actions: */ 22,432, - /* default action: */ -317, - 4,3, /* actions: */ 20,815,27,-413,21,-413,22,-413, /* gotos: */ -47,434,-46,813,-48,843, - 3,1, /* actions: */ 27,369,21,-341,22,-341, /* gotos: */ -30,435, - 2,1, /* actions: */ 21,437,22,-421, /* gotos: */ -6,436, - /* default action: */ -331, - 63,41, /* actions: */ 86,27,14,28,57,43,18,142,59,148,60,153,131,136,118,225,122,228,119,286,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,121,226,120,227,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,84,372,103,291,98,300,43,335,58,321,51,342,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,423,19,430,15,440,16,446,17,451,93,457,44,465,147,498,64,501,65,504,148,507,42,525,33,539,34,541,35,544,36,545,89,591,2,598,22,-529, /* gotos: */ -4,438,-108,4,-109,5,-132,26,-3,29,-2,31,-10,42,-68,158,-11,352,-14,353,-13,354,-27,18,-29,19,-69,34,-12,355,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-70,371,-25,345,-18,394,-22,415,-23,439,-28,483,-26,484,-19,509,-105,510,-104,520,-7,523,-8,524,-9,543,-99,546,-100,547,-102,589,-103,556, - /* default action: */ -422, - /* default action: */ -313, - 46,19, /* actions: */ 81,806,84,787,122,792,118,793,128,244,129,245,130,246,146,577,116,126,126,257,111,254,113,260,112,264,114,268,115,277,121,226,120,227,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,131,136,119,286,103,291,98,300,43,308,58,584,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,503, /* gotos: */ -45,441,-74,791,-12,794,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-70,683,-68,684,-69,475,-25,345,-18,394,-22,415,-23,439, - 4,2, /* actions: */ 86,27,14,28,138,800,2,804, /* gotos: */ -15,442,-132,799, - 0,1, /* default action: */ -318, /* gotos: */ -130,443, - 66,42, /* actions: */ 86,27,14,28,57,43,18,142,59,148,60,153,131,136,118,225,122,228,119,286,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,121,226,120,227,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,84,372,103,291,98,300,43,335,58,321,51,342,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,423,19,430,15,440,16,446,17,451,93,457,44,465,147,498,64,501,65,504,148,507,42,525,33,539,34,541,35,544,36,545,89,591,2,598,20,-529,27,-529,21,-529,22,-529, /* gotos: */ -24,444,-4,433,-108,4,-109,5,-132,26,-3,29,-2,31,-10,42,-68,158,-11,352,-14,353,-13,354,-27,18,-29,19,-69,34,-12,355,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-70,371,-25,345,-18,394,-22,415,-23,439,-28,483,-26,484,-19,509,-105,510,-104,520,-7,523,-8,524,-9,543,-99,546,-100,547,-102,589,-103,556, - 1,0, /* actions: */ 22,445, - /* default action: */ -319, - 45,19, /* actions: */ 84,787,122,792,118,793,128,244,129,245,130,246,146,577,116,126,126,257,111,254,113,260,112,264,114,268,115,277,121,226,120,227,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,131,136,119,286,103,291,98,300,43,308,58,584,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,503, /* gotos: */ -45,447,-74,791,-12,794,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-70,683,-68,684,-69,475,-25,345,-18,394,-22,415,-23,439, - 0,1, /* default action: */ -323, /* gotos: */ -134,448, - 66,42, /* actions: */ 86,27,14,28,57,43,18,142,59,148,60,153,131,136,118,225,122,228,119,286,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,121,226,120,227,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,84,372,103,291,98,300,43,335,58,321,51,342,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,423,19,430,15,440,16,446,17,451,93,457,44,465,147,498,64,501,65,504,148,507,42,525,33,539,34,541,35,544,36,545,89,591,2,598,20,-529,27,-529,21,-529,22,-529, /* gotos: */ -24,449,-4,433,-108,4,-109,5,-132,26,-3,29,-2,31,-10,42,-68,158,-11,352,-14,353,-13,354,-27,18,-29,19,-69,34,-12,355,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-70,371,-25,345,-18,394,-22,415,-23,439,-28,483,-26,484,-19,509,-105,510,-104,520,-7,523,-8,524,-9,543,-99,546,-100,547,-102,589,-103,556, - 1,0, /* actions: */ 22,450, - /* default action: */ -324, - 79,6, /* actions: */ 118,773,122,774,119,50,139,52,140,53,91,54,67,55,68,56,69,57,75,58,76,59,137,60,71,61,138,62,72,63,70,64,81,65,82,66,141,67,142,68,143,69,89,70,144,71,145,72,66,73,147,74,148,75,64,76,65,77,79,78,80,79,92,80,61,775,62,776,63,777,59,85,60,86,57,87,49,88,19,89,33,90,28,91,15,92,17,93,58,94,38,95,40,96,27,97,26,98,22,99,21,100,48,778,32,102,37,103,16,104,34,105,46,779,51,107,50,108,35,109,20,110,36,111,42,112,45,780,44,114,25,115,47,781,18,117,29,118,43,119,52,120,53,121,54,122,55,123,56,124,121,226,120,227,123,229,94,783, /* gotos: */ -76,452,-17,763,-75,51,-117,81,-16,782,-70,683, - 0,1, /* default action: */ -325, /* gotos: */ -135,453, - 13,11, /* actions: */ 94,758,122,618,121,619,120,620,123,621,118,730,95,637,143,671,89,672,91,663,90,664,86,-489,14,-489, /* gotos: */ -80,454,-82,761,-95,718,-98,665,-90,636,-85,741,-87,739,-91,751,-144,669,-92,756,-145,661, - 66,42, /* actions: */ 86,27,14,28,57,43,18,142,59,148,60,153,131,136,118,225,122,228,119,286,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,121,226,120,227,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,84,372,103,291,98,300,43,335,58,321,51,342,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,423,19,430,15,440,16,446,17,451,93,457,44,465,147,498,64,501,65,504,148,507,42,525,33,539,34,541,35,544,36,545,89,591,2,598,20,-529,27,-529,21,-529,22,-529, /* gotos: */ -24,455,-4,433,-108,4,-109,5,-132,26,-3,29,-2,31,-10,42,-68,158,-11,352,-14,353,-13,354,-27,18,-29,19,-69,34,-12,355,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-70,371,-25,345,-18,394,-22,415,-23,439,-28,483,-26,484,-19,509,-105,510,-104,520,-7,523,-8,524,-9,543,-99,546,-100,547,-102,589,-103,556, - 1,0, /* actions: */ 22,456, - /* default action: */ -326, - 0,2, /* default action: */ -386, /* gotos: */ -38,458,-139,459, - /* default action: */ -330, - 13,11, /* actions: */ 94,714,122,618,121,619,120,620,123,621,118,730,95,637,143,671,89,672,91,663,90,664,101,-489,41,-489, /* gotos: */ -79,460,-82,757,-95,718,-98,665,-90,636,-85,741,-87,739,-91,751,-144,669,-92,756,-145,661, - 2,1, /* actions: */ 101,462,41,711, /* gotos: */ -5,461, - /* default action: */ -387, - 63,41, /* actions: */ 86,27,14,28,57,43,18,142,59,148,60,153,131,136,118,225,122,228,119,286,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,121,226,120,227,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,84,372,103,291,98,300,43,335,58,321,51,342,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,423,19,430,15,440,16,446,17,451,93,457,44,465,147,498,64,501,65,504,148,507,42,525,33,539,34,541,35,544,36,545,89,591,2,598,102,-529, /* gotos: */ -4,463,-108,4,-109,5,-132,26,-3,29,-2,31,-10,42,-68,158,-11,352,-14,353,-13,354,-27,18,-29,19,-69,34,-12,355,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-70,371,-25,345,-18,394,-22,415,-23,439,-28,483,-26,484,-19,509,-105,510,-104,520,-7,523,-8,524,-9,543,-99,546,-100,547,-102,589,-103,556, - 1,0, /* actions: */ 102,464, - /* default action: */ -390, - 110,3, /* actions: */ 94,468,99,-405,38,-405,88,-405,83,-405,104,-405,141,-405,142,-405,143,-405,144,-405,145,-405,66,-405,139,-405,140,-405,91,-405,67,-405,137,-405,71,-405,138,-405,72,-405,68,-405,69,-405,70,-405,75,-405,76,-405,81,-405,82,-405,73,-405,74,-405,77,-405,78,-405,135,-405,49,-405,50,-405,52,-405,53,-405,54,-405,55,-405,56,-405,86,-405,14,-405,3,-405,22,-405,102,-405,108,-405,27,-405,26,-405,21,-405,29,-405,97,-405,20,-405,25,-405,39,-405,85,-405,87,-405,105,-405,100,-405,40,-405,118,-265,121,-265,120,-265,122,-265,123,-265,46,-265,45,-265,47,-265,48,-265,62,-265,61,-265,63,-265,128,-265,129,-265,130,-265,146,-265,116,-265,126,-265,111,-265,113,-265,112,-265,114,-265,115,-265,131,-265,119,-265,84,-265,103,-265,98,-265,43,-265,58,-265,51,-265,23,-265,24,-265,30,-265,31,-265,28,-265,32,-265,96,-265,95,-265,19,-265,15,-265,16,-265,17,-265,93,-265,44,-265,64,-265,65,-265,147,-265,148,-265,89,-265,125,-265,90,-265, /* gotos: */ -40,466,-44,467,-120,332, - /* default action: */ -404, - /* default action: */ -71, - 54,28, /* actions: */ 118,225,121,226,120,227,122,228,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,131,136,119,286,84,287,103,291,98,300,43,335,58,321,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,465,64,501,65,504,147,506,148,507,89,515,125,532,90,534,14,-258,97,-258, /* gotos: */ -43,469,-42,471,-20,316,-19,334,-105,218,-70,224,-12,326,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-68,284,-69,34,-25,345,-18,394,-22,415,-23,439,-104,472,-21,527,-51,528,-52,536,-33,537,-29,538, - 2,2, /* actions: */ 14,314,97,-531, /* gotos: */ -116,470,-114,312, - /* default action: */ -255, - /* default action: */ -259, - 1,0, /* actions: */ 124,473, - 49,20, /* actions: */ 118,225,121,226,120,227,122,228,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,131,136,119,286,84,287,103,291,98,300,43,308,58,321,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,503,64,501,65,504,147,506,148,507, /* gotos: */ -19,474,-105,218,-70,224,-12,237,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-68,284,-69,475,-25,345,-18,394,-22,415,-23,439,-104,472, - 55,0, /* actions: */ 141,162,142,164,143,166,144,168,145,170,66,172,139,174,140,176,91,178,67,180,137,182,71,184,138,186,72,188,68,190,69,192,70,194,75,196,76,198,81,200,82,202,73,204,74,206,77,208,78,210,135,212,49,-203,50,-203,52,-203,53,-203,54,-203,55,-203,56,-203,86,-203,14,-203,3,-203,22,-203,102,-203,108,-203,27,-203,26,-203,21,-203,29,-203,97,-203,20,-203,25,-203,39,-203,136,-203,85,-203,87,-203,105,-203,100,-203,40,-203,101,-203,41,-203, - 3,2, /* actions: */ 99,347,38,478,94,468, /* gotos: */ -36,476,-40,477, - /* default action: */ -297, - /* default action: */ -397, - 0,1, /* default action: */ -408, /* gotos: */ -142,479, - 65,2, /* actions: */ 74,609,139,610,86,-378,14,-378,57,-378,18,-378,59,-378,60,-378,131,-378,118,-378,122,-378,119,-378,128,-378,129,-378,130,-378,146,-378,116,-378,126,-378,111,-378,113,-378,112,-378,114,-378,115,-378,121,-378,120,-378,123,-378,46,-378,45,-378,47,-378,48,-378,62,-378,61,-378,63,-378,84,-378,103,-378,98,-378,43,-378,58,-378,51,-378,23,-378,24,-378,30,-378,31,-378,28,-378,32,-378,96,-378,95,-378,19,-378,15,-378,16,-378,17,-378,93,-378,44,-378,147,-378,64,-378,65,-378,148,-378,42,-378,33,-378,34,-378,35,-378,36,-378,89,-378,2,-378,22,-378, /* gotos: */ -78,480,-77,608, - 63,41, /* actions: */ 86,27,14,28,57,43,18,142,59,148,60,153,131,136,118,225,122,228,119,286,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,121,226,120,227,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,84,372,103,291,98,300,43,335,58,321,51,342,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,423,19,430,15,440,16,446,17,451,93,457,44,465,147,498,64,501,65,504,148,507,42,525,33,539,34,541,35,544,36,545,89,591,2,598,22,-529, /* gotos: */ -4,481,-108,4,-109,5,-132,26,-3,29,-2,31,-10,42,-68,158,-11,352,-14,353,-13,354,-27,18,-29,19,-69,34,-12,355,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-70,371,-25,345,-18,394,-22,415,-23,439,-28,483,-26,484,-19,509,-105,510,-104,520,-7,523,-8,524,-9,543,-99,546,-100,547,-102,589,-103,556, - 1,0, /* actions: */ 22,482, - /* default action: */ -409, - /* default action: */ -59, - 23,0, /* actions: */ 88,485,83,494,49,-60,50,-60,52,-60,53,-60,54,-60,55,-60,56,-60,86,-60,14,-60,3,-60,22,-60,102,-60,108,-60,27,-60,26,-60,21,-60,29,-60,97,-60,20,-60,25,-60,39,-60, - 32,2, /* actions: */ 118,490,122,491,119,492,139,52,140,53,91,54,67,55,68,56,69,57,75,58,76,59,137,60,71,61,138,62,72,63,70,64,81,65,82,66,141,67,142,68,143,69,89,70,144,71,145,72,66,73,147,74,148,75,64,76,65,77,79,78,80,79,92,80, /* gotos: */ -72,486,-75,493, - 76,4, /* actions: */ 94,468,88,-256,83,-256,49,-256,50,-256,52,-256,53,-256,54,-256,55,-256,56,-256,86,-256,14,-256,3,-256,22,-256,102,-256,108,-256,27,-256,26,-256,21,-256,29,-256,97,-256,20,-256,25,-256,39,-256,118,-265,121,-265,120,-265,122,-265,123,-265,46,-265,45,-265,47,-265,48,-265,62,-265,61,-265,63,-265,128,-265,129,-265,130,-265,146,-265,116,-265,126,-265,111,-265,113,-265,112,-265,114,-265,115,-265,131,-265,119,-265,84,-265,103,-265,98,-265,43,-265,58,-265,51,-265,23,-265,24,-265,30,-265,31,-265,28,-265,32,-265,96,-265,95,-265,19,-265,15,-265,16,-265,17,-265,93,-265,44,-265,64,-265,65,-265,147,-265,148,-265,89,-265,125,-265,90,-265, /* gotos: */ -41,487,-44,488,-40,489,-120,332, - /* default action: */ -395, - /* default action: */ -61, - /* default action: */ -257, - /* default action: */ -520, - /* default action: */ -521, - /* default action: */ -522, - /* default action: */ -523, - 32,2, /* actions: */ 118,490,122,491,119,492,139,52,140,53,91,54,67,55,68,56,69,57,75,58,76,59,137,60,71,61,138,62,72,63,70,64,81,65,82,66,141,67,142,68,143,69,89,70,144,71,145,72,66,73,147,74,148,75,64,76,65,77,79,78,80,79,92,80, /* gotos: */ -72,495,-75,493, - 76,4, /* actions: */ 94,468,88,-256,83,-256,49,-256,50,-256,52,-256,53,-256,54,-256,55,-256,56,-256,86,-256,14,-256,3,-256,22,-256,102,-256,108,-256,27,-256,26,-256,21,-256,29,-256,97,-256,20,-256,25,-256,39,-256,118,-265,121,-265,120,-265,122,-265,123,-265,46,-265,45,-265,47,-265,48,-265,62,-265,61,-265,63,-265,128,-265,129,-265,130,-265,146,-265,116,-265,126,-265,111,-265,113,-265,112,-265,114,-265,115,-265,131,-265,119,-265,84,-265,103,-265,98,-265,43,-265,58,-265,51,-265,23,-265,24,-265,30,-265,31,-265,28,-265,32,-265,96,-265,95,-265,19,-265,15,-265,16,-265,17,-265,93,-265,44,-265,64,-265,65,-265,147,-265,148,-265,89,-265,125,-265,90,-265, /* gotos: */ -41,496,-44,497,-40,489,-120,332, - /* default action: */ -396, - /* default action: */ -62, - 49,24, /* actions: */ 118,225,122,228,119,286,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,121,226,120,227,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,131,136,84,287,103,291,98,300,43,335,58,321,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,465,64,501,65,504,147,506,148,507, /* gotos: */ -27,499,-19,500,-29,19,-69,34,-12,326,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-70,224,-68,284,-25,345,-18,394,-22,415,-23,439,-28,483,-26,484,-105,218,-104,472, - /* default action: */ -56, - /* default action: */ -235, - 49,20, /* actions: */ 118,225,121,226,120,227,122,228,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,131,136,119,286,84,287,103,291,98,300,43,308,58,321,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,503,64,501,65,504,147,506,148,507, /* gotos: */ -19,502,-105,218,-70,224,-12,237,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-68,284,-69,475,-25,345,-18,394,-22,415,-23,439,-104,472, - /* default action: */ -220, - 61,1, /* actions: */ 94,468,99,-405,38,-405,104,-405,83,-405,88,-405,141,-405,142,-405,143,-405,144,-405,145,-405,66,-405,139,-405,140,-405,91,-405,67,-405,137,-405,71,-405,138,-405,72,-405,68,-405,69,-405,70,-405,75,-405,76,-405,81,-405,82,-405,73,-405,74,-405,77,-405,78,-405,135,-405,49,-405,50,-405,52,-405,53,-405,54,-405,55,-405,56,-405,86,-405,14,-405,3,-405,22,-405,102,-405,108,-405,27,-405,26,-405,21,-405,29,-405,97,-405,20,-405,25,-405,39,-405,136,-405,85,-405,87,-405,105,-405,100,-405,40,-405,101,-405,41,-405, /* gotos: */ -40,466, - 49,20, /* actions: */ 118,225,121,226,120,227,122,228,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,131,136,119,286,84,287,103,291,98,300,43,308,58,321,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,503,64,501,65,504,147,506,148,507, /* gotos: */ -19,505,-105,218,-70,224,-12,237,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-68,284,-69,475,-25,345,-18,394,-22,415,-23,439,-104,472, - 55,0, /* actions: */ 141,-221,142,-221,143,-221,144,-221,145,-221,66,172,139,-221,140,-221,91,-221,67,-221,137,-221,71,-221,138,-221,72,-221,68,-221,69,-221,70,-221,75,-221,76,-221,81,-221,82,-221,73,-221,74,-221,77,-221,78,-221,135,-221,49,-221,50,-221,52,-221,53,-221,54,-221,55,-221,56,-221,86,-221,14,-221,3,-221,22,-221,102,-221,108,-221,27,-221,26,-221,21,-221,29,-221,97,-221,20,-221,25,-221,39,-221,136,-221,85,-221,87,-221,105,-221,100,-221,40,-221,101,-221,41,-221, - 49,20, /* actions: */ 118,225,121,226,120,227,122,228,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,131,136,119,286,84,287,103,291,98,300,43,308,58,321,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,503,64,501,65,504,147,506,148,507, /* gotos: */ -19,500,-105,218,-70,224,-12,237,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-68,284,-69,475,-25,345,-18,394,-22,415,-23,439,-104,472, - 49,20, /* actions: */ 118,225,121,226,120,227,122,228,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,131,136,119,286,84,287,103,291,98,300,43,308,58,321,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,503,64,501,65,504,147,506,148,507, /* gotos: */ -19,508,-105,218,-70,224,-12,237,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-68,284,-69,475,-25,345,-18,394,-22,415,-23,439,-104,472, - /* default action: */ -236, - 47,0, /* actions: */ 141,162,142,164,143,166,144,168,145,170,66,172,139,174,140,176,91,178,67,180,137,182,71,184,138,186,72,188,68,190,69,192,70,194,75,196,76,198,81,200,82,202,73,204,74,206,77,208,78,210,135,212,49,-57,50,-57,52,-57,53,-57,54,-57,55,-57,56,-57,86,-57,14,-57,3,-57,22,-57,102,-57,108,-57,27,-57,26,-57,21,-57,29,-57,97,-57,20,-57,25,-57,39,-57, - 1,0, /* actions: */ 134,511, - 50,26, /* actions: */ 118,225,121,226,120,227,122,228,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,131,136,119,286,84,287,103,291,98,300,43,335,58,321,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,465,64,501,65,504,147,506,148,507,89,515, /* gotos: */ -19,512,-27,513,-21,514,-105,218,-70,224,-12,326,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-68,284,-69,34,-25,345,-18,394,-22,415,-23,439,-104,472,-29,19,-28,483,-26,484,-20,517, - 46,0, /* actions: */ 56,221,141,162,142,164,143,166,144,168,145,170,66,172,139,174,140,176,91,178,67,180,137,182,71,184,138,186,72,188,68,190,69,192,70,194,75,196,76,198,81,200,82,202,73,204,74,206,77,208,78,210,135,212,49,-200,50,-200,52,-200,53,-200,54,-200,55,-200,86,-200,14,-200,3,-200,22,-200,102,-200,108,-200,27,-200,26,-200,21,-200,29,-200,97,-200,20,-200,87,-271, - /* default action: */ -34, - 18,0, /* actions: */ 52,-42,53,-42,54,-42,55,-42,56,-42,86,-42,14,-42,3,-42,22,-42,102,-42,108,-42,27,-42,26,-42,21,-42,29,-42,97,-42,20,-42,87,-272, - 49,20, /* actions: */ 118,225,121,226,120,227,122,228,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,131,136,119,286,84,287,103,291,98,300,43,308,58,321,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,503,64,501,65,504,147,506,148,507, /* gotos: */ -19,516,-105,218,-70,224,-12,237,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-68,284,-69,475,-25,345,-18,394,-22,415,-23,439,-104,472, - 52,0, /* actions: */ 141,162,142,164,143,166,144,168,145,170,66,172,139,174,140,176,91,178,67,180,137,182,71,184,138,186,72,188,68,190,69,192,70,194,75,196,76,198,81,200,82,202,73,204,74,206,77,208,78,210,135,212,87,-273,14,-273,105,-273,97,-273,100,-273,40,-273,49,-273,50,-273,52,-273,53,-273,54,-273,55,-273,56,-273,86,-273,3,-273,22,-273,102,-273,108,-273,27,-273,26,-273,21,-273,29,-273,20,-273,25,-273,39,-273,85,-273, - 1,0, /* actions: */ 87,518, - 50,20, /* actions: */ 89,319,118,225,121,226,120,227,122,228,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,131,136,119,286,84,287,103,291,98,300,43,308,58,321,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,503,64,501,65,504,147,506,148,507, /* gotos: */ -19,519,-105,218,-70,224,-12,237,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-68,284,-69,475,-25,345,-18,394,-22,415,-23,439,-104,472, - 46,0, /* actions: */ 141,162,142,164,143,166,144,168,145,170,66,172,139,174,140,176,91,178,67,180,137,182,71,184,138,186,72,188,68,190,69,192,70,194,75,196,76,198,81,200,82,202,73,204,74,206,77,208,78,210,135,212,87,-274,86,-274,14,-274,25,-274,52,-274,53,-274,54,-274,55,-274,56,-274,3,-274,22,-274,102,-274,108,-274,27,-274,26,-274,21,-274,29,-274,97,-274,20,-274,85,-274, - 1,0, /* actions: */ 124,521, - 49,24, /* actions: */ 118,225,121,226,120,227,122,228,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,131,136,119,286,84,287,103,291,98,300,43,335,58,321,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,465,64,501,65,504,147,506,148,507, /* gotos: */ -19,474,-27,522,-105,218,-70,224,-12,326,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-68,284,-69,34,-25,345,-18,394,-22,415,-23,439,-104,472,-29,19,-28,483,-26,484, - /* default action: */ -36, - /* default action: */ -33, - /* default action: */ -22, - 73,27, /* actions: */ 118,225,121,226,120,227,122,228,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,131,136,119,286,84,287,103,291,98,300,43,335,58,321,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,465,64,501,65,504,147,506,148,507,89,515,125,532,90,534,52,-27,53,-27,54,-27,55,-27,56,-27,86,-27,14,-27,3,-27,22,-27,102,-27,108,-27,27,-27,26,-27,21,-27,29,-27,97,-27,20,-27,49,-27,50,-27,25,-27,39,-27, /* gotos: */ -42,526,-20,316,-19,334,-105,218,-70,224,-12,326,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-68,284,-69,34,-25,345,-18,394,-22,415,-23,439,-104,472,-21,527,-51,528,-52,536,-33,537,-29,538, - /* default action: */ -24, - /* default action: */ -272, - 25,1, /* actions: */ 87,530,14,-270,105,-270,97,-270,100,-270,40,-270,49,-270,50,-270,52,-270,53,-270,54,-270,55,-270,56,-270,86,-270,3,-270,22,-270,102,-270,108,-270,27,-270,26,-270,21,-270,29,-270,20,-270,25,-270,39,-270, /* gotos: */ -34,529, - /* default action: */ -262, - 75,22, /* actions: */ 118,225,121,226,120,227,122,228,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,131,136,119,286,84,287,103,291,98,300,43,308,58,321,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,503,64,501,65,504,147,506,148,507,125,532,90,534,14,-269,105,-269,97,-269,100,-269,40,-269,49,-269,50,-269,52,-269,53,-269,54,-269,55,-269,56,-269,86,-269,3,-269,22,-269,102,-269,108,-269,27,-269,26,-269,21,-269,29,-269,20,-269,25,-269,39,-269, /* gotos: */ -52,306,-33,531,-19,307,-105,218,-70,224,-12,237,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-68,284,-69,475,-25,345,-18,394,-22,415,-23,439,-104,472, - /* default action: */ -268, - 49,20, /* actions: */ 118,225,121,226,120,227,122,228,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,131,136,119,286,84,287,103,291,98,300,43,308,58,321,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,503,64,501,65,504,147,506,148,507, /* gotos: */ -19,533,-105,218,-70,224,-12,237,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-68,284,-69,475,-25,345,-18,394,-22,415,-23,439,-104,472, - 51,0, /* actions: */ 141,162,142,164,143,166,144,168,145,170,66,172,139,174,140,176,91,178,67,180,137,182,71,184,138,186,72,188,68,190,69,192,70,194,75,196,76,198,81,200,82,202,73,204,74,206,77,208,78,210,135,212,87,-516,14,-516,105,-516,102,-516,97,-516,100,-516,40,-516,49,-516,50,-516,52,-516,53,-516,54,-516,55,-516,56,-516,86,-516,3,-516,22,-516,108,-516,27,-516,26,-516,21,-516,29,-516,20,-516,25,-516,39,-516, - 49,20, /* actions: */ 118,225,121,226,120,227,122,228,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,131,136,119,286,84,287,103,291,98,300,43,308,58,321,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,503,64,501,65,504,147,506,148,507, /* gotos: */ -19,535,-105,218,-70,224,-12,237,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-68,284,-69,475,-25,345,-18,394,-22,415,-23,439,-104,472, - 50,0, /* actions: */ 141,162,142,164,143,166,144,168,145,170,66,172,139,174,140,176,91,178,67,180,137,182,71,184,138,186,72,188,68,190,69,192,70,194,75,196,76,198,81,200,82,202,73,204,74,206,77,208,78,210,135,212,14,-267,105,-267,97,-267,100,-267,40,-267,49,-267,50,-267,52,-267,53,-267,54,-267,55,-267,56,-267,86,-267,3,-267,22,-267,102,-267,108,-267,27,-267,26,-267,21,-267,29,-267,20,-267,25,-267,39,-267, - /* default action: */ -513, - /* default action: */ -263, - /* default action: */ -264, - 73,27, /* actions: */ 118,225,121,226,120,227,122,228,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,131,136,119,286,84,287,103,291,98,300,43,335,58,321,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,465,64,501,65,504,147,506,148,507,89,515,125,532,90,534,52,-28,53,-28,54,-28,55,-28,56,-28,86,-28,14,-28,3,-28,22,-28,102,-28,108,-28,27,-28,26,-28,21,-28,29,-28,97,-28,20,-28,49,-28,50,-28,25,-28,39,-28, /* gotos: */ -42,540,-20,316,-19,334,-105,218,-70,224,-12,326,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-68,284,-69,34,-25,345,-18,394,-22,415,-23,439,-104,472,-21,527,-51,528,-52,536,-33,537,-29,538, - /* default action: */ -25, - 73,27, /* actions: */ 118,225,121,226,120,227,122,228,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,131,136,119,286,84,287,103,291,98,300,43,335,58,321,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,465,64,501,65,504,147,506,148,507,89,515,125,532,90,534,52,-29,53,-29,54,-29,55,-29,56,-29,86,-29,14,-29,3,-29,22,-29,102,-29,108,-29,27,-29,26,-29,21,-29,29,-29,97,-29,20,-29,49,-29,50,-29,25,-29,39,-29, /* gotos: */ -42,542,-20,316,-19,334,-105,218,-70,224,-12,326,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-68,284,-69,34,-25,345,-18,394,-22,415,-23,439,-104,472,-21,527,-51,528,-52,536,-33,537,-29,538, - /* default action: */ -26, - /* default action: */ -23, - /* default action: */ -30, - /* default action: */ -31, - 1,0, /* actions: */ 134,426, - 50,19, /* actions: */ 89,550,118,225,121,226,120,227,122,228,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,128,244,129,245,130,246,146,577,116,126,126,257,111,254,113,260,112,264,114,268,115,277,131,136,119,286,84,582,103,291,98,300,43,308,58,584,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,586,19,430,15,440,16,446,17,451,93,457,44,503,134,-74,37,-74,14,-74,97,-74, /* gotos: */ -102,548,-103,556,-70,557,-12,558,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-68,581,-69,475,-25,345,-18,394,-22,415,-23,439, - 5,0, /* actions: */ 87,549,134,-75,37,-75,14,-75,97,-75, - /* default action: */ -84, - 50,18, /* actions: */ 87,606,118,225,121,226,120,227,122,228,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,128,244,129,245,130,246,146,577,116,126,126,257,111,254,113,260,112,264,114,268,115,277,131,136,119,286,84,582,103,291,98,300,43,308,58,584,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,503,134,-78,37,-78,14,-78,97,-78, /* gotos: */ -103,551,-70,557,-12,558,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-68,581,-69,475,-25,345,-18,394,-22,415,-23,439, - 5,0, /* actions: */ 87,552,134,-76,37,-76,14,-76,97,-76, - 45,20, /* actions: */ 118,225,121,226,120,227,122,228,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,128,244,129,245,130,246,146,577,116,126,126,257,111,254,113,260,112,264,114,268,115,277,131,136,119,286,84,582,103,291,98,300,43,308,58,584,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,586,19,430,15,440,16,446,17,451,93,457,44,503, /* gotos: */ -101,553,-102,595,-103,556,-70,557,-12,558,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-68,581,-69,475,-25,345,-18,394,-22,415,-23,439, - 5,0, /* actions: */ 87,554,134,-77,37,-77,14,-77,97,-77, - 45,19, /* actions: */ 118,225,121,226,120,227,122,228,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,128,244,129,245,130,246,146,577,116,126,126,257,111,254,113,260,112,264,114,268,115,277,131,136,119,286,84,582,103,291,98,300,43,308,58,584,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,586,19,430,15,440,16,446,17,451,93,457,44,503, /* gotos: */ -102,555,-103,556,-70,557,-12,558,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-68,581,-69,475,-25,345,-18,394,-22,415,-23,439, - /* default action: */ -86, - /* default action: */ -88, - 8,0, /* actions: */ 87,-90,134,-90,37,-90,14,-90,97,-90,104,-466,83,-466,88,-466, - 3,0, /* actions: */ 104,559,83,564,88,573, - 54,28, /* actions: */ 118,225,121,226,120,227,122,228,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,131,136,119,286,84,287,103,291,98,300,43,335,58,321,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,465,64,501,65,504,147,506,148,507,89,515,125,532,90,534,14,-258,105,-258, /* gotos: */ -43,560,-42,471,-20,316,-19,334,-105,218,-70,224,-12,326,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-68,284,-69,34,-25,345,-18,394,-22,415,-23,439,-104,472,-21,527,-51,528,-52,536,-33,537,-29,538, - 2,2, /* actions: */ 14,314,105,-531, /* gotos: */ -113,561,-114,562, - 10,0, /* actions: */ 87,-91,134,-91,37,-91,14,-91,97,-91,99,-403,38,-403,104,-403,83,-403,88,-403, - 1,0, /* actions: */ 105,563, - /* default action: */ -534, - 33,4, /* actions: */ 122,565,118,570,119,571,139,52,140,53,91,54,67,55,68,56,69,57,75,58,76,59,137,60,71,61,138,62,72,63,70,64,81,65,82,66,141,67,142,68,143,69,89,70,144,71,145,72,66,73,147,74,148,75,64,76,65,77,79,78,80,79,92,80,94,468, /* gotos: */ -72,566,-73,568,-40,569,-75,572, - 9,0, /* actions: */ 104,-286,83,-286,88,-286,87,-95,134,-95,37,-95,14,-95,97,-95,94,-521, - 1,1, /* actions: */ 94,468, /* gotos: */ -40,567, - /* default action: */ -399, - /* default action: */ -400, - /* default action: */ -402, - 11,0, /* actions: */ 87,-93,134,-93,37,-93,14,-93,97,-93,94,-520,99,-524,38,-524,104,-524,83,-524,88,-524, - 113,0, /* actions: */ 94,-522,118,-522,121,-522,120,-522,122,-522,123,-522,46,-522,45,-522,47,-522,48,-522,62,-522,61,-522,63,-522,128,-522,129,-522,130,-522,146,-522,116,-522,126,-522,111,-522,113,-522,112,-522,114,-522,115,-522,131,-522,119,-522,84,-522,103,-522,98,-522,43,-522,58,-522,51,-522,23,-522,24,-522,30,-522,31,-522,28,-522,32,-522,96,-522,95,-522,19,-522,15,-522,16,-522,17,-522,93,-522,44,-522,64,-522,65,-522,147,-522,148,-522,89,-522,125,-522,90,-522,99,-525,38,-525,104,-525,83,-525,88,-525,87,-525,86,-525,139,-525,141,-525,142,-525,143,-525,144,-525,145,-525,66,-525,140,-525,91,-525,67,-525,137,-525,71,-525,138,-525,72,-525,68,-525,69,-525,70,-525,75,-525,76,-525,81,-525,82,-525,73,-525,74,-525,77,-525,78,-525,135,-525,49,-525,50,-525,52,-525,53,-525,54,-525,55,-525,56,-525,14,-525,3,-525,22,-525,102,-525,108,-525,27,-525,26,-525,21,-525,29,-525,97,-525,20,-525,25,-525,39,-525,85,-525,105,-525,100,-525,40,-525,136,-525,101,-525,41,-525, - 113,0, /* actions: */ 94,-523,118,-523,121,-523,120,-523,122,-523,123,-523,46,-523,45,-523,47,-523,48,-523,62,-523,61,-523,63,-523,128,-523,129,-523,130,-523,146,-523,116,-523,126,-523,111,-523,113,-523,112,-523,114,-523,115,-523,131,-523,119,-523,84,-523,103,-523,98,-523,43,-523,58,-523,51,-523,23,-523,24,-523,30,-523,31,-523,28,-523,32,-523,96,-523,95,-523,19,-523,15,-523,16,-523,17,-523,93,-523,44,-523,64,-523,65,-523,147,-523,148,-523,89,-523,125,-523,90,-523,99,-526,38,-526,104,-526,83,-526,88,-526,87,-526,86,-526,139,-526,141,-526,142,-526,143,-526,144,-526,145,-526,66,-526,140,-526,91,-526,67,-526,137,-526,71,-526,138,-526,72,-526,68,-526,69,-526,70,-526,75,-526,76,-526,81,-526,82,-526,73,-526,74,-526,77,-526,78,-526,135,-526,49,-526,50,-526,52,-526,53,-526,54,-526,55,-526,56,-526,14,-526,3,-526,22,-526,102,-526,108,-526,27,-526,26,-526,21,-526,29,-526,97,-526,20,-526,25,-526,39,-526,85,-526,105,-526,100,-526,40,-526,136,-526,101,-526,41,-526, - 33,3, /* actions: */ 118,575,122,576,119,492,139,52,140,53,91,54,67,55,68,56,69,57,75,58,76,59,137,60,71,61,138,62,72,63,70,64,81,65,82,66,141,67,142,68,143,69,89,70,144,71,145,72,66,73,147,74,148,75,64,76,65,77,79,78,80,79,92,80,94,468, /* gotos: */ -72,574,-40,357,-75,493, - 61,2, /* actions: */ 94,468,99,-256,38,-256,104,-256,83,-256,88,-256,141,-256,142,-256,143,-256,144,-256,145,-256,66,-256,139,-256,140,-256,91,-256,67,-256,137,-256,71,-256,138,-256,72,-256,68,-256,69,-256,70,-256,75,-256,76,-256,81,-256,82,-256,73,-256,74,-256,77,-256,78,-256,135,-256,49,-256,50,-256,52,-256,53,-256,54,-256,55,-256,56,-256,86,-256,14,-256,3,-256,22,-256,102,-256,108,-256,27,-256,26,-256,21,-256,29,-256,97,-256,20,-256,25,-256,39,-256,136,-256,85,-256,87,-256,105,-256,100,-256,40,-256,101,-256,41,-256, /* gotos: */ -41,331,-40,489, - 11,0, /* actions: */ 87,-92,134,-92,37,-92,14,-92,97,-92,94,-520,99,-520,38,-520,104,-520,83,-520,88,-520, - 11,0, /* actions: */ 87,-94,134,-94,37,-94,14,-94,97,-94,94,-521,99,-521,38,-521,104,-521,83,-521,88,-521, - 3,0, /* actions: */ 128,578,129,579,130,580, - /* default action: */ -451, - /* default action: */ -452, - /* default action: */ -453, - 8,0, /* actions: */ 104,-284,83,-284,88,-284,87,-97,134,-97,37,-97,14,-97,97,-97, - 1,0, /* actions: */ 122,583, - 8,0, /* actions: */ 104,-287,83,-287,88,-287,87,-96,134,-96,37,-96,14,-96,97,-96, - 2,1, /* actions: */ 14,314,94,-531, /* gotos: */ -114,585, - 1,0, /* actions: */ 94,323, - 63,41, /* actions: */ 86,27,14,28,57,43,18,142,59,148,60,153,131,136,118,225,122,228,119,286,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,121,226,120,227,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,84,372,103,291,98,300,43,335,58,321,51,342,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,423,19,430,15,440,16,446,17,451,93,457,44,465,147,498,64,501,65,504,148,507,42,525,33,539,34,541,35,544,36,545,89,591,2,598,97,-529, /* gotos: */ -4,421,-99,587,-108,4,-109,5,-132,26,-3,29,-2,31,-10,42,-68,158,-11,352,-14,353,-13,354,-27,18,-29,19,-69,34,-12,355,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-70,371,-25,345,-18,394,-22,415,-23,439,-28,483,-26,484,-19,509,-105,510,-104,520,-7,523,-8,524,-9,543,-100,547,-102,589,-103,556, - 3,2, /* actions: */ 134,426,14,314,97,-531, /* gotos: */ -116,588,-114,312, - /* default action: */ -89, - 1,0, /* actions: */ 87,590, - /* default action: */ -85, - 50,18, /* actions: */ 87,596,118,225,121,226,120,227,122,228,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,128,244,129,245,130,246,146,577,116,126,126,257,111,254,113,260,112,264,114,268,115,277,131,136,119,286,84,582,103,291,98,300,43,308,58,584,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,503,134,-83,37,-83,14,-83,97,-83, /* gotos: */ -103,592,-70,557,-12,558,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-68,581,-69,475,-25,345,-18,394,-22,415,-23,439, - 5,0, /* actions: */ 87,593,134,-82,37,-82,14,-82,97,-82, - 45,20, /* actions: */ 118,225,121,226,120,227,122,228,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,128,244,129,245,130,246,146,577,116,126,126,257,111,254,113,260,112,264,114,268,115,277,131,136,119,286,84,582,103,291,98,300,43,308,58,584,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,586,19,430,15,440,16,446,17,451,93,457,44,503, /* gotos: */ -101,594,-102,595,-103,556,-70,557,-12,558,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-68,581,-69,475,-25,345,-18,394,-22,415,-23,439, - 5,0, /* actions: */ 87,554,134,-80,37,-80,14,-80,97,-80, - /* default action: */ -87, - 45,20, /* actions: */ 118,225,121,226,120,227,122,228,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,128,244,129,245,130,246,146,577,116,126,126,257,111,254,113,260,112,264,114,268,115,277,131,136,119,286,84,582,103,291,98,300,43,308,58,584,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,586,19,430,15,440,16,446,17,451,93,457,44,503, /* gotos: */ -101,597,-102,595,-103,556,-70,557,-12,558,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-68,581,-69,475,-25,345,-18,394,-22,415,-23,439, - 5,0, /* actions: */ 87,554,134,-81,37,-81,14,-81,97,-81, - 59,36, /* actions: */ 57,43,18,142,59,148,60,153,131,136,118,225,122,228,119,286,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,121,226,120,227,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,84,372,103,291,98,300,43,335,58,321,51,342,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,423,19,430,15,440,16,446,17,451,93,457,44,465,147,498,64,501,65,504,148,507,42,525,33,539,34,541,35,544,36,545,89,591, /* gotos: */ -2,599,-10,42,-68,158,-11,352,-14,353,-13,354,-27,18,-29,19,-69,34,-12,355,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-70,371,-25,345,-18,394,-22,415,-23,439,-28,483,-26,484,-19,509,-105,510,-104,520,-7,523,-8,524,-9,543,-99,546,-100,547,-102,589,-103,556, - 17,0, /* actions: */ 52,11,53,32,54,600,55,602,56,604,86,-8,14,-8,3,-8,22,-8,102,-8,108,-8,27,-8,26,-8,21,-8,29,-8,97,-8,20,-8, - 49,25, /* actions: */ 118,225,122,228,119,286,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,121,226,120,227,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,131,136,84,287,103,291,98,300,43,335,58,321,51,342,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,465,147,498,64,501,65,504,148,507, /* gotos: */ -13,601,-27,18,-29,19,-69,34,-12,326,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-70,224,-68,284,-25,345,-18,394,-22,415,-23,439,-28,483,-26,484,-19,509,-105,218,-104,472, - 19,0, /* actions: */ 49,13,50,15,52,-47,53,-47,54,-47,55,-47,56,-47,86,-47,14,-47,3,-47,22,-47,102,-47,108,-47,27,-47,26,-47,21,-47,29,-47,97,-47,20,-47, - 49,25, /* actions: */ 118,225,122,228,119,286,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,121,226,120,227,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,131,136,84,287,103,291,98,300,43,335,58,321,51,342,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,465,147,498,64,501,65,504,148,507, /* gotos: */ -13,603,-27,18,-29,19,-69,34,-12,326,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-70,224,-68,284,-25,345,-18,394,-22,415,-23,439,-28,483,-26,484,-19,509,-105,218,-104,472, - 19,0, /* actions: */ 49,13,50,15,52,-48,53,-48,54,-48,55,-48,56,-48,86,-48,14,-48,3,-48,22,-48,102,-48,108,-48,27,-48,26,-48,21,-48,29,-48,97,-48,20,-48, - 59,36, /* actions: */ 57,43,18,142,59,148,60,153,131,136,118,225,122,228,119,286,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,121,226,120,227,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,84,372,103,291,98,300,43,335,58,321,51,342,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,423,19,430,15,440,16,446,17,451,93,457,44,465,147,498,64,501,65,504,148,507,42,525,33,539,34,541,35,544,36,545,89,591, /* gotos: */ -2,605,-10,42,-68,158,-11,352,-14,353,-13,354,-27,18,-29,19,-69,34,-12,355,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-70,371,-25,345,-18,394,-22,415,-23,439,-28,483,-26,484,-19,509,-105,510,-104,520,-7,523,-8,524,-9,543,-99,546,-100,547,-102,589,-103,556, - /* default action: */ -49, - 45,20, /* actions: */ 118,225,121,226,120,227,122,228,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,128,244,129,245,130,246,146,577,116,126,126,257,111,254,113,260,112,264,114,268,115,277,131,136,119,286,84,582,103,291,98,300,43,308,58,584,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,586,19,430,15,440,16,446,17,451,93,457,44,503, /* gotos: */ -101,607,-102,595,-103,556,-70,557,-12,558,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-68,581,-69,475,-25,345,-18,394,-22,415,-23,439, - 5,0, /* actions: */ 87,554,134,-79,37,-79,14,-79,97,-79, - /* default action: */ -379, - /* default action: */ -380, - 12,10, /* actions: */ 122,618,121,619,120,620,123,621,118,673,95,637,143,671,89,672,91,663,90,664,86,-377,139,-377, /* gotos: */ -81,611,-95,624,-98,665,-90,636,-86,695,-88,693,-91,705,-144,669,-92,710,-145,661, - 2,1, /* actions: */ 86,614,139,-382, /* gotos: */ -84,612, - 1,0, /* actions: */ 139,613, - /* default action: */ -381, - 5,2, /* actions: */ 122,618,121,619,120,620,123,621,118,622, /* gotos: */ -83,615,-90,623, - 4,0, /* actions: */ 87,616,139,-383,14,-383,97,-383, - 5,1, /* actions: */ 122,618,121,619,120,620,123,621,118,622, /* gotos: */ -90,617, - /* default action: */ -385, - /* default action: */ -490, - /* default action: */ -491, - /* default action: */ -492, - /* default action: */ -493, - /* default action: */ -494, - /* default action: */ -384, - 3,1, /* actions: */ 87,625,86,-508,139,-508, /* gotos: */ -93,694, - 12,8, /* actions: */ 118,673,122,618,121,619,120,620,123,621,95,637,143,671,89,672,91,663,90,664,86,-367,139,-367, /* gotos: */ -86,626,-98,634,-91,688,-92,635,-88,693,-90,636,-144,669,-145,661, - 3,1, /* actions: */ 87,627,86,-508,139,-508, /* gotos: */ -93,687, - 10,8, /* actions: */ 143,671,89,672,122,618,121,619,120,620,123,621,118,673,95,637,91,663,90,664, /* gotos: */ -91,628,-95,666,-88,668,-92,635,-144,669,-98,665,-90,636,-145,661, - 3,1, /* actions: */ 87,630,86,-508,139,-508, /* gotos: */ -93,629, - /* default action: */ -362, - 8,5, /* actions: */ 122,618,121,619,120,620,123,621,118,622,95,637,91,663,90,664, /* gotos: */ -95,631,-92,635,-98,665,-90,636,-145,661, - 3,1, /* actions: */ 87,633,86,-508,139,-508, /* gotos: */ -93,632, - /* default action: */ -363, - 8,4, /* actions: */ 122,618,121,619,120,620,123,621,118,622,95,637,91,663,90,664, /* gotos: */ -98,634,-92,635,-90,636,-145,661, - /* default action: */ -346, - /* default action: */ -509, - /* default action: */ -347, - 7,4, /* actions: */ 122,618,121,619,120,620,123,621,118,622,95,649,89,653, /* gotos: */ -94,638,-96,640,-97,652,-90,648, - 2,2, /* actions: */ 14,314,97,-531, /* gotos: */ -116,639,-114,312, - /* default action: */ -348, - 3,0, /* actions: */ 87,641,14,-349,97,-349, - 7,2, /* actions: */ 89,643,122,618,121,619,120,620,123,621,118,622,95,649, /* gotos: */ -97,642,-90,648, - /* default action: */ -359, - 8,1, /* actions: */ 87,659,122,618,121,619,120,620,123,621,118,622,14,-351,97,-351, /* gotos: */ -90,644, - 3,0, /* actions: */ 87,645,14,-350,97,-350, - 6,3, /* actions: */ 122,618,121,619,120,620,123,621,118,622,95,649, /* gotos: */ -96,646,-97,652,-90,648, - 3,0, /* actions: */ 87,647,14,-352,97,-352, - 6,2, /* actions: */ 122,618,121,619,120,620,123,621,118,622,95,649, /* gotos: */ -97,642,-90,648, - /* default action: */ -360, - 7,4, /* actions: */ 122,618,121,619,120,620,123,621,118,622,95,649,89,653, /* gotos: */ -94,650,-96,640,-97,652,-90,648, - 2,2, /* actions: */ 14,314,97,-531, /* gotos: */ -116,651,-114,312, - /* default action: */ -361, - /* default action: */ -358, - 8,1, /* actions: */ 87,657,122,618,121,619,120,620,123,621,118,622,14,-357,97,-357, /* gotos: */ -90,654, - 3,0, /* actions: */ 87,655,14,-356,97,-356, - 6,3, /* actions: */ 122,618,121,619,120,620,123,621,118,622,95,649, /* gotos: */ -96,656,-97,652,-90,648, - 3,0, /* actions: */ 87,647,14,-354,97,-354, - 6,3, /* actions: */ 122,618,121,619,120,620,123,621,118,622,95,649, /* gotos: */ -96,658,-97,652,-90,648, - 3,0, /* actions: */ 87,647,14,-355,97,-355, - 6,3, /* actions: */ 122,618,121,619,120,620,123,621,118,622,95,649, /* gotos: */ -96,660,-97,652,-90,648, - 3,0, /* actions: */ 87,647,14,-353,97,-353, - 5,1, /* actions: */ 122,618,121,619,120,620,123,621,118,622, /* gotos: */ -90,662, - /* default action: */ -507, - /* default action: */ -505, - /* default action: */ -506, - /* default action: */ -345, - 3,1, /* actions: */ 87,633,86,-508,139,-508, /* gotos: */ -93,667, - /* default action: */ -365, - /* default action: */ -500, - 12,1, /* actions: */ 122,618,121,619,120,620,123,621,118,622,87,-504,86,-504,14,-504,101,-504,41,-504,139,-504,97,-504, /* gotos: */ -90,670, - /* default action: */ -503, - /* default action: */ -501, - /* default action: */ -502, - 4,0, /* actions: */ 134,674,87,-494,86,-494,139,-494, - 45,17, /* actions: */ 128,244,129,245,130,246,146,577,116,126,126,257,111,254,113,260,112,264,114,268,115,277,118,225,121,226,120,227,122,228,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,131,136,119,286,84,685,103,291,98,300,43,308,58,584,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,503, /* gotos: */ -12,675,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-70,683,-68,684,-69,475,-25,345,-18,394,-22,415,-23,439, - 6,0, /* actions: */ 83,676,88,679,104,680,87,-496,86,-496,139,-496, - 33,4, /* actions: */ 122,677,118,678,119,571,139,52,140,53,91,54,67,55,68,56,69,57,75,58,76,59,137,60,71,61,138,62,72,63,70,64,81,65,82,66,141,67,142,68,143,69,89,70,144,71,145,72,66,73,147,74,148,75,64,76,65,77,79,78,80,79,92,80,94,468, /* gotos: */ -72,566,-73,568,-40,569,-75,572, - 7,0, /* actions: */ 83,-286,88,-286,104,-286,87,-286,86,-286,139,-286,94,-521, - 9,0, /* actions: */ 94,-520,99,-524,38,-524,83,-524,88,-524,104,-524,87,-524,86,-524,139,-524, - 33,3, /* actions: */ 118,490,122,491,119,492,139,52,140,53,91,54,67,55,68,56,69,57,75,58,76,59,137,60,71,61,138,62,72,63,70,64,81,65,82,66,141,67,142,68,143,69,89,70,144,71,145,72,66,73,147,74,148,75,64,76,65,77,79,78,80,79,92,80,94,468, /* gotos: */ -72,574,-40,357,-75,493, - 54,28, /* actions: */ 118,225,121,226,120,227,122,228,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,131,136,119,286,84,287,103,291,98,300,43,335,58,321,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,465,64,501,65,504,147,506,148,507,89,515,125,532,90,534,14,-258,105,-258, /* gotos: */ -43,681,-42,471,-20,316,-19,334,-105,218,-70,224,-12,326,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-68,284,-69,34,-25,345,-18,394,-22,415,-23,439,-104,472,-21,527,-51,528,-52,536,-33,537,-29,538, - 2,2, /* actions: */ 14,314,105,-531, /* gotos: */ -113,682,-114,562, - /* default action: */ -403, - /* default action: */ -466, - /* default action: */ -284, - 1,0, /* actions: */ 122,686, - /* default action: */ -287, - /* default action: */ -364, - 3,1, /* actions: */ 87,690,86,-508,139,-508, /* gotos: */ -93,689, - /* default action: */ -366, - 8,5, /* actions: */ 122,618,121,619,120,620,123,621,118,622,95,637,91,663,90,664, /* gotos: */ -95,691,-92,635,-98,665,-90,636,-145,661, - 3,1, /* actions: */ 87,633,86,-508,139,-508, /* gotos: */ -93,692, - /* default action: */ -368, - /* default action: */ -499, - /* default action: */ -369, - 3,1, /* actions: */ 87,696,86,-508,139,-508, /* gotos: */ -93,704, - 10,8, /* actions: */ 143,671,89,672,118,673,122,618,121,619,120,620,123,621,95,637,91,663,90,664, /* gotos: */ -91,697,-88,668,-95,702,-92,635,-144,669,-98,665,-90,636,-145,661, - 3,1, /* actions: */ 87,699,86,-508,139,-508, /* gotos: */ -93,698, - /* default action: */ -370, - 8,5, /* actions: */ 122,618,121,619,120,620,123,621,118,622,95,637,91,663,90,664, /* gotos: */ -95,700,-92,635,-98,665,-90,636,-145,661, - 3,1, /* actions: */ 87,633,86,-508,139,-508, /* gotos: */ -93,701, - /* default action: */ -371, - 3,1, /* actions: */ 87,633,86,-508,139,-508, /* gotos: */ -93,703, - /* default action: */ -373, - /* default action: */ -372, - 3,1, /* actions: */ 87,707,86,-508,139,-508, /* gotos: */ -93,706, - /* default action: */ -374, - 8,5, /* actions: */ 122,618,121,619,120,620,123,621,118,622,95,637,91,663,90,664, /* gotos: */ -95,708,-92,635,-98,665,-90,636,-145,661, - 3,1, /* actions: */ 87,633,86,-508,139,-508, /* gotos: */ -93,709, - /* default action: */ -375, - /* default action: */ -376, - 63,41, /* actions: */ 86,27,14,28,57,43,18,142,59,148,60,153,131,136,118,225,122,228,119,286,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,121,226,120,227,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,84,372,103,291,98,300,43,335,58,321,51,342,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,423,19,430,15,440,16,446,17,451,93,457,44,465,147,498,64,501,65,504,148,507,42,525,33,539,34,541,35,544,36,545,89,591,2,598,22,-529, /* gotos: */ -4,712,-108,4,-109,5,-132,26,-3,29,-2,31,-10,42,-68,158,-11,352,-14,353,-13,354,-27,18,-29,19,-69,34,-12,355,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-70,371,-25,345,-18,394,-22,415,-23,439,-28,483,-26,484,-19,509,-105,510,-104,520,-7,523,-8,524,-9,543,-99,546,-100,547,-102,589,-103,556, - 1,0, /* actions: */ 22,713, - /* default action: */ -391, - 13,10, /* actions: */ 122,618,121,619,120,620,123,621,118,730,95,637,143,671,89,672,91,663,90,664,86,-489,14,-489,97,-489, /* gotos: */ -82,715,-95,718,-98,665,-90,636,-85,741,-87,739,-91,751,-144,669,-92,756,-145,661, - 3,1, /* actions: */ 86,614,14,-382,97,-382, /* gotos: */ -84,716, - 2,2, /* actions: */ 14,314,97,-531, /* gotos: */ -116,717,-114,312, - /* default action: */ -388, - 6,1, /* actions: */ 87,719,86,-508,14,-508,101,-508,41,-508,97,-508, /* gotos: */ -93,740, - 10,8, /* actions: */ 118,730,122,618,121,619,120,620,123,621,95,637,143,671,89,672,91,663,90,664, /* gotos: */ -85,720,-98,634,-91,734,-92,635,-87,739,-90,636,-144,669,-145,661, - 6,1, /* actions: */ 87,721,86,-508,14,-508,101,-508,41,-508,97,-508, /* gotos: */ -93,733, - 10,8, /* actions: */ 143,671,89,672,122,618,121,619,120,620,123,621,118,730,95,637,91,663,90,664, /* gotos: */ -91,722,-95,727,-87,729,-92,635,-144,669,-98,665,-90,636,-145,661, - 6,1, /* actions: */ 87,724,86,-508,14,-508,101,-508,41,-508,97,-508, /* gotos: */ -93,723, - /* default action: */ -475, - 8,5, /* actions: */ 122,618,121,619,120,620,123,621,118,622,95,637,91,663,90,664, /* gotos: */ -95,725,-92,635,-98,665,-90,636,-145,661, - 6,1, /* actions: */ 87,633,86,-508,14,-508,101,-508,41,-508,97,-508, /* gotos: */ -93,726, - /* default action: */ -476, - 6,1, /* actions: */ 87,633,86,-508,14,-508,101,-508,41,-508,97,-508, /* gotos: */ -93,728, - /* default action: */ -478, - /* default action: */ -498, - 7,0, /* actions: */ 134,731,87,-494,86,-494,14,-494,101,-494,41,-494,97,-494, - 49,20, /* actions: */ 118,225,121,226,120,227,122,228,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,131,136,119,286,84,287,103,291,98,300,43,308,58,321,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,503,64,501,65,504,147,506,148,507, /* gotos: */ -19,732,-105,218,-70,224,-12,237,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-68,284,-69,475,-25,345,-18,394,-22,415,-23,439,-104,472, - 32,0, /* actions: */ 141,162,142,164,143,166,144,168,145,170,66,172,139,174,140,176,91,178,67,180,137,182,71,184,138,186,72,188,68,190,69,192,70,194,75,196,76,198,81,200,82,202,73,204,74,206,77,208,78,210,135,212,87,-495,86,-495,14,-495,101,-495,41,-495,97,-495, - /* default action: */ -477, - 6,1, /* actions: */ 87,736,86,-508,14,-508,101,-508,41,-508,97,-508, /* gotos: */ -93,735, - /* default action: */ -479, - 8,5, /* actions: */ 122,618,121,619,120,620,123,621,118,622,95,637,91,663,90,664, /* gotos: */ -95,737,-92,635,-98,665,-90,636,-145,661, - 6,1, /* actions: */ 87,633,86,-508,14,-508,101,-508,41,-508,97,-508, /* gotos: */ -93,738, - /* default action: */ -480, - /* default action: */ -497, - /* default action: */ -481, - 6,1, /* actions: */ 87,742,86,-508,14,-508,101,-508,41,-508,97,-508, /* gotos: */ -93,750, - 10,8, /* actions: */ 143,671,89,672,118,730,122,618,121,619,120,620,123,621,95,637,91,663,90,664, /* gotos: */ -91,743,-87,729,-95,748,-92,635,-144,669,-98,665,-90,636,-145,661, - 6,1, /* actions: */ 87,745,86,-508,14,-508,101,-508,41,-508,97,-508, /* gotos: */ -93,744, - /* default action: */ -482, - 8,5, /* actions: */ 122,618,121,619,120,620,123,621,118,622,95,637,91,663,90,664, /* gotos: */ -95,746,-92,635,-98,665,-90,636,-145,661, - 6,1, /* actions: */ 87,633,86,-508,14,-508,101,-508,41,-508,97,-508, /* gotos: */ -93,747, - /* default action: */ -483, - 6,1, /* actions: */ 87,633,86,-508,14,-508,101,-508,41,-508,97,-508, /* gotos: */ -93,749, - /* default action: */ -485, - /* default action: */ -484, - 6,1, /* actions: */ 87,753,86,-508,14,-508,101,-508,41,-508,97,-508, /* gotos: */ -93,752, - /* default action: */ -486, - 8,5, /* actions: */ 122,618,121,619,120,620,123,621,118,622,95,637,91,663,90,664, /* gotos: */ -95,754,-92,635,-98,665,-90,636,-145,661, - 6,1, /* actions: */ 87,633,86,-508,14,-508,101,-508,41,-508,97,-508, /* gotos: */ -93,755, - /* default action: */ -487, - /* default action: */ -488, - /* default action: */ -389, - 12,10, /* actions: */ 122,618,121,619,120,620,123,621,118,730,95,637,143,671,89,672,91,663,90,664,14,-489,97,-489, /* gotos: */ -82,759,-95,718,-98,665,-90,636,-85,741,-87,739,-91,751,-144,669,-92,756,-145,661, - 2,2, /* actions: */ 14,314,97,-531, /* gotos: */ -116,760,-114,312, - /* default action: */ -473, - 2,1, /* actions: */ 86,27,14,28, /* gotos: */ -132,762, - /* default action: */ -474, - 2,1, /* actions: */ 88,771,83,772, /* gotos: */ -136,764, - 0,1, /* default action: */ -327, /* gotos: */ -137,765, - 75,3, /* actions: */ 118,48,122,49,119,50,139,52,140,53,91,54,67,55,68,56,69,57,75,58,76,59,137,60,71,61,138,62,72,63,70,64,81,65,82,66,141,67,142,68,143,69,89,70,144,71,145,72,66,73,147,74,148,75,64,76,65,77,79,78,80,79,92,80,61,82,62,83,63,84,59,85,60,86,57,87,49,88,19,89,33,90,28,91,15,92,17,93,58,94,38,95,40,96,27,97,26,98,22,99,21,100,48,101,32,102,37,103,16,104,34,105,46,106,51,107,50,108,35,109,20,110,36,111,42,112,45,113,44,114,25,115,47,116,18,117,29,118,43,119,52,120,53,121,54,122,55,123,56,124, /* gotos: */ -76,766,-75,51,-117,81, - 0,1, /* default action: */ -328, /* gotos: */ -138,767, - 13,11, /* actions: */ 94,758,122,618,121,619,120,620,123,621,118,730,95,637,143,671,89,672,91,663,90,664,86,-489,14,-489, /* gotos: */ -80,768,-82,761,-95,718,-98,665,-90,636,-85,741,-87,739,-91,751,-144,669,-92,756,-145,661, - 66,42, /* actions: */ 86,27,14,28,57,43,18,142,59,148,60,153,131,136,118,225,122,228,119,286,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,121,226,120,227,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,84,372,103,291,98,300,43,335,58,321,51,342,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,423,19,430,15,440,16,446,17,451,93,457,44,465,147,498,64,501,65,504,148,507,42,525,33,539,34,541,35,544,36,545,89,591,2,598,20,-529,27,-529,21,-529,22,-529, /* gotos: */ -24,769,-4,433,-108,4,-109,5,-132,26,-3,29,-2,31,-10,42,-68,158,-11,352,-14,353,-13,354,-27,18,-29,19,-69,34,-12,355,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-70,371,-25,345,-18,394,-22,415,-23,439,-28,483,-26,484,-19,509,-105,510,-104,520,-7,523,-8,524,-9,543,-99,546,-100,547,-102,589,-103,556, - 1,0, /* actions: */ 22,770, - /* default action: */ -329, - /* default action: */ -527, - /* default action: */ -528, - 15,0, /* actions: */ 94,-111,122,-111,121,-111,120,-111,123,-111,118,-111,95,-111,143,-111,89,-111,91,-111,90,-111,86,-111,14,-111,88,-454,83,-454, - 15,0, /* actions: */ 94,-112,122,-112,121,-112,120,-112,123,-112,118,-112,95,-112,143,-112,89,-112,91,-112,90,-112,86,-112,14,-112,88,-457,83,-457, - 15,0, /* actions: */ 94,-157,122,-157,121,-157,120,-157,123,-157,118,-157,95,-157,143,-157,89,-157,91,-157,90,-157,86,-157,14,-157,88,-464,83,-464, - 15,0, /* actions: */ 94,-158,122,-158,121,-158,120,-158,123,-158,118,-158,95,-158,143,-158,89,-158,91,-158,90,-158,86,-158,14,-158,88,-463,83,-463, - 15,0, /* actions: */ 94,-159,122,-159,121,-159,120,-159,123,-159,118,-159,95,-159,143,-159,89,-159,91,-159,90,-159,86,-159,14,-159,88,-465,83,-465, - 15,0, /* actions: */ 94,-176,122,-176,121,-176,120,-176,123,-176,118,-176,95,-176,143,-176,89,-176,91,-176,90,-176,86,-176,14,-176,88,-462,83,-462, - 15,0, /* actions: */ 94,-181,122,-181,121,-181,120,-181,123,-181,118,-181,95,-181,143,-181,89,-181,91,-181,90,-181,86,-181,14,-181,88,-459,83,-459, - 15,0, /* actions: */ 94,-188,122,-188,121,-188,120,-188,123,-188,118,-188,95,-188,143,-188,89,-188,91,-188,90,-188,86,-188,14,-188,88,-460,83,-460, - 15,0, /* actions: */ 94,-191,122,-191,121,-191,120,-191,123,-191,118,-191,95,-191,143,-191,89,-191,91,-191,90,-191,86,-191,14,-191,88,-461,83,-461, - /* default action: */ -510, - 0,1, /* default action: */ -511, /* gotos: */ -146,784, - 49,25, /* actions: */ 118,225,122,228,119,286,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,121,226,120,227,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,131,136,84,287,103,291,98,300,43,335,58,321,51,342,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,465,147,498,64,501,65,504,148,507, /* gotos: */ -13,785,-27,18,-29,19,-69,34,-12,326,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-70,224,-68,284,-25,345,-18,394,-22,415,-23,439,-28,483,-26,484,-19,509,-105,218,-104,472, - 4,2, /* actions: */ 49,13,50,15,14,314,97,-531, /* gotos: */ -116,786,-114,312, - /* default action: */ -512, - 2,1, /* actions: */ 122,789,118,790, /* gotos: */ -74,788, - /* default action: */ -108, - 70,0, /* actions: */ 83,-287,88,-287,104,-287,86,-106,14,-106,138,-106,2,-106,57,-106,18,-106,59,-106,60,-106,131,-106,118,-106,122,-106,119,-106,128,-106,129,-106,130,-106,146,-106,116,-106,126,-106,111,-106,113,-106,112,-106,114,-106,115,-106,121,-106,120,-106,123,-106,46,-106,45,-106,47,-106,48,-106,62,-106,61,-106,63,-106,84,-106,103,-106,98,-106,43,-106,58,-106,51,-106,23,-106,24,-106,30,-106,31,-106,28,-106,32,-106,96,-106,95,-106,19,-106,15,-106,16,-106,17,-106,93,-106,44,-106,147,-106,64,-106,65,-106,148,-106,42,-106,33,-106,34,-106,35,-106,36,-106,89,-106,22,-106,20,-106,27,-106,21,-106, - /* default action: */ -107, - /* default action: */ -109, - 73,0, /* actions: */ 86,-106,14,-106,138,-106,2,-106,57,-106,18,-106,59,-106,60,-106,131,-106,118,-106,122,-106,119,-106,128,-106,129,-106,130,-106,146,-106,116,-106,126,-106,111,-106,113,-106,112,-106,114,-106,115,-106,121,-106,120,-106,123,-106,46,-106,45,-106,47,-106,48,-106,62,-106,61,-106,63,-106,84,-106,103,-106,98,-106,43,-106,58,-106,51,-106,23,-106,24,-106,30,-106,31,-106,28,-106,32,-106,96,-106,95,-106,19,-106,15,-106,16,-106,17,-106,93,-106,44,-106,147,-106,64,-106,65,-106,148,-106,42,-106,33,-106,34,-106,35,-106,36,-106,89,-106,22,-106,20,-106,27,-106,21,-106,83,-457,88,-457,104,-457,99,-518,38,-518,94,-518, - 73,0, /* actions: */ 86,-107,14,-107,138,-107,2,-107,57,-107,18,-107,59,-107,60,-107,131,-107,118,-107,122,-107,119,-107,128,-107,129,-107,130,-107,146,-107,116,-107,126,-107,111,-107,113,-107,112,-107,114,-107,115,-107,121,-107,120,-107,123,-107,46,-107,45,-107,47,-107,48,-107,62,-107,61,-107,63,-107,84,-107,103,-107,98,-107,43,-107,58,-107,51,-107,23,-107,24,-107,30,-107,31,-107,28,-107,32,-107,96,-107,95,-107,19,-107,15,-107,16,-107,17,-107,93,-107,44,-107,147,-107,64,-107,65,-107,148,-107,42,-107,33,-107,34,-107,35,-107,36,-107,89,-107,22,-107,20,-107,27,-107,21,-107,83,-454,88,-454,104,-454,99,-517,38,-517,94,-517, - 3,0, /* actions: */ 83,795,88,679,104,680, - 33,5, /* actions: */ 122,797,118,798,119,571,139,52,140,53,91,54,67,55,68,56,69,57,75,58,76,59,137,60,71,61,138,62,72,63,70,64,81,65,82,66,141,67,142,68,143,69,89,70,144,71,145,72,66,73,147,74,148,75,64,76,65,77,79,78,80,79,92,80,94,468, /* gotos: */ -74,796,-72,566,-73,568,-40,569,-75,572, - /* default action: */ -110, - 71,0, /* actions: */ 83,-286,88,-286,104,-286,86,-106,14,-106,138,-106,2,-106,57,-106,18,-106,59,-106,60,-106,131,-106,118,-106,122,-106,119,-106,128,-106,129,-106,130,-106,146,-106,116,-106,126,-106,111,-106,113,-106,112,-106,114,-106,115,-106,121,-106,120,-106,123,-106,46,-106,45,-106,47,-106,48,-106,62,-106,61,-106,63,-106,84,-106,103,-106,98,-106,43,-106,58,-106,51,-106,23,-106,24,-106,30,-106,31,-106,28,-106,32,-106,96,-106,95,-106,19,-106,15,-106,16,-106,17,-106,93,-106,44,-106,147,-106,64,-106,65,-106,148,-106,42,-106,33,-106,34,-106,35,-106,36,-106,89,-106,22,-106,20,-106,27,-106,21,-106,94,-521, - 73,0, /* actions: */ 86,-107,14,-107,138,-107,2,-107,57,-107,18,-107,59,-107,60,-107,131,-107,118,-107,122,-107,119,-107,128,-107,129,-107,130,-107,146,-107,116,-107,126,-107,111,-107,113,-107,112,-107,114,-107,115,-107,121,-107,120,-107,123,-107,46,-107,45,-107,47,-107,48,-107,62,-107,61,-107,63,-107,84,-107,103,-107,98,-107,43,-107,58,-107,51,-107,23,-107,24,-107,30,-107,31,-107,28,-107,32,-107,96,-107,95,-107,19,-107,15,-107,16,-107,17,-107,93,-107,44,-107,147,-107,64,-107,65,-107,148,-107,42,-107,33,-107,34,-107,35,-107,36,-107,89,-107,22,-107,20,-107,27,-107,21,-107,94,-520,99,-524,38,-524,83,-524,88,-524,104,-524, - /* default action: */ -469, - 0,1, /* default action: */ -470, /* gotos: */ -143,801, - 49,25, /* actions: */ 118,225,122,228,119,286,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,121,226,120,227,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,131,136,84,287,103,291,98,300,43,335,58,321,51,342,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,465,147,498,64,501,65,504,148,507, /* gotos: */ -13,802,-27,18,-29,19,-69,34,-12,326,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-70,224,-68,284,-25,345,-18,394,-22,415,-23,439,-28,483,-26,484,-19,509,-105,218,-104,472, - 4,1, /* actions: */ 49,13,50,15,86,27,14,28, /* gotos: */ -132,803, - /* default action: */ -471, - 2,1, /* actions: */ 86,27,14,28, /* gotos: */ -132,805, - /* default action: */ -472, - 49,25, /* actions: */ 118,225,122,228,119,286,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,121,226,120,227,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,131,136,84,287,103,291,98,300,43,335,58,321,51,342,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,465,147,498,64,501,65,504,148,507, /* gotos: */ -13,807,-27,18,-29,19,-69,34,-12,326,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-70,224,-68,284,-25,345,-18,394,-22,415,-23,439,-28,483,-26,484,-19,509,-105,218,-104,472, - 4,1, /* actions: */ 49,13,50,15,86,-320,14,-320, /* gotos: */ -131,808, - 2,1, /* actions: */ 86,27,14,28, /* gotos: */ -132,809, - 0,1, /* default action: */ -321, /* gotos: */ -133,810, - 66,42, /* actions: */ 86,27,14,28,57,43,18,142,59,148,60,153,131,136,118,225,122,228,119,286,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,121,226,120,227,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,84,372,103,291,98,300,43,335,58,321,51,342,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,423,19,430,15,440,16,446,17,451,93,457,44,465,147,498,64,501,65,504,148,507,42,525,33,539,34,541,35,544,36,545,89,591,2,598,20,-529,27,-529,21,-529,22,-529, /* gotos: */ -24,811,-4,433,-108,4,-109,5,-132,26,-3,29,-2,31,-10,42,-68,158,-11,352,-14,353,-13,354,-27,18,-29,19,-69,34,-12,355,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-70,371,-25,345,-18,394,-22,415,-23,439,-28,483,-26,484,-19,509,-105,510,-104,520,-7,523,-8,524,-9,543,-99,546,-100,547,-102,589,-103,556, - 1,0, /* actions: */ 22,812, - /* default action: */ -322, - 4,1, /* actions: */ 20,815,27,-414,21,-414,22,-414, /* gotos: */ -48,814, - /* default action: */ -416, - 54,23, /* actions: */ 85,826,118,225,121,226,120,227,122,228,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,131,136,119,286,84,287,103,291,98,300,43,308,58,321,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,503,64,501,65,504,147,506,148,507,89,515,86,-419,14,-419,25,-419, /* gotos: */ -106,816,-20,822,-19,842,-105,218,-70,224,-12,237,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-68,284,-69,475,-25,345,-18,394,-22,415,-23,439,-104,472,-21,527, - 3,2, /* actions: */ 86,27,14,28,25,821, /* gotos: */ -121,817,-132,819, - 66,41, /* actions: */ 86,27,14,28,57,43,18,142,59,148,60,153,131,136,118,225,122,228,119,286,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,121,226,120,227,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,84,372,103,291,98,300,43,335,58,321,51,342,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,423,19,430,15,440,16,446,17,451,93,457,44,465,147,498,64,501,65,504,148,507,42,525,33,539,34,541,35,544,36,545,89,591,2,598,20,-529,27,-529,21,-529,22,-529, /* gotos: */ -4,818,-108,4,-109,5,-132,26,-3,29,-2,31,-10,42,-68,158,-11,352,-14,353,-13,354,-27,18,-29,19,-69,34,-12,355,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-70,371,-25,345,-18,394,-22,415,-23,439,-28,483,-26,484,-19,509,-105,510,-104,520,-7,523,-8,524,-9,543,-99,546,-100,547,-102,589,-103,556, - /* default action: */ -417, - 69,0, /* actions: */ 25,820,86,-334,14,-334,57,-334,18,-334,59,-334,60,-334,131,-334,118,-334,122,-334,119,-334,128,-334,129,-334,130,-334,146,-334,116,-334,126,-334,111,-334,113,-334,112,-334,114,-334,115,-334,121,-334,120,-334,123,-334,46,-334,45,-334,47,-334,48,-334,62,-334,61,-334,63,-334,84,-334,103,-334,98,-334,43,-334,58,-334,51,-334,23,-334,24,-334,30,-334,31,-334,28,-334,32,-334,96,-334,95,-334,19,-334,15,-334,16,-334,17,-334,93,-334,44,-334,147,-334,64,-334,65,-334,148,-334,42,-334,33,-334,34,-334,35,-334,36,-334,89,-334,2,-334,27,-334,26,-334,22,-334,29,-334,20,-334,21,-334, - /* default action: */ -336, - /* default action: */ -335, - 5,1, /* actions: */ 87,518,85,826,86,-419,14,-419,25,-419, /* gotos: */ -106,823, - 3,2, /* actions: */ 86,27,14,28,25,821, /* gotos: */ -121,824,-132,819, - 66,41, /* actions: */ 86,27,14,28,57,43,18,142,59,148,60,153,131,136,118,225,122,228,119,286,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,121,226,120,227,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,84,372,103,291,98,300,43,335,58,321,51,342,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,423,19,430,15,440,16,446,17,451,93,457,44,465,147,498,64,501,65,504,148,507,42,525,33,539,34,541,35,544,36,545,89,591,2,598,20,-529,27,-529,21,-529,22,-529, /* gotos: */ -4,825,-108,4,-109,5,-132,26,-3,29,-2,31,-10,42,-68,158,-11,352,-14,353,-13,354,-27,18,-29,19,-69,34,-12,355,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-70,371,-25,345,-18,394,-22,415,-23,439,-28,483,-26,484,-19,509,-105,510,-104,520,-7,523,-8,524,-9,543,-99,546,-100,547,-102,589,-103,556, - /* default action: */ -418, - 45,18, /* actions: */ 118,225,121,226,120,227,122,228,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,128,244,129,245,130,246,146,577,116,126,126,257,111,254,113,260,112,264,114,268,115,277,131,136,119,286,84,840,103,291,98,300,43,308,58,584,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,503, /* gotos: */ -105,827,-70,828,-12,829,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-68,839,-69,475,-25,345,-18,394,-22,415,-23,439, - /* default action: */ -420, - 6,0, /* actions: */ 86,-98,14,-98,25,-98,104,-466,83,-466,88,-466, - 3,0, /* actions: */ 104,830,83,833,88,836, - 54,28, /* actions: */ 118,225,121,226,120,227,122,228,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,131,136,119,286,84,287,103,291,98,300,43,335,58,321,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,465,64,501,65,504,147,506,148,507,89,515,125,532,90,534,14,-258,105,-258, /* gotos: */ -43,831,-42,471,-20,316,-19,334,-105,218,-70,224,-12,326,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-68,284,-69,34,-25,345,-18,394,-22,415,-23,439,-104,472,-21,527,-51,528,-52,536,-33,537,-29,538, - 2,2, /* actions: */ 14,314,105,-531, /* gotos: */ -113,832,-114,562, - 8,0, /* actions: */ 86,-99,14,-99,25,-99,99,-403,38,-403,104,-403,83,-403,88,-403, - 33,4, /* actions: */ 122,834,118,835,119,571,139,52,140,53,91,54,67,55,68,56,69,57,75,58,76,59,137,60,71,61,138,62,72,63,70,64,81,65,82,66,141,67,142,68,143,69,89,70,144,71,145,72,66,73,147,74,148,75,64,76,65,77,79,78,80,79,92,80,94,468, /* gotos: */ -72,566,-73,568,-40,569,-75,572, - 7,0, /* actions: */ 104,-286,83,-286,88,-286,86,-103,14,-103,25,-103,94,-521, - 9,0, /* actions: */ 86,-101,14,-101,25,-101,94,-520,99,-524,38,-524,104,-524,83,-524,88,-524, - 33,3, /* actions: */ 118,837,122,838,119,492,139,52,140,53,91,54,67,55,68,56,69,57,75,58,76,59,137,60,71,61,138,62,72,63,70,64,81,65,82,66,141,67,142,68,143,69,89,70,144,71,145,72,66,73,147,74,148,75,64,76,65,77,79,78,80,79,92,80,94,468, /* gotos: */ -72,574,-40,357,-75,493, - 9,0, /* actions: */ 86,-100,14,-100,25,-100,94,-520,99,-520,38,-520,104,-520,83,-520,88,-520, - 9,0, /* actions: */ 86,-102,14,-102,25,-102,94,-521,99,-521,38,-521,104,-521,83,-521,88,-521, - 6,0, /* actions: */ 104,-284,83,-284,88,-284,86,-105,14,-105,25,-105, - 1,0, /* actions: */ 122,841, - 6,0, /* actions: */ 104,-287,83,-287,88,-287,86,-104,14,-104,25,-104, - 31,0, /* actions: */ 141,162,142,164,143,166,144,168,145,170,66,172,139,174,140,176,91,178,67,180,137,182,71,184,138,186,72,188,68,190,69,192,70,194,75,196,76,198,81,200,82,202,73,204,74,206,77,208,78,210,135,212,87,-271,86,-271,14,-271,25,-271,85,-271, - /* default action: */ -415, - /* default action: */ -337, - /* default action: */ -338, - /* default action: */ -343, - 5,0, /* actions: */ 37,-98,104,-466,83,-466,88,-466,87,-90, - 3,0, /* actions: */ 104,849,83,852,88,855, - 54,28, /* actions: */ 118,225,121,226,120,227,122,228,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,131,136,119,286,84,287,103,291,98,300,43,335,58,321,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,465,64,501,65,504,147,506,148,507,89,515,125,532,90,534,14,-258,105,-258, /* gotos: */ -43,850,-42,471,-20,316,-19,334,-105,218,-70,224,-12,326,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-68,284,-69,34,-25,345,-18,394,-22,415,-23,439,-104,472,-21,527,-51,528,-52,536,-33,537,-29,538, - 2,2, /* actions: */ 14,314,105,-531, /* gotos: */ -113,851,-114,562, - 7,0, /* actions: */ 37,-99,99,-403,38,-403,104,-403,83,-403,88,-403,87,-91, - 33,4, /* actions: */ 122,853,118,854,119,571,139,52,140,53,91,54,67,55,68,56,69,57,75,58,76,59,137,60,71,61,138,62,72,63,70,64,81,65,82,66,141,67,142,68,143,69,89,70,144,71,145,72,66,73,147,74,148,75,64,76,65,77,79,78,80,79,92,80,94,468, /* gotos: */ -72,566,-73,568,-40,569,-75,572, - 6,0, /* actions: */ 104,-286,83,-286,88,-286,37,-103,87,-95,94,-521, - 8,0, /* actions: */ 37,-101,87,-93,94,-520,99,-524,38,-524,104,-524,83,-524,88,-524, - 33,3, /* actions: */ 118,856,122,857,119,492,139,52,140,53,91,54,67,55,68,56,69,57,75,58,76,59,137,60,71,61,138,62,72,63,70,64,81,65,82,66,141,67,142,68,143,69,89,70,144,71,145,72,66,73,147,74,148,75,64,76,65,77,79,78,80,79,92,80,94,468, /* gotos: */ -72,574,-40,357,-75,493, - 8,0, /* actions: */ 37,-100,87,-92,94,-520,99,-520,38,-520,104,-520,83,-520,88,-520, - 8,0, /* actions: */ 37,-102,87,-94,94,-521,99,-521,38,-521,104,-521,83,-521,88,-521, - 5,0, /* actions: */ 104,-284,83,-284,88,-284,37,-105,87,-97, - 1,0, /* actions: */ 122,860, - 5,0, /* actions: */ 104,-287,83,-287,88,-287,37,-104,87,-96, - /* default action: */ -344, - /* default action: */ -410, - 2,0, /* actions: */ 86,6,29,-530, - 1,2, /* actions: */ 29,402, /* gotos: */ -49,865,-50,862, - 3,2, /* actions: */ 27,369,29,402,22,-341, /* gotos: */ -30,866,-50,401, - 1,0, /* actions: */ 22,867, - /* default action: */ -333, - 49,25, /* actions: */ 118,225,122,228,119,286,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,121,226,120,227,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,131,136,84,287,103,291,98,300,43,335,58,321,51,342,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,465,147,498,64,501,65,504,148,507, /* gotos: */ -13,869,-27,18,-29,19,-69,34,-12,326,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-70,224,-68,284,-25,345,-18,394,-22,415,-23,439,-28,483,-26,484,-19,509,-105,218,-104,472, - 5,2, /* actions: */ 49,13,50,15,86,27,14,28,25,821, /* gotos: */ -121,870,-132,819, - 65,41, /* actions: */ 86,27,14,28,57,43,18,142,59,148,60,153,131,136,118,225,122,228,119,286,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,121,226,120,227,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,84,372,103,291,98,300,43,335,58,321,51,342,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,423,19,430,15,440,16,446,17,451,93,457,44,465,147,498,64,501,65,504,148,507,42,525,33,539,34,541,35,544,36,545,89,591,2,598,27,-529,26,-529,22,-529, /* gotos: */ -4,871,-108,4,-109,5,-132,26,-3,29,-2,31,-10,42,-68,158,-11,352,-14,353,-13,354,-27,18,-29,19,-69,34,-12,355,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-70,371,-25,345,-18,394,-22,415,-23,439,-28,483,-26,484,-19,509,-105,510,-104,520,-7,523,-8,524,-9,543,-99,546,-100,547,-102,589,-103,556, - 3,2, /* actions: */ 27,369,26,868,22,-341, /* gotos: */ -31,872,-30,368, - /* default action: */ -340, - 106,0, /* actions: */ 124,874,134,-102,87,-94,94,-521,118,-521,121,-521,120,-521,122,-521,123,-521,46,-521,45,-521,47,-521,48,-521,62,-521,61,-521,63,-521,128,-521,129,-521,130,-521,146,-521,116,-521,126,-521,111,-521,113,-521,112,-521,114,-521,115,-521,131,-521,119,-521,84,-521,103,-521,98,-521,43,-521,58,-521,51,-521,23,-521,24,-521,30,-521,31,-521,28,-521,32,-521,96,-521,95,-521,19,-521,15,-521,16,-521,17,-521,93,-521,44,-521,64,-521,65,-521,147,-521,148,-521,89,-521,125,-521,90,-521,99,-521,38,-521,88,-521,83,-521,104,-521,141,-521,142,-521,143,-521,144,-521,145,-521,66,-521,139,-521,140,-521,91,-521,67,-521,137,-521,71,-521,138,-521,72,-521,68,-521,69,-521,70,-521,75,-521,76,-521,81,-521,82,-521,73,-521,74,-521,77,-521,78,-521,135,-521,49,-521,50,-521,52,-521,53,-521,54,-521,55,-521,56,-521,86,-521,14,-521,3,-521,22,-521,102,-521,108,-521,27,-521,26,-521,21,-521,29,-521,97,-521,20,-521, - 49,24, /* actions: */ 118,225,121,226,120,227,122,228,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,131,136,119,286,84,287,103,291,98,300,43,335,58,321,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,465,64,501,65,504,147,506,148,507, /* gotos: */ -19,875,-27,876,-105,218,-70,224,-12,326,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-68,284,-69,34,-25,345,-18,394,-22,415,-23,439,-104,472,-29,19,-28,483,-26,484, - 55,0, /* actions: */ 141,162,142,164,143,166,144,168,145,170,66,172,139,174,140,176,91,178,67,180,137,182,71,184,138,186,72,188,68,190,69,192,70,194,75,196,76,198,81,200,82,202,73,204,74,206,77,208,78,210,135,212,49,-206,50,-206,52,-206,53,-206,54,-206,55,-206,56,-206,86,-206,14,-206,3,-206,22,-206,102,-206,108,-206,27,-206,26,-206,21,-206,29,-206,97,-206,20,-206,25,-206,39,-206,136,-206,85,-206,87,-206,105,-206,100,-206,40,-206,101,-206,41,-206, - /* default action: */ -39, - 33,4, /* actions: */ 122,878,118,885,119,571,139,52,140,53,91,54,67,55,68,56,69,57,75,58,76,59,137,60,71,61,138,62,72,63,70,64,81,65,82,66,141,67,142,68,143,69,89,70,144,71,145,72,66,73,147,74,148,75,64,76,65,77,79,78,80,79,92,80,94,468, /* gotos: */ -72,882,-73,568,-40,569,-75,572, - 104,0, /* actions: */ 124,879,88,-286,83,-286,104,-286,141,-286,142,-286,143,-286,144,-286,145,-286,66,-286,139,-286,140,-286,91,-286,67,-286,137,-286,71,-286,138,-286,72,-286,68,-286,69,-286,70,-286,75,-286,76,-286,81,-286,82,-286,73,-286,74,-286,77,-286,78,-286,135,-286,49,-286,50,-286,52,-286,53,-286,54,-286,55,-286,56,-286,86,-286,14,-286,3,-286,22,-286,102,-286,108,-286,27,-286,26,-286,21,-286,29,-286,97,-286,20,-286,134,-103,87,-95,94,-521,118,-521,121,-521,120,-521,122,-521,123,-521,46,-521,45,-521,47,-521,48,-521,62,-521,61,-521,63,-521,128,-521,129,-521,130,-521,146,-521,116,-521,126,-521,111,-521,113,-521,112,-521,114,-521,115,-521,131,-521,119,-521,84,-521,103,-521,98,-521,43,-521,58,-521,51,-521,23,-521,24,-521,30,-521,31,-521,28,-521,32,-521,96,-521,95,-521,19,-521,15,-521,16,-521,17,-521,93,-521,44,-521,64,-521,65,-521,147,-521,148,-521,89,-521,125,-521,90,-521, - 49,24, /* actions: */ 118,225,121,226,120,227,122,228,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,131,136,119,286,84,287,103,291,98,300,43,335,58,321,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,465,64,501,65,504,147,506,148,507, /* gotos: */ -19,880,-27,881,-105,218,-70,224,-12,326,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-68,284,-69,34,-25,345,-18,394,-22,415,-23,439,-104,472,-29,19,-28,483,-26,484, - 55,0, /* actions: */ 141,162,142,164,143,166,144,168,145,170,66,172,139,174,140,176,91,178,67,180,137,182,71,184,138,186,72,188,68,190,69,192,70,194,75,196,76,198,81,200,82,202,73,204,74,206,77,208,78,210,135,212,49,-208,50,-208,52,-208,53,-208,54,-208,55,-208,56,-208,86,-208,14,-208,3,-208,22,-208,102,-208,108,-208,27,-208,26,-208,21,-208,29,-208,97,-208,20,-208,25,-208,39,-208,136,-208,85,-208,87,-208,105,-208,100,-208,40,-208,101,-208,41,-208, - /* default action: */ -40, - 53,3, /* actions: */ 94,468,118,-265,121,-265,120,-265,122,-265,123,-265,46,-265,45,-265,47,-265,48,-265,62,-265,61,-265,63,-265,128,-265,129,-265,130,-265,146,-265,116,-265,126,-265,111,-265,113,-265,112,-265,114,-265,115,-265,131,-265,119,-265,84,-265,103,-265,98,-265,43,-265,58,-265,51,-265,23,-265,24,-265,30,-265,31,-265,28,-265,32,-265,96,-265,95,-265,19,-265,15,-265,16,-265,17,-265,93,-265,44,-265,64,-265,65,-265,147,-265,148,-265,89,-265,125,-265,90,-265, /* gotos: */ -40,567,-44,883,-120,332, - 24,1, /* actions: */ 100,37,40,-69,49,-69,50,-69,52,-69,53,-69,54,-69,55,-69,56,-69,86,-69,14,-69,3,-69,22,-69,102,-69,108,-69,27,-69,26,-69,21,-69,29,-69,97,-69,20,-69,25,-69,39,-69,105,-69, /* gotos: */ -35,884, - /* default action: */ -70, - 106,0, /* actions: */ 124,886,134,-101,87,-93,94,-520,118,-520,121,-520,120,-520,122,-520,123,-520,46,-520,45,-520,47,-520,48,-520,62,-520,61,-520,63,-520,128,-520,129,-520,130,-520,146,-520,116,-520,126,-520,111,-520,113,-520,112,-520,114,-520,115,-520,131,-520,119,-520,84,-520,103,-520,98,-520,43,-520,58,-520,51,-520,23,-520,24,-520,30,-520,31,-520,28,-520,32,-520,96,-520,95,-520,19,-520,15,-520,16,-520,17,-520,93,-520,44,-520,64,-520,65,-520,147,-520,148,-520,89,-520,125,-520,90,-520,99,-524,38,-524,88,-524,83,-524,104,-524,141,-524,142,-524,143,-524,144,-524,145,-524,66,-524,139,-524,140,-524,91,-524,67,-524,137,-524,71,-524,138,-524,72,-524,68,-524,69,-524,70,-524,75,-524,76,-524,81,-524,82,-524,73,-524,74,-524,77,-524,78,-524,135,-524,49,-524,50,-524,52,-524,53,-524,54,-524,55,-524,56,-524,86,-524,14,-524,3,-524,22,-524,102,-524,108,-524,27,-524,26,-524,21,-524,29,-524,97,-524,20,-524, - 49,24, /* actions: */ 118,225,121,226,120,227,122,228,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,131,136,119,286,84,287,103,291,98,300,43,335,58,321,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,465,64,501,65,504,147,506,148,507, /* gotos: */ -19,887,-27,888,-105,218,-70,224,-12,326,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-68,284,-69,34,-25,345,-18,394,-22,415,-23,439,-104,472,-29,19,-28,483,-26,484, - 55,0, /* actions: */ 141,162,142,164,143,166,144,168,145,170,66,172,139,174,140,176,91,178,67,180,137,182,71,184,138,186,72,188,68,190,69,192,70,194,75,196,76,198,81,200,82,202,73,204,74,206,77,208,78,210,135,212,49,-207,50,-207,52,-207,53,-207,54,-207,55,-207,56,-207,86,-207,14,-207,3,-207,22,-207,102,-207,108,-207,27,-207,26,-207,21,-207,29,-207,97,-207,20,-207,25,-207,39,-207,136,-207,85,-207,87,-207,105,-207,100,-207,40,-207,101,-207,41,-207, - /* default action: */ -41, - 54,28, /* actions: */ 118,225,121,226,120,227,122,228,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,131,136,119,286,84,287,103,291,98,300,43,335,58,321,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,465,64,501,65,504,147,506,148,507,89,515,125,532,90,534,14,-258,105,-258, /* gotos: */ -43,890,-42,471,-20,316,-19,334,-105,218,-70,224,-12,326,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-68,284,-69,34,-25,345,-18,394,-22,415,-23,439,-104,472,-21,527,-51,528,-52,536,-33,537,-29,538, - 2,2, /* actions: */ 14,314,105,-531, /* gotos: */ -113,891,-114,562, - 53,0, /* actions: */ 124,892,99,-403,38,-403,88,-403,83,-403,104,-403,141,-403,142,-403,143,-403,144,-403,145,-403,66,-403,139,-403,140,-403,91,-403,67,-403,137,-403,71,-403,138,-403,72,-403,68,-403,69,-403,70,-403,75,-403,76,-403,81,-403,82,-403,73,-403,74,-403,77,-403,78,-403,135,-403,49,-403,50,-403,52,-403,53,-403,54,-403,55,-403,56,-403,86,-403,14,-403,3,-403,22,-403,102,-403,108,-403,27,-403,26,-403,21,-403,29,-403,97,-403,20,-403,134,-99,87,-91, - 49,24, /* actions: */ 118,225,121,226,120,227,122,228,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,131,136,119,286,84,287,103,291,98,300,43,335,58,321,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,465,64,501,65,504,147,506,148,507, /* gotos: */ -19,242,-27,893,-105,218,-70,224,-12,326,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-68,284,-69,34,-25,345,-18,394,-22,415,-23,439,-104,472,-29,19,-28,483,-26,484, - /* default action: */ -37, - 115,0, /* actions: */ 124,895,134,-100,94,-520,118,-520,121,-520,120,-520,122,-520,123,-520,46,-520,45,-520,47,-520,48,-520,62,-520,61,-520,63,-520,128,-520,129,-520,130,-520,146,-520,116,-520,126,-520,111,-520,113,-520,112,-520,114,-520,115,-520,131,-520,119,-520,84,-520,103,-520,98,-520,43,-520,58,-520,51,-520,23,-520,24,-520,30,-520,31,-520,28,-520,32,-520,96,-520,95,-520,19,-520,15,-520,16,-520,17,-520,93,-520,44,-520,64,-520,65,-520,147,-520,148,-520,89,-520,125,-520,90,-520,99,-520,38,-520,88,-520,83,-520,104,-520,141,-520,142,-520,143,-520,144,-520,145,-520,66,-520,139,-520,140,-520,91,-520,67,-520,137,-520,71,-520,138,-520,72,-520,68,-520,69,-520,70,-520,75,-520,76,-520,81,-520,82,-520,73,-520,74,-520,77,-520,78,-520,135,-520,49,-520,50,-520,52,-520,53,-520,54,-520,55,-520,56,-520,86,-520,14,-520,3,-520,22,-520,102,-520,108,-520,27,-520,26,-520,21,-520,29,-520,97,-520,20,-520,25,-520,39,-520,85,-520,87,-520,105,-520,100,-520,40,-520,136,-520,101,-520,41,-520, - 49,20, /* actions: */ 118,225,121,226,120,227,122,228,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,131,136,119,286,84,287,103,291,98,300,43,308,58,321,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,503,64,501,65,504,147,506,148,507, /* gotos: */ -19,360,-105,218,-70,224,-12,237,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-68,284,-69,475,-25,345,-18,394,-22,415,-23,439,-104,472, - 115,0, /* actions: */ 124,897,134,-102,94,-521,118,-521,121,-521,120,-521,122,-521,123,-521,46,-521,45,-521,47,-521,48,-521,62,-521,61,-521,63,-521,128,-521,129,-521,130,-521,146,-521,116,-521,126,-521,111,-521,113,-521,112,-521,114,-521,115,-521,131,-521,119,-521,84,-521,103,-521,98,-521,43,-521,58,-521,51,-521,23,-521,24,-521,30,-521,31,-521,28,-521,32,-521,96,-521,95,-521,19,-521,15,-521,16,-521,17,-521,93,-521,44,-521,64,-521,65,-521,147,-521,148,-521,89,-521,125,-521,90,-521,99,-521,38,-521,88,-521,83,-521,104,-521,141,-521,142,-521,143,-521,144,-521,145,-521,66,-521,139,-521,140,-521,91,-521,67,-521,137,-521,71,-521,138,-521,72,-521,68,-521,69,-521,70,-521,75,-521,76,-521,81,-521,82,-521,73,-521,74,-521,77,-521,78,-521,135,-521,49,-521,50,-521,52,-521,53,-521,54,-521,55,-521,56,-521,86,-521,14,-521,3,-521,22,-521,102,-521,108,-521,27,-521,26,-521,21,-521,29,-521,97,-521,20,-521,25,-521,39,-521,85,-521,87,-521,105,-521,100,-521,40,-521,136,-521,101,-521,41,-521, - 49,20, /* actions: */ 118,225,121,226,120,227,122,228,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,131,136,119,286,84,287,103,291,98,300,43,308,58,321,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,503,64,501,65,504,147,506,148,507, /* gotos: */ -19,875,-105,218,-70,224,-12,237,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-68,284,-69,475,-25,345,-18,394,-22,415,-23,439,-104,472, - 33,4, /* actions: */ 122,899,118,901,119,571,139,52,140,53,91,54,67,55,68,56,69,57,75,58,76,59,137,60,71,61,138,62,72,63,70,64,81,65,82,66,141,67,142,68,143,69,89,70,144,71,145,72,66,73,147,74,148,75,64,76,65,77,79,78,80,79,92,80,94,468, /* gotos: */ -72,882,-73,568,-40,569,-75,572, - 113,0, /* actions: */ 124,900,88,-286,83,-286,104,-286,141,-286,142,-286,143,-286,144,-286,145,-286,66,-286,139,-286,140,-286,91,-286,67,-286,137,-286,71,-286,138,-286,72,-286,68,-286,69,-286,70,-286,75,-286,76,-286,81,-286,82,-286,73,-286,74,-286,77,-286,78,-286,135,-286,49,-286,50,-286,52,-286,53,-286,54,-286,55,-286,56,-286,86,-286,14,-286,3,-286,22,-286,102,-286,108,-286,27,-286,26,-286,21,-286,29,-286,97,-286,20,-286,25,-286,39,-286,136,-286,85,-286,87,-286,105,-286,100,-286,40,-286,101,-286,41,-286,134,-103,94,-521,118,-521,121,-521,120,-521,122,-521,123,-521,46,-521,45,-521,47,-521,48,-521,62,-521,61,-521,63,-521,128,-521,129,-521,130,-521,146,-521,116,-521,126,-521,111,-521,113,-521,112,-521,114,-521,115,-521,131,-521,119,-521,84,-521,103,-521,98,-521,43,-521,58,-521,51,-521,23,-521,24,-521,30,-521,31,-521,28,-521,32,-521,96,-521,95,-521,19,-521,15,-521,16,-521,17,-521,93,-521,44,-521,64,-521,65,-521,147,-521,148,-521,89,-521,125,-521,90,-521, - 49,20, /* actions: */ 118,225,121,226,120,227,122,228,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,131,136,119,286,84,287,103,291,98,300,43,308,58,321,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,503,64,501,65,504,147,506,148,507, /* gotos: */ -19,880,-105,218,-70,224,-12,237,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-68,284,-69,475,-25,345,-18,394,-22,415,-23,439,-104,472, - 115,0, /* actions: */ 124,902,134,-101,94,-520,118,-520,121,-520,120,-520,122,-520,123,-520,46,-520,45,-520,47,-520,48,-520,62,-520,61,-520,63,-520,128,-520,129,-520,130,-520,146,-520,116,-520,126,-520,111,-520,113,-520,112,-520,114,-520,115,-520,131,-520,119,-520,84,-520,103,-520,98,-520,43,-520,58,-520,51,-520,23,-520,24,-520,30,-520,31,-520,28,-520,32,-520,96,-520,95,-520,19,-520,15,-520,16,-520,17,-520,93,-520,44,-520,64,-520,65,-520,147,-520,148,-520,89,-520,125,-520,90,-520,99,-524,38,-524,88,-524,83,-524,104,-524,141,-524,142,-524,143,-524,144,-524,145,-524,66,-524,139,-524,140,-524,91,-524,67,-524,137,-524,71,-524,138,-524,72,-524,68,-524,69,-524,70,-524,75,-524,76,-524,81,-524,82,-524,73,-524,74,-524,77,-524,78,-524,135,-524,49,-524,50,-524,52,-524,53,-524,54,-524,55,-524,56,-524,86,-524,14,-524,3,-524,22,-524,102,-524,108,-524,27,-524,26,-524,21,-524,29,-524,97,-524,20,-524,25,-524,39,-524,85,-524,87,-524,105,-524,100,-524,40,-524,136,-524,101,-524,41,-524, - 49,20, /* actions: */ 118,225,121,226,120,227,122,228,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,131,136,119,286,84,287,103,291,98,300,43,308,58,321,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,503,64,501,65,504,147,506,148,507, /* gotos: */ -19,887,-105,218,-70,224,-12,237,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-68,284,-69,475,-25,345,-18,394,-22,415,-23,439,-104,472, - 55,0, /* actions: */ 141,162,142,164,143,166,144,168,145,170,66,172,139,174,140,176,91,178,67,180,137,182,71,184,138,186,72,188,68,190,69,192,70,194,75,196,76,198,81,200,82,202,73,204,74,206,77,208,78,210,135,212,49,-245,50,-245,52,-245,53,-245,54,-245,55,-245,56,-245,86,-245,14,-245,3,-245,22,-245,102,-245,108,-245,27,-245,26,-245,21,-245,29,-245,97,-245,20,-245,25,-245,39,-245,136,-245,85,-245,87,-245,105,-245,100,-245,40,-245,101,-245,41,-245, - 25,1, /* actions: */ 87,530,14,-270,105,-270,97,-270,100,-270,40,-270,49,-270,50,-270,52,-270,53,-270,54,-270,55,-270,56,-270,86,-270,3,-270,22,-270,102,-270,108,-270,27,-270,26,-270,21,-270,29,-270,20,-270,25,-270,39,-270, /* gotos: */ -34,905, - /* default action: */ -261, - /* default action: */ -536, - 3,1, /* actions: */ 87,305,14,906,105,-535, /* gotos: */ -119,908, - /* default action: */ -253, - 3,1, /* actions: */ 87,305,14,906,105,-535, /* gotos: */ -119,910, - /* default action: */ -254, - 58,0, /* actions: */ 66,912,88,-452,83,-452,104,-452,141,-452,142,-452,143,-452,144,-452,145,-452,139,-452,140,-452,91,-452,67,-452,137,-452,71,-452,138,-452,72,-452,68,-452,69,-452,70,-452,75,-452,76,-452,81,-452,82,-452,73,-452,74,-452,77,-452,78,-452,135,-452,49,-452,50,-452,52,-452,53,-452,54,-452,55,-452,56,-452,86,-452,14,-452,3,-452,22,-452,102,-452,108,-452,27,-452,26,-452,21,-452,29,-452,97,-452,20,-452,25,-452,39,-452,136,-452,85,-452,87,-452,105,-452,100,-452,40,-452,101,-452,41,-452, - 49,20, /* actions: */ 118,225,121,226,120,227,122,228,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,131,136,119,286,84,287,103,291,98,300,43,308,58,321,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,503,64,501,65,504,147,506,148,507, /* gotos: */ -19,913,-105,218,-70,224,-12,237,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-68,284,-69,475,-25,345,-18,394,-22,415,-23,439,-104,472, - 55,0, /* actions: */ 141,-218,142,-218,143,-218,144,-218,145,-218,66,172,139,-218,140,-218,91,-218,67,-218,137,-218,71,-218,138,-218,72,-218,68,-218,69,-218,70,-218,75,-218,76,-218,81,-218,82,-218,73,-218,74,-218,77,-218,78,-218,135,-218,49,-218,50,-218,52,-218,53,-218,54,-218,55,-218,56,-218,86,-218,14,-218,3,-218,22,-218,102,-218,108,-218,27,-218,26,-218,21,-218,29,-218,97,-218,20,-218,25,-218,39,-218,136,-218,85,-218,87,-218,105,-218,100,-218,40,-218,101,-218,41,-218, - 58,0, /* actions: */ 66,915,88,-453,83,-453,104,-453,141,-453,142,-453,143,-453,144,-453,145,-453,139,-453,140,-453,91,-453,67,-453,137,-453,71,-453,138,-453,72,-453,68,-453,69,-453,70,-453,75,-453,76,-453,81,-453,82,-453,73,-453,74,-453,77,-453,78,-453,135,-453,49,-453,50,-453,52,-453,53,-453,54,-453,55,-453,56,-453,86,-453,14,-453,3,-453,22,-453,102,-453,108,-453,27,-453,26,-453,21,-453,29,-453,97,-453,20,-453,25,-453,39,-453,136,-453,85,-453,87,-453,105,-453,100,-453,40,-453,101,-453,41,-453, - 49,20, /* actions: */ 118,225,121,226,120,227,122,228,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,131,136,119,286,84,287,103,291,98,300,43,308,58,321,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,503,64,501,65,504,147,506,148,507, /* gotos: */ -19,916,-105,218,-70,224,-12,237,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-68,284,-69,475,-25,345,-18,394,-22,415,-23,439,-104,472, - 55,0, /* actions: */ 141,-219,142,-219,143,-219,144,-219,145,-219,66,172,139,-219,140,-219,91,-219,67,-219,137,-219,71,-219,138,-219,72,-219,68,-219,69,-219,70,-219,75,-219,76,-219,81,-219,82,-219,73,-219,74,-219,77,-219,78,-219,135,-219,49,-219,50,-219,52,-219,53,-219,54,-219,55,-219,56,-219,86,-219,14,-219,3,-219,22,-219,102,-219,108,-219,27,-219,26,-219,21,-219,29,-219,97,-219,20,-219,25,-219,39,-219,136,-219,85,-219,87,-219,105,-219,100,-219,40,-219,101,-219,41,-219, - 33,4, /* actions: */ 122,899,118,901,119,571,139,52,140,53,91,54,67,55,68,56,69,57,75,58,76,59,137,60,71,61,138,62,72,63,70,64,81,65,82,66,141,67,142,68,143,69,89,70,144,71,145,72,66,73,147,74,148,75,64,76,65,77,79,78,80,79,92,80,94,468, /* gotos: */ -72,566,-73,568,-40,569,-75,572, - 33,3, /* actions: */ 118,894,122,896,119,492,139,52,140,53,91,54,67,55,68,56,69,57,75,58,76,59,137,60,71,61,138,62,72,63,70,64,81,65,82,66,141,67,142,68,143,69,89,70,144,71,145,72,66,73,147,74,148,75,64,76,65,77,79,78,80,79,92,80,94,468, /* gotos: */ -72,574,-40,357,-75,493, - /* default action: */ -27, - /* default action: */ -28, - /* default action: */ -29, - 2,1, /* actions: */ 14,314,136,-531, /* gotos: */ -114,923, - 1,0, /* actions: */ 136,924, - 54,21, /* actions: */ 118,225,121,226,120,227,122,228,123,229,46,230,45,231,47,232,48,233,62,234,61,235,63,236,128,244,129,245,130,246,146,247,116,126,126,257,111,254,113,260,112,264,114,268,115,277,131,136,119,286,84,287,103,291,98,300,43,308,58,321,51,337,23,362,24,374,30,380,31,387,28,395,32,406,96,416,95,420,19,430,15,440,16,446,17,451,93,457,44,503,64,501,65,504,147,506,148,507,42,919,33,920,34,921,35,544,36,545, /* gotos: */ -19,925,-9,926,-105,218,-70,224,-12,237,-65,243,-66,251,-57,252,-56,258,-58,259,-64,263,-62,267,-63,276,-16,283,-68,284,-69,475,-25,345,-18,394,-22,415,-23,439,-104,472, - 55,0, /* actions: */ 141,162,142,164,143,166,144,168,145,170,66,172,139,174,140,176,91,178,67,180,137,182,71,184,138,186,72,188,68,190,69,192,70,194,75,196,76,198,81,200,82,202,73,204,74,206,77,208,78,210,135,212,49,-247,50,-247,52,-247,53,-247,54,-247,55,-247,56,-247,86,-247,14,-247,3,-247,22,-247,102,-247,108,-247,27,-247,26,-247,21,-247,29,-247,97,-247,20,-247,25,-247,39,-247,136,-247,85,-247,87,-247,105,-247,100,-247,40,-247,101,-247,41,-247, - /* default action: */ -249, - /* default action: */ -242, - /* default action: */ -241, - /* default action: */ -120, - /* default action: */ -121, - /* default action: */ -122, - /* default action: */ -123, - /* default action: */ -124, - 2,1, /* actions: */ 120,935,131,136, /* gotos: */ -68,936, - /* default action: */ -20, - /* default action: */ -21, - /* default action: */ -53, - }); - - tables.Rules = new int[] {7012354, 65537, 262145, 262147, 262146, 196609, 196611, 196610, 131073, 131074, 7208960, 131077, 7274496, 131077, 131075, 131073, 131073, 7340032, 655364, 655363, 655363, 458753, 458753, 524290, 524290, 524290, 589825, 589825, 589825, 589825, 589825, 917505, 917505, 917507, 917507, 917507, 917510, 917509, 917509, 917509, 917509, 917507, 917507, 917507, 720899, 720899, 720899, 720899, 720899, 851969, 851971, 851971, 851971, 851971, 851971, 851970, 851969, 1769473, 1769473, 1835009, 1835012, 1835012, 7536640, 2293765, 1900546, 1900547, 1900548, 1900549, 1900548, 1900549, 1900546, 1900546, 6488067, 6488065, 6488066, 6488067, 6488069, 6488066, 6488068, 6488068, 6488067, 6488066, 6488065, 6553603, 6553602, 6619139, 6619137, 6684673, 6684675, 6750209, 6750212, 6750211, 6750211, 6750211, 6750211, 6750210, 6750209, 6881281, 6881284, 6881283, 6881283, 6881283, 6881283, 6881282, 6881281, 4849665, 4849665, 2949122, 2949121, 2949123, 4980737, 4980737, 4980737, 4980737, 4980737, 4390913, 4390913, 4325378, 4325379, 4653057, 4653057, 4653057, 4653057, 4653057, 2097153, 7733248, 2097156, 4915201, 4915201, 4915201, 4915201, 4915201, 4915201, 4915201, 4915201, 4915201, 4915201, 4915201, 4915201, 4915201, 4915201, 4915201, 4915201, 4915201, 4915201, 4915201, 4915201, 4915201, 4915201, 4915201, 4915201, 4915201, 4915201, 4915201, 4915201, 4915201, 7667713, 7667713, 7667713, 7667713, 7667713, 7667713, 7667713, 7667713, 7667713, 7667713, 7667713, 7667713, 7667713, 7667713, 7667713, 7667713, 7667713, 7667713, 7667713, 7667713, 7667713, 7667713, 7667713, 7667713, 7667713, 7667713, 7667713, 7667713, 7667713, 7667713, 7667713, 7667713, 7667713, 7667713, 7667713, 7667713, 7667713, 7667713, 7667713, 7667713, 7667713, 7667713, 7667713, 1245187, 1245189, 1245189, 1245187, 1245190, 1245189, 1245189, 1245189, 1245189, 1245188, 1245187, 1245187, 1245187, 1245187, 1245187, 1245187, 1245187, 1245188, 1245188, 1245188, 1245186, 1245186, 1245187, 1245187, 1245187, 1245187, 1245187, 1245187, 1245187, 1245187, 1245187, 1245187, 1245187, 1245187, 1245187, 1245186, 1245186, 1245187, 1245187, 1245187, 1245187, 1245187, 1245187, 1245187, 1245187, 1245187, 1245190, 1245190, 1245190, 1245190, 1245185, 2555904, 2555906, 2555908, 2555906, 2621443, 2686976, 2686977, 2818048, 2818049, 2752514, 2752516, 2752514, 2752513, 2752513, 7864320, 2883586, 2162690, 2228226, 2228225, 2228224, 1310721, 1310721, 1376258, 1376259, 1376260, 786433, 786433, 786433, 786433, 786433, 786433, 786433, 786433, 786433, 786433, 786435, 786434, 786435, 786434, 786436, 786436, 786435, 786433, 786437, 786436, 786435, 786434, 786433, 786434, 786438, 786438, 7995392, 8126464, 786439, 8192000, 8257536, 786439, 786433, 8323072, 8388608, 786441, 786433, 786433, 8454144, 1441796, 1441795, 1441795, 8519680, 1507334, 8585216, 8716288, 1507336, 8781824, 1507333, 8847360, 1507334, 8978432, 9043968, 1507337, 1507330, 1572868, 1179654, 1179653, 7929857, 7929857, 7929858, 8060929, 8060929, 2031617, 2031621, 1966080, 1966082, 5832705, 5832705, 6225921, 6225923, 6422529, 6422531, 6160385, 6160388, 6160387, 6160390, 6160389, 6160388, 6160387, 6160386, 6160385, 6291457, 6291459, 6356993, 6356995, 5308422, 5308424, 5308420, 5308422, 5308420, 5308418, 5308422, 5308418, 5308420, 5308422, 5308418, 5308420, 5308418, 5308420, 5308417, 5308416, 5111808, 5111809, 5046273, 5046276, 5505024, 5505026, 5439489, 5439491, 9109504, 2490371, 5177348, 5177345, 327683, 327683, 9175040, 2424837, 1703938, 1703940, 1703940, 1638402, 1638404, 1638404, 1638403, 1638403, 1638403, 1638404, 1638402, 1638401, 9240576, 2359301, 9306112, 2359301, 3211265, 3211266, 3276804, 3080192, 3080193, 3014657, 3014658, 3145732, 3145733, 6946816, 6946818, 393216, 393218, 3735553, 3735553, 3735554, 3670019, 3801091, 4194307, 4063234, 4063236, 3932160, 3932163, 3866625, 3866626, 4128770, 4128772, 3997696, 3997699, 3604480, 3604482, 3538945, 3538946, 3538947, 3473409, 3473409, 3473409, 3473409, 4259841, 4259841, 4259841, 4259842, 4259842, 4259842, 4587521, 4587521, 4587521, 4587521, 4587521, 4587521, 4587521, 4587521, 4587521, 4587521, 4587521, 4587521, 1048577, 6815745, 4456449, 983041, 9371648, 983044, 983042, 5242883, 5242882, 5373958, 5373960, 5373956, 5373958, 5373956, 5373958, 5373954, 5373956, 5373958, 5373954, 5373956, 5373954, 5373956, 5373953, 5373952, 5898241, 5898241, 5898241, 5898241, 5898241, 5701635, 5767171, 5570561, 5570563, 5636097, 5636099, 9437185, 9437185, 5963778, 5963777, 9502721, 9502721, 6029314, 6094848, 6094850, 1114113, 9568256, 1114116, 3342337, 3342339, 3407875, 3407874, 4521985, 4521985, 4521985, 4718593, 4718593, 4718593, 4718593, 4784129, 4784129, 4784129, 8912897, 8912897, 7077888, 7077889, 7471104, 7471105, 7602178, 7405570, 7798784, 7798785, 7798785, 8650753, 8650753, 7143425, 7143426, }; - } - -#if DEBUG - private void InitializeMetadata(ParserTables tables) { - tables.NonTerminalNames = new string[] {"", -"program", "stmt", "stmts", "compstmt", - "lambda_body", "ensure_opt", "jump_statement", "jump_statement_with_parameters", - "jump_statement_parameterless", "alias_statement", "conditional_statement", - "primary", "expr", "expression_statement", "superclass", "var_ref", "singleton", - "case_expression", "arg", "args", "compound_rhs", "block_expression", "definition_expression", - "body", "method_call", "block_call", "command_call", "block_command", "command", - "else_opt", "if_tail", "undef_list", "block_reference", "block_reference_opt", - "cmd_brace_block", "brace_block", "do_block", "lambda", "array_items", - "parenthesized_args", "parenthesized_args_opt", "call_args", "call_args_opt", - "command_args", "qualified_module_name", "rescue_clauses", "rescue_clauses_opt", - "rescue_clause", "when_clauses", "when_clause", "maplets", "maplet", "string_embedded_variable", - "string_content", "string_contents", "string", "string_concatenation", - "shell_string", "word", "word_list", "verbatim_word_list", "words", "verbatim_words", - "regexp", "numeric_literal", "symbol", "method_name_or_symbol", "match_reference", - "operation", "variable", "sym", "operation2", "operation3", "module_name", - "op", "method_name", "block_parameters", "block_parameters_opt", "lambda_parameters", - "method_parameters", "block_parameter_list", "parameters", "block_variables", - "block_variables_opt", "default_parameter_list", "default_block_parameter_list", - "default_parameter", "default_block_parameter", "for_parameters", "parameter", - "parameter_array", "block_parameter", "block_parameter_opt", "compound_parameters", - "parameter_list", "compound_parameter_list", "compound_parameter", "parenthesized_parameter", - "compound_lhs", "compound_lhs_nodes", "compound_lhs_tail", "compound_lhs_node", - "compound_lhs_leaf", "var_lhs", "lhs", "exc_var", "$accept", "terms_opt", - "terms", "@1", "@2", "@3", "closing_bracket", "new_line_opt", "@4", "closing_parenthesis", - "reswords", "@5", "trailer", "@6", "then", "@7", "do", "@8", "@9", "@10", - "@11", "@12", "@13", "@14", "@15", "term", "@16", "@17", "@18", "dot_or_colon", - "@19", "@20", "@21", "@22", "@23", "@24", "@25", "array_parameter_mark", - "block_parameter_mark", "@26", }; - tables.RuleRhsSymbols = new short[] { - -1, 3, // 1 - -4, // 2 - -108, // 3 - -109, -3, -108, // 4 - -3, -108, // 5 - -2, // 6 - -3, -109, -2, // 7 - 2, -2, // 8 - -10, // 9 - 18, -32, // 10 - // 11 - 59, -110, 99, -4, 102, // 12 - // 13 - 60, -111, 99, -4, 102, // 14 - -68, 124, -27, // 15 - -11, // 16 - -14, // 17 - // 18 - 57, -67, -112, -67, // 19 - 57, 120, 120, // 20 - 57, 120, -68, // 21 - -8, // 22 - -9, // 23 - 42, -42, // 24 - 33, -42, // 25 - 34, -42, // 26 - 42, // 27 - 33, // 28 - 34, // 29 - 35, // 30 - 36, // 31 - -13, // 32 - -7, // 33 - -105, 134, -27, // 34 - -99, 134, -27, // 35 - -104, 124, -27, // 36 - -12, 104, -43, -113, 124, -27, // 37 - -12, 88, 118, 124, -27, // 38 - -12, 88, 122, 124, -27, // 39 - -12, 83, 122, 124, -27, // 40 - -12, 83, 118, 124, -27, // 41 - -105, 134, -21, // 42 - -99, 134, -19, // 43 - -99, 134, -21, // 44 - -2, 52, -13, // 45 - -2, 53, -13, // 46 - -2, 54, -13, // 47 - -2, 55, -13, // 48 - -2, 56, -2, // 49 - -27, // 50 - -13, 49, -13, // 51 - -13, 50, -13, // 52 - -13, 49, -7, // 53 - -13, 50, -7, // 54 - 51, -114, -13, // 55 - 147, -27, // 56 - -19, // 57 - -29, // 58 - -28, // 59 - -26, // 60 - -26, 88, -72, -44, // 61 - -26, 83, -72, -44, // 62 - // 63 - 100, -115, -78, -4, 102, // 64 - -69, -44, // 65 - -69, -44, -35, // 66 - -12, 88, -72, -44, // 67 - -12, 88, -72, -44, -35, // 68 - -12, 83, -72, -44, // 69 - -12, 83, -72, -44, -35, // 70 - 44, -44, // 71 - 43, -44, // 72 - 95, -99, -116, // 73 - -100, // 74 - -100, -102, // 75 - -100, 89, -103, // 76 - -100, 89, -103, 87, -101, // 77 - -100, 89, // 78 - -100, 89, 87, -101, // 79 - 89, -103, 87, -101, // 80 - 89, 87, -101, // 81 - 89, -103, // 82 - 89, // 83 - -100, -102, 87, // 84 - -102, 87, // 85 - -101, 87, -102, // 86 - -102, // 87 - -103, // 88 - 95, -99, -116, // 89 - -70, // 90 - -12, 104, -43, -113, // 91 - -12, 88, 118, // 92 - -12, 83, 118, // 93 - -12, 88, 122, // 94 - -12, 83, 122, // 95 - 84, 122, // 96 - -68, // 97 - -70, // 98 - -12, 104, -43, -113, // 99 - -12, 88, 118, // 100 - -12, 83, 118, // 101 - -12, 88, 122, // 102 - -12, 83, 122, // 103 - 84, 122, // 104 - -68, // 105 - 122, // 106 - 118, // 107 - 84, -74, // 108 - -74, // 109 - -12, 83, -74, // 110 - 118, // 111 - 122, // 112 - 119, // 113 - -75, // 114 - -117, // 115 - -76, // 116 - -66, // 117 - 116, -71, // 118 - 116, -55, 117, // 119 - -76, // 120 - 121, // 121 - 120, // 122 - 123, // 123 - -68, // 124 - -67, // 125 - // 126 - -32, 87, -118, -67, // 127 - 139, // 128 - 140, // 129 - 91, // 130 - 67, // 131 - 68, // 132 - 69, // 133 - 75, // 134 - 76, // 135 - 137, // 136 - 71, // 137 - 138, // 138 - 72, // 139 - 70, // 140 - 81, // 141 - 82, // 142 - 141, // 143 - 142, // 144 - 143, // 145 - 89, // 146 - 144, // 147 - 145, // 148 - 66, // 149 - 147, // 150 - 148, // 151 - 64, // 152 - 65, // 153 - 79, // 154 - 80, // 155 - 92, // 156 - 61, // 157 - 62, // 158 - 63, // 159 - 59, // 160 - 60, // 161 - 57, // 162 - 49, // 163 - 19, // 164 - 33, // 165 - 28, // 166 - 15, // 167 - 17, // 168 - 58, // 169 - 38, // 170 - 40, // 171 - 27, // 172 - 26, // 173 - 22, // 174 - 21, // 175 - 48, // 176 - 32, // 177 - 37, // 178 - 16, // 179 - 34, // 180 - 46, // 181 - 51, // 182 - 50, // 183 - 35, // 184 - 20, // 185 - 36, // 186 - 42, // 187 - 45, // 188 - 44, // 189 - 25, // 190 - 47, // 191 - 18, // 192 - 29, // 193 - 43, // 194 - 52, // 195 - 53, // 196 - 54, // 197 - 55, // 198 - 56, // 199 - -105, 134, -19, // 200 - -105, 134, -19, 56, -19, // 201 - -105, 134, -19, 56, -9, // 202 - -104, 124, -19, // 203 - -12, 104, -43, -113, 124, -19, // 204 - -12, 88, 118, 124, -19, // 205 - -12, 88, 122, 124, -19, // 206 - -12, 83, 118, 124, -19, // 207 - -12, 83, 122, 124, -19, // 208 - 84, 122, 124, -19, // 209 - -68, 124, -19, // 210 - -19, 141, -19, // 211 - -19, 142, -19, // 212 - -19, 143, -19, // 213 - -19, 144, -19, // 214 - -19, 145, -19, // 215 - -19, 66, -19, // 216 - 146, 128, 66, -19, // 217 - 146, 129, 66, -19, // 218 - 146, 130, 66, -19, // 219 - 64, -19, // 220 - 65, -19, // 221 - -19, 139, -19, // 222 - -19, 140, -19, // 223 - -19, 91, -19, // 224 - -19, 67, -19, // 225 - -19, 137, -19, // 226 - -19, 71, -19, // 227 - -19, 138, -19, // 228 - -19, 72, -19, // 229 - -19, 68, -19, // 230 - -19, 69, -19, // 231 - -19, 70, -19, // 232 - -19, 75, -19, // 233 - -19, 76, -19, // 234 - 147, -19, // 235 - 148, -19, // 236 - -19, 81, -19, // 237 - -19, 82, -19, // 238 - -19, 73, -19, // 239 - -19, 74, -19, // 240 - -19, 73, -9, // 241 - -19, 74, -9, // 242 - -19, 77, -19, // 243 - -19, 78, -19, // 244 - 58, -114, -19, // 245 - -19, 135, -19, -114, 136, -19, // 246 - -19, 135, -9, -114, 136, -19, // 247 - -19, 135, -19, -114, 136, -9, // 248 - -19, 135, -9, -114, 136, -9, // 249 - -12, // 250 - // 251 - -20, -119, // 252 - -20, 87, -51, -119, // 253 - -51, -119, // 254 - 94, -43, -116, // 255 - // 256 - -40, // 257 - // 258 - -42, // 259 - -20, -34, // 260 - -20, 87, -51, -34, // 261 - -51, -34, // 262 - -33, // 263 - -29, // 264 - // 265 - -120, -42, // 266 - 90, -19, // 267 - 87, -33, // 268 - 87, // 269 - // 270 - -19, // 271 - -21, // 272 - 89, -19, // 273 - -20, 87, -19, // 274 - -20, 87, 89, -19, // 275 - -65, // 276 - -66, // 277 - -57, // 278 - -58, // 279 - -64, // 280 - -62, // 281 - -63, // 282 - -16, // 283 - -68, // 284 - 119, // 285 - -12, 83, 122, // 286 - 84, 122, // 287 - 103, -39, 105, // 288 - 98, 102, // 289 - 98, -51, -119, 102, // 290 - 43, 94, -42, -116, // 291 - 43, 94, -116, // 292 - 43, // 293 - 58, -114, 94, -13, -116, // 294 - 51, 94, -13, -116, // 295 - 51, 94, -116, // 296 - -69, -36, // 297 - -25, // 298 - -25, -36, // 299 - 23, -13, -121, -4, -31, 22, // 300 - 24, -13, -121, -4, -30, 22, // 301 - // 302 - // 303 - 30, -122, -13, -123, -124, -4, 22, // 304 - // 305 - // 306 - 31, -125, -13, -123, -126, -4, 22, // 307 - -18, // 308 - // 309 - // 310 - 32, -89, 37, -127, -13, -123, -128, -4, 22, // 311 - -22, // 312 - -23, // 313 - // 314 - 96, -13, -129, -116, // 315 - 95, -4, 97, // 316 - 19, -24, 22, // 317 - // 318 - 15, -45, -15, -130, -24, 22, // 319 - // 320 - // 321 - 15, 81, -13, -131, -132, -133, -24, 22, // 322 - // 323 - 16, -45, -134, -24, 22, // 324 - // 325 - 17, -76, -135, -80, -24, 22, // 326 - // 327 - // 328 - 17, -17, -136, -137, -76, -138, -80, -24, 22, // 329 - 93, -38, // 330 - -4, -47, -30, -6, // 331 - 28, -13, -108, -49, -30, 22, // 332 - 28, -108, -49, -30, 22, // 333 - -132, // 334 - 25, // 335 - -132, 25, // 336 - -132, // 337 - 39, // 338 - -30, // 339 - 26, -13, -121, -4, -31, // 340 - // 341 - 27, -4, // 342 - -105, // 343 - -99, // 344 - -98, // 345 - -95, 87, -98, // 346 - -90, // 347 - 95, -94, -116, // 348 - -96, // 349 - -96, 87, 89, -90, // 350 - -96, 87, 89, // 351 - -96, 87, 89, -90, 87, -96, // 352 - -96, 87, 89, 87, -96, // 353 - 89, -90, 87, -96, // 354 - 89, 87, -96, // 355 - 89, -90, // 356 - 89, // 357 - -97, // 358 - -96, 87, -97, // 359 - -90, // 360 - 95, -94, -116, // 361 - -95, 87, -86, 87, -91, -93, // 362 - -95, 87, -86, 87, -91, 87, -95, -93, // 363 - -95, 87, -86, -93, // 364 - -95, 87, -86, 87, -95, -93, // 365 - -95, 87, -91, -93, // 366 - -95, 87, // 367 - -95, 87, -91, 87, -95, -93, // 368 - -95, -93, // 369 - -86, 87, -91, -93, // 370 - -86, 87, -91, 87, -95, -93, // 371 - -86, -93, // 372 - -86, 87, -95, -93, // 373 - -91, -93, // 374 - -91, 87, -95, -93, // 375 - -92, // 376 - // 377 - // 378 - -77, // 379 - 74, // 380 - 139, -81, -84, 139, // 381 - // 382 - 86, -83, // 383 - -90, // 384 - -83, 87, -90, // 385 - // 386 - -139, -79, -5, // 387 - 94, -82, -84, -116, // 388 - -82, // 389 - 101, -4, 102, // 390 - 41, -4, 22, // 391 - // 392 - 40, -140, -78, -4, 22, // 393 - -29, -37, // 394 - -26, 88, -72, -41, // 395 - -26, 83, -72, -41, // 396 - -69, -40, // 397 - -12, 88, -72, -41, // 398 - -12, 83, -72, -40, // 399 - -12, 83, -73, // 400 - -12, 88, -40, // 401 - -12, 83, -40, // 402 - -12, 104, -43, -113, // 403 - 44, -40, // 404 - 44, // 405 - // 406 - 99, -141, -78, -4, 102, // 407 - // 408 - 38, -142, -78, -4, 22, // 409 - -50, // 410 - -49, -50, // 411 - 29, -20, -121, -4, // 412 - // 413 - -46, // 414 - -48, // 415 - -46, -48, // 416 - 20, -106, -121, -4, // 417 - 20, -20, -106, -121, -4, // 418 - // 419 - 85, -105, // 420 - // 421 - 21, -4, // 422 - 126, // 423 - -56, // 424 - -57, -56, // 425 - 111, -55, 117, // 426 - 113, -55, 117, // 427 - 112, -55, 132, // 428 - 114, 117, // 429 - 114, -60, -59, 117, // 430 - // 431 - -60, -59, 13, // 432 - -54, // 433 - -59, -54, // 434 - 115, 117, // 435 - 115, -61, 127, 117, // 436 - // 437 - -61, 127, 13, // 438 - // 439 - -55, -54, // 440 - 127, // 441 - 106, -53, // 442 - 107, -4, 108, // 443 - 120, // 444 - -68, // 445 - 121, // 446 - 123, // 447 - 128, // 448 - 129, // 449 - 130, // 450 - 146, 128, // 451 - 146, 129, // 452 - 146, 130, // 453 - 118, // 454 - 121, // 455 - 120, // 456 - 122, // 457 - 123, // 458 - 46, // 459 - 45, // 460 - 47, // 461 - 48, // 462 - 62, // 463 - 61, // 464 - 63, // 465 - -70, // 466 - -70, // 467 - 131, // 468 - -132, // 469 - // 470 - 138, -143, -13, -132, // 471 - 2, -132, // 472 - 94, -82, -116, // 473 - -82, -132, // 474 - -95, 87, -85, 87, -91, -93, // 475 - -95, 87, -85, 87, -91, 87, -95, -93, // 476 - -95, 87, -85, -93, // 477 - -95, 87, -85, 87, -95, -93, // 478 - -95, 87, -91, -93, // 479 - -95, 87, -91, 87, -95, -93, // 480 - -95, -93, // 481 - -85, 87, -91, -93, // 482 - -85, 87, -91, 87, -95, -93, // 483 - -85, -93, // 484 - -85, 87, -95, -93, // 485 - -91, -93, // 486 - -91, 87, -95, -93, // 487 - -92, // 488 - // 489 - 122, // 490 - 121, // 491 - 120, // 492 - 123, // 493 - 118, // 494 - 118, 134, -19, // 495 - 118, 134, -12, // 496 - -87, // 497 - -85, 87, -87, // 498 - -88, // 499 - -86, 87, -88, // 500 - 143, // 501 - 89, // 502 - -144, -90, // 503 - -144, // 504 - 91, // 505 - 90, // 506 - -145, -90, // 507 - // 508 - 87, -92, // 509 - -16, // 510 - // 511 - 94, -146, -13, -116, // 512 - -52, // 513 - -51, 87, -52, // 514 - -19, 85, -19, // 515 - 125, -19, // 516 - 118, // 517 - 122, // 518 - 119, // 519 - 118, // 520 - 122, // 521 - 119, // 522 - -75, // 523 - 118, // 524 - 119, // 525 - -75, // 526 - 88, // 527 - 83, // 528 - // 529 - -109, // 530 - // 531 - 14, // 532 - -114, 97, // 533 - -114, 105, // 534 - // 535 - 14, // 536 - 87, // 537 - 86, // 538 - 14, // 539 - -132, // 540 - -109, 86, // 541 - }; - } -#endif - - private void DoAction(int action) - { - switch (action) - { - default: DoDefaultAction(); return; - case 1: _1(); return; - case 2: _2(); return; - case 3: _3(); return; - case 4: _4(); return; - case 5: _5(); return; - case 6: _6(); return; - case 7: _7(); return; - case 9: _9(); return; - case 10: _10(); return; - case 11: _11(); return; - case 12: _12(); return; - case 13: _13(); return; - case 14: _14(); return; - case 15: _15(); return; - case 16: _16(); return; - case 17: _17(); return; - case 18: _18(); return; - case 19: _19(); return; - case 20: _20(); return; - case 21: _21(); return; - case 22: _22(); return; - case 23: _23(); return; - case 24: _24(); return; - case 25: _25(); return; - case 26: _26(); return; - case 27: _27(); return; - case 28: _28(); return; - case 29: _29(); return; - case 30: _30(); return; - case 31: _31(); return; - case 32: _32(); return; - case 33: _33(); return; - case 34: _34(); return; - case 35: _35(); return; - case 36: _36(); return; - case 37: _37(); return; - case 38: _38(); return; - case 39: _39(); return; - case 40: _40(); return; - case 41: _41(); return; - case 42: _42(); return; - case 43: _43(); return; - case 44: _44(); return; - case 45: _45(); return; - case 46: _46(); return; - case 47: _47(); return; - case 48: _48(); return; - case 50: _50(); return; - case 51: _51(); return; - case 52: _52(); return; - case 53: _53(); return; - case 54: _54(); return; - case 55: _55(); return; - case 57: _57(); return; - case 58: _58(); return; - case 59: _59(); return; - case 60: _60(); return; - case 61: _61(); return; - case 62: _62(); return; - case 63: _63(); return; - case 64: _64(); return; - case 65: _65(); return; - case 66: _66(); return; - case 67: _67(); return; - case 68: _68(); return; - case 69: _69(); return; - case 70: _70(); return; - case 71: _71(); return; - case 72: _72(); return; - case 73: _73(); return; - case 74: _74(); return; - case 75: _75(); return; - case 76: _76(); return; - case 77: _77(); return; - case 78: _78(); return; - case 79: _79(); return; - case 80: _80(); return; - case 81: _81(); return; - case 82: _82(); return; - case 83: _83(); return; - case 84: _84(); return; - case 85: _85(); return; - case 86: _86(); return; - case 87: _87(); return; - case 88: _88(); return; - case 89: _89(); return; - case 90: _90(); return; - case 91: _91(); return; - case 92: _92(); return; - case 93: _93(); return; - case 94: _94(); return; - case 95: _95(); return; - case 96: _96(); return; - case 97: _97(); return; - case 98: _98(); return; - case 99: _99(); return; - case 100: _100(); return; - case 101: _101(); return; - case 102: _102(); return; - case 103: _103(); return; - case 104: _104(); return; - case 105: _105(); return; - case 106: _106(); return; - case 107: _107(); return; - case 108: _108(); return; - case 109: _109(); return; - case 110: _110(); return; - case 111: _111(); return; - case 112: _112(); return; - case 113: _113(); return; - case 114: _114(); return; - case 115: _115(); return; - case 116: _116(); return; - case 117: _117(); return; - case 118: _118(); return; - case 121: _121(); return; - case 123: _123(); return; - case 124: _124(); return; - case 125: _125(); return; - case 126: _126(); return; - case 127: _127(); return; - case 128: _128(); return; - case 129: _129(); return; - case 130: _130(); return; - case 131: _131(); return; - case 132: _132(); return; - case 133: _133(); return; - case 134: _134(); return; - case 135: _135(); return; - case 136: _136(); return; - case 137: _137(); return; - case 138: _138(); return; - case 139: _139(); return; - case 140: _140(); return; - case 141: _141(); return; - case 142: _142(); return; - case 143: _143(); return; - case 144: _144(); return; - case 145: _145(); return; - case 146: _146(); return; - case 147: _147(); return; - case 148: _148(); return; - case 149: _149(); return; - case 150: _150(); return; - case 151: _151(); return; - case 152: _152(); return; - case 153: _153(); return; - case 154: _154(); return; - case 155: _155(); return; - case 199: _199(); return; - case 200: _200(); return; - case 201: _201(); return; - case 202: _202(); return; - case 203: _203(); return; - case 204: _204(); return; - case 205: _205(); return; - case 206: _206(); return; - case 207: _207(); return; - case 208: _208(); return; - case 209: _209(); return; - case 210: _210(); return; - case 211: _211(); return; - case 212: _212(); return; - case 213: _213(); return; - case 214: _214(); return; - case 215: _215(); return; - case 216: _216(); return; - case 217: _217(); return; - case 218: _218(); return; - case 219: _219(); return; - case 220: _220(); return; - case 221: _221(); return; - case 222: _222(); return; - case 223: _223(); return; - case 224: _224(); return; - case 225: _225(); return; - case 226: _226(); return; - case 227: _227(); return; - case 228: _228(); return; - case 229: _229(); return; - case 230: _230(); return; - case 231: _231(); return; - case 232: _232(); return; - case 233: _233(); return; - case 234: _234(); return; - case 235: _235(); return; - case 236: _236(); return; - case 237: _237(); return; - case 238: _238(); return; - case 239: _239(); return; - case 240: _240(); return; - case 241: _241(); return; - case 242: _242(); return; - case 243: _243(); return; - case 244: _244(); return; - case 245: _245(); return; - case 246: _246(); return; - case 247: _247(); return; - case 248: _248(); return; - case 249: _249(); return; - case 250: _250(); return; - case 251: _251(); return; - case 252: _252(); return; - case 253: _253(); return; - case 254: _254(); return; - case 255: _255(); return; - case 256: _256(); return; - case 257: _257(); return; - case 258: _258(); return; - case 259: _259(); return; - case 260: _260(); return; - case 261: _261(); return; - case 262: _262(); return; - case 263: _263(); return; - case 264: _264(); return; - case 265: _265(); return; - case 266: _266(); return; - case 267: _267(); return; - case 268: _268(); return; - case 269: _269(); return; - case 270: _270(); return; - case 271: _271(); return; - case 272: _272(); return; - case 273: _273(); return; - case 274: _274(); return; - case 276: _276(); return; - case 277: _277(); return; - case 283: _283(); return; - case 284: _284(); return; - case 285: _285(); return; - case 286: _286(); return; - case 287: _287(); return; - case 288: _288(); return; - case 289: _289(); return; - case 290: _290(); return; - case 291: _291(); return; - case 292: _292(); return; - case 293: _293(); return; - case 294: _294(); return; - case 295: _295(); return; - case 296: _296(); return; - case 298: _298(); return; - case 299: _299(); return; - case 300: _300(); return; - case 301: _301(); return; - case 302: _302(); return; - case 303: _303(); return; - case 304: _304(); return; - case 305: _305(); return; - case 306: _306(); return; - case 308: _308(); return; - case 309: _309(); return; - case 310: _310(); return; - case 311: _311(); return; - case 312: _312(); return; - case 313: _313(); return; - case 314: _314(); return; - case 315: _315(); return; - case 316: _316(); return; - case 317: _317(); return; - case 318: _318(); return; - case 319: _319(); return; - case 320: _320(); return; - case 321: _321(); return; - case 322: _322(); return; - case 323: _323(); return; - case 324: _324(); return; - case 325: _325(); return; - case 326: _326(); return; - case 327: _327(); return; - case 328: _328(); return; - case 329: _329(); return; - case 330: _330(); return; - case 331: _331(); return; - case 332: _332(); return; - case 338: _338(); return; - case 339: _339(); return; - case 340: _340(); return; - case 341: _341(); return; - case 342: _342(); return; - case 343: _343(); return; - case 344: _344(); return; - case 345: _345(); return; - case 346: _346(); return; - case 347: _347(); return; - case 348: _348(); return; - case 349: _349(); return; - case 350: _350(); return; - case 351: _351(); return; - case 352: _352(); return; - case 353: _353(); return; - case 354: _354(); return; - case 355: _355(); return; - case 356: _356(); return; - case 357: _357(); return; - case 358: _358(); return; - case 359: _359(); return; - case 360: _360(); return; - case 361: _361(); return; - case 362: _362(); return; - case 363: _363(); return; - case 364: _364(); return; - case 365: _365(); return; - case 366: _366(); return; - case 367: _367(); return; - case 368: _368(); return; - case 369: _369(); return; - case 370: _370(); return; - case 371: _371(); return; - case 372: _372(); return; - case 373: _373(); return; - case 374: _374(); return; - case 375: _375(); return; - case 376: _376(); return; - case 377: _377(); return; - case 378: _378(); return; - case 379: _379(); return; - case 380: _380(); return; - case 381: _381(); return; - case 385: _385(); return; - case 386: _386(); return; - case 387: _387(); return; - case 388: _388(); return; - case 389: _389(); return; - case 390: _390(); return; - case 391: _391(); return; - case 392: _392(); return; - case 393: _393(); return; - case 394: _394(); return; - case 395: _395(); return; - case 396: _396(); return; - case 397: _397(); return; - case 398: _398(); return; - case 399: _399(); return; - case 400: _400(); return; - case 401: _401(); return; - case 402: _402(); return; - case 403: _403(); return; - case 404: _404(); return; - case 405: _405(); return; - case 406: _406(); return; - case 407: _407(); return; - case 408: _408(); return; - case 409: _409(); return; - case 410: _410(); return; - case 411: _411(); return; - case 412: _412(); return; - case 414: _414(); return; - case 415: _415(); return; - case 416: _416(); return; - case 417: _417(); return; - case 418: _418(); return; - case 419: _419(); return; - case 420: _420(); return; - case 421: _421(); return; - case 422: _422(); return; - case 423: _423(); return; - case 424: _424(); return; - case 425: _425(); return; - case 426: _426(); return; - case 427: _427(); return; - case 428: _428(); return; - case 429: _429(); return; - case 430: _430(); return; - case 431: _431(); return; - case 432: _432(); return; - case 433: _433(); return; - case 434: _434(); return; - case 435: _435(); return; - case 436: _436(); return; - case 437: _437(); return; - case 438: _438(); return; - case 439: _439(); return; - case 440: _440(); return; - case 441: _441(); return; - case 442: _442(); return; - case 443: _443(); return; - case 444: _444(); return; - case 445: _445(); return; - case 446: _446(); return; - case 447: _447(); return; - case 448: _448(); return; - case 449: _449(); return; - case 450: _450(); return; - case 451: _451(); return; - case 452: _452(); return; - case 453: _453(); return; - case 454: _454(); return; - case 455: _455(); return; - case 456: _456(); return; - case 457: _457(); return; - case 458: _458(); return; - case 459: _459(); return; - case 460: _460(); return; - case 461: _461(); return; - case 462: _462(); return; - case 463: _463(); return; - case 464: _464(); return; - case 465: _465(); return; - case 466: _466(); return; - case 467: _467(); return; - case 468: _468(); return; - case 469: _469(); return; - case 470: _470(); return; - case 471: _471(); return; - case 472: _472(); return; - case 473: _473(); return; - case 474: _474(); return; - case 475: _475(); return; - case 476: _476(); return; - case 477: _477(); return; - case 478: _478(); return; - case 479: _479(); return; - case 480: _480(); return; - case 481: _481(); return; - case 482: _482(); return; - case 483: _483(); return; - case 484: _484(); return; - case 485: _485(); return; - case 486: _486(); return; - case 487: _487(); return; - case 488: _488(); return; - case 489: _489(); return; - case 490: _490(); return; - case 491: _491(); return; - case 492: _492(); return; - case 493: _493(); return; - case 494: _494(); return; - case 495: _495(); return; - case 496: _496(); return; - case 497: _497(); return; - case 498: _498(); return; - case 499: _499(); return; - case 502: _502(); return; - case 503: _503(); return; - case 506: _506(); return; - case 507: _507(); return; - case 508: _508(); return; - case 510: _510(); return; - case 511: _511(); return; - case 512: _512(); return; - case 513: _513(); return; - case 514: _514(); return; - case 515: _515(); return; - case 528: _528(); return; - case 530: _530(); return; - case 534: _534(); return; - case 537: _537(); return; - case 540: _540(); return; - } - } - - private void _1() - { - // program -> compstmt -#line 175 "Parser.y" - { - _ast = new SourceUnitTree(CurrentScope, GetValue(1).Statements, _initializers, Encoding, _tokenizer.DataOffset); - } - } - - private void _2() - { - // compstmt -> terms_opt -#line 182 "Parser.y" - { - yyval.Statements = Statements.Empty; - } - } - - private void _3() - { - // compstmt -> terms stmts terms_opt -#line 186 "Parser.y" - { - yyval.Statements = GetValue(2).Statements; - } - } - - private void _4() - { - // compstmt -> stmts terms_opt -#line 190 "Parser.y" - { - yyval.Statements = GetValue(2).Statements; - } - } - - private void _5() - { - // stmts -> stmt -#line 197 "Parser.y" - { - yyval.Statements = new Statements(GetValue(1).Expression); - } - } - - private void _6() - { - // stmts -> stmts terms stmt -#line 201 "Parser.y" - { - (yyval.Statements = GetValue(3).Statements).Add(GetValue(1).Expression); - } - } - - private void _7() - { - // stmts -> Error stmt -#line 205 "Parser.y" - { - yyval.Statements = new Statements(GetValue(1).Expression); - } - } - - private void _9() - { - // stmt -> Undef undef_list -#line 213 "Parser.y" - { - yyval.Expression = new UndefineStatement(GetValue(1).ConstructedSymbols, yyloc); - } - } - - private void _10() - { - // @1 -> -#line 217 "Parser.y" - { - if (InMethod) { - _tokenizer.ReportError(Errors.FileInitializerInMethod); - } - - EnterFileInitializerScope(); - } - } - - private void _11() - { - // stmt -> UppercaseBegin @1 LeftBlockBrace compstmt RightBrace -#line 225 "Parser.y" - { - yyval.Expression = AddInitializer(new FileInitializerStatement(CurrentScope, GetValue(2).Statements, yyloc)); - LeaveScope(); - } - } - - private void _12() - { - // @2 -> -#line 230 "Parser.y" - { - if (InMethod) { - _tokenizer.ReportWarning(Errors.ShutdownHandlerInMethod); - } - - // END block behaves like a block definition (allows variable closures, super, etc): - EnterNestedScope(); - } - } - - private void _13() - { - // stmt -> UppercaseEnd @2 LeftBlockBrace compstmt RightBrace -#line 239 "Parser.y" - { - yyval.Expression = new ShutdownHandlerStatement(CurrentScope, GetValue(2).Statements, yyloc); - LeaveScope(); - } - } - - private void _14() - { - // stmt -> match_reference OpAssignment command_call -#line 244 "Parser.y" - { - MatchReferenceReadOnlyError(GetValue(3).RegexMatchReference); - yyval.Expression = new ErrorExpression(yyloc); - } - } - - private void _15() - { - // stmt -> conditional_statement -#line 249 "Parser.y" - { - yyval.Expression = GetValue(1).Expression; - } - } - - private void _16() - { - // stmt -> expression_statement -#line 253 "Parser.y" - { - yyval.Expression = GetValue(1).Expression; - } - } - - private void _17() - { - // @3 -> -#line 260 "Parser.y" - { - _tokenizer.LexicalState = LexicalState.EXPR_FNAME; - } - } - - private void _18() - { - // alias_statement -> Alias method_name_or_symbol @3 method_name_or_symbol -#line 264 "Parser.y" - { - yyval.Expression = new AliasStatement(true, GetValue(3).ConstructedSymbol, GetValue(1).ConstructedSymbol, yyloc); - } - } - - private void _19() - { - // alias_statement -> Alias GlobalVariable GlobalVariable -#line 268 "Parser.y" - { - yyval.Expression = MakeGlobalAlias(GetValue(2).String, GetValue(1).String, yyloc); - } - } - - private void _20() - { - // alias_statement -> Alias GlobalVariable match_reference -#line 272 "Parser.y" - { - yyval.Expression = MakeGlobalAlias(GetValue(2).String, GetValue(1).RegexMatchReference, yyloc); - } - } - - private void _21() - { - // jump_statement -> jump_statement_with_parameters -#line 279 "Parser.y" - { - yyval.JumpStatement = GetValue(1).JumpStatement; - } - } - - private void _22() - { - // jump_statement -> jump_statement_parameterless -#line 283 "Parser.y" - { - yyval.JumpStatement = GetValue(1).JumpStatement; - } - } - - private void _23() - { - // jump_statement_with_parameters -> Return call_args -#line 290 "Parser.y" - { - yyval.JumpStatement = new ReturnStatement(RequireNoBlockArg(GetValue(1)), yyloc); - } - } - - private void _24() - { - // jump_statement_with_parameters -> Break call_args -#line 294 "Parser.y" - { - yyval.JumpStatement = new BreakStatement(RequireNoBlockArg(GetValue(1)), yyloc); - } - } - - private void _25() - { - // jump_statement_with_parameters -> Next call_args -#line 298 "Parser.y" - { - yyval.JumpStatement = new NextStatement(RequireNoBlockArg(GetValue(1)), yyloc); - } - } - - private void _26() - { - // jump_statement_parameterless -> Return -#line 305 "Parser.y" - { - yyval.JumpStatement = new ReturnStatement(null, yyloc); - } - } - - private void _27() - { - // jump_statement_parameterless -> Break -#line 309 "Parser.y" - { - yyval.JumpStatement = new BreakStatement(null, yyloc); - } - } - - private void _28() - { - // jump_statement_parameterless -> Next -#line 313 "Parser.y" - { - yyval.JumpStatement = new NextStatement(null, yyloc); - } - } - - private void _29() - { - // jump_statement_parameterless -> Redo -#line 317 "Parser.y" - { - yyval.JumpStatement = new RedoStatement(yyloc); - } - } - - private void _30() - { - // jump_statement_parameterless -> Retry -#line 321 "Parser.y" - { - yyval.JumpStatement = new RetryStatement(yyloc); - } - } - - private void _31() - { - // expression_statement -> expr -#line 328 "Parser.y" - { - yyval.Expression = GetValue(1).Expression; - } - } - - private void _32() - { - // expression_statement -> jump_statement -#line 332 "Parser.y" - { - yyval.Expression = GetValue(1).JumpStatement; - } - } - - private void _33() - { - // expression_statement -> lhs Assignment command_call -#line 336 "Parser.y" - { - yyval.Expression = new SimpleAssignmentExpression(GetValue(3).LeftValue, GetValue(1).CallExpression, null, yyloc); - } - } - - private void _34() - { - // expression_statement -> compound_lhs Assignment command_call -#line 340 "Parser.y" - { - yyval.Expression = new ParallelAssignmentExpression(GetValue(3).CompoundLeftValue, new Expression[] { GetValue(1).CallExpression }, yyloc); - } - } - - private void _35() - { - // expression_statement -> var_lhs OpAssignment command_call -#line 344 "Parser.y" - { - yyval.Expression = new SimpleAssignmentExpression(GetValue(3).LeftValue, GetValue(1).CallExpression, GetValue(2).String, yyloc); - } - } - - private void _36() - { - // expression_statement -> primary LeftIndexingBracket call_args_opt closing_bracket OpAssignment command_call -#line 348 "Parser.y" - { - yyval.Expression = new SimpleAssignmentExpression(MakeArrayItemAccess(GetValue(6).Expression, GetValue(4), GetLocation(5)), GetValue(1).CallExpression, GetValue(2).String, yyloc); - } - } - - private void _37() - { - // expression_statement -> primary Dot Identifier OpAssignment command_call -#line 352 "Parser.y" - { - yyval.Expression = new MemberAssignmentExpression(GetValue(5).Expression, GetValue(3).String, GetValue(2).String, GetValue(1).CallExpression, yyloc); - } - } - - private void _38() - { - // expression_statement -> primary Dot ConstantIdentifier OpAssignment command_call -#line 356 "Parser.y" - { - yyval.Expression = new MemberAssignmentExpression(GetValue(5).Expression, GetValue(3).String, GetValue(2).String, GetValue(1).CallExpression, yyloc); - } - } - - private void _39() - { - // expression_statement -> primary SeparatingDoubleColon ConstantIdentifier OpAssignment command_call -#line 360 "Parser.y" - { - _tokenizer.ReportError(Errors.ConstantReassigned); - yyval.Expression = new MemberAssignmentExpression(GetValue(5).Expression, GetValue(3).String, GetValue(2).String, GetValue(1).CallExpression, yyloc); - } - } - - private void _40() - { - // expression_statement -> primary SeparatingDoubleColon Identifier OpAssignment command_call -#line 365 "Parser.y" - { - yyval.Expression = new MemberAssignmentExpression(GetValue(5).Expression, GetValue(3).String, GetValue(2).String, GetValue(1).CallExpression, yyloc); - } - } - - private void _41() - { - // expression_statement -> lhs Assignment compound_rhs -#line 369 "Parser.y" - { - yyval.Expression = new ParallelAssignmentExpression(new CompoundLeftValue(new LeftValue[] { GetValue(3).LeftValue }), PopArguments(GetValue(1).ArgumentCount), yyloc); - } - } - - private void _42() - { - // expression_statement -> compound_lhs Assignment arg -#line 373 "Parser.y" - { - yyval.Expression = new ParallelAssignmentExpression(GetValue(3).CompoundLeftValue, new Expression[] { GetValue(1).Expression }, yyloc); - } - } - - private void _43() - { - // expression_statement -> compound_lhs Assignment compound_rhs -#line 377 "Parser.y" - { - yyval.Expression = new ParallelAssignmentExpression(GetValue(3).CompoundLeftValue, PopArguments(GetValue(1).ArgumentCount), yyloc); - } - } - - private void _44() - { - // conditional_statement -> stmt IfMod expr -#line 384 "Parser.y" - { - yyval.Expression = new ConditionalStatement(ToCondition(GetValue(1).Expression), false, GetValue(3).Expression, null, yyloc); - } - } - - private void _45() - { - // conditional_statement -> stmt UnlessMod expr -#line 388 "Parser.y" - { - yyval.Expression = new ConditionalStatement(ToCondition(GetValue(1).Expression), true, GetValue(3).Expression, null, yyloc); - } - } - - private void _46() - { - // conditional_statement -> stmt WhileMod expr -#line 392 "Parser.y" - { - yyval.Expression = MakeLoopStatement(GetValue(3).Expression, ToCondition(GetValue(1).Expression), true, yyloc); - } - } - - private void _47() - { - // conditional_statement -> stmt UntilMod expr -#line 396 "Parser.y" - { - yyval.Expression = MakeLoopStatement(GetValue(3).Expression, ToCondition(GetValue(1).Expression), false, yyloc); - } - } - - private void _48() - { - // conditional_statement -> stmt RescueMod stmt -#line 400 "Parser.y" - { - yyval.Expression = new RescueExpression(GetValue(3).Expression, GetValue(1).Expression, MergeLocations(GetLocation(2), GetLocation(1)), yyloc); - } - } - - private void _50() - { - // expr -> expr And expr -#line 408 "Parser.y" - { - yyval.Expression = new AndExpression(GetValue(3).Expression, GetValue(1).Expression, yyloc); - } - } - - private void _51() - { - // expr -> expr Or expr -#line 412 "Parser.y" - { - yyval.Expression = new OrExpression(GetValue(3).Expression, GetValue(1).Expression, yyloc); - } - } - - private void _52() - { - // expr -> expr And jump_statement -#line 416 "Parser.y" - { - yyval.Expression = new ConditionalJumpExpression(GetValue(3).Expression, GetValue(1).JumpStatement, false, null, yyloc); - } - } - - private void _53() - { - // expr -> expr Or jump_statement -#line 420 "Parser.y" - { - yyval.Expression = new ConditionalJumpExpression(GetValue(3).Expression, GetValue(1).JumpStatement, true, null, yyloc); - } - } - - private void _54() - { - // expr -> Not new_line_opt expr -#line 424 "Parser.y" - { - yyval.Expression = new NotExpression(GetValue(1).Expression, yyloc); - } - } - - private void _55() - { - // expr -> Bang command_call -#line 428 "Parser.y" - { - yyval.Expression = new NotExpression(GetValue(1).CallExpression, yyloc); - } - } - - private void _57() - { - // command_call -> command -#line 436 "Parser.y" - { - yyval.CallExpression = GetValue(1).CallExpression; - } - } - - private void _58() - { - // command_call -> block_command -#line 440 "Parser.y" - { - yyval.CallExpression = GetValue(1).CallExpression; - } - } - - private void _59() - { - // block_command -> block_call -#line 447 "Parser.y" - { - yyval.CallExpression = GetValue(1).CallExpression; - } - } - - private void _60() - { - // block_command -> block_call Dot operation2 command_args -#line 451 "Parser.y" - { - yyval.CallExpression = MakeMethodCall(GetValue(4).CallExpression, GetValue(2).String, GetValue(1), yyloc); - } - } - - private void _61() - { - // block_command -> block_call SeparatingDoubleColon operation2 command_args -#line 455 "Parser.y" - { - yyval.CallExpression = MakeMethodCall(GetValue(4).CallExpression, GetValue(2).String, GetValue(1), yyloc); - } - } - - private void _62() - { - // @4 -> -#line 462 "Parser.y" - { - EnterNestedScope(); - } - } - - private void _63() - { - // cmd_brace_block -> LeftBlockArgBrace @4 block_parameters_opt compstmt RightBrace -#line 466 "Parser.y" - { - yyval.BlockDefinition = MakeBlockDefinition(GetValue(3).Parameters, GetValue(2).Statements, yyloc); - LeaveScope(); - } - } - - private void _64() - { - // command -> operation command_args -#line 474 "Parser.y" - { - yyval.CallExpression = MakeMethodCall(null, GetValue(2).String, GetValue(1), yyloc); - } - } - - private void _65() - { - // command -> operation command_args cmd_brace_block -#line 478 "Parser.y" - { - yyval.CallExpression = MakeMethodCall(null, GetValue(3).String, GetValue(2), GetValue(1).BlockDefinition, yyloc); - } - } - - private void _66() - { - // command -> primary Dot operation2 command_args -#line 482 "Parser.y" - { - yyval.CallExpression = MakeMethodCall(GetValue(4).Expression, GetValue(2).String, GetValue(1), yyloc); - } - } - - private void _67() - { - // command -> primary Dot operation2 command_args cmd_brace_block -#line 486 "Parser.y" - { - yyval.CallExpression = MakeMethodCall(GetValue(5).Expression, GetValue(3).String, GetValue(2), GetValue(1).BlockDefinition, yyloc); - } - } - - private void _68() - { - // command -> primary SeparatingDoubleColon operation2 command_args -#line 490 "Parser.y" - { - yyval.CallExpression = MakeMethodCall(GetValue(4).Expression, GetValue(2).String, GetValue(1), yyloc); - } - } - - private void _69() - { - // command -> primary SeparatingDoubleColon operation2 command_args cmd_brace_block -#line 494 "Parser.y" - { - yyval.CallExpression = MakeMethodCall(GetValue(5).Expression, GetValue(3).String, GetValue(2), GetValue(1).BlockDefinition, yyloc); - } - } - - private void _70() - { - // command -> Super command_args -#line 498 "Parser.y" - { - yyval.CallExpression = MakeSuperCall(GetValue(1), yyloc); - } - } - - private void _71() - { - // command -> Yield command_args -#line 502 "Parser.y" - { - yyval.CallExpression = new YieldCall(RequireNoBlockArg(GetValue(1)), yyloc); - } - } - - private void _72() - { - // compound_lhs -> LeftExprParenthesis compound_lhs closing_parenthesis -#line 509 "Parser.y" - { - yyval.CompoundLeftValue = new CompoundLeftValue(new LeftValue[] { GetValue(2).CompoundLeftValue }); - } - } - - private void _73() - { - // compound_lhs -> compound_lhs_nodes -#line 513 "Parser.y" - { - // the list ends with COMMA: - GetValue(1).LeftValues.Add(Placeholder.Singleton); - yyval.CompoundLeftValue = new CompoundLeftValue(GetValue(1).LeftValues.ToArray()); - } - } - - private void _74() - { - // compound_lhs -> compound_lhs_nodes compound_lhs_node -#line 519 "Parser.y" - { - GetValue(2).LeftValues.Add(GetValue(1).LeftValue); - yyval.CompoundLeftValue = new CompoundLeftValue(GetValue(2).LeftValues.ToArray()); - } - } - - private void _75() - { - // compound_lhs -> compound_lhs_nodes Star compound_lhs_leaf -#line 524 "Parser.y" - { - yyval.CompoundLeftValue = MakeCompoundLeftValue(GetValue(3).LeftValues, GetValue(1).LeftValue, null); - } - } - - private void _76() - { - // compound_lhs -> compound_lhs_nodes Star compound_lhs_leaf Comma compound_lhs_tail -#line 528 "Parser.y" - { - yyval.CompoundLeftValue = MakeCompoundLeftValue(GetValue(5).LeftValues, GetValue(3).LeftValue, GetValue(1).LeftValues); - } - } - - private void _77() - { - // compound_lhs -> compound_lhs_nodes Star -#line 532 "Parser.y" - { - yyval.CompoundLeftValue = MakeCompoundLeftValue(GetValue(2).LeftValues, Placeholder.Singleton, null); - } - } - - private void _78() - { - // compound_lhs -> compound_lhs_nodes Star Comma compound_lhs_tail -#line 536 "Parser.y" - { - yyval.CompoundLeftValue = MakeCompoundLeftValue(GetValue(4).LeftValues, Placeholder.Singleton, GetValue(1).LeftValues); - } - } - - private void _79() - { - // compound_lhs -> Star compound_lhs_leaf Comma compound_lhs_tail -#line 540 "Parser.y" - { - yyval.CompoundLeftValue = MakeCompoundLeftValue(null, GetValue(3).LeftValue, GetValue(1).LeftValues); - } - } - - private void _80() - { - // compound_lhs -> Star Comma compound_lhs_tail -#line 544 "Parser.y" - { - yyval.CompoundLeftValue = MakeCompoundLeftValue(null, Placeholder.Singleton, GetValue(1).LeftValues); - } - } - - private void _81() - { - // compound_lhs -> Star compound_lhs_leaf -#line 548 "Parser.y" - { - yyval.CompoundLeftValue = new CompoundLeftValue(new LeftValue[] { GetValue(1).LeftValue }, 0); - } - } - - private void _82() - { - // compound_lhs -> Star -#line 552 "Parser.y" - { - yyval.CompoundLeftValue = new CompoundLeftValue(new LeftValue[] { Placeholder.Singleton }, 0); - } - } - - private void _83() - { - // compound_lhs_nodes -> compound_lhs_nodes compound_lhs_node Comma -#line 559 "Parser.y" - { - (yyval.LeftValues = GetValue(3).LeftValues).Add(GetValue(2).LeftValue); - } - } - - private void _84() - { - // compound_lhs_nodes -> compound_lhs_node Comma -#line 563 "Parser.y" - { - yyval.LeftValues = CollectionUtils.MakeList(GetValue(2).LeftValue); - } - } - - private void _85() - { - // compound_lhs_tail -> compound_lhs_tail Comma compound_lhs_node -#line 570 "Parser.y" - { - (yyval.LeftValues = GetValue(3).LeftValues).Add(GetValue(1).LeftValue); - } - } - - private void _86() - { - // compound_lhs_tail -> compound_lhs_node -#line 574 "Parser.y" - { - yyval.LeftValues = CollectionUtils.MakeList(GetValue(1).LeftValue); - } - } - - private void _87() - { - // compound_lhs_node -> compound_lhs_leaf -#line 581 "Parser.y" - { - yyval.LeftValue = GetValue(1).LeftValue; - } - } - - private void _88() - { - // compound_lhs_node -> LeftExprParenthesis compound_lhs closing_parenthesis -#line 585 "Parser.y" - { - yyval.LeftValue = GetValue(2).CompoundLeftValue; - } - } - - private void _89() - { - // compound_lhs_leaf -> variable -#line 592 "Parser.y" - { - yyval.LeftValue = VariableFactory.MakeLeftValue(GetValue(1).VariableFactory, this, GetValue(1).String, yyloc); - } - } - - private void _90() - { - // compound_lhs_leaf -> primary LeftIndexingBracket call_args_opt closing_bracket -#line 596 "Parser.y" - { - yyval.LeftValue = MakeArrayItemAccess(GetValue(4).Expression, GetValue(2), yyloc); - } - } - - private void _91() - { - // compound_lhs_leaf -> primary Dot Identifier -#line 600 "Parser.y" - { - yyval.LeftValue = new AttributeAccess(GetValue(3).Expression, GetValue(1).String, yyloc); - } - } - - private void _92() - { - // compound_lhs_leaf -> primary SeparatingDoubleColon Identifier -#line 604 "Parser.y" - { - yyval.LeftValue = new AttributeAccess(GetValue(3).Expression, GetValue(1).String, yyloc); - } - } - - private void _93() - { - // compound_lhs_leaf -> primary Dot ConstantIdentifier -#line 608 "Parser.y" - { - yyval.LeftValue = new AttributeAccess(GetValue(3).Expression, GetValue(1).String, yyloc); - } - } - - private void _94() - { - // compound_lhs_leaf -> primary SeparatingDoubleColon ConstantIdentifier -#line 612 "Parser.y" - { - yyval.LeftValue = new ConstantVariable(GetValue(3).Expression, GetValue(1).String, yyloc); - } - } - - private void _95() - { - // compound_lhs_leaf -> LeadingDoubleColon ConstantIdentifier -#line 616 "Parser.y" - { - yyval.LeftValue = new ConstantVariable(null, GetValue(1).String, yyloc); - } - } - - private void _96() - { - // compound_lhs_leaf -> match_reference -#line 620 "Parser.y" - { - MatchReferenceReadOnlyError(GetValue(1).RegexMatchReference); - yyval.LeftValue = new GlobalVariable(Symbols.Error, yyloc); - } - } - - private void _97() - { - // lhs -> variable -#line 627 "Parser.y" - { - yyval.LeftValue = VariableFactory.MakeLeftValue(GetValue(1).VariableFactory, this, GetValue(1).String, yyloc); - } - } - - private void _98() - { - // lhs -> primary LeftIndexingBracket call_args_opt closing_bracket -#line 631 "Parser.y" - { - yyval.LeftValue = MakeArrayItemAccess(GetValue(4).Expression, GetValue(2), yyloc); - } - } - - private void _99() - { - // lhs -> primary Dot Identifier -#line 635 "Parser.y" - { - yyval.LeftValue = new AttributeAccess(GetValue(3).Expression, GetValue(1).String, yyloc); - } - } - - private void _100() - { - // lhs -> primary SeparatingDoubleColon Identifier -#line 639 "Parser.y" - { - yyval.LeftValue = new AttributeAccess(GetValue(3).Expression, GetValue(1).String, yyloc); - } - } - - private void _101() - { - // lhs -> primary Dot ConstantIdentifier -#line 643 "Parser.y" - { - yyval.LeftValue = new AttributeAccess(GetValue(3).Expression, GetValue(1).String, yyloc); - } - } - - private void _102() - { - // lhs -> primary SeparatingDoubleColon ConstantIdentifier -#line 647 "Parser.y" - { - yyval.LeftValue = new ConstantVariable(GetValue(3).Expression, GetValue(1).String, yyloc); - } - } - - private void _103() - { - // lhs -> LeadingDoubleColon ConstantIdentifier -#line 651 "Parser.y" - { - yyval.LeftValue = new ConstantVariable(null, GetValue(1).String, yyloc); - } - } - - private void _104() - { - // lhs -> match_reference -#line 655 "Parser.y" - { - MatchReferenceReadOnlyError(GetValue(1).RegexMatchReference); - yyval.LeftValue = new GlobalVariable(Symbols.Error, yyloc); - } - } - - private void _105() - { - // module_name -> ConstantIdentifier -#line 663 "Parser.y" - { - yyval.String = GetValue(1).String; - } - } - - private void _106() - { - // module_name -> Identifier -#line 667 "Parser.y" - { - _tokenizer.ReportError(Errors.ModuleNameNotConstant); - yyval.String = GetValue(1).String; - } - } - - private void _107() - { - // qualified_module_name -> LeadingDoubleColon module_name -#line 675 "Parser.y" - { - yyval.ConstantVariable = new ConstantVariable(null, GetValue(1).String, yyloc); - } - } - - private void _108() - { - // qualified_module_name -> module_name -#line 679 "Parser.y" - { - yyval.ConstantVariable = new ConstantVariable(GetValue(1).String, yyloc); - } - } - - private void _109() - { - // qualified_module_name -> primary SeparatingDoubleColon module_name -#line 683 "Parser.y" - { - yyval.ConstantVariable = new ConstantVariable(GetValue(3).Expression, GetValue(1).String, yyloc); - } - } - - private void _110() - { - // method_name -> Identifier -#line 690 "Parser.y" - { - yyval.String = GetValue(1).String; - } - } - - private void _111() - { - // method_name -> ConstantIdentifier -#line 694 "Parser.y" - { - yyval.String = GetValue(1).String; - } - } - - private void _112() - { - // method_name -> FunctionIdentifier -#line 698 "Parser.y" - { - yyval.String = GetValue(1).String; - } - } - - private void _113() - { - // method_name -> op -#line 702 "Parser.y" - { - _tokenizer.LexicalState = LexicalState.EXPR_ENDFN; // 1.8: EXPR_END - yyval.String = GetValue(1).String; - } - } - - private void _114() - { - // method_name -> reswords -#line 707 "Parser.y" - { - _tokenizer.LexicalState = LexicalState.EXPR_ENDFN; // 1.8: EXPR_END - yyval.String = GetValue(1).String; - } - } - - private void _115() - { - // method_name_or_symbol -> method_name -#line 715 "Parser.y" - { - yyval.ConstructedSymbol = new ConstructedSymbol(GetValue(1).String); - } - } - - private void _116() - { - // method_name_or_symbol -> symbol -#line 719 "Parser.y" - { - yyval.ConstructedSymbol = GetValue(1).ConstructedSymbol; - } - } - - private void _117() - { - // symbol -> SymbolBegin sym -#line 726 "Parser.y" - { - _tokenizer.LexicalState = LexicalState.EXPR_END; - yyval.ConstructedSymbol = new ConstructedSymbol(GetValue(1).String); - } - } - - private void _118() - { - // symbol -> SymbolBegin string_contents StringEnd -#line 731 "Parser.y" - { - yyval.ConstructedSymbol = new ConstructedSymbol(MakeSymbolConstructor(GetValue(2).Expressions, yyloc)); - } - } - - private void _121() - { - // sym -> GlobalVariable -#line 740 "Parser.y" - { - yyval.String = "$" + GetValue(1).String; - } - } - - private void _123() - { - // sym -> match_reference -#line 745 "Parser.y" - { - yyval.String = GetValue(1).RegexMatchReference.FullName; - } - } - - private void _124() - { - // undef_list -> method_name_or_symbol -#line 752 "Parser.y" - { - yyval.ConstructedSymbols = CollectionUtils.MakeList(GetValue(1).ConstructedSymbol); - } - } - - private void _125() - { - // @5 -> -#line 756 "Parser.y" - { - _tokenizer.LexicalState = LexicalState.EXPR_FNAME; - } - } - - private void _126() - { - // undef_list -> undef_list Comma @5 method_name_or_symbol -#line 760 "Parser.y" - { - (yyval.ConstructedSymbols = GetValue(4).ConstructedSymbols).Add(GetValue(1).ConstructedSymbol); - } - } - - private void _127() - { - // op -> Pipe -#line 766 "Parser.y" - { yyval.String = Symbols.BitwiseOr; } - } - - private void _128() - { - // op -> Caret -#line 767 "Parser.y" - { yyval.String = Symbols.Xor; } - } - - private void _129() - { - // op -> Ampersand -#line 768 "Parser.y" - { yyval.String = Symbols.BitwiseAnd; } - } - - private void _130() - { - // op -> Cmp -#line 769 "Parser.y" - { yyval.String = Symbols.Comparison; } - } - - private void _131() - { - // op -> Equal -#line 770 "Parser.y" - { yyval.String = Symbols.Equal; } - } - - private void _132() - { - // op -> StrictEqual -#line 771 "Parser.y" - { yyval.String = Symbols.StrictEqual; } - } - - private void _133() - { - // op -> Match -#line 772 "Parser.y" - { yyval.String = Symbols.Match; } - } - - private void _134() - { - // op -> Nmatch -#line 773 "Parser.y" - { yyval.String = Symbols.NotMatch; } - } - - private void _135() - { - // op -> Greater -#line 774 "Parser.y" - { yyval.String = Symbols.GreaterThan; } - } - - private void _136() - { - // op -> GreaterOrEqual -#line 775 "Parser.y" - { yyval.String = Symbols.GreaterEqual; } - } - - private void _137() - { - // op -> Less -#line 776 "Parser.y" - { yyval.String = Symbols.LessThan; } - } - - private void _138() - { - // op -> LessOrEqual -#line 777 "Parser.y" - { yyval.String = Symbols.LessEqual; } - } - - private void _139() - { - // op -> NotEqual -#line 778 "Parser.y" - { yyval.String = Symbols.NotEqual; } - } - - private void _140() - { - // op -> Lshft -#line 779 "Parser.y" - { yyval.String = Symbols.LeftShift; } - } - - private void _141() - { - // op -> Rshft -#line 780 "Parser.y" - { yyval.String = Symbols.RightShift; } - } - - private void _142() - { - // op -> Plus -#line 781 "Parser.y" - { yyval.String = Symbols.Plus; } - } - - private void _143() - { - // op -> Minus -#line 782 "Parser.y" - { yyval.String = Symbols.Minus; } - } - - private void _144() - { - // op -> Asterisk -#line 783 "Parser.y" - { yyval.String = Symbols.Multiply; } - } - - private void _145() - { - // op -> Star -#line 784 "Parser.y" - { yyval.String = Symbols.Multiply; } - } - - private void _146() - { - // op -> Slash -#line 785 "Parser.y" - { yyval.String = Symbols.Divide; } - } - - private void _147() - { - // op -> Percent -#line 786 "Parser.y" - { yyval.String = Symbols.Mod; } - } - - private void _148() - { - // op -> Pow -#line 787 "Parser.y" - { yyval.String = Symbols.Power; } - } - - private void _149() - { - // op -> Bang -#line 788 "Parser.y" - { yyval.String = Symbols.Bang; } - } - - private void _150() - { - // op -> Tilde -#line 789 "Parser.y" - { yyval.String = Symbols.BitwiseNot; } - } - - private void _151() - { - // op -> UnaryPlus -#line 790 "Parser.y" - { yyval.String = Symbols.UnaryPlus; } - } - - private void _152() - { - // op -> UnaryMinus -#line 791 "Parser.y" - { yyval.String = Symbols.UnaryMinus; } - } - - private void _153() - { - // op -> ItemGetter -#line 792 "Parser.y" - { yyval.String = Symbols.ArrayItemRead; } - } - - private void _154() - { - // op -> ItemSetter -#line 793 "Parser.y" - { yyval.String = Symbols.ArrayItemWrite; } - } - - private void _155() - { - // op -> Backtick -#line 794 "Parser.y" - { yyval.String = Symbols.Backtick; } - } - - private void _199() - { - // arg -> lhs Assignment arg -#line 809 "Parser.y" - { - yyval.Expression = new SimpleAssignmentExpression(GetValue(3).LeftValue, GetValue(1).Expression, null, yyloc); - } - } - - private void _200() - { - // arg -> lhs Assignment arg RescueMod arg -#line 813 "Parser.y" - { - yyval.Expression = new SimpleAssignmentExpression(GetValue(5).LeftValue, new RescueExpression(GetValue(3).Expression, GetValue(1).Expression, MergeLocations(GetLocation(2), GetLocation(1)), MergeLocations(GetLocation(3), GetLocation(1))), null, yyloc); - } - } - - private void _201() - { - // arg -> lhs Assignment arg RescueMod jump_statement_parameterless -#line 817 "Parser.y" - { - yyval.Expression = new SimpleAssignmentExpression(GetValue(5).LeftValue, new RescueExpression(GetValue(3).Expression, GetValue(1).JumpStatement, MergeLocations(GetLocation(2), GetLocation(1)), MergeLocations(GetLocation(3), GetLocation(1))), null, yyloc); - } - } - - private void _202() - { - // arg -> var_lhs OpAssignment arg -#line 821 "Parser.y" - { - yyval.Expression = new SimpleAssignmentExpression(GetValue(3).LeftValue, GetValue(1).Expression, GetValue(2).String, yyloc); - } - } - - private void _203() - { - // arg -> primary LeftIndexingBracket call_args_opt closing_bracket OpAssignment arg -#line 825 "Parser.y" - { - yyval.Expression = new SimpleAssignmentExpression(MakeArrayItemAccess(GetValue(6).Expression, GetValue(4), GetLocation(5)), GetValue(1).Expression, GetValue(2).String, yyloc); - } - } - - private void _204() - { - // arg -> primary Dot Identifier OpAssignment arg -#line 829 "Parser.y" - { - yyval.Expression = new MemberAssignmentExpression(GetValue(5).Expression, GetValue(3).String, GetValue(2).String, GetValue(1).Expression, yyloc); - } - } - - private void _205() - { - // arg -> primary Dot ConstantIdentifier OpAssignment arg -#line 833 "Parser.y" - { - yyval.Expression = new MemberAssignmentExpression(GetValue(5).Expression, GetValue(3).String, GetValue(2).String, GetValue(1).Expression, yyloc); - } - } - - private void _206() - { - // arg -> primary SeparatingDoubleColon Identifier OpAssignment arg -#line 837 "Parser.y" - { - yyval.Expression = new MemberAssignmentExpression(GetValue(5).Expression, GetValue(3).String, GetValue(2).String, GetValue(1).Expression, yyloc); - } - } - - private void _207() - { - // arg -> primary SeparatingDoubleColon ConstantIdentifier OpAssignment arg -#line 841 "Parser.y" - { - _tokenizer.ReportError(Errors.ConstantReassigned); - yyval.Expression = new ErrorExpression(yyloc); - } - } - - private void _208() - { - // arg -> LeadingDoubleColon ConstantIdentifier OpAssignment arg -#line 846 "Parser.y" - { - _tokenizer.ReportError(Errors.ConstantReassigned); - yyval.Expression = new ErrorExpression(yyloc); - } - } - - private void _209() - { - // arg -> match_reference OpAssignment arg -#line 851 "Parser.y" - { - MatchReferenceReadOnlyError(GetValue(3).RegexMatchReference); - yyval.Expression = new ErrorExpression(yyloc); - } - } - - private void _210() - { - // arg -> arg Plus arg -#line 856 "Parser.y" - { - yyval.Expression = new MethodCall(GetValue(3).Expression, Symbols.Plus, new Arguments(GetValue(1).Expression), yyloc); - } - } - - private void _211() - { - // arg -> arg Minus arg -#line 860 "Parser.y" - { - yyval.Expression = new MethodCall(GetValue(3).Expression, Symbols.Minus, new Arguments(GetValue(1).Expression), yyloc); - } - } - - private void _212() - { - // arg -> arg Asterisk arg -#line 864 "Parser.y" - { - yyval.Expression = new MethodCall(GetValue(3).Expression, Symbols.Multiply, new Arguments(GetValue(1).Expression), yyloc); - } - } - - private void _213() - { - // arg -> arg Slash arg -#line 868 "Parser.y" - { - yyval.Expression = new MethodCall(GetValue(3).Expression, Symbols.Divide, new Arguments(GetValue(1).Expression), yyloc); - } - } - - private void _214() - { - // arg -> arg Percent arg -#line 872 "Parser.y" - { - yyval.Expression = new MethodCall(GetValue(3).Expression, Symbols.Mod, new Arguments(GetValue(1).Expression), yyloc); - } - } - - private void _215() - { - // arg -> arg Pow arg -#line 876 "Parser.y" - { - yyval.Expression = new MethodCall(GetValue(3).Expression, Symbols.Power, new Arguments(GetValue(1).Expression), yyloc); - } - } - - private void _216() - { - // arg -> NumberNegation Integer Pow arg -#line 880 "Parser.y" - { - // ** has precedence over unary minus, hence -number**arg is equivalent to -(number**arg) - yyval.Expression = new MethodCall(new MethodCall(Literal.Integer(GetValue(3).Integer1, GetLocation(3)), Symbols.Power, new Arguments(GetValue(1).Expression), GetLocation(2)), Symbols.UnaryMinus, Arguments.Empty, yyloc); - } - } - - private void _217() - { - // arg -> NumberNegation BigInteger Pow arg -#line 885 "Parser.y" - { - yyval.Expression = new MethodCall(new MethodCall(Literal.BigInteger(GetValue(3).BigInteger, GetLocation(3)), Symbols.Power, new Arguments(GetValue(1).Expression), GetLocation(2)), Symbols.UnaryMinus, Arguments.Empty, yyloc); - } - } - - private void _218() - { - // arg -> NumberNegation Float Pow arg -#line 889 "Parser.y" - { - yyval.Expression = new MethodCall(new MethodCall(Literal.Double(GetValue(3).Double, GetLocation(3)), Symbols.Power, new Arguments(GetValue(1).Expression), GetLocation(2)), Symbols.UnaryMinus, Arguments.Empty, yyloc); - } - } - - private void _219() - { - // arg -> UnaryPlus arg -#line 893 "Parser.y" - { - yyval.Expression = new MethodCall(GetValue(1).Expression, Symbols.UnaryPlus, null, yyloc); - } - } - - private void _220() - { - // arg -> UnaryMinus arg -#line 897 "Parser.y" - { - yyval.Expression = new MethodCall(GetValue(1).Expression, Symbols.UnaryMinus, null, yyloc); - } - } - - private void _221() - { - // arg -> arg Pipe arg -#line 901 "Parser.y" - { - yyval.Expression = new MethodCall(GetValue(3).Expression, Symbols.BitwiseOr, new Arguments(GetValue(1).Expression), yyloc); - } - } - - private void _222() - { - // arg -> arg Caret arg -#line 905 "Parser.y" - { - yyval.Expression = new MethodCall(GetValue(3).Expression, Symbols.Xor, new Arguments(GetValue(1).Expression), yyloc); - } - } - - private void _223() - { - // arg -> arg Ampersand arg -#line 909 "Parser.y" - { - yyval.Expression = new MethodCall(GetValue(3).Expression, Symbols.BitwiseAnd, new Arguments(GetValue(1).Expression), yyloc); - } - } - - private void _224() - { - // arg -> arg Cmp arg -#line 913 "Parser.y" - { - yyval.Expression = new MethodCall(GetValue(3).Expression, Symbols.Comparison, new Arguments(GetValue(1).Expression), yyloc); - } - } - - private void _225() - { - // arg -> arg Greater arg -#line 917 "Parser.y" - { - yyval.Expression = new MethodCall(GetValue(3).Expression, Symbols.GreaterThan, new Arguments(GetValue(1).Expression), yyloc); - } - } - - private void _226() - { - // arg -> arg GreaterOrEqual arg -#line 921 "Parser.y" - { - yyval.Expression = new MethodCall(GetValue(3).Expression, Symbols.GreaterEqual, new Arguments(GetValue(1).Expression), yyloc); - } - } - - private void _227() - { - // arg -> arg Less arg -#line 925 "Parser.y" - { - yyval.Expression = new MethodCall(GetValue(3).Expression, Symbols.LessThan, new Arguments(GetValue(1).Expression), yyloc); - } - } - - private void _228() - { - // arg -> arg LessOrEqual arg -#line 929 "Parser.y" - { - yyval.Expression = new MethodCall(GetValue(3).Expression, Symbols.LessEqual, new Arguments(GetValue(1).Expression), yyloc); - } - } - - private void _229() - { - // arg -> arg Equal arg -#line 933 "Parser.y" - { - yyval.Expression = new MethodCall(GetValue(3).Expression, Symbols.Equal, new Arguments(GetValue(1).Expression), yyloc); - } - } - - private void _230() - { - // arg -> arg StrictEqual arg -#line 937 "Parser.y" - { - yyval.Expression = new MethodCall(GetValue(3).Expression, Symbols.StrictEqual, new Arguments(GetValue(1).Expression), yyloc); - } - } - - private void _231() - { - // arg -> arg NotEqual arg -#line 941 "Parser.y" - { - yyval.Expression = new MethodCall(GetValue(3).Expression, Symbols.NotEqual, new Arguments(GetValue(1).Expression), yyloc); - } - } - - private void _232() - { - // arg -> arg Match arg -#line 945 "Parser.y" - { - // TODO: MRI inconsistent (NMATCH vs MATCH): - yyval.Expression = MakeMatch(GetValue(3).Expression, GetValue(1).Expression, yyloc); - } - } - - private void _233() - { - // arg -> arg Nmatch arg -#line 950 "Parser.y" - { - yyval.Expression = new MethodCall(GetValue(3).Expression, Symbols.NotMatch, new Arguments(GetValue(1).Expression), yyloc); - } - } - - private void _234() - { - // arg -> Bang arg -#line 954 "Parser.y" - { - yyval.Expression = new NotExpression(GetValue(1).Expression, yyloc); - } - } - - private void _235() - { - // arg -> Tilde arg -#line 958 "Parser.y" - { - yyval.Expression = new MethodCall(GetValue(1).Expression, Symbols.BitwiseNot, Arguments.Empty, yyloc); - } - } - - private void _236() - { - // arg -> arg Lshft arg -#line 962 "Parser.y" - { - yyval.Expression = new MethodCall(GetValue(3).Expression, Symbols.LeftShift, new Arguments(GetValue(1).Expression), yyloc); - } - } - - private void _237() - { - // arg -> arg Rshft arg -#line 966 "Parser.y" - { - yyval.Expression = new MethodCall(GetValue(3).Expression, Symbols.RightShift, new Arguments(GetValue(1).Expression), yyloc); - } - } - - private void _238() - { - // arg -> arg LogicalAnd arg -#line 970 "Parser.y" - { - yyval.Expression = new AndExpression(GetValue(3).Expression, GetValue(1).Expression, yyloc); - } - } - - private void _239() - { - // arg -> arg LogicalOr arg -#line 974 "Parser.y" - { - yyval.Expression = new OrExpression(GetValue(3).Expression, GetValue(1).Expression, yyloc); - } - } - - private void _240() - { - // arg -> arg LogicalAnd jump_statement_parameterless -#line 978 "Parser.y" - { - yyval.Expression = new ConditionalJumpExpression(GetValue(3).Expression, GetValue(1).JumpStatement, false, null, yyloc); - } - } - - private void _241() - { - // arg -> arg LogicalOr jump_statement_parameterless -#line 982 "Parser.y" - { - yyval.Expression = new ConditionalJumpExpression(GetValue(3).Expression, GetValue(1).JumpStatement, true, null, yyloc); - } - } - - private void _242() - { - // arg -> arg DoubleDot arg -#line 986 "Parser.y" - { - yyval.Expression = new RangeExpression(GetValue(3).Expression, GetValue(1).Expression, false, yyloc); - } - } - - private void _243() - { - // arg -> arg TripleDot arg -#line 990 "Parser.y" - { - yyval.Expression = new RangeExpression(GetValue(3).Expression, GetValue(1).Expression, true, yyloc); - } - } - - private void _244() - { - // arg -> Defined new_line_opt arg -#line 994 "Parser.y" - { - yyval.Expression = new IsDefinedExpression(GetValue(1).Expression, yyloc); - } - } - - private void _245() - { - // arg -> arg QuestionMark arg new_line_opt Colon arg -#line 998 "Parser.y" - { - yyval.Expression = new ConditionalExpression(ToCondition(GetValue(6).Expression), GetValue(4).Expression, GetValue(1).Expression, yyloc); - } - } - - private void _246() - { - // arg -> arg QuestionMark jump_statement_parameterless new_line_opt Colon arg -#line 1002 "Parser.y" - { - yyval.Expression = new ConditionalJumpExpression(ToCondition(GetValue(6).Expression), GetValue(4).JumpStatement, false, GetValue(1).Expression, yyloc); - } - } - - private void _247() - { - // arg -> arg QuestionMark arg new_line_opt Colon jump_statement_parameterless -#line 1006 "Parser.y" - { - yyval.Expression = new ConditionalJumpExpression(ToCondition(GetValue(6).Expression), GetValue(1).JumpStatement, true, GetValue(4).Expression, yyloc); - } - } - - private void _248() - { - // arg -> arg QuestionMark jump_statement_parameterless new_line_opt Colon jump_statement_parameterless -#line 1010 "Parser.y" - { - yyval.Expression = new ConditionalStatement(ToCondition(GetValue(6).Expression), false, GetValue(4).JumpStatement, GetValue(1).JumpStatement, yyloc); - } - } - - private void _249() - { - // arg -> primary -#line 1014 "Parser.y" - { - yyval.Expression = GetValue(1).Expression; - } - } - - private void _250() - { - // array_items -> -#line 1021 "Parser.y" - { - SetArguments(); - } - } - - private void _251() - { - // array_items -> args trailer -#line 1025 "Parser.y" - { - PopAndSetArguments(GetValue(2).ArgumentCount, null); - } - } - - private void _252() - { - // array_items -> args Comma maplets trailer -#line 1029 "Parser.y" - { - PushArgument(GetValue(4).ArgumentCount, new HashConstructor(GetValue(2).Maplets.ToArray(), GetLocation(2))); - PopAndSetArguments(GetValue(4).ArgumentCount + 1, null); - } - } - - private void _253() - { - // array_items -> maplets trailer -#line 1034 "Parser.y" - { - SetArguments(new HashConstructor(GetValue(2).Maplets.ToArray(), GetLocation(2)), null); - } - } - - private void _254() - { - // parenthesized_args -> LeftParenthesis call_args_opt closing_parenthesis -#line 1041 "Parser.y" - { - yyval.Arguments = GetValue(2).Arguments ?? Arguments.Empty; - yyval.Block = GetValue(2).Block; - } - } - - private void _255() - { - // parenthesized_args_opt -> -#line 1049 "Parser.y" - { - SetNoArguments(null); - } - } - - private void _256() - { - // parenthesized_args_opt -> parenthesized_args -#line 1053 "Parser.y" - { - yyval = GetValue(1); - } - } - - private void _257() - { - // call_args_opt -> -#line 1060 "Parser.y" - { - SetNoArguments(null); - } - } - - private void _258() - { - // call_args_opt -> call_args -#line 1064 "Parser.y" - { - yyval = GetValue(1); - } - } - - private void _259() - { - // call_args -> args block_reference_opt -#line 1071 "Parser.y" - { - PopAndSetArguments(GetValue(2).ArgumentCount, GetValue(1).BlockReference); - } - } - - private void _260() - { - // call_args -> args Comma maplets block_reference_opt -#line 1075 "Parser.y" - { - PushArgument(GetValue(4).ArgumentCount, new HashConstructor(GetValue(2).Maplets.ToArray(), GetLocation(2))); - PopAndSetArguments(GetValue(4).ArgumentCount + 1, GetValue(1).BlockReference); - } - } - - private void _261() - { - // call_args -> maplets block_reference_opt -#line 1080 "Parser.y" - { - SetArguments(new HashConstructor(GetValue(2).Maplets.ToArray(), GetLocation(2)), GetValue(1).BlockReference); - } - } - - private void _262() - { - // call_args -> block_reference -#line 1084 "Parser.y" - { - SetArguments(GetValue(1).BlockReference); - } - } - - private void _263() - { - // call_args -> command -#line 1088 "Parser.y" - { - SetArguments(GetValue(1).CallExpression); - } - } - - private void _264() - { - // @6 -> -#line 1094 "Parser.y" - { - yyval.Integer1 = _tokenizer.EnterCommandArguments(); - } - } - - private void _265() - { - // command_args -> @6 call_args -#line 1098 "Parser.y" - { - _tokenizer.LeaveCommandArguments(GetValue(2).Integer1); - yyval = GetValue(1); - } - } - - private void _266() - { - // block_reference -> BlockReference arg -#line 1106 "Parser.y" - { - yyval.BlockReference = new BlockReference(GetValue(1).Expression, yyloc); - } - } - - private void _267() - { - // block_reference_opt -> Comma block_reference -#line 1113 "Parser.y" - { - yyval.BlockReference = GetValue(1).BlockReference; - } - } - - private void _268() - { - // block_reference_opt -> Comma -#line 1117 "Parser.y" - { - yyval.BlockReference = null; - } - } - - private void _269() - { - // block_reference_opt -> -#line 1121 "Parser.y" - { - yyval.BlockReference = null; - } - } - - private void _270() - { - // args -> arg -#line 1128 "Parser.y" - { - PushArgument(0, GetValue(1).Expression); - } - } - - private void _271() - { - // args -> compound_rhs -#line 1132 "Parser.y" - { - yyval.ArgumentCount = GetValue(1).ArgumentCount; - } - } - - private void _272() - { - // compound_rhs -> Star arg -#line 1139 "Parser.y" - { - PushArgument(0, new SplattedArgument(GetValue(1).Expression)); - } - } - - private void _273() - { - // compound_rhs -> args Comma arg -#line 1143 "Parser.y" - { - PushArgument(GetValue(3).ArgumentCount, GetValue(1).Expression); - } - } - - private void _274() - { - // compound_rhs -> args Comma Star arg -#line 1147 "Parser.y" - { - PushArgument(GetValue(4).ArgumentCount, new SplattedArgument(GetValue(1).Expression)); - } - } - - private void _276() - { - // primary -> symbol -#line 1155 "Parser.y" - { - yyval.Expression = MakeSymbolLiteral(GetValue(1).ConstructedSymbol, GetLocation(1)); - } - } - - private void _277() - { - // primary -> string_concatenation -#line 1159 "Parser.y" - { - yyval.Expression = new StringConstructor(GetValue(1).Expressions, StringKind.Mutable, GetLocation(1)); - } - } - - private void _283() - { - // primary -> match_reference -#line 1168 "Parser.y" - { - yyval.Expression = GetValue(1).RegexMatchReference; - } - } - - private void _284() - { - // primary -> FunctionIdentifier -#line 1172 "Parser.y" - { - yyval.Expression = new MethodCall(null, GetValue(1).String, null, GetLocation(1)); - } - } - - private void _285() - { - // primary -> primary SeparatingDoubleColon ConstantIdentifier -#line 1176 "Parser.y" - { - yyval.Expression = new ConstantVariable(GetValue(3).Expression, GetValue(1).String, yyloc); - } - } - - private void _286() - { - // primary -> LeadingDoubleColon ConstantIdentifier -#line 1180 "Parser.y" - { - yyval.Expression = new ConstantVariable(null, GetValue(1).String, yyloc); - } - } - - private void _287() - { - // primary -> LeftBracket array_items RightBracket -#line 1184 "Parser.y" - { - yyval.Expression = new ArrayConstructor(GetValue(2).Arguments, yyloc); - } - } - - private void _288() - { - // primary -> LeftBrace RightBrace -#line 1188 "Parser.y" - { - yyval.Expression = new HashConstructor(Maplet.EmptyArray, yyloc); - } - } - - private void _289() - { - // primary -> LeftBrace maplets trailer RightBrace -#line 1192 "Parser.y" - { - yyval.Expression = new HashConstructor(GetValue(3).Maplets.ToArray(), yyloc); - } - } - - private void _290() - { - // primary -> Yield LeftParenthesis call_args closing_parenthesis -#line 1196 "Parser.y" - { - yyval.Expression = new YieldCall(RequireNoBlockArg(GetValue(2)), yyloc); - } - } - - private void _291() - { - // primary -> Yield LeftParenthesis closing_parenthesis -#line 1200 "Parser.y" - { - yyval.Expression = new YieldCall(Arguments.Empty, yyloc); - } - } - - private void _292() - { - // primary -> Yield -#line 1204 "Parser.y" - { - yyval.Expression = new YieldCall(null, GetLocation(1)); - } - } - - private void _293() - { - // primary -> Defined new_line_opt LeftParenthesis expr closing_parenthesis -#line 1208 "Parser.y" - { - yyval.Expression = new IsDefinedExpression(GetValue(2).Expression, yyloc); - } - } - - private void _294() - { - // primary -> Not LeftParenthesis expr closing_parenthesis -#line 1212 "Parser.y" - { - yyval.Expression = new NotExpression(GetValue(2).Expression, yyloc); - } - } - - private void _295() - { - // primary -> Not LeftParenthesis closing_parenthesis -#line 1216 "Parser.y" - { - yyval.Expression = new NotExpression(null, yyloc); - } - } - - private void _296() - { - // primary -> operation brace_block -#line 1220 "Parser.y" - { - yyval.Expression = new MethodCall(null, GetValue(2).String, null, GetValue(1).BlockDefinition, GetLocation(2)); - } - } - - private void _298() - { - // primary -> method_call brace_block -#line 1225 "Parser.y" - { - SetBlock(GetValue(2).CallExpression, GetValue(1).BlockDefinition); - yyval.Expression = GetValue(2).CallExpression; - } - } - - private void _299() - { - // primary -> If expr then compstmt if_tail End -#line 1230 "Parser.y" - { - yyval.Expression = MakeIfExpression(ToCondition(GetValue(5).Expression), GetValue(3).Statements, GetValue(2).ElseIfClauses, yyloc); - } - } - - private void _300() - { - // primary -> Unless expr then compstmt else_opt End -#line 1234 "Parser.y" - { - yyval.Expression = new UnlessExpression(ToCondition(GetValue(5).Expression), GetValue(3).Statements, GetValue(2).ElseIfClause, yyloc); - } - } - - private void _301() - { - // @7 -> -#line 1238 "Parser.y" - { - _tokenizer.EnterLoopCondition(); - } - } - - private void _302() - { - // @8 -> -#line 1242 "Parser.y" - { - _tokenizer.LeaveLoopCondition(); - } - } - - private void _303() - { - // primary -> While @7 expr do @8 compstmt End -#line 1246 "Parser.y" - { - yyval.Expression = new WhileLoopExpression(ToCondition(GetValue(5).Expression), true, false, GetValue(2).Statements, yyloc); - } - } - - private void _304() - { - // @9 -> -#line 1250 "Parser.y" - { - _tokenizer.EnterLoopCondition(); - } - } - - private void _305() - { - // @10 -> -#line 1254 "Parser.y" - { - _tokenizer.LeaveLoopCondition(); - } - } - - private void _306() - { - // primary -> Until @9 expr do @10 compstmt End -#line 1258 "Parser.y" - { - yyval.Expression = new WhileLoopExpression(ToCondition(GetValue(5).Expression), false, false, GetValue(2).Statements, yyloc); - } - } - - private void _308() - { - // @11 -> -#line 1263 "Parser.y" - { - _tokenizer.EnterLoopCondition(); - } - } - - private void _309() - { - // @12 -> -#line 1267 "Parser.y" - { - _tokenizer.LeaveLoopCondition(); - EnterPaddingScope(); - } - } - - private void _310() - { - // primary -> For for_parameters In @11 expr do @12 compstmt End -#line 1272 "Parser.y" - { - yyval.Expression = MakeForLoopExpression(GetValue(8).CompoundLeftValue, GetValue(5).Expression, GetValue(2).Statements, yyloc); - LeaveScope(); - } - } - - private void _311() - { - // primary -> block_expression -#line 1277 "Parser.y" - { - yyval.Expression = GetValue(1).Expression; - } - } - - private void _312() - { - // primary -> definition_expression -#line 1281 "Parser.y" - { - yyval.Expression = GetValue(1).Expression; - } - } - - private void _313() - { - // @13 -> -#line 1288 "Parser.y" - { - _tokenizer.LexicalState = LexicalState.EXPR_ENDARG; - } - } - - private void _314() - { - // block_expression -> LeftArgParenthesis expr @13 closing_parenthesis -#line 1292 "Parser.y" - { - _tokenizer.ReportWarning(Errors.InterpretedAsGroupedExpression); - // BlockExpression behaves like an expression, so we don't need to create one here: - yyval.Expression = GetValue(3).Expression; - } - } - - private void _315() - { - // block_expression -> LeftExprParenthesis compstmt RightParenthesis -#line 1298 "Parser.y" - { - yyval.Expression = MakeBlockExpression(GetValue(2).Statements, yyloc); - } - } - - private void _316() - { - // block_expression -> Begin body End -#line 1302 "Parser.y" - { - yyval.Expression = GetValue(2).Body; - } - } - - private void _317() - { - // @14 -> -#line 1309 "Parser.y" - { - EnterClassDefinitionScope(); - } - } - - private void _318() - { - // definition_expression -> Class qualified_module_name superclass @14 body End -#line 1313 "Parser.y" - { - if (InMethod) { - ErrorSink.Add(_sourceUnit, "class definition in method body", GetLocation(6), -1, Severity.Error); - } - yyval.Expression = new ClassDefinition(CurrentScope, GetValue(5).ConstantVariable, GetValue(4).Expression, GetValue(2).Body, yyloc); - LeaveScope(); - } - } - - private void _319() - { - // @15 -> -#line 1321 "Parser.y" - { - yyval.Integer1 = _inInstanceMethodDefinition; - _inInstanceMethodDefinition = 0; - } - } - - private void _320() - { - // @16 -> -#line 1326 "Parser.y" - { - yyval.Integer1 = _inSingletonMethodDefinition; - _inSingletonMethodDefinition = 0; - EnterSingletonClassDefinitionScope(); - } - } - - private void _321() - { - // definition_expression -> Class Lshft expr @15 term @16 body End -#line 1332 "Parser.y" - { - _inInstanceMethodDefinition = GetValue(5).Integer1; - _inSingletonMethodDefinition = GetValue(3).Integer1; - yyval.Expression = new SingletonDefinition(LeaveScope(), GetValue(6).Expression, GetValue(2).Body, yyloc); - } - } - - private void _322() - { - // @17 -> -#line 1338 "Parser.y" - { - EnterModuleDefinitionScope(); - } - } - - private void _323() - { - // definition_expression -> Module qualified_module_name @17 body End -#line 1342 "Parser.y" - { - if (InMethod) { - ErrorSink.Add(_sourceUnit, "module definition in method body", GetLocation(5), -1, Severity.Error); - } - yyval.Expression = new ModuleDefinition(CurrentScope, GetValue(4).ConstantVariable, GetValue(2).Body, yyloc); - LeaveScope(); - } - } - - private void _324() - { - // @18 -> -#line 1350 "Parser.y" - { - _inInstanceMethodDefinition++; - EnterMethodDefinitionScope(); - } - } - - private void _325() - { - // definition_expression -> Def method_name @18 method_parameters body End -#line 1355 "Parser.y" - { - _inInstanceMethodDefinition--; - yyval.Expression = new MethodDefinition(CurrentScope, null, GetValue(5).String, GetValue(3).Parameters, GetValue(2).Body, yyloc); - LeaveScope(); - } - } - - private void _326() - { - // @19 -> -#line 1361 "Parser.y" - { - _tokenizer.LexicalState = LexicalState.EXPR_FNAME; - } - } - - private void _327() - { - // @20 -> -#line 1365 "Parser.y" - { - _inSingletonMethodDefinition++; - _tokenizer.LexicalState = LexicalState.EXPR_ENDFN; // 1.8: EXPR_END - EnterSingletonMethodDefinitionScope(); - } - } - - private void _328() - { - // definition_expression -> Def singleton dot_or_colon @19 method_name @20 method_parameters body End -#line 1371 "Parser.y" - { - _inSingletonMethodDefinition--; - yyval.Expression = new MethodDefinition(CurrentScope, GetValue(8).Expression, GetValue(5).String, GetValue(3).Parameters, GetValue(2).Body, yyloc); - LeaveScope(); - } - } - - private void _329() - { - // definition_expression -> Lambda lambda -#line 1377 "Parser.y" - { - yyval.Expression = GetValue(1).LambdaDefinition; - } - } - - private void _330() - { - // body -> compstmt rescue_clauses_opt else_opt ensure_opt -#line 1384 "Parser.y" - { - yyval.Body = MakeBody(GetValue(4).Statements, GetValue(3).RescueClauses, GetValue(2).ElseIfClause, GetLocation(2), GetValue(1).Statements, yyloc); - } - } - - private void _331() - { - // case_expression -> Case expr terms_opt when_clauses else_opt End -#line 1391 "Parser.y" - { - yyval.Expression = new CaseExpression(GetValue(5).Expression, GetValue(3).WhenClauses.ToArray(), GetValue(2).ElseIfClause, yyloc); - } - } - - private void _332() - { - // case_expression -> Case terms_opt when_clauses else_opt End -#line 1395 "Parser.y" - { - yyval.Expression = new CaseExpression(null, GetValue(3).WhenClauses.ToArray(), GetValue(2).ElseIfClause, yyloc); - } - } - - private void _338() - { - // if_tail -> else_opt -#line 1413 "Parser.y" - { - yyval.ElseIfClauses = MakeListAddOpt(GetValue(1).ElseIfClause); - } - } - - private void _339() - { - // if_tail -> Elsif expr then compstmt if_tail -#line 1417 "Parser.y" - { - GetValue(1).ElseIfClauses.Add(new ElseIfClause(GetValue(4).Expression, GetValue(2).Statements, yyloc)); - yyval.ElseIfClauses = GetValue(1).ElseIfClauses; - } - } - - private void _340() - { - // else_opt -> -#line 1424 "Parser.y" - { - yyval.ElseIfClause = null; - } - } - - private void _341() - { - // else_opt -> Else compstmt -#line 1428 "Parser.y" - { - yyval.ElseIfClause = new ElseIfClause(null, GetValue(1).Statements, yyloc); - } - } - - private void _342() - { - // for_parameters -> lhs -#line 1435 "Parser.y" - { - yyval.CompoundLeftValue = new CompoundLeftValue(new LeftValue[] { GetValue(1).LeftValue }); - } - } - - private void _343() - { - // for_parameters -> compound_lhs -#line 1439 "Parser.y" - { - yyval.CompoundLeftValue = GetValue(1).CompoundLeftValue; - } - } - - private void _344() - { - // parameter_list -> parenthesized_parameter -#line 1446 "Parser.y" - { - yyval.LeftValues = CollectionUtils.MakeList(GetValue(1).LeftValue); - } - } - - private void _345() - { - // parameter_list -> parameter_list Comma parenthesized_parameter -#line 1450 "Parser.y" - { - (yyval.LeftValues = GetValue(3).LeftValues).Add(GetValue(1).LeftValue); - } - } - - private void _346() - { - // parenthesized_parameter -> parameter -#line 1457 "Parser.y" - { - yyval.LeftValue = GetValue(1).LocalVariable; - } - } - - private void _347() - { - // parenthesized_parameter -> LeftExprParenthesis compound_parameters closing_parenthesis -#line 1461 "Parser.y" - { - yyval.LeftValue = GetValue(2).CompoundLeftValue; - } - } - - private void _348() - { - // compound_parameters -> compound_parameter_list -#line 1468 "Parser.y" - { - yyval.CompoundLeftValue = new CompoundLeftValue(GetValue(1).LeftValues.ToArray()); - } - } - - private void _349() - { - // compound_parameters -> compound_parameter_list Comma Star parameter -#line 1472 "Parser.y" - { - yyval.CompoundLeftValue = MakeCompoundLeftValue(GetValue(4).LeftValues, GetValue(1).LocalVariable, null); - } - } - - private void _350() - { - // compound_parameters -> compound_parameter_list Comma Star -#line 1476 "Parser.y" - { - yyval.CompoundLeftValue = MakeCompoundLeftValue(GetValue(3).LeftValues, Placeholder.Singleton, null); - } - } - - private void _351() - { - // compound_parameters -> compound_parameter_list Comma Star parameter Comma compound_parameter_list -#line 1480 "Parser.y" - { - yyval.CompoundLeftValue = MakeCompoundLeftValue(GetValue(6).LeftValues, GetValue(3).LocalVariable, GetValue(1).LeftValues); - } - } - - private void _352() - { - // compound_parameters -> compound_parameter_list Comma Star Comma compound_parameter_list -#line 1484 "Parser.y" - { - yyval.CompoundLeftValue = MakeCompoundLeftValue(GetValue(5).LeftValues, Placeholder.Singleton, GetValue(1).LeftValues); - } - } - - private void _353() - { - // compound_parameters -> Star parameter Comma compound_parameter_list -#line 1488 "Parser.y" - { - yyval.CompoundLeftValue = MakeCompoundLeftValue(null, GetValue(3).LocalVariable, GetValue(1).LeftValues); - } - } - - private void _354() - { - // compound_parameters -> Star Comma compound_parameter_list -#line 1492 "Parser.y" - { - yyval.CompoundLeftValue = MakeCompoundLeftValue(null, Placeholder.Singleton, GetValue(1).LeftValues); - } - } - - private void _355() - { - // compound_parameters -> Star parameter -#line 1496 "Parser.y" - { - yyval.CompoundLeftValue = new CompoundLeftValue(new LeftValue[] { GetValue(1).LocalVariable }, 0); - } - } - - private void _356() - { - // compound_parameters -> Star -#line 1500 "Parser.y" - { - yyval.CompoundLeftValue = new CompoundLeftValue(new LeftValue[] { Placeholder.Singleton }, 0); - } - } - - private void _357() - { - // compound_parameter_list -> compound_parameter -#line 1507 "Parser.y" - { - yyval.LeftValues = CollectionUtils.MakeList(GetValue(1).LeftValue); - } - } - - private void _358() - { - // compound_parameter_list -> compound_parameter_list Comma compound_parameter -#line 1511 "Parser.y" - { - (yyval.LeftValues = GetValue(3).LeftValues).Add(GetValue(1).LeftValue); - } - } - - private void _359() - { - // compound_parameter -> parameter -#line 1518 "Parser.y" - { - yyval.LeftValue = GetValue(1).LocalVariable; - } - } - - private void _360() - { - // compound_parameter -> LeftExprParenthesis compound_parameters closing_parenthesis -#line 1522 "Parser.y" - { - yyval.LeftValue = GetValue(2).CompoundLeftValue; - } - } - - private void _361() - { - // block_parameter_list -> parameter_list Comma default_block_parameter_list Comma parameter_array block_parameter_opt -#line 1529 "Parser.y" - { - yyval.Parameters = new Parameters(GetValue(6).LeftValues.ToArray(), GetValue(6).LeftValues.Count, GetValue(4).SimpleAssignmentExpressions.ToArray(), GetValue(1).LocalVariable, GetValue(1).LocalVariable, yyloc); - } - } - - private void _362() - { - // block_parameter_list -> parameter_list Comma default_block_parameter_list Comma parameter_array Comma parameter_list block_parameter_opt -#line 1533 "Parser.y" - { - yyval.Parameters = new Parameters(MakeArray(GetValue(8).LeftValues, GetValue(2).LeftValues), GetValue(8).LeftValues.Count, GetValue(6).SimpleAssignmentExpressions.ToArray(), GetValue(4).LocalVariable, GetValue(1).LocalVariable, yyloc); - } - } - - private void _363() - { - // block_parameter_list -> parameter_list Comma default_block_parameter_list block_parameter_opt -#line 1537 "Parser.y" - { - yyval.Parameters = new Parameters(GetValue(4).LeftValues.ToArray(), GetValue(4).LeftValues.Count, GetValue(2).SimpleAssignmentExpressions.ToArray(), null, GetValue(1).LocalVariable, yyloc); - } - } - - private void _364() - { - // block_parameter_list -> parameter_list Comma default_block_parameter_list Comma parameter_list block_parameter_opt -#line 1541 "Parser.y" - { - yyval.Parameters = new Parameters(MakeArray(GetValue(6).LeftValues, GetValue(2).LeftValues), GetValue(6).LeftValues.Count, GetValue(4).SimpleAssignmentExpressions.ToArray(), null, GetValue(1).LocalVariable, yyloc); - } - } - - private void _365() - { - // block_parameter_list -> parameter_list Comma parameter_array block_parameter_opt -#line 1545 "Parser.y" - { - yyval.Parameters = new Parameters(GetValue(4).LeftValues.ToArray(), GetValue(4).LeftValues.Count, null, GetValue(2).LocalVariable, GetValue(1).LocalVariable, yyloc); - } - } - - private void _366() - { - // block_parameter_list -> parameter_list Comma -#line 1549 "Parser.y" - { - yyval.Parameters = new Parameters(MakeArray(GetValue(2).LeftValues, Placeholder.Singleton), GetValue(2).LeftValues.Count, null, null, null, yyloc); - } - } - - private void _367() - { - // block_parameter_list -> parameter_list Comma parameter_array Comma parameter_list block_parameter_opt -#line 1553 "Parser.y" - { - yyval.Parameters = new Parameters(MakeArray(GetValue(6).LeftValues, GetValue(2).LeftValues), GetValue(6).LeftValues.Count, null, GetValue(4).LocalVariable, GetValue(1).LocalVariable, yyloc); - } - } - - private void _368() - { - // block_parameter_list -> parameter_list block_parameter_opt -#line 1557 "Parser.y" - { - yyval.Parameters = new Parameters(GetValue(2).LeftValues.ToArray(), GetValue(2).LeftValues.Count, null, null, GetValue(1).LocalVariable, yyloc); - } - } - - private void _369() - { - // block_parameter_list -> default_block_parameter_list Comma parameter_array block_parameter_opt -#line 1561 "Parser.y" - { - yyval.Parameters = new Parameters(null, 0, GetValue(4).SimpleAssignmentExpressions.ToArray(), GetValue(2).LocalVariable, GetValue(1).LocalVariable, yyloc); - } - } - - private void _370() - { - // block_parameter_list -> default_block_parameter_list Comma parameter_array Comma parameter_list block_parameter_opt -#line 1565 "Parser.y" - { - yyval.Parameters = new Parameters(GetValue(2).LeftValues.ToArray(), 0, GetValue(6).SimpleAssignmentExpressions.ToArray(), GetValue(4).LocalVariable, GetValue(1).LocalVariable, yyloc); - } - } - - private void _371() - { - // block_parameter_list -> default_block_parameter_list block_parameter_opt -#line 1569 "Parser.y" - { - yyval.Parameters = new Parameters(null, 0, GetValue(2).SimpleAssignmentExpressions.ToArray(), null, GetValue(1).LocalVariable, yyloc); - } - } - - private void _372() - { - // block_parameter_list -> default_block_parameter_list Comma parameter_list block_parameter_opt -#line 1573 "Parser.y" - { - yyval.Parameters = new Parameters(GetValue(2).LeftValues.ToArray(), 0, GetValue(4).SimpleAssignmentExpressions.ToArray(), null, GetValue(1).LocalVariable, yyloc); - } - } - - private void _373() - { - // block_parameter_list -> parameter_array block_parameter_opt -#line 1577 "Parser.y" - { - yyval.Parameters = new Parameters(null, 0, null, GetValue(2).LocalVariable, GetValue(1).LocalVariable, yyloc); - } - } - - private void _374() - { - // block_parameter_list -> parameter_array Comma parameter_list block_parameter_opt -#line 1581 "Parser.y" - { - yyval.Parameters = new Parameters(GetValue(2).LeftValues.ToArray(), 0, null, GetValue(4).LocalVariable, GetValue(1).LocalVariable, yyloc); - } - } - - private void _375() - { - // block_parameter_list -> block_parameter -#line 1585 "Parser.y" - { - yyval.Parameters = new Parameters(null, 0, null, null, GetValue(1).LocalVariable, yyloc); - } - } - - private void _376() - { - // block_parameter_list -> -#line 1589 "Parser.y" - { - yyval.Parameters = Parameters.Empty; - } - } - - private void _377() - { - // block_parameters_opt -> -#line 1596 "Parser.y" - { - yyval.Parameters = null; - } - } - - private void _378() - { - // block_parameters_opt -> block_parameters -#line 1600 "Parser.y" - { - _tokenizer.CommandMode = true; - yyval.Parameters = GetValue(1).Parameters; - } - } - - private void _379() - { - // block_parameters -> LogicalOr -#line 1608 "Parser.y" - { - yyval.Parameters = null; - } - } - - private void _380() - { - // block_parameters -> Pipe block_parameter_list block_variables_opt Pipe -#line 1612 "Parser.y" - { - yyval.Parameters = GetValue(3).Parameters; - } - } - - private void _381() - { - // block_variables_opt -> - } - - private void _385() - { - // @21 -> -#line 1628 "Parser.y" - { - yyval.Integer1 = _tokenizer.EnterLambdaDefinition(); - EnterNestedScope(); - } - } - - private void _386() - { - // lambda -> @21 lambda_parameters lambda_body -#line 1633 "Parser.y" - { - yyval.LambdaDefinition = MakeLambdaDefinition(GetValue(2).Parameters, GetValue(1).Statements, yyloc); - _tokenizer.LeaveLambdaDefinition(yyval.Integer1); - LeaveScope(); - } - } - - private void _387() - { - // lambda_parameters -> LeftParenthesis parameters block_variables_opt closing_parenthesis -#line 1642 "Parser.y" - { - yyval.Parameters = GetValue(3).Parameters; - } - } - - private void _388() - { - // lambda_parameters -> parameters -#line 1646 "Parser.y" - { - yyval.Parameters = GetValue(1).Parameters; - } - } - - private void _389() - { - // lambda_body -> LeftLambdaBrace compstmt RightBrace -#line 1653 "Parser.y" - { - yyval.Statements = GetValue(2).Statements; - } - } - - private void _390() - { - // lambda_body -> LambdaDo compstmt End -#line 1657 "Parser.y" - { - yyval.Statements = GetValue(2).Statements; - } - } - - private void _391() - { - // @22 -> -#line 1664 "Parser.y" - { - EnterNestedScope(); - } - } - - private void _392() - { - // do_block -> BlockDo @22 block_parameters_opt compstmt End -#line 1668 "Parser.y" - { - yyval.BlockDefinition = MakeBlockDefinition(GetValue(3).Parameters, GetValue(2).Statements, yyloc); - LeaveScope(); - } - } - - private void _393() - { - // block_call -> command do_block -#line 1676 "Parser.y" - { - if (GetValue(2).CallExpression is YieldCall) { - _tokenizer.ReportError(Errors.BlockGivenToYield); - } - - SetBlock(yyval.CallExpression = GetValue(2).CallExpression, GetValue(1).BlockDefinition); - } - } - - private void _394() - { - // block_call -> block_call Dot operation2 parenthesized_args_opt -#line 1684 "Parser.y" - { - yyval.CallExpression = MakeMethodCall(GetValue(4).CallExpression, GetValue(2).String, GetValue(1), yyloc); - } - } - - private void _395() - { - // block_call -> block_call SeparatingDoubleColon operation2 parenthesized_args_opt -#line 1688 "Parser.y" - { - yyval.CallExpression = MakeMethodCall(GetValue(4).CallExpression, GetValue(2).String, GetValue(1), yyloc); - } - } - - private void _396() - { - // method_call -> operation parenthesized_args -#line 1695 "Parser.y" - { - yyval.CallExpression = MakeMethodCall(null, GetValue(2).String, GetValue(1), yyloc); - } - } - - private void _397() - { - // method_call -> primary Dot operation2 parenthesized_args_opt -#line 1699 "Parser.y" - { - yyval.CallExpression = MakeMethodCall(GetValue(4).Expression, GetValue(2).String, GetValue(1), yyloc); - } - } - - private void _398() - { - // method_call -> primary SeparatingDoubleColon operation2 parenthesized_args -#line 1703 "Parser.y" - { - yyval.CallExpression = MakeMethodCall(GetValue(4).Expression, GetValue(2).String, GetValue(1), yyloc); - } - } - - private void _399() - { - // method_call -> primary SeparatingDoubleColon operation3 -#line 1707 "Parser.y" - { - yyval.CallExpression = new MethodCall(GetValue(3).Expression, GetValue(1).String, null, GetLocation(1)); - } - } - - private void _400() - { - // method_call -> primary Dot parenthesized_args -#line 1711 "Parser.y" - { - yyval.CallExpression = MakeMethodCall(GetValue(3).Expression, Symbols.Call, GetValue(1), yyloc); - } - } - - private void _401() - { - // method_call -> primary SeparatingDoubleColon parenthesized_args -#line 1715 "Parser.y" - { - yyval.CallExpression = MakeMethodCall(GetValue(3).Expression, Symbols.Call, GetValue(1), yyloc); - } - } - - private void _402() - { - // method_call -> primary LeftIndexingBracket call_args_opt closing_bracket -#line 1719 "Parser.y" - { - yyval.CallExpression = MakeMethodCall(GetValue(4).Expression, Symbols.ArrayItemRead, GetValue(2), yyloc); - } - } - - private void _403() - { - // method_call -> Super parenthesized_args -#line 1723 "Parser.y" - { - yyval.CallExpression = MakeSuperCall(GetValue(1), GetLocation(2)); - } - } - - private void _404() - { - // method_call -> Super -#line 1727 "Parser.y" - { - yyval.CallExpression = new SuperCall(null, null, GetLocation(1)); - } - } - - private void _405() - { - // @23 -> -#line 1734 "Parser.y" - { - EnterNestedScope(); - } - } - - private void _406() - { - // brace_block -> LeftBlockBrace @23 block_parameters_opt compstmt RightBrace -#line 1738 "Parser.y" - { - yyval.BlockDefinition = MakeBlockDefinition(GetValue(3).Parameters, GetValue(2).Statements, yyloc); - LeaveScope(); - } - } - - private void _407() - { - // @24 -> -#line 1743 "Parser.y" - { - EnterNestedScope(); - } - } - - private void _408() - { - // brace_block -> Do @24 block_parameters_opt compstmt End -#line 1747 "Parser.y" - { - yyval.BlockDefinition = MakeBlockDefinition(GetValue(3).Parameters, GetValue(2).Statements, yyloc); - LeaveScope(); - } - } - - private void _409() - { - // when_clauses -> when_clause -#line 1755 "Parser.y" - { - yyval.WhenClauses = CollectionUtils.MakeList(GetValue(1).WhenClause); - } - } - - private void _410() - { - // when_clauses -> when_clauses when_clause -#line 1759 "Parser.y" - { - (yyval.WhenClauses = GetValue(2).WhenClauses).Add(GetValue(1).WhenClause); - } - } - - private void _411() - { - // when_clause -> When args then compstmt -#line 1766 "Parser.y" - { - yyval.WhenClause = new WhenClause(PopArguments(GetValue(3).ArgumentCount), GetValue(1).Statements, GetLocation(1)); - } - } - - private void _412() - { - // rescue_clauses_opt -> -#line 1773 "Parser.y" - { - yyval.RescueClauses = null; - } - } - - private void _414() - { - // rescue_clauses -> rescue_clause -#line 1781 "Parser.y" - { - yyval.RescueClauses = CollectionUtils.MakeList(GetValue(1).RescueClause); - } - } - - private void _415() - { - // rescue_clauses -> rescue_clauses rescue_clause -#line 1785 "Parser.y" - { - (yyval.RescueClauses = GetValue(2).RescueClauses).Add(GetValue(1).RescueClause); - } - } - - private void _416() - { - // rescue_clause -> Rescue exc_var then compstmt -#line 1792 "Parser.y" - { - yyval.RescueClause = new RescueClause(Expression.EmptyArray, GetValue(3).LeftValue, GetValue(1).Statements, yyloc); - } - } - - private void _417() - { - // rescue_clause -> Rescue args exc_var then compstmt -#line 1796 "Parser.y" - { - yyval.RescueClause = new RescueClause(PopArguments(GetValue(4).ArgumentCount), GetValue(3).LeftValue, GetValue(1).Statements, yyloc); - } - } - - private void _418() - { - // exc_var -> -#line 1803 "Parser.y" - { - yyval.LeftValue = null; - } - } - - private void _419() - { - // exc_var -> DoubleArrow lhs -#line 1807 "Parser.y" - { - yyval.LeftValue = GetValue(1).LeftValue; - } - } - - private void _420() - { - // ensure_opt -> -#line 1814 "Parser.y" - { - yyval.Statements = null; - } - } - - private void _421() - { - // ensure_opt -> Ensure compstmt -#line 1818 "Parser.y" - { - yyval.Statements = GetValue(1).Statements; - } - } - - private void _422() - { - // string_concatenation -> Character -#line 1825 "Parser.y" - { - yyval.Expressions = CollectionUtils.MakeList(MakeStringLiteral(GetValue(1), GetLocation(1))); - } - } - - private void _423() - { - // string_concatenation -> string -#line 1829 "Parser.y" - { - yyval.Expressions = GetValue(1).Expressions; - } - } - - private void _424() - { - // string_concatenation -> string_concatenation string -#line 1833 "Parser.y" - { - (yyval.Expressions = GetValue(2).Expressions).AddRange(GetValue(1).Expressions); - } - } - - private void _425() - { - // string -> StringBegin string_contents StringEnd -#line 1840 "Parser.y" - { - yyval.Expressions = GetValue(2).Expressions; - } - } - - private void _426() - { - // shell_string -> ShellStringBegin string_contents StringEnd -#line 1847 "Parser.y" - { - yyval.Expression = new StringConstructor(GetValue(2).Expressions, StringKind.Command, yyloc); - } - } - - private void _427() - { - // regexp -> RegexpBegin string_contents RegexpEnd -#line 1854 "Parser.y" - { - yyval.Expression = new RegularExpression(GetValue(2).Expressions, GetValue(1).RegExOptions, yyloc); - } - } - - private void _428() - { - // words -> WordsBegin StringEnd -#line 1861 "Parser.y" - { - yyval.Expression = new ArrayConstructor(null, yyloc); - } - } - - private void _429() - { - // words -> WordsBegin word_list word StringEnd -#line 1865 "Parser.y" - { - GetValue(3).Expressions.Add(new StringConstructor(GetValue(2).Expressions, StringKind.Mutable, GetLocation(2))); - yyval.Expression = new ArrayConstructor(new Arguments(GetValue(3).Expressions.ToArray()), yyloc); - } - } - - private void _430() - { - // word_list -> -#line 1873 "Parser.y" - { - yyval.Expressions = new List(); - } - } - - private void _431() - { - // word_list -> word_list word WordSeparator -#line 1877 "Parser.y" - { - (yyval.Expressions = GetValue(3).Expressions).Add(new StringConstructor(GetValue(2).Expressions, StringKind.Mutable, GetLocation(2))); - } - } - - private void _432() - { - // word -> string_content -#line 1884 "Parser.y" - { - yyval.Expressions = CollectionUtils.MakeList(GetValue(1).Expression); - } - } - - private void _433() - { - // word -> word string_content -#line 1888 "Parser.y" - { - (yyval.Expressions = GetValue(2).Expressions).Add(GetValue(1).Expression); - } - } - - private void _434() - { - // verbatim_words -> VerbatimWordsBegin StringEnd -#line 1895 "Parser.y" - { - yyval.Expression = new ArrayConstructor(null, yyloc); - } - } - - private void _435() - { - // verbatim_words -> VerbatimWordsBegin verbatim_word_list StringContent StringEnd -#line 1899 "Parser.y" - { - GetValue(3).Expressions.Add(MakeStringLiteral(GetValue(2), GetLocation(2))); - yyval.Expression = MakeVerbatimWords(GetValue(3).Expressions, yyloc); - } - } - - private void _436() - { - // verbatim_word_list -> -#line 1907 "Parser.y" - { - yyval.Expressions = new List(); - } - } - - private void _437() - { - // verbatim_word_list -> verbatim_word_list StringContent WordSeparator -#line 1911 "Parser.y" - { - (yyval.Expressions = GetValue(3).Expressions).Add(MakeStringLiteral(GetValue(2), GetLocation(2))); - } - } - - private void _438() - { - // string_contents -> -#line 1918 "Parser.y" - { - yyval.Expressions = new List(); - } - } - - private void _439() - { - // string_contents -> string_contents string_content -#line 1922 "Parser.y" - { - (yyval.Expressions = GetValue(2).Expressions).Add(GetValue(1).Expression); - } - } - - private void _440() - { - // string_content -> StringContent -#line 1930 "Parser.y" - { - yyval.Expression = MakeStringLiteral(GetValue(1), yyloc); - } - } - - private void _441() - { - // string_content -> StringEmbeddedVariableBegin string_embedded_variable -#line 1934 "Parser.y" - { - yyval.Expression = GetValue(1).Expression; - } - } - - private void _442() - { - // string_content -> StringEmbeddedCodeBegin compstmt StringEmbeddedCodeEnd -#line 1938 "Parser.y" - { - // STRING_EMBEDDED_CODE_END leaves parenthesised expression, but command_args in compstmt restores it back to the state after - // STRING_EMBEDDED_CODE_BEGIN. So we need to leave it again. - _tokenizer.PopParenthesisedExpressionStack(); - yyval.Expression = MakeBlockExpression(GetValue(2).Statements, GetLocation(2)); - } - } - - private void _443() - { - // string_embedded_variable -> GlobalVariable -#line 1948 "Parser.y" - { - yyval.Expression = new GlobalVariable(GetValue(1).String, yyloc); - } - } - - private void _444() - { - // string_embedded_variable -> match_reference -#line 1952 "Parser.y" - { - yyval.Expression = GetValue(1).RegexMatchReference; - } - } - - private void _445() - { - // string_embedded_variable -> InstanceVariable -#line 1956 "Parser.y" - { - yyval.Expression = new InstanceVariable(GetValue(1).String, yyloc); - } - } - - private void _446() - { - // string_embedded_variable -> ClassVariable -#line 1960 "Parser.y" - { - yyval.Expression = new ClassVariable(GetValue(1).String, yyloc); - } - } - - private void _447() - { - // numeric_literal -> Integer -#line 1967 "Parser.y" - { - // unsigned integer: - yyval.Expression = Literal.Integer(GetValue(1).Integer1, yyloc); - } - } - - private void _448() - { - // numeric_literal -> BigInteger -#line 1972 "Parser.y" - { - yyval.Expression = Literal.BigInteger(GetValue(1).BigInteger, yyloc); - } - } - - private void _449() - { - // numeric_literal -> Float -#line 1976 "Parser.y" - { - yyval.Expression = Literal.Double(GetValue(1).Double, yyloc); - } - } - - private void _450() - { - // numeric_literal -> NumberNegation Integer -#line 1980 "Parser.y" - { - // cannot overflow INTEGER is unsigned and Int32.MaxValue < |Int32.MinValue| - yyval.Expression = Literal.Integer(-GetValue(1).Integer1, yyloc); - } - } - - private void _451() - { - // numeric_literal -> NumberNegation BigInteger -#line 1985 "Parser.y" - { - // TODO: -|Int32.MinValue| actually ends up here (converted to bigint) instead of being Int32. We should fix that. - yyval.Expression = Literal.BigInteger(-GetValue(1).BigInteger, yyloc); - } - } - - private void _452() - { - // numeric_literal -> NumberNegation Float -#line 1990 "Parser.y" - { - yyval.Expression = Literal.Double(-GetValue(1).Double, yyloc); - } - } - - private void _453() - { - // variable -> Identifier -#line 1996 "Parser.y" - { yyval.VariableFactory = VariableFactory.Identifier; yyval.String = GetValue(1).String; } - } - - private void _454() - { - // variable -> InstanceVariable -#line 1997 "Parser.y" - { yyval.VariableFactory = VariableFactory.Instance; yyval.String = GetValue(1).String; } - } - - private void _455() - { - // variable -> GlobalVariable -#line 1998 "Parser.y" - { yyval.VariableFactory = VariableFactory.Global; yyval.String = GetValue(1).String; } - } - - private void _456() - { - // variable -> ConstantIdentifier -#line 1999 "Parser.y" - { yyval.VariableFactory = VariableFactory.Constant; yyval.String = GetValue(1).String; } - } - - private void _457() - { - // variable -> ClassVariable -#line 2000 "Parser.y" - { yyval.VariableFactory = VariableFactory.Class; yyval.String = GetValue(1).String; } - } - - private void _458() - { - // variable -> Nil -#line 2001 "Parser.y" - { yyval.VariableFactory = VariableFactory.Nil; yyval.String = null; } - } - - private void _459() - { - // variable -> Self -#line 2002 "Parser.y" - { yyval.VariableFactory = VariableFactory.Self; yyval.String = null; } - } - - private void _460() - { - // variable -> True -#line 2003 "Parser.y" - { yyval.VariableFactory = VariableFactory.True; yyval.String = null; } - } - - private void _461() - { - // variable -> False -#line 2004 "Parser.y" - { yyval.VariableFactory = VariableFactory.False; yyval.String = null; } - } - - private void _462() - { - // variable -> File -#line 2005 "Parser.y" - { yyval.VariableFactory = VariableFactory.File; yyval.String = null; } - } - - private void _463() - { - // variable -> Line -#line 2006 "Parser.y" - { yyval.VariableFactory = VariableFactory.Line; yyval.String = null; } - } - - private void _464() - { - // variable -> Encoding -#line 2007 "Parser.y" - { yyval.VariableFactory = VariableFactory.Encoding; yyval.String = null; } - } - - private void _465() - { - // var_ref -> variable -#line 2012 "Parser.y" - { - yyval.Expression = VariableFactory.MakeRead(GetValue(1).VariableFactory, this, GetValue(1).String, yyloc); - } - } - - private void _466() - { - // var_lhs -> variable -#line 2019 "Parser.y" - { - yyval.LeftValue = VariableFactory.MakeLeftValue(GetValue(1).VariableFactory, this, GetValue(1).String, yyloc); - } - } - - private void _467() - { - // match_reference -> MatchReference -#line 2026 "Parser.y" - { - yyval.RegexMatchReference = new RegexMatchReference(GetValue(1).Integer1, GetLocation(1)); - } - } - - private void _468() - { - // superclass -> term -#line 2033 "Parser.y" - { - yyval.Expression = null; - } - } - - private void _469() - { - // @25 -> -#line 2037 "Parser.y" - { - _tokenizer.LexicalState = LexicalState.EXPR_BEG; - } - } - - private void _470() - { - // superclass -> Less @25 expr term -#line 2041 "Parser.y" - { - yyval.Expression = GetValue(2).Expression; - } - } - - private void _471() - { - // superclass -> Error term -#line 2045 "Parser.y" - { - StopErrorRecovery(); - yyval.Expression = null; - } - } - - private void _472() - { - // method_parameters -> LeftParenthesis parameters closing_parenthesis -#line 2053 "Parser.y" - { - yyval.Parameters = GetValue(2).Parameters; - _tokenizer.LexicalState = LexicalState.EXPR_BEG; - _tokenizer.CommandMode = true; - } - } - - private void _473() - { - // method_parameters -> parameters term -#line 2059 "Parser.y" - { - yyval.Parameters = GetValue(2).Parameters; - } - } - - private void _474() - { - // parameters -> parameter_list Comma default_parameter_list Comma parameter_array block_parameter_opt -#line 2066 "Parser.y" - { - yyval.Parameters = new Parameters(GetValue(6).LeftValues.ToArray(), GetValue(6).LeftValues.Count, GetValue(4).SimpleAssignmentExpressions.ToArray(), GetValue(2).LocalVariable, GetValue(1).LocalVariable, yyloc); - } - } - - private void _475() - { - // parameters -> parameter_list Comma default_parameter_list Comma parameter_array Comma parameter_list block_parameter_opt -#line 2070 "Parser.y" - { - yyval.Parameters = new Parameters(MakeArray(GetValue(8).LeftValues, GetValue(2).LeftValues), GetValue(8).LeftValues.Count, GetValue(6).SimpleAssignmentExpressions.ToArray(), GetValue(4).LocalVariable, GetValue(1).LocalVariable, yyloc); - } - } - - private void _476() - { - // parameters -> parameter_list Comma default_parameter_list block_parameter_opt -#line 2074 "Parser.y" - { - yyval.Parameters = new Parameters(GetValue(4).LeftValues.ToArray(), GetValue(4).LeftValues.Count, GetValue(2).SimpleAssignmentExpressions.ToArray(), null, GetValue(1).LocalVariable, yyloc); - } - } - - private void _477() - { - // parameters -> parameter_list Comma default_parameter_list Comma parameter_list block_parameter_opt -#line 2078 "Parser.y" - { - yyval.Parameters = new Parameters(MakeArray(GetValue(6).LeftValues, GetValue(2).LeftValues), GetValue(6).LeftValues.Count, GetValue(4).SimpleAssignmentExpressions.ToArray(), null, GetValue(1).LocalVariable, yyloc); - } - } - - private void _478() - { - // parameters -> parameter_list Comma parameter_array block_parameter_opt -#line 2082 "Parser.y" - { - yyval.Parameters = new Parameters(GetValue(4).LeftValues.ToArray(), GetValue(4).LeftValues.Count, null, GetValue(2).LocalVariable, GetValue(1).LocalVariable, yyloc); - } - } - - private void _479() - { - // parameters -> parameter_list Comma parameter_array Comma parameter_list block_parameter_opt -#line 2086 "Parser.y" - { - yyval.Parameters = new Parameters(MakeArray(GetValue(6).LeftValues, GetValue(2).LeftValues), GetValue(6).LeftValues.Count, null, GetValue(4).LocalVariable, GetValue(1).LocalVariable, yyloc); - } - } - - private void _480() - { - // parameters -> parameter_list block_parameter_opt -#line 2090 "Parser.y" - { - yyval.Parameters = new Parameters(GetValue(2).LeftValues.ToArray(), GetValue(2).LeftValues.Count, null, null, GetValue(1).LocalVariable, yyloc); - } - } - - private void _481() - { - // parameters -> default_parameter_list Comma parameter_array block_parameter_opt -#line 2094 "Parser.y" - { - yyval.Parameters = new Parameters(null, 0, GetValue(4).SimpleAssignmentExpressions.ToArray(), GetValue(2).LocalVariable, GetValue(1).LocalVariable, yyloc); - } - } - - private void _482() - { - // parameters -> default_parameter_list Comma parameter_array Comma parameter_list block_parameter_opt -#line 2098 "Parser.y" - { - yyval.Parameters = new Parameters(GetValue(2).LeftValues.ToArray(), 0, GetValue(6).SimpleAssignmentExpressions.ToArray(), GetValue(4).LocalVariable, GetValue(1).LocalVariable, yyloc); - } - } - - private void _483() - { - // parameters -> default_parameter_list block_parameter_opt -#line 2102 "Parser.y" - { - yyval.Parameters = new Parameters(null, 0, GetValue(2).SimpleAssignmentExpressions.ToArray(), null, GetValue(1).LocalVariable, yyloc); - } - } - - private void _484() - { - // parameters -> default_parameter_list Comma parameter_list block_parameter_opt -#line 2106 "Parser.y" - { - yyval.Parameters = new Parameters(GetValue(2).LeftValues.ToArray(), 0, GetValue(4).SimpleAssignmentExpressions.ToArray(), null, GetValue(1).LocalVariable, yyloc); - } - } - - private void _485() - { - // parameters -> parameter_array block_parameter_opt -#line 2110 "Parser.y" - { - yyval.Parameters = new Parameters(null, 0, null, GetValue(2).LocalVariable, GetValue(1).LocalVariable, yyloc); - } - } - - private void _486() - { - // parameters -> parameter_array Comma parameter_list block_parameter_opt -#line 2114 "Parser.y" - { - yyval.Parameters = new Parameters(GetValue(2).LeftValues.ToArray(), 0, null, GetValue(4).LocalVariable, GetValue(1).LocalVariable, yyloc); - } - } - - private void _487() - { - // parameters -> block_parameter -#line 2118 "Parser.y" - { - yyval.Parameters = new Parameters(null, 0, null, null, GetValue(1).LocalVariable, yyloc); - } - } - - private void _488() - { - // parameters -> -#line 2122 "Parser.y" - { - yyval.Parameters = Parameters.Empty; - } - } - - private void _489() - { - // parameter -> ConstantIdentifier -#line 2129 "Parser.y" - { - _tokenizer.ReportError(Errors.FormalArgumentIsConstantVariable); - yyval.LocalVariable = DefineParameter(GenerateErrorConstantName(), yyloc); - } - } - - private void _490() - { - // parameter -> InstanceVariable -#line 2134 "Parser.y" - { - _tokenizer.ReportError(Errors.FormalArgumentIsInstanceVariable); - yyval.LocalVariable = DefineParameter(GenerateErrorConstantName(), yyloc); - } - } - - private void _491() - { - // parameter -> GlobalVariable -#line 2139 "Parser.y" - { - _tokenizer.ReportError(Errors.FormalArgumentIsGlobalVariable); - yyval.LocalVariable = DefineParameter(GenerateErrorConstantName(), yyloc); - } - } - - private void _492() - { - // parameter -> ClassVariable -#line 2144 "Parser.y" - { - _tokenizer.ReportError(Errors.FormalArgumentIsClassVariable); - yyval.LocalVariable = DefineParameter(GenerateErrorConstantName(), yyloc); - } - } - - private void _493() - { - // parameter -> Identifier -#line 2149 "Parser.y" - { - yyval.LocalVariable = DefineParameter(GetValue(1).String, yyloc); - } - } - - private void _494() - { - // default_parameter -> Identifier Assignment arg -#line 2156 "Parser.y" - { - yyval.SimpleAssignmentExpression = new SimpleAssignmentExpression(DefineParameter(GetValue(3).String, yyloc), GetValue(1).Expression, null, yyloc); - } - } - - private void _495() - { - // default_block_parameter -> Identifier Assignment primary -#line 2165 "Parser.y" - { - yyval.SimpleAssignmentExpression = new SimpleAssignmentExpression(DefineParameter(GetValue(3).String, yyloc), GetValue(1).Expression, null, yyloc); - } - } - - private void _496() - { - // default_parameter_list -> default_parameter -#line 2172 "Parser.y" - { - yyval.SimpleAssignmentExpressions = CollectionUtils.MakeList(GetValue(1).SimpleAssignmentExpression); - } - } - - private void _497() - { - // default_parameter_list -> default_parameter_list Comma default_parameter -#line 2176 "Parser.y" - { - (yyval.SimpleAssignmentExpressions = GetValue(3).SimpleAssignmentExpressions).Add(GetValue(1).SimpleAssignmentExpression); - } - } - - private void _498() - { - // default_block_parameter_list -> default_block_parameter -#line 2183 "Parser.y" - { - yyval.SimpleAssignmentExpressions = CollectionUtils.MakeList(GetValue(1).SimpleAssignmentExpression); - } - } - - private void _499() - { - // default_block_parameter_list -> default_block_parameter_list Comma default_block_parameter -#line 2187 "Parser.y" - { - (yyval.SimpleAssignmentExpressions = GetValue(3).SimpleAssignmentExpressions).Add(GetValue(1).SimpleAssignmentExpression); - } - } - - private void _502() - { - // parameter_array -> array_parameter_mark parameter -#line 2199 "Parser.y" - { - yyval.LocalVariable = GetValue(1).LocalVariable; - } - } - - private void _503() - { - // parameter_array -> array_parameter_mark -#line 2203 "Parser.y" - { - yyval.LocalVariable = DefineParameter(Symbols.RestArgsLocal, GetLocation(1)); - } - } - - private void _506() - { - // block_parameter -> block_parameter_mark parameter -#line 2215 "Parser.y" - { - yyval.LocalVariable = GetValue(1).LocalVariable; - } - } - - private void _507() - { - // block_parameter_opt -> -#line 2222 "Parser.y" - { - yyval.LocalVariable = null; - } - } - - private void _508() - { - // block_parameter_opt -> Comma block_parameter -#line 2226 "Parser.y" - { - yyval.LocalVariable = GetValue(1).LocalVariable; - } - } - - private void _510() - { - // @26 -> -#line 2234 "Parser.y" - { - _tokenizer.LexicalState = LexicalState.EXPR_BEG; - } - } - - private void _511() - { - // singleton -> LeftParenthesis @26 expr closing_parenthesis -#line 2238 "Parser.y" - { - yyval.Expression = GetValue(2).Expression; - } - } - - private void _512() - { - // maplets -> maplet -#line 2245 "Parser.y" - { - yyval.Maplets = CollectionUtils.MakeList(GetValue(1).Maplet); - } - } - - private void _513() - { - // maplets -> maplets Comma maplet -#line 2249 "Parser.y" - { - (yyval.Maplets = GetValue(3).Maplets).Add(GetValue(1).Maplet); - } - } - - private void _514() - { - // maplet -> arg DoubleArrow arg -#line 2256 "Parser.y" - { - yyval.Maplet = new Maplet(GetValue(3).Expression, GetValue(1).Expression, yyloc); - } - } - - private void _515() - { - // maplet -> Label arg -#line 2260 "Parser.y" - { - yyval.Maplet = new Maplet(MakeSymbolLiteral(GetValue(2).String, GetLocation(2)), GetValue(1).Expression, yyloc); - } - } - - private void _528() - { - // terms_opt -> - } - - private void _530() - { - // new_line_opt -> - } - - private void _534() - { - // trailer -> - } - - private void _537() - { - // term -> Semicolon -#line 2314 "Parser.y" - { StopErrorRecovery(); } - } - - private void _540() - { - // terms -> terms Semicolon -#line 2320 "Parser.y" - { StopErrorRecovery(); } - } - -#line 2323 "Parser.y" - -} -} diff --git a/Src/Ruby/Compiler/Parser/Parser.cs b/Src/Ruby/Compiler/Parser/Parser.cs deleted file mode 100644 index ae64501d2..000000000 --- a/Src/Ruby/Compiler/Parser/Parser.cs +++ /dev/null @@ -1,693 +0,0 @@ -/* **************************************************************************** - * - * Copyright (c) Microsoft Corporation. - * - * This source code is subject to terms and conditions of the Apache License, Version 2.0. A - * copy of the license can be found in the License.html file at the root of this distribution. If - * you cannot locate the Apache License, Version 2.0, please send an email to - * ironruby@microsoft.com. By using this source code in any fashion, you are agreeing to be bound - * by the terms of the Apache License, Version 2.0. - * - * You must not remove this notice, or any other, from this software. - * - * - * ***************************************************************************/ - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Dynamic; -using System.Text; -using Microsoft.Scripting; -using Microsoft.Scripting.Runtime; -using Microsoft.Scripting.Utils; -using IronRuby.Compiler.Ast; -using IronRuby.Runtime; -using IronRuby.Builtins; -using System.Globalization; - -namespace IronRuby.Compiler { - - public interface ILexicalVariableResolver { - bool IsLocalVariable(string/*!*/ identifier); - } - - internal sealed class DummyVariableResolver : ILexicalVariableResolver { - public static readonly ILexicalVariableResolver AllVariableNames = new DummyVariableResolver(true); - public static readonly ILexicalVariableResolver AllMethodNames = new DummyVariableResolver(false); - private readonly bool _isVariable; - - private DummyVariableResolver(bool isVariable) { - _isVariable = isVariable; - } - - public bool IsLocalVariable(string/*!*/ identifier) { - return _isVariable; - } - } - - // The non-autogenerated part of the Parser class. - [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1506:AvoidExcessiveClassCoupling")] - public partial class Parser : ILexicalVariableResolver { - internal sealed class InternalSyntaxError : Exception { - } - - private int _inSingletonMethodDefinition = 0; - private int _inInstanceMethodDefinition = 0; - - private SourceUnitTree _ast; - private List _initializers; // lazy - - private Stack/*!*/ _lexicalScopes = new Stack(); - private SourceUnit _sourceUnit; - private readonly Tokenizer/*!*/ _tokenizer; - private Action _tokenSink; - private int _generatedNameId; - - // current encoding (used for __ENCODING__ pseudo-constant, literal string, symbol, regex encodings): - internal RubyEncoding/*!*/ Encoding { - get { return _tokenizer.Encoding; } - } - - private bool InMethod { - get { return _inSingletonMethodDefinition > 0 || _inInstanceMethodDefinition > 0; } - } - - public Tokenizer/*!*/ Tokenizer { - get { return _tokenizer; } - } - - public ErrorSink/*!*/ ErrorSink { - get { return _tokenizer.ErrorSink; } - } - - public Action TokenSink { - get { return _tokenSink; } - set { _tokenSink = value; } - } - - private SourceSpan GetTokenSpan() { - return _tokenizer.TokenSpan; - } - - private TokenValue GetTokenValue() { - return _tokenizer.TokenValue; - } - - private int GetNextToken() { - Tokens token = _tokenizer.GetNextToken(); - if (_tokenSink != null) { - _tokenSink(token, _tokenizer.TokenSpan); - } - return (int)token; - } - - private void ReportSyntaxError(string message) { - ErrorSink.Add(_sourceUnit, message, GetTokenSpan(), -1, Severity.FatalError); - throw new InternalSyntaxError(); - } - - internal void ReportSyntaxError(ErrorInfo error) { - ErrorSink.Add(_sourceUnit, error.GetMessage(), GetTokenSpan(), error.Code, Severity.FatalError); - throw new InternalSyntaxError(); - } - - private string/*!*/ GenerateErrorLocalName() { - return "error#" + _generatedNameId++; - } - - private string/*!*/ GenerateErrorConstantName() { - return "Error#" + _generatedNameId++; - } - - public Parser() - : this(ErrorSink.Default) { - } - - public Parser(ErrorSink/*!*/ errorSink) { - _tokenizer = new Tokenizer(false, this) { - ErrorSink = errorSink - }; - InitializeTables(); - } - - public SourceUnitTree Parse(SourceUnit/*!*/ sourceUnit, RubyCompilerOptions/*!*/ options, ErrorSink/*!*/ errorSink) { - Assert.NotNull(sourceUnit, options, errorSink); - - ErrorCounter counter = new ErrorCounter(errorSink); - _tokenizer.ErrorSink = counter; - _tokenizer.Compatibility = options.Compatibility; - - _lexicalScopes.Clear(); - - EnterScope(CreateTopScope(options.LocalNames)); - - using (SourceCodeReader reader = sourceUnit.GetReader()) { - _sourceUnit = sourceUnit; - _tokenizer.Initialize(null, reader, sourceUnit, options.InitialLocation); - - // Default encoding when hosted: - _tokenizer.Encoding = (reader.Encoding != null) ? RubyEncoding.GetRubyEncoding(reader.Encoding) : RubyEncoding.UTF8; - _tokenizer.AllowNonAsciiIdentifiers = _tokenizer.Encoding != RubyEncoding.Ascii; - - try { - Parse(); - LeaveScope(); - } catch (InternalSyntaxError) { - _ast = null; - _lexicalScopes.Clear(); - } finally { - ScriptCodeParseResult props; - if (counter.AnyError) { - _ast = null; - - if (_tokenizer.UnterminatedToken) { - props = ScriptCodeParseResult.IncompleteToken; - } else if (_tokenizer.EndOfFileReached) { - props = ScriptCodeParseResult.IncompleteStatement; - } else { - props = ScriptCodeParseResult.Invalid; - } - - } else { - props = ScriptCodeParseResult.Complete; - } - - sourceUnit.CodeProperties = props; - } - - return _ast; - } - } - - // Top level scope is created for top level code. - // Variables defined outside of compilation unit (we are compiling eval) are stored in "outer scope", - // to which the top level scope is nested in such case. - private static LexicalScope/*!*/ CreateTopScope(List localVariableNames) { - LexicalScope outer; - if (localVariableNames != null) { - outer = new RuntimeLexicalScope(localVariableNames); - } else { - outer = null; - } - - return new TopStaticLexicalScope(outer); - } - - private int _duplicateParameterCount; - - private LocalVariable/*!*/ DefineParameter(string/*!*/ name, SourceSpan location) { - // we are in a method or a block: - Debug.Assert(CurrentScope.IsTop && !(CurrentScope is TopStaticLexicalScope) || CurrentScope is BlockLexicalScope); - - LocalVariable variable; - if (CurrentScope.TryGetValue(name, out variable)) { - if (name != "_") { - _tokenizer.ReportError(Errors.DuplicateParameterName); - return variable; - } - // `_` may repeat; each occurrence needs its own slot since a LocalVariable - // can only hold one closure index. Reads of `_` bind to the first one. - return CurrentScope.AddVariable("?dup" + _duplicateParameterCount++ + "?", location); - } - - return CurrentScope.AddVariable(name, location); - } - - private FileInitializerStatement/*!*/ AddInitializer(FileInitializerStatement/*!*/ initializer) { - if (_initializers == null) { - _initializers = new List(); - } - - _initializers.Add(initializer); - - return initializer; - } - - private SourceSpan MergeLocations(SourceSpan start, SourceSpan end) { - Debug.Assert(start.IsValid && end.IsValid); - - return new SourceSpan(start.Start, end.End); - } - - private LexicalScope/*!*/ EnterScope(LexicalScope/*!*/ scope) { - Assert.NotNull(scope); - _lexicalScopes.Push(scope); - return scope; - } - - /// - /// Block scope. - /// - private LexicalScope/*!*/ EnterNestedScope() { - LexicalScope result = new BlockLexicalScope(CurrentScope); - _lexicalScopes.Push(result); - return result; - } - - /// - /// for-loop scope. - /// - private LexicalScope/*!*/ EnterPaddingScope() { - LexicalScope result = new PaddingLexicalScope(CurrentScope); - _lexicalScopes.Push(result); - return result; - } - - /// - /// BEGIN block. - /// - private LexicalScope/*!*/ EnterFileInitializerScope() { - LexicalScope result = new TopStaticLexicalScope(null); - _lexicalScopes.Push(result); - return result; - } - - /// - /// Source unit scope. - /// - private LexicalScope/*!*/ EnterTopStaticScope() { - LexicalScope result = new TopStaticLexicalScope(CurrentScope); - _lexicalScopes.Push(result); - return result; - } - - private LexicalScope/*!*/ EnterModuleDefinitionScope() { - LexicalScope result = new TopLocalDefinitionLexicalScope(CurrentScope); - _lexicalScopes.Push(result); - return result; - } - - private LexicalScope/*!*/ EnterClassDefinitionScope() { - LexicalScope result = new ClassLexicalScope(CurrentScope); - _lexicalScopes.Push(result); - return result; - } - - private LexicalScope/*!*/ EnterSingletonClassDefinitionScope() { - LexicalScope result = new TopLocalDefinitionLexicalScope(CurrentScope); - _lexicalScopes.Push(result); - return result; - } - - private LexicalScope/*!*/ EnterMethodDefinitionScope() { - LexicalScope result = new MethodLexicalScope(CurrentScope); - _lexicalScopes.Push(result); - return result; - } - - private LexicalScope/*!*/ EnterSingletonMethodDefinitionScope() { - LexicalScope result = new TopLocalDefinitionLexicalScope(CurrentScope); - _lexicalScopes.Push(result); - return result; - } - - private LexicalScope LeaveScope() { - return _lexicalScopes.Pop(); - } - - public LexicalScope CurrentScope { - get { - Debug.Assert(_lexicalScopes.Count > 0); - return _lexicalScopes.Peek(); - } - } - - public bool IsLocalVariable(string/*!*/ identifier) { - return CurrentScope.ResolveVariable(identifier) != null; - } - - private Expression/*!*/ ToCondition(Expression/*!*/ expression) { - return expression.ToCondition(CurrentScope); - } - - private Body/*!*/ MakeBody(Statements/*!*/ statements, List rescueClauses, ElseIfClause elseIf, - SourceSpan elseIfLocation, Statements ensureStatements, SourceSpan location) { - Debug.Assert(elseIf == null || elseIf.Condition == null); - - if (elseIf != null && rescueClauses == null) { - ErrorSink.Add(_sourceUnit, "else without rescue is useless", elseIfLocation, -1, Severity.Warning); - } - - return new Body( - statements, - rescueClauses, - (elseIf != null) ? elseIf.Statements : null, - ensureStatements, - location - ); - } - - internal LeftValue/*!*/ CannotAssignError(string/*!*/ constantName, SourceSpan location) { - Tokenizer.ReportError(Errors.CannotAssignTo, constantName); - return CurrentScope.ResolveOrAddVariable(GenerateErrorLocalName(), location); - } - - private void MatchReferenceReadOnlyError(RegexMatchReference/*!*/ matchRef) { - Tokenizer.ReportError(Errors.MatchGroupReferenceReadOnly, matchRef.VariableName); - } - - private AliasStatement/*!*/ MakeGlobalAlias(string/*!*/ newVar, string/*!*/ existingVar, SourceSpan location) { - return new AliasStatement(false, new ConstructedSymbol(newVar), new ConstructedSymbol(existingVar), location); - } - - private Expression/*!*/ MakeGlobalAlias(string/*!*/ newVar, RegexMatchReference/*!*/ existingVar, SourceSpan location) { - if (existingVar.CanAlias) { - return new AliasStatement(false, new ConstructedSymbol(newVar), new ConstructedSymbol(existingVar.VariableName), location); - } else { - _tokenizer.ReportError(Errors.CannotAliasGroupMatchVariable); - return new ErrorExpression(location); - } - } - - private AliasStatement/*!*/ MakeGlobalAlias(RegexMatchReference/*!*/ newVar, string/*!*/ existingVar, SourceSpan location) { - return new AliasStatement(false, new ConstructedSymbol(newVar.VariableName), new ConstructedSymbol(existingVar), location); - } - - private Expression/*!*/ MakeGlobalAlias(RegexMatchReference/*!*/ newVar, RegexMatchReference/*!*/ existingVar, SourceSpan location) { - if (existingVar.CanAlias) { - return new AliasStatement(false, new ConstructedSymbol(newVar.VariableName), new ConstructedSymbol(existingVar.VariableName), location); - } else { - _tokenizer.ReportError(Errors.CannotAliasGroupMatchVariable); - return new ErrorExpression(location); - } - } - - private List/*!*/ MakeListAddOpt(T item) { - List result = new List(); - if (item != null) { - result.Add(item); - } - return result; - } - - // BlockExpression behaves like an expression, so we don't need to create one that comprises of a single expression: - private Expression/*!*/ MakeBlockExpression(Statements/*!*/ statements, SourceSpan location) { - if (statements.Count == 0) { - return BlockExpression.Empty; - } else if (statements.Count == 1) { - return statements.First; - } else { - return new BlockExpression(statements, location); - } - } - - private ForLoopExpression/*!*/ MakeForLoopExpression(CompoundLeftValue/*!*/ lvalue, Expression/*!*/ list, Statements/*!*/ body, SourceSpan location) { - // MRI allows this - // CheckForLoopVariables(lvalue.LeftValues); - - Parameters parameters; - if (lvalue.HasUnsplattedValue) { - parameters = new Parameters( - ArrayUtils.RemoveAt(lvalue.LeftValues, lvalue.UnsplattedValueIndex), - lvalue.UnsplattedValueIndex, - null, - lvalue.UnsplattedValue, - null, - SourceSpan.None - ); - } else { - parameters = new Parameters(lvalue.LeftValues, lvalue.LeftValues.Length, null, null, null, SourceSpan.None); - } - - return new ForLoopExpression(CurrentScope, parameters, list, body, location); - } -#if TODO // ? - private bool CheckForLoopVariables(LeftValue/*!*/[]/*!*/ lvalues) { - for (int i = 0; i < lvalues.Length; i++) { - switch (lvalues[i].NodeType) { - case NodeTypes.LocalVariable: - case NodeTypes.CompoundLeftValue: - case NodeTypes.Placeholder: - break; - - case NodeTypes.ConstantVariable: - _tokenizer.ReportError(Errors.ForLoopVariableIsConstantVariable, lvalues[i].Location); - return false; - - case NodeTypes.InstanceVariable: - _tokenizer.ReportError(Errors.ForLoopVariableIsInstanceVariable, lvalues[i].Location); - return false; - - case NodeTypes.GlobalVariable: - _tokenizer.ReportError(Errors.ForLoopVariableIsGlobalVariable, lvalues[i].Location); - return false; - - case NodeTypes.ClassVariable: - _tokenizer.ReportError(Errors.ForLoopVariableIsClassVariable, lvalues[i].Location); - return false; - - default: - throw Assert.Unreachable; - } - } - return true; - } -#endif - private IfExpression/*!*/ MakeIfExpression(Expression/*!*/ condition, Statements/*!*/ body, List/*!*/ elseIfClauses, SourceSpan location) { - // last else-if/else clause is the first one in the list: - elseIfClauses.Reverse(); - return new IfExpression(condition, body, elseIfClauses, location); - } - - private ArrayConstructor/*!*/ MakeVerbatimWords(List/*!*/ words, SourceSpan location) { - Debug.Assert(CollectionUtils.TrueForAll(words, (word) => word is StringLiteral), "all words are string literals"); - - return new ArrayConstructor(new Arguments(words.ToArray()), location); - } - - private Expression/*!*/[]/*!*/ PopHashArguments(int argumentCount, SourceSpan location) { - if (argumentCount % 2 != 0) { - ErrorSink.Add(_sourceUnit, "odd number list for Hash", location, -1, Severity.Error); - return PopArguments(argumentCount, Literal.Nil(SourceSpan.None)); - } else { - return PopArguments(argumentCount); - } - } - - private Arguments/*!*/ RequireNoBlockArg(TokenValue arguments) { - if (arguments.Block != null) { - ErrorSink.Add(_sourceUnit, "block argument should not be given", arguments.Block.Location, -1, Severity.Error); - arguments.Block = null; - } - - return arguments.Arguments; - } - - private static MethodCall/*!*/ MakeMethodCall(Expression target, string/*!*/ methodName, TokenValue args, SourceSpan location) { - return new MethodCall(target, methodName, args.Arguments, args.Block, location); - } - - private static MethodCall/*!*/ MakeMethodCall(Expression target, string/*!*/ methodName, TokenValue args, Block block, SourceSpan location) { - Debug.Assert(args.Block == null); - return new MethodCall(target, methodName, args.Arguments, block, location); - } - - private static ArrayItemAccess/*!*/ MakeArrayItemAccess(Expression/*!*/ array, TokenValue args, SourceSpan location) { - return new ArrayItemAccess(array, args.Arguments, args.Block, location); - } - - private static Expression/*!*/ MakeMatch(Expression/*!*/ left, Expression/*!*/ right, SourceSpan location) { - var regex = left as RegularExpression; - if (regex != null) { - return new MatchExpression(regex, right, location); - } else { - return new MethodCall(left, Symbols.Match, new Arguments(right), location); - } - } - - private static SuperCall/*!*/ MakeSuperCall(TokenValue args, SourceSpan location) { - return new SuperCall(args.Arguments, args.Block, location); - } - - private static CompoundLeftValue/*!*/ MakeCompoundLeftValue(List leading, LeftValue/*!*/ unsplat, List trailing) { - int leadingCount = (leading != null ? leading.Count : 0); - int trailingCount = (trailing != null ? trailing.Count : 0); - var array = new LeftValue[leadingCount + 1 + trailingCount]; - if (leadingCount > 0) { - leading.CopyTo(array, 0); - } - array[leadingCount] = unsplat; - if (trailingCount > 0) { - trailing.CopyTo(array, leadingCount + 1); - } - return new CompoundLeftValue(array, leadingCount); - } - - private static T[]/*!*/ MakeArray(List/*!*/ left, List/*!*/ right) { - var array = new T[left.Count + right.Count]; - left.CopyTo(array, 0); - right.CopyTo(array, left.Count); - return array; - } - - private static T[]/*!*/ MakeArray(List/*!*/ left, T/*!*/ right) { - var array = new T[left.Count + 1]; - left.CopyTo(array, 0); - array[array.Length - 1] = right; - return array; - } - - private Expression[]/*!*/ _argumentStack = new Expression[10]; - private int _argumentCount; - - private void PushArgument(int argumentCount, Expression/*!*/ argument) { - Assert.NotNull(argument); - if (_argumentCount == _argumentStack.Length) { - Array.Resize(ref _argumentStack, _argumentCount * 2); - } - _argumentStack[_argumentCount++] = argument; - yyval.ArgumentCount = argumentCount + 1; - } - - private Expression/*!*/[]/*!*/ PopArguments(int count) { - var result = new Expression[count]; - _argumentCount -= count; - Array.Copy(_argumentStack, _argumentCount, result, 0, count); - return result; - } - - private Expression/*!*/[]/*!*/ PopArguments(int count, Expression/*!*/ additionalArgument) { - var result = new Expression[count + 1]; - _argumentCount -= count; - Array.Copy(_argumentStack, _argumentCount, result, 0, count); - result[count] = additionalArgument; - return result; - } - - private Expression/*!*/[]/*!*/ PopArguments(Expression/*!*/ additionalArgument, int count) { - var result = new Expression[count + 1]; - _argumentCount -= count; - Array.Copy(_argumentStack, _argumentCount, result, 1, count); - result[0] = additionalArgument; - return result; - } - - // foo - // foo {} - private void SetNoArguments(Block block) { - yyval.Arguments = null; - yyval.Block = block; - } - - // foo() - private void SetArguments() { - yyval.Arguments = Arguments.Empty; - yyval.Block = null; - } - - // foo() - // foo() {} - // foo(&p) - // foo &p - private void SetArguments(Block block) { - yyval.Arguments = Arguments.Empty; - yyval.Block = block; - } - - // foo(expr) - private void SetArguments(Expression/*!*/ expression) { - yyval.Arguments = new Arguments(expression); - yyval.Block = null; - } - - // foo(expr) - // foo(expr) {} - // foo(expr, &p) - private void SetArguments(Expression/*!*/ expression, Block block) { - yyval.Arguments = new Arguments(expression); - yyval.Block = block; - } - - // foo([*]?expr1, ..., [*]?exprN, k1 => v1, ..., kN => vN) - // foo([*]?expr1, ..., [*]?exprN, k1 => v1, ..., kN => vN) {} - // foo([*]?expr1, ..., [*]?exprN, k1 => v1, ..., kN => vN, &p) - private void PopAndSetArguments(int argumentCount, Block block) { - yyval.Arguments = new Arguments(PopArguments(argumentCount)); - yyval.Block = block; - } - - private void SetArguments(Expression/*!*/[] arguments, Block block) { - yyval.Arguments = new Arguments(arguments); - yyval.Block = block; - } - - private void SetBlock(CallExpression/*!*/ expression, BlockDefinition/*!*/ block) { - if (expression.Block != null) { - ReportSyntaxError(Errors.BothBlockDefAndBlockRefGiven); - } else { - expression.Block = block; - } - } - - private LambdaDefinition/*!*/ MakeLambdaDefinition(Parameters parameters, Statements body, SourceSpan location) { - return new LambdaDefinition(new BlockDefinition(CurrentScope, parameters, body, location)); - } - - private BlockDefinition/*!*/ MakeBlockDefinition(Parameters parameters, Statements body, SourceSpan location) { - return new BlockDefinition(CurrentScope, parameters, body, location); - } - - private static Expression/*!*/ MakeLoopStatement(Expression/*!*/ statement, Expression/*!*/ condition, bool isWhileLoop, SourceSpan location) { - return new WhileLoopExpression(condition, isWhileLoop, statement is Body, new Statements(statement), location); - } - - public static string/*!*/ GetTerminalName(int terminal) { - return RubyUtils.TryMangleName(((Tokens)terminal).ToString()).ToUpperInvariant(); - } - - public static StringLiteral/*!*/ MakeStringLiteral(TokenValue token, SourceSpan location) { - return new StringLiteral(token.StringContent, token.Encoding, location); - } - - public SymbolLiteral/*!*/ MakeSymbolLiteral(string/*!*/ symbol, SourceSpan location) { - return new SymbolLiteral(symbol, symbol.IsAscii() ? RubyEncoding.Ascii : Encoding, location); - } - - internal Expression/*!*/ MakeSymbolLiteral(ConstructedSymbol symbol, SourceSpan location) { - string str = symbol.Value as string; - if (str != null) { - return MakeSymbolLiteral(str, location); - } else { - return (StringConstructor)symbol.Value; - } - } - - private StringConstructor/*!*/ MakeSymbolConstructor(List/*!*/ content, SourceSpan location) { - return new StringConstructor(content, StringKind.Symbol, location); - } - - // TODO: utils - - public static string/*!*/ CharToString(char ch) { - switch (ch) { - case '\a': return @"'\a'"; - case '\b': return @"'\b'"; - case '\f': return @"'\f'"; - case '\n': return @"'\n'"; - case '\r': return @"'\r'"; - case '\t': return @"'\t'"; - case '\v': return @"'\v'"; - case '\0': return @"'\0'"; - default: return String.Concat("'", ch.ToString(), "'"); - } - } - - public static string/*!*/ EscapeString(string str) { - return (str == null) ? String.Empty : - new StringBuilder(str). - Replace(@"\", @"\\"). - Replace(@"""", @"\"""). - Replace("\a", @"\a"). - Replace("\b", @"\b"). - Replace("\f", @"\f"). - Replace("\n", @"\n"). - Replace("\r", @"\r"). - Replace("\t", @"\t"). - Replace("\v", @"\v"). - Replace("\0", @"\0").ToString(); - } - } -} - - diff --git a/Src/Ruby/Compiler/Parser/Parser.y b/Src/Ruby/Compiler/Parser/Parser.y deleted file mode 100644 index 7699a3dbf..000000000 --- a/Src/Ruby/Compiler/Parser/Parser.y +++ /dev/null @@ -1,2323 +0,0 @@ -/* **************************************************************************** - * - * Copyright (c) Microsoft Corporation. - * - * This source code is subject to terms and conditions of the Apache License, Version 2.0. A - * copy of the license can be found in the License.html file at the root of this distribution. If - * you cannot locate the Apache License, Version 2.0, please send an email to - * ironruby@microsoft.com. By using this source code in any fashion, you are agreeing to be bound - * by the terms of the Apache License, Version 2.0. - * - * You must not remove this notice, or any other, from this software. - * - * - * ***************************************************************************/ - -using System.Collections.Generic; -using System.Diagnostics; -using System.Dynamic; -using Microsoft.Scripting; -using Microsoft.Scripting.Utils; -using IronRuby.Compiler.Ast; - -%% - -%namespace IronRuby.Compiler - -%union { } - -%SymbolLocationType SourceSpan -%SymbolValueType TokenValue - -%partial -%visibility public - -%token SINGLE_LINE_COMMENT MULTI_LINE_COMMENT WHITESPACE END_OF_LINE INVALID_CHARACTER POUND AT DOLLAR BACKSLASH -%token WORD_SEPARATOR NEW_LINE -%token CLASS MODULE DEF UNDEF BEGIN RESCUE ENSURE END IF UNLESS THEN ELSIF ELSE -%token CASE WHEN WHILE UNTIL FOR BREAK NEXT REDO RETRY IN DO LOOP_DO BLOCK_DO LAMBDA_DO -%token RETURN YIELD SUPER SELF NIL TRUE FALSE AND OR NOT IF_MOD UNLESS_MOD -%token WHILE_MOD UNTIL_MOD RESCUE_MOD ALIAS DEFINED UPPERCASE_BEGIN UPPERCASE_END LINE FILE ENCODING -%token UNARY_PLUS UNARY_MINUS POW CMP EQUAL STRICT_EQUAL NOT_EQUAL GREATER_OR_EQUAL LESS_OR_EQUAL LOGICAL_AND LOGICAL_OR MATCH NMATCH -%token DOUBLE_DOT TRIPLE_DOT ITEM_GETTER ITEM_SETTER LSHFT RSHFT SEPARATING_DOUBLE_COLON LEADING_DOUBLE_COLON DOUBLE_ARROW -%token SEMICOLON COMMA DOT STAR BLOCK_REFERENCE AMPERSAND BACKTICK -%token LAMBDA -%token LEFT_PARENTHESIS LEFT_EXPR_PARENTHESIS LEFT_ARG_PARENTHESIS RIGHT_PARENTHESIS -%token LEFT_BRACE LEFT_BLOCK_BRACE LEFT_BLOCK_ARG_BRACE LEFT_LAMBDA_BRACE RIGHT_BRACE -%token LEFT_BRACKET LEFT_INDEXING_BRACKET RIGHT_BRACKET -%token STRING_EMBEDDED_VARIABLE_BEGIN STRING_EMBEDDED_CODE_BEGIN STRING_EMBEDDED_CODE_END -%token VERBATIM_HEREDOC_BEGIN VERBATIM_HEREDOC_END -%token STRING_BEGIN REGEXP_BEGIN SHELL_STRING_BEGIN WORDS_BEGIN VERBATIM_WORDS_BEGIN SYMBOL_BEGIN STRING_END - -%token IDENTIFIER FUNCTION_IDENTIFIER GLOBAL_VARIABLE INSTANCE_VARIABLE CONSTANT_IDENTIFIER CLASS_VARIABLE OP_ASSIGNMENT -%token LABEL // 1.9 -%token CHARACTER STRING_CONTENT // (String & Encoding) -%token INTEGER -%token BIG_INTEGER -%token FLOAT -%token MATCH_REFERENCE -%token REGEXP_END - -%type program - -%type stmt -%type stmts compstmt lambda_body ensure_opt -%type jump_statement jump_statement_with_parameters jump_statement_parameterless -%type alias_statement -%type conditional_statement - -%type primary expr expression_statement superclass var_ref singleton case_expression -%type arg -%type args compound_rhs // arguments pushed to the argument stack -%type block_expression // (Expression | BlockExpression | Body) -%type definition_expression // DefinitionExpression -%type body -%type - -%type method_call block_call command_call block_command command - -%type else_opt -%type if_tail -%type undef_list -%type block_reference block_reference_opt -%type cmd_brace_block brace_block do_block -%type lambda - -%type array_items // (Arguments! & Block == null) -%type parenthesized_args // (Arguments! & Block?) -%type parenthesized_args_opt call_args call_args_opt command_args // (Arguments? & Block?) - -%type qualified_module_name - -%type rescue_clauses rescue_clauses_opt -%type rescue_clause - -%type when_clauses -%type when_clause - -%type maplets -%type maplet - -%type string_embedded_variable // string embedded variable -%type string_content // string piece - literal, string embedded code/variable -%type string_contents // list of string pieces -%type string // quoted string constructor taking list of string pieces "#{foo}bar#{baz}" -%type string_concatenation // string constructor taking a list of quoted strings "foo" 'bar' "baz" -%type shell_string // shell string constructor taking list of string pieces `#{foo}bar#{baz}` -%type word // concatenation of string pieces -%type word_list verbatim_word_list // list of words separated by space -%type words verbatim_words // array constructor taking a list of words - -%type regexp -%type numeric_literal -%type symbol method_name_or_symbol -%type match_reference - -%type operation variable sym operation2 operation3 module_name op method_name - -%type block_parameters block_parameters_opt lambda_parameters // Parameters? -%type method_parameters block_parameter_list parameters -%type block_variables block_variables_opt // 1.9 - -%type default_parameter_list default_block_parameter_list -%type default_parameter default_block_parameter - -%type for_parameters - -%type parameter parameter_array block_parameter block_parameter_opt - -%type compound_parameters // 1.9 -%type parameter_list -%type compound_parameter_list // 1.9 -%type compound_parameter parenthesized_parameter // 1.9 - -%type compound_lhs -%type compound_lhs_nodes -%type compound_lhs_tail // 1.9 -%type compound_lhs_node -%type compound_lhs_leaf // 1.9 - -%type var_lhs -%type lhs -%type exc_var - -%nonassoc LOWEST -%nonassoc LEFT_BLOCK_ARG_BRACE -%nonassoc IF_MOD UNLESS_MOD WHILE_MOD UNTIL_MOD -%left OR AND -%right NOT -%nonassoc DEFINED -%right ASSIGNMENT OP_ASSIGNMENT -%left RESCUE_MOD -%right QUESTION_MARK COLON -%nonassoc DOUBLE_DOT TRIPLE_DOT -%left LOGICAL_OR -%left LOGICAL_AND -%nonassoc CMP EQUAL STRICT_EQUAL NOT_EQUAL MATCH NMATCH -%left GREATER GREATER_OR_EQUAL LESS LESS_OR_EQUAL -%left PIPE CARET -%left AMPERSAND -%left LSHFT RSHFT -%left PLUS MINUS -%left ASTERISK SLASH PERCENT -%right NUMBER_NEGATION UNARY_MINUS -%right POW -%right BANG TILDE UNARY_PLUS - -%token LAST_TOKEN - - -%% - - -program: - compstmt - { - _ast = new SourceUnitTree(CurrentScope, $1, _initializers, Encoding, _tokenizer.DataOffset); - } -; - -compstmt: - terms_opt - { - $$ = Statements.Empty; - } - | terms stmts terms_opt - { - $$ = $2; - } - | stmts terms_opt - { - $$ = $1; - } -; - -stmts: - stmt - { - $$ = new Statements($1); - } - | stmts terms stmt - { - ($$ = $1).Add($3); - } - | ERROR stmt - { - $$ = new Statements($2); - } -; - -stmt: - alias_statement - | UNDEF undef_list - { - $$ = new UndefineStatement($2, @$); - } - | UPPERCASE_BEGIN // TODO: 1.9 move to top_stmt - { - if (InMethod) { - _tokenizer.ReportError(Errors.FileInitializerInMethod); - } - - EnterFileInitializerScope(); - } - LEFT_BLOCK_BRACE compstmt RIGHT_BRACE - { - $$ = AddInitializer(new FileInitializerStatement(CurrentScope, $4, @$)); - LeaveScope(); - } - | UPPERCASE_END - { - if (InMethod) { - _tokenizer.ReportWarning(Errors.ShutdownHandlerInMethod); - } - - // END block behaves like a block definition (allows variable closures, super, etc): - EnterNestedScope(); - } - LEFT_BLOCK_BRACE compstmt RIGHT_BRACE - { - $$ = new ShutdownHandlerStatement(CurrentScope, $4, @$); - LeaveScope(); - } - | match_reference OP_ASSIGNMENT command_call - { - MatchReferenceReadOnlyError($1); - $$ = new ErrorExpression(@$); - } - | conditional_statement - { - $$ = $1; - } - | expression_statement - { - $$ = $1; - } -; - -alias_statement: - ALIAS method_name_or_symbol - { - _tokenizer.LexicalState = LexicalState.EXPR_FNAME; - } - method_name_or_symbol - { - $$ = new AliasStatement(true, $2, $4, @$); - } - | ALIAS GLOBAL_VARIABLE GLOBAL_VARIABLE - { - $$ = MakeGlobalAlias($2, $3, @$); - } - | ALIAS GLOBAL_VARIABLE match_reference - { - $$ = MakeGlobalAlias($2, $3, @$); - } -; - -jump_statement: - jump_statement_with_parameters - { - $$ = $1; - } - | jump_statement_parameterless - { - $$ = $1; - } -; - -jump_statement_with_parameters: - RETURN call_args - { - $$ = new ReturnStatement(RequireNoBlockArg($2), @$); - } - | BREAK call_args - { - $$ = new BreakStatement(RequireNoBlockArg($2), @$); - } - | NEXT call_args - { - $$ = new NextStatement(RequireNoBlockArg($2), @$); - } -; - -jump_statement_parameterless: - RETURN - { - $$ = new ReturnStatement(null, @$); - } - | BREAK - { - $$ = new BreakStatement(null, @$); - } - | NEXT - { - $$ = new NextStatement(null, @$); - } - | REDO - { - $$ = new RedoStatement(@$); - } - | RETRY - { - $$ = new RetryStatement(@$); - } -; - -expression_statement: - expr - { - $$ = $1; - } - | jump_statement - { - $$ = $1; - } - | lhs ASSIGNMENT command_call - { - $$ = new SimpleAssignmentExpression($1, $3, null, @$); - } - | compound_lhs ASSIGNMENT command_call - { - $$ = new ParallelAssignmentExpression($1, new Expression[] { $3 }, @$); - } - | var_lhs OP_ASSIGNMENT command_call - { - $$ = new SimpleAssignmentExpression($1, $3, $2, @$); - } - | primary LEFT_INDEXING_BRACKET call_args_opt closing_bracket OP_ASSIGNMENT command_call // 1.9 change - { - $$ = new SimpleAssignmentExpression(MakeArrayItemAccess($1, $3, @2), $6, $5, @$); - } - | primary DOT IDENTIFIER OP_ASSIGNMENT command_call - { - $$ = new MemberAssignmentExpression($1, $3, $4, $5, @$); - } - | primary DOT CONSTANT_IDENTIFIER OP_ASSIGNMENT command_call - { - $$ = new MemberAssignmentExpression($1, $3, $4, $5, @$); - } - | primary SEPARATING_DOUBLE_COLON CONSTANT_IDENTIFIER OP_ASSIGNMENT command_call - { - _tokenizer.ReportError(Errors.ConstantReassigned); - $$ = new MemberAssignmentExpression($1, $3, $4, $5, @$); - } - | primary SEPARATING_DOUBLE_COLON IDENTIFIER OP_ASSIGNMENT command_call - { - $$ = new MemberAssignmentExpression($1, $3, $4, $5, @$); - } - | lhs ASSIGNMENT compound_rhs - { - $$ = new ParallelAssignmentExpression(new CompoundLeftValue(new LeftValue[] { $1 }), PopArguments($3), @$); - } - | compound_lhs ASSIGNMENT arg - { - $$ = new ParallelAssignmentExpression($1, new Expression[] { $3 }, @$); - } - | compound_lhs ASSIGNMENT compound_rhs - { - $$ = new ParallelAssignmentExpression($1, PopArguments($3), @$); - } -; - -conditional_statement: - stmt IF_MOD expr - { - $$ = new ConditionalStatement(ToCondition($3), false, $1, null, @$); - } - | stmt UNLESS_MOD expr - { - $$ = new ConditionalStatement(ToCondition($3), true, $1, null, @$); - } - | stmt WHILE_MOD expr - { - $$ = MakeLoopStatement($1, ToCondition($3), true, @$); - } - | stmt UNTIL_MOD expr - { - $$ = MakeLoopStatement($1, ToCondition($3), false, @$); - } - | stmt RESCUE_MOD stmt - { - $$ = new RescueExpression($1, $3, MergeLocations(@2, @3), @$); - } -; - -expr: - command_call - | expr AND expr - { - $$ = new AndExpression($1, $3, @$); - } - | expr OR expr - { - $$ = new OrExpression($1, $3, @$); - } - | expr AND jump_statement - { - $$ = new ConditionalJumpExpression($1, $3, false, null, @$); - } - | expr OR jump_statement - { - $$ = new ConditionalJumpExpression($1, $3, true, null, @$); - } - | NOT new_line_opt expr // 1.9 added new_line_opt - { - $$ = new NotExpression($3, @$); - } - | BANG command_call - { - $$ = new NotExpression($2, @$); - } - | arg -; - -command_call: - command - { - $$ = $1; - } - | block_command - { - $$ = $1; - } -; - -block_command: - block_call - { - $$ = $1; - } - | block_call DOT operation2 command_args - { - $$ = MakeMethodCall($1, $3, $4, @$); - } - | block_call SEPARATING_DOUBLE_COLON operation2 command_args - { - $$ = MakeMethodCall($1, $3, $4, @$); - } -; - -cmd_brace_block: - LEFT_BLOCK_ARG_BRACE - { - EnterNestedScope(); - } - block_parameters_opt compstmt RIGHT_BRACE - { - $$ = MakeBlockDefinition($3, $4, @$); - LeaveScope(); - } -; - -command: - operation command_args %prec LOWEST - { - $$ = MakeMethodCall(null, $1, $2, @$); - } - | operation command_args cmd_brace_block - { - $$ = MakeMethodCall(null, $1, $2, $3, @$); - } - | primary DOT operation2 command_args %prec LOWEST - { - $$ = MakeMethodCall($1, $3, $4, @$); - } - | primary DOT operation2 command_args cmd_brace_block - { - $$ = MakeMethodCall($1, $3, $4, $5, @$); - } - | primary SEPARATING_DOUBLE_COLON operation2 command_args %prec LOWEST - { - $$ = MakeMethodCall($1, $3, $4, @$); - } - | primary SEPARATING_DOUBLE_COLON operation2 command_args cmd_brace_block - { - $$ = MakeMethodCall($1, $3, $4, $5, @$); - } - | SUPER command_args - { - $$ = MakeSuperCall($2, @$); - } - | YIELD command_args - { - $$ = new YieldCall(RequireNoBlockArg($2), @$); - } -; - -compound_lhs: // 1.9 change - LEFT_EXPR_PARENTHESIS compound_lhs closing_parenthesis - { - $$ = new CompoundLeftValue(new LeftValue[] { $2 }); - } - | compound_lhs_nodes - { - // the list ends with COMMA: - $1.Add(Placeholder.Singleton); - $$ = new CompoundLeftValue($1.ToArray()); - } - | compound_lhs_nodes compound_lhs_node - { - $1.Add($2); - $$ = new CompoundLeftValue($1.ToArray()); - } - | compound_lhs_nodes STAR compound_lhs_leaf - { - $$ = MakeCompoundLeftValue($1, $3, null); - } - | compound_lhs_nodes STAR compound_lhs_leaf COMMA compound_lhs_tail - { - $$ = MakeCompoundLeftValue($1, $3, $5); - } - | compound_lhs_nodes STAR - { - $$ = MakeCompoundLeftValue($1, Placeholder.Singleton, null); - } - | compound_lhs_nodes STAR COMMA compound_lhs_tail - { - $$ = MakeCompoundLeftValue($1, Placeholder.Singleton, $4); - } - | STAR compound_lhs_leaf COMMA compound_lhs_tail - { - $$ = MakeCompoundLeftValue(null, $2, $4); - } - | STAR COMMA compound_lhs_tail - { - $$ = MakeCompoundLeftValue(null, Placeholder.Singleton, $3); - } - | STAR compound_lhs_leaf - { - $$ = new CompoundLeftValue(new LeftValue[] { $2 }, 0); - } - | STAR - { - $$ = new CompoundLeftValue(new LeftValue[] { Placeholder.Singleton }, 0); - } -; - -compound_lhs_nodes: - compound_lhs_nodes compound_lhs_node COMMA - { - ($$ = $1).Add($2); - } - | compound_lhs_node COMMA - { - $$ = CollectionUtils.MakeList($1); - } -; - -compound_lhs_tail: // 1.9 - compound_lhs_tail COMMA compound_lhs_node - { - ($$ = $1).Add($3); - } - | compound_lhs_node - { - $$ = CollectionUtils.MakeList($1); - } -; - -compound_lhs_node: - compound_lhs_leaf - { - $$ = $1; - } - | LEFT_EXPR_PARENTHESIS compound_lhs closing_parenthesis // 1.9 change - { - $$ = $2; - } -; - -compound_lhs_leaf: // 1.9, the same as lhs - variable - { - $$ = VariableFactory.MakeLeftValue($1, this, $1, @$); - } - | primary LEFT_INDEXING_BRACKET call_args_opt closing_bracket - { - $$ = MakeArrayItemAccess($1, $3, @$); - } - | primary DOT IDENTIFIER - { - $$ = new AttributeAccess($1, $3, @$); - } - | primary SEPARATING_DOUBLE_COLON IDENTIFIER - { - $$ = new AttributeAccess($1, $3, @$); - } - | primary DOT CONSTANT_IDENTIFIER - { - $$ = new AttributeAccess($1, $3, @$); - } - | primary SEPARATING_DOUBLE_COLON CONSTANT_IDENTIFIER - { - $$ = new ConstantVariable($1, $3, @$); - } - | LEADING_DOUBLE_COLON CONSTANT_IDENTIFIER - { - $$ = new ConstantVariable(null, $2, @$); - } - | match_reference - { - MatchReferenceReadOnlyError($1); - $$ = new GlobalVariable(Symbols.Error, @$); - } -; - -lhs: variable - { - $$ = VariableFactory.MakeLeftValue($1, this, $1, @$); - } - | primary LEFT_INDEXING_BRACKET call_args_opt closing_bracket // 1.9 change - { - $$ = MakeArrayItemAccess($1, $3, @$); - } - | primary DOT IDENTIFIER - { - $$ = new AttributeAccess($1, $3, @$); - } - | primary SEPARATING_DOUBLE_COLON IDENTIFIER - { - $$ = new AttributeAccess($1, $3, @$); - } - | primary DOT CONSTANT_IDENTIFIER - { - $$ = new AttributeAccess($1, $3, @$); - } - | primary SEPARATING_DOUBLE_COLON CONSTANT_IDENTIFIER - { - $$ = new ConstantVariable($1, $3, @$); - } - | LEADING_DOUBLE_COLON CONSTANT_IDENTIFIER - { - $$ = new ConstantVariable(null, $2, @$); - } - | match_reference - { - MatchReferenceReadOnlyError($1); - $$ = new GlobalVariable(Symbols.Error, @$); - } - ; - -module_name: - CONSTANT_IDENTIFIER - { - $$ = $1; - } - | IDENTIFIER - { - _tokenizer.ReportError(Errors.ModuleNameNotConstant); - $$ = $1; - } -; - -qualified_module_name: - LEADING_DOUBLE_COLON module_name - { - $$ = new ConstantVariable(null, $2, @$); - } - | module_name - { - $$ = new ConstantVariable($1, @$); - } - | primary SEPARATING_DOUBLE_COLON module_name - { - $$ = new ConstantVariable($1, $3, @$); - } -; - -method_name: - IDENTIFIER - { - $$ = $1; - } - | CONSTANT_IDENTIFIER - { - $$ = $1; - } - | FUNCTION_IDENTIFIER - { - $$ = $1; - } - | op - { - _tokenizer.LexicalState = LexicalState.EXPR_ENDFN; // 1.8: EXPR_END - $$ = $1; - } - | reswords - { - _tokenizer.LexicalState = LexicalState.EXPR_ENDFN; // 1.8: EXPR_END - $$ = $1; - } -; - -method_name_or_symbol: - method_name - { - $$ = new ConstructedSymbol($1); - } - | symbol - { - $$ = $1; - } -; - -symbol: - SYMBOL_BEGIN sym - { - _tokenizer.LexicalState = LexicalState.EXPR_END; - $$ = new ConstructedSymbol($2); - } - | SYMBOL_BEGIN string_contents STRING_END - { - $$ = new ConstructedSymbol(MakeSymbolConstructor($2, @$)); - } -; - -sym: - method_name - | INSTANCE_VARIABLE - | GLOBAL_VARIABLE - { - $$ = "$" + $1; - } - | CLASS_VARIABLE - | match_reference - { - $$ = $1.FullName; - } -; - -undef_list: - method_name_or_symbol - { - $$ = CollectionUtils.MakeList($1); - } - | undef_list COMMA - { - _tokenizer.LexicalState = LexicalState.EXPR_FNAME; - } - method_name_or_symbol - { - ($$ = $1).Add($4); - } -; - -op: - PIPE { $$ = Symbols.BitwiseOr; } - | CARET { $$ = Symbols.Xor; } - | AMPERSAND { $$ = Symbols.BitwiseAnd; } - | CMP { $$ = Symbols.Comparison; } - | EQUAL { $$ = Symbols.Equal; } - | STRICT_EQUAL { $$ = Symbols.StrictEqual; } - | MATCH { $$ = Symbols.Match; } - | NMATCH { $$ = Symbols.NotMatch; } // 1.9 - | GREATER { $$ = Symbols.GreaterThan; } - | GREATER_OR_EQUAL { $$ = Symbols.GreaterEqual; } - | LESS { $$ = Symbols.LessThan; } - | LESS_OR_EQUAL { $$ = Symbols.LessEqual; } - | NOT_EQUAL { $$ = Symbols.NotEqual; } // 1.9 - | LSHFT { $$ = Symbols.LeftShift; } - | RSHFT { $$ = Symbols.RightShift; } - | PLUS { $$ = Symbols.Plus; } - | MINUS { $$ = Symbols.Minus; } - | ASTERISK { $$ = Symbols.Multiply; } - | STAR { $$ = Symbols.Multiply; } - | SLASH { $$ = Symbols.Divide; } - | PERCENT { $$ = Symbols.Mod; } - | POW { $$ = Symbols.Power; } - | BANG { $$ = Symbols.Bang; } - | TILDE { $$ = Symbols.BitwiseNot; } - | UNARY_PLUS { $$ = Symbols.UnaryPlus; } - | UNARY_MINUS { $$ = Symbols.UnaryMinus; } - | ITEM_GETTER { $$ = Symbols.ArrayItemRead; } - | ITEM_SETTER { $$ = Symbols.ArrayItemWrite; } - | BACKTICK { $$ = Symbols.Backtick; } -; - -reswords: - LINE | FILE | ENCODING | UPPERCASE_BEGIN | UPPERCASE_END - | ALIAS | AND | BEGIN | BREAK | CASE | CLASS | DEF - | DEFINED | DO | BLOCK_DO | ELSE | ELSIF | END | ENSURE | FALSE - | FOR | IN | MODULE | NEXT | NIL | NOT - | OR | REDO | RESCUE | RETRY | RETURN | SELF | SUPER - | THEN | TRUE | UNDEF | WHEN | YIELD - | IF_MOD | UNLESS_MOD | WHILE_MOD | UNTIL_MOD | RESCUE_MOD -; - -arg: - lhs ASSIGNMENT arg - { - $$ = new SimpleAssignmentExpression($1, $3, null, @$); - } - | lhs ASSIGNMENT arg RESCUE_MOD arg - { - $$ = new SimpleAssignmentExpression($1, new RescueExpression($3, $5, MergeLocations(@4, @5), MergeLocations(@3, @5)), null, @$); - } - | lhs ASSIGNMENT arg RESCUE_MOD jump_statement_parameterless - { - $$ = new SimpleAssignmentExpression($1, new RescueExpression($3, $5, MergeLocations(@4, @5), MergeLocations(@3, @5)), null, @$); - } - | var_lhs OP_ASSIGNMENT arg - { - $$ = new SimpleAssignmentExpression($1, $3, $2, @$); - } - | primary LEFT_INDEXING_BRACKET call_args_opt closing_bracket OP_ASSIGNMENT arg // 1.9 change - { - $$ = new SimpleAssignmentExpression(MakeArrayItemAccess($1, $3, @2), $6, $5, @$); - } - | primary DOT IDENTIFIER OP_ASSIGNMENT arg - { - $$ = new MemberAssignmentExpression($1, $3, $4, $5, @$); - } - | primary DOT CONSTANT_IDENTIFIER OP_ASSIGNMENT arg - { - $$ = new MemberAssignmentExpression($1, $3, $4, $5, @$); - } - | primary SEPARATING_DOUBLE_COLON IDENTIFIER OP_ASSIGNMENT arg - { - $$ = new MemberAssignmentExpression($1, $3, $4, $5, @$); - } - | primary SEPARATING_DOUBLE_COLON CONSTANT_IDENTIFIER OP_ASSIGNMENT arg - { - _tokenizer.ReportError(Errors.ConstantReassigned); - $$ = new ErrorExpression(@$); - } - | LEADING_DOUBLE_COLON CONSTANT_IDENTIFIER OP_ASSIGNMENT arg - { - _tokenizer.ReportError(Errors.ConstantReassigned); - $$ = new ErrorExpression(@$); - } - | match_reference OP_ASSIGNMENT arg - { - MatchReferenceReadOnlyError($1); - $$ = new ErrorExpression(@$); - } - | arg PLUS arg - { - $$ = new MethodCall($1, Symbols.Plus, new Arguments($3), @$); - } - | arg MINUS arg - { - $$ = new MethodCall($1, Symbols.Minus, new Arguments($3), @$); - } - | arg ASTERISK arg - { - $$ = new MethodCall($1, Symbols.Multiply, new Arguments($3), @$); - } - | arg SLASH arg - { - $$ = new MethodCall($1, Symbols.Divide, new Arguments($3), @$); - } - | arg PERCENT arg - { - $$ = new MethodCall($1, Symbols.Mod, new Arguments($3), @$); - } - | arg POW arg - { - $$ = new MethodCall($1, Symbols.Power, new Arguments($3), @$); - } - | NUMBER_NEGATION INTEGER POW arg - { - // ** has precedence over unary minus, hence -number**arg is equivalent to -(number**arg) - $$ = new MethodCall(new MethodCall(Literal.Integer($2, @2), Symbols.Power, new Arguments($4), @3), Symbols.UnaryMinus, Arguments.Empty, @$); - } - | NUMBER_NEGATION BIG_INTEGER POW arg - { - $$ = new MethodCall(new MethodCall(Literal.BigInteger($2, @2), Symbols.Power, new Arguments($4), @3), Symbols.UnaryMinus, Arguments.Empty, @$); - } - | NUMBER_NEGATION FLOAT POW arg - { - $$ = new MethodCall(new MethodCall(Literal.Double($2, @2), Symbols.Power, new Arguments($4), @3), Symbols.UnaryMinus, Arguments.Empty, @$); - } - | UNARY_PLUS arg - { - $$ = new MethodCall($2, Symbols.UnaryPlus, null, @$); - } - | UNARY_MINUS arg - { - $$ = new MethodCall($2, Symbols.UnaryMinus, null, @$); - } - | arg PIPE arg - { - $$ = new MethodCall($1, Symbols.BitwiseOr, new Arguments($3), @$); - } - | arg CARET arg - { - $$ = new MethodCall($1, Symbols.Xor, new Arguments($3), @$); - } - | arg AMPERSAND arg - { - $$ = new MethodCall($1, Symbols.BitwiseAnd, new Arguments($3), @$); - } - | arg CMP arg - { - $$ = new MethodCall($1, Symbols.Comparison, new Arguments($3), @$); - } - | arg GREATER arg - { - $$ = new MethodCall($1, Symbols.GreaterThan, new Arguments($3), @$); - } - | arg GREATER_OR_EQUAL arg - { - $$ = new MethodCall($1, Symbols.GreaterEqual, new Arguments($3), @$); - } - | arg LESS arg - { - $$ = new MethodCall($1, Symbols.LessThan, new Arguments($3), @$); - } - | arg LESS_OR_EQUAL arg - { - $$ = new MethodCall($1, Symbols.LessEqual, new Arguments($3), @$); - } - | arg EQUAL arg - { - $$ = new MethodCall($1, Symbols.Equal, new Arguments($3), @$); - } - | arg STRICT_EQUAL arg - { - $$ = new MethodCall($1, Symbols.StrictEqual, new Arguments($3), @$); - } - | arg NOT_EQUAL arg - { - $$ = new MethodCall($1, Symbols.NotEqual, new Arguments($3), @$); - } - | arg MATCH arg - { - // TODO: MRI inconsistent (NMATCH vs MATCH): - $$ = MakeMatch($1, $3, @$); - } - | arg NMATCH arg - { - $$ = new MethodCall($1, Symbols.NotMatch, new Arguments($3), @$); - } - | BANG arg - { - $$ = new NotExpression($2, @$); - } - | TILDE arg - { - $$ = new MethodCall($2, Symbols.BitwiseNot, Arguments.Empty, @$); - } - | arg LSHFT arg - { - $$ = new MethodCall($1, Symbols.LeftShift, new Arguments($3), @$); - } - | arg RSHFT arg - { - $$ = new MethodCall($1, Symbols.RightShift, new Arguments($3), @$); - } - | arg LOGICAL_AND arg - { - $$ = new AndExpression($1, $3, @$); - } - | arg LOGICAL_OR arg - { - $$ = new OrExpression($1, $3, @$); - } - | arg LOGICAL_AND jump_statement_parameterless - { - $$ = new ConditionalJumpExpression($1, $3, false, null, @$); - } - | arg LOGICAL_OR jump_statement_parameterless - { - $$ = new ConditionalJumpExpression($1, $3, true, null, @$); - } - | arg DOUBLE_DOT arg - { - $$ = new RangeExpression($1, $3, false, @$); - } - | arg TRIPLE_DOT arg - { - $$ = new RangeExpression($1, $3, true, @$); - } - | DEFINED new_line_opt arg - { - $$ = new IsDefinedExpression($3, @$); - } - | arg QUESTION_MARK arg new_line_opt COLON arg - { - $$ = new ConditionalExpression(ToCondition($1), $3, $6, @$); - } - | arg QUESTION_MARK jump_statement_parameterless new_line_opt COLON arg - { - $$ = new ConditionalJumpExpression(ToCondition($1), $3, false, $6, @$); - } - | arg QUESTION_MARK arg new_line_opt COLON jump_statement_parameterless - { - $$ = new ConditionalJumpExpression(ToCondition($1), $6, true, $3, @$); - } - | arg QUESTION_MARK jump_statement_parameterless new_line_opt COLON jump_statement_parameterless - { - $$ = new ConditionalStatement(ToCondition($1), false, $3, $6, @$); - } - | primary - { - $$ = $1; - } -; - -array_items: // 1.9 changes - /* empty */ - { - SetArguments(); - } - | args trailer - { - PopAndSetArguments($1, null); - } - | args COMMA maplets trailer - { - PushArgument($1, new HashConstructor($3.ToArray(), @3)); - PopAndSetArguments($1 + 1, null); - } - | maplets trailer - { - SetArguments(new HashConstructor($1.ToArray(), @1), null); - } -; - -parenthesized_args: // 1.9 changes - LEFT_PARENTHESIS call_args_opt closing_parenthesis - { - $$ = $2 ?? Arguments.Empty; - $$ = $2; - } -; - -parenthesized_args_opt: - /* empty */ - { - SetNoArguments(null); - } - | parenthesized_args - { - $$ = $1; - } -; - -call_args_opt: // 1.9 changes - /* empty */ - { - SetNoArguments(null); - } - | call_args - { - $$ = $1; - } -; - -call_args: // 1.9 changes - args block_reference_opt - { - PopAndSetArguments($1, $2); - } - | args COMMA maplets block_reference_opt - { - PushArgument($1, new HashConstructor($3.ToArray(), @3)); - PopAndSetArguments($1 + 1, $4); - } - | maplets block_reference_opt - { - SetArguments(new HashConstructor($1.ToArray(), @1), $2); - } - | block_reference - { - SetArguments($1); - } - | command - { - SetArguments($1); - } -; - -command_args: // 1.9 changes - { - $$ = _tokenizer.EnterCommandArguments(); - } - call_args - { - _tokenizer.LeaveCommandArguments($1); - $$ = $2; - } -; - -block_reference: - BLOCK_REFERENCE arg - { - $$ = new BlockReference($2, @$); - } -; - -block_reference_opt: - COMMA block_reference - { - $$ = $2; - } - | COMMA // 1.9 - { - $$ = null; - } - | /* empty */ - { - $$ = null; - } -; - -args: - arg - { - PushArgument(0, $1); - } - | compound_rhs - { - $$ = $1; - } -; - -compound_rhs: - STAR arg - { - PushArgument(0, new SplattedArgument($2)); - } - | args COMMA arg - { - PushArgument($1, $3); - } - | args COMMA STAR arg - { - PushArgument($1, new SplattedArgument($4)); - } -; - -primary: - numeric_literal - | symbol - { - $$ = MakeSymbolLiteral($1, @1); - } - | string_concatenation - { - $$ = new StringConstructor($1, StringKind.Mutable, @1); - } - | shell_string - | regexp - | words - | verbatim_words - | var_ref - | match_reference - { - $$ = $1; - } - | FUNCTION_IDENTIFIER - { - $$ = new MethodCall(null, $1, null, @1); - } - | primary SEPARATING_DOUBLE_COLON CONSTANT_IDENTIFIER - { - $$ = new ConstantVariable($1, $3, @$); - } - | LEADING_DOUBLE_COLON CONSTANT_IDENTIFIER - { - $$ = new ConstantVariable(null, $2, @$); - } - | LEFT_BRACKET array_items RIGHT_BRACKET - { - $$ = new ArrayConstructor($2, @$); - } - | LEFT_BRACE RIGHT_BRACE - { - $$ = new HashConstructor(Maplet.EmptyArray, @$); - } - | LEFT_BRACE maplets trailer RIGHT_BRACE - { - $$ = new HashConstructor($2.ToArray(), @$); - } - | YIELD LEFT_PARENTHESIS call_args closing_parenthesis - { - $$ = new YieldCall(RequireNoBlockArg($3), @$); - } - | YIELD LEFT_PARENTHESIS closing_parenthesis - { - $$ = new YieldCall(Arguments.Empty, @$); - } - | YIELD - { - $$ = new YieldCall(null, @1); - } - | DEFINED new_line_opt LEFT_PARENTHESIS expr closing_parenthesis - { - $$ = new IsDefinedExpression($4, @$); - } - | NOT LEFT_PARENTHESIS expr closing_parenthesis - { - $$ = new NotExpression($3, @$); - } - | NOT LEFT_PARENTHESIS closing_parenthesis - { - $$ = new NotExpression(null, @$); - } - | operation brace_block - { - $$ = new MethodCall(null, $1, null, $2, @1); - } - | method_call - | method_call brace_block - { - SetBlock($1, $2); - $$ = $1; - } - | IF expr then compstmt if_tail END - { - $$ = MakeIfExpression(ToCondition($2), $4, $5, @$); - } - | UNLESS expr then compstmt else_opt END - { - $$ = new UnlessExpression(ToCondition($2), $4, $5, @$); - } - | WHILE - { - _tokenizer.EnterLoopCondition(); - } - expr do - { - _tokenizer.LeaveLoopCondition(); - } - compstmt END - { - $$ = new WhileLoopExpression(ToCondition($3), true, false, $6, @$); - } - | UNTIL - { - _tokenizer.EnterLoopCondition(); - } - expr do - { - _tokenizer.LeaveLoopCondition(); - } - compstmt END - { - $$ = new WhileLoopExpression(ToCondition($3), false, false, $6, @$); - } - | case_expression - | FOR for_parameters IN - { - _tokenizer.EnterLoopCondition(); - } - expr do - { - _tokenizer.LeaveLoopCondition(); - EnterPaddingScope(); - } - compstmt END - { - $$ = MakeForLoopExpression($2, $5, $8, @$); - LeaveScope(); - } - | block_expression - { - $$ = $1; - } - | definition_expression - { - $$ = $1; - } -; - -block_expression: - LEFT_ARG_PARENTHESIS expr - { - _tokenizer.LexicalState = LexicalState.EXPR_ENDARG; - } - closing_parenthesis - { - _tokenizer.ReportWarning(Errors.InterpretedAsGroupedExpression); - // BlockExpression behaves like an expression, so we don't need to create one here: - $$ = $2; - } - | LEFT_EXPR_PARENTHESIS compstmt RIGHT_PARENTHESIS - { - $$ = MakeBlockExpression($2, @$); - } - | BEGIN body END - { - $$ = $2; - } -; - -definition_expression: - CLASS qualified_module_name superclass - { - EnterClassDefinitionScope(); - } - body END - { - if (InMethod) { - ErrorSink.Add(_sourceUnit, "class definition in method body", @1, -1, Severity.Error); - } - $$ = new ClassDefinition(CurrentScope, $2, $3, $5, @$); - LeaveScope(); - } - | CLASS LSHFT expr - { - $$ = _inInstanceMethodDefinition; - _inInstanceMethodDefinition = 0; - } - term - { - $$ = _inSingletonMethodDefinition; - _inSingletonMethodDefinition = 0; - EnterSingletonClassDefinitionScope(); - } - body END - { - _inInstanceMethodDefinition = $4; - _inSingletonMethodDefinition = $6; - $$ = new SingletonDefinition(LeaveScope(), $3, $7, @$); - } - | MODULE qualified_module_name - { - EnterModuleDefinitionScope(); - } - body END - { - if (InMethod) { - ErrorSink.Add(_sourceUnit, "module definition in method body", @1, -1, Severity.Error); - } - $$ = new ModuleDefinition(CurrentScope, $2, $4, @$); - LeaveScope(); - } - | DEF method_name - { - _inInstanceMethodDefinition++; - EnterMethodDefinitionScope(); - } - method_parameters body END - { - _inInstanceMethodDefinition--; - $$ = new MethodDefinition(CurrentScope, null, $2, $4, $5, @$); - LeaveScope(); - } - | DEF singleton dot_or_colon - { - _tokenizer.LexicalState = LexicalState.EXPR_FNAME; - } - method_name - { - _inSingletonMethodDefinition++; - _tokenizer.LexicalState = LexicalState.EXPR_ENDFN; // 1.8: EXPR_END - EnterSingletonMethodDefinitionScope(); - } - method_parameters body END - { - _inSingletonMethodDefinition--; - $$ = new MethodDefinition(CurrentScope, $2, $5, $7, $8, @$); - LeaveScope(); - } - | LAMBDA lambda // 1.9 - { - $$ = $2; - } -; - -body: - compstmt rescue_clauses_opt else_opt ensure_opt - { - $$ = MakeBody($1, $2, $3, @3, $4, @$); - } -; - -case_expression: - CASE expr terms_opt when_clauses else_opt END - { - $$ = new CaseExpression($2, $4.ToArray(), $5, @$); - } - | CASE terms_opt when_clauses else_opt END - { - $$ = new CaseExpression(null, $3.ToArray(), $4, @$); - } -; - -then: // 1.9: COLON removed - term - | THEN - | term THEN -; - -do: // 1.9: COLON removed - term - | LOOP_DO -; - -if_tail: - else_opt - { - $$ = MakeListAddOpt($1); - } - | ELSIF expr then compstmt if_tail - { - $5.Add(new ElseIfClause($2, $4, @$)); - $$ = $5; - } -; - -else_opt: /* empty */ - { - $$ = null; - } - | ELSE compstmt - { - $$ = new ElseIfClause(null, $2, @$); - } - ; - -for_parameters: - lhs - { - $$ = new CompoundLeftValue(new LeftValue[] { $1 }); - } - | compound_lhs - { - $$ = $1; - } -; - -parameter_list: // 1.9 change - parenthesized_parameter - { - $$ = CollectionUtils.MakeList($1); - } - | parameter_list COMMA parenthesized_parameter - { - ($$ = $1).Add($3); - } -; - -parenthesized_parameter: // 1.9 - parameter - { - $$ = $1; - } - | LEFT_EXPR_PARENTHESIS compound_parameters closing_parenthesis - { - $$ = $2; - } -; - -compound_parameters: // 1.9 - compound_parameter_list - { - $$ = new CompoundLeftValue($1.ToArray()); - } - | compound_parameter_list COMMA STAR parameter - { - $$ = MakeCompoundLeftValue($1, $4, null); - } - | compound_parameter_list COMMA STAR - { - $$ = MakeCompoundLeftValue($1, Placeholder.Singleton, null); - } - | compound_parameter_list COMMA STAR parameter COMMA compound_parameter_list - { - $$ = MakeCompoundLeftValue($1, $4, $6); - } - | compound_parameter_list COMMA STAR COMMA compound_parameter_list - { - $$ = MakeCompoundLeftValue($1, Placeholder.Singleton, $5); - } - | STAR parameter COMMA compound_parameter_list - { - $$ = MakeCompoundLeftValue(null, $2, $4); - } - | STAR COMMA compound_parameter_list - { - $$ = MakeCompoundLeftValue(null, Placeholder.Singleton, $3); - } - | STAR parameter - { - $$ = new CompoundLeftValue(new LeftValue[] { $2 }, 0); - } - | STAR - { - $$ = new CompoundLeftValue(new LeftValue[] { Placeholder.Singleton }, 0); - } -; - -compound_parameter_list: // 1.9 - compound_parameter - { - $$ = CollectionUtils.MakeList($1); - } - | compound_parameter_list COMMA compound_parameter - { - ($$ = $1).Add($3); - } -; - -compound_parameter: // 1.9 - parameter - { - $$ = $1; - } - | LEFT_EXPR_PARENTHESIS compound_parameters closing_parenthesis - { - $$ = $2; - } -; - -block_parameter_list: - parameter_list COMMA default_block_parameter_list COMMA parameter_array block_parameter_opt - { - $$ = new Parameters($1.ToArray(), $1.Count, $3.ToArray(), $6, $6, @$); - } - | parameter_list COMMA default_block_parameter_list COMMA parameter_array COMMA parameter_list block_parameter_opt - { - $$ = new Parameters(MakeArray($1, $7), $1.Count, $3.ToArray(), $5, $8, @$); - } - | parameter_list COMMA default_block_parameter_list block_parameter_opt - { - $$ = new Parameters($1.ToArray(), $1.Count, $3.ToArray(), null, $4, @$); - } - | parameter_list COMMA default_block_parameter_list COMMA parameter_list block_parameter_opt - { - $$ = new Parameters(MakeArray($1, $5), $1.Count, $3.ToArray(), null, $6, @$); - } - | parameter_list COMMA parameter_array block_parameter_opt - { - $$ = new Parameters($1.ToArray(), $1.Count, null, $3, $4, @$); - } - | parameter_list COMMA // missing from method parameters - { - $$ = new Parameters(MakeArray($1, Placeholder.Singleton), $1.Count, null, null, null, @$); - } - | parameter_list COMMA parameter_array COMMA parameter_list block_parameter_opt - { - $$ = new Parameters(MakeArray($1, $5), $1.Count, null, $3, $6, @$); - } - | parameter_list block_parameter_opt - { - $$ = new Parameters($1.ToArray(), $1.Count, null, null, $2, @$); - } - | default_block_parameter_list COMMA parameter_array block_parameter_opt - { - $$ = new Parameters(null, 0, $1.ToArray(), $3, $4, @$); - } - | default_block_parameter_list COMMA parameter_array COMMA parameter_list block_parameter_opt - { - $$ = new Parameters($5.ToArray(), 0, $1.ToArray(), $3, $6, @$); - } - | default_block_parameter_list block_parameter_opt - { - $$ = new Parameters(null, 0, $1.ToArray(), null, $2, @$); - } - | default_block_parameter_list COMMA parameter_list block_parameter_opt - { - $$ = new Parameters($3.ToArray(), 0, $1.ToArray(), null, $4, @$); - } - | parameter_array block_parameter_opt - { - $$ = new Parameters(null, 0, null, $1, $2, @$); - } - | parameter_array COMMA parameter_list block_parameter_opt - { - $$ = new Parameters($3.ToArray(), 0, null, $1, $4, @$); - } - | block_parameter - { - $$ = new Parameters(null, 0, null, null, $1, @$); - } - | /* empty */ - { - $$ = Parameters.Empty; - } -; - -block_parameters_opt: // 1.9 - /* empty */ - { - $$ = null; - } - | block_parameters - { - _tokenizer.CommandMode = true; - $$ = $1; - } -; - -block_parameters: // 1.9 - LOGICAL_OR - { - $$ = null; - } - | PIPE block_parameter_list block_variables_opt PIPE - { - $$ = $2; - } -; - -block_variables_opt: // 1.9 - /* empty */ - | SEMICOLON block_variables -; - -block_variables: // 1.9 - parameter - | block_variables COMMA parameter -; - -lambda: // 1.9 - { - $$ = _tokenizer.EnterLambdaDefinition(); - EnterNestedScope(); - } - lambda_parameters lambda_body - { - $$ = MakeLambdaDefinition($2, $3, @$); - _tokenizer.LeaveLambdaDefinition($$); - LeaveScope(); - } -; - -lambda_parameters: // 1.9 - LEFT_PARENTHESIS parameters block_variables_opt closing_parenthesis - { - $$ = $2; - } - | parameters - { - $$ = $1; - } -; - -lambda_body: // 1.9 - LEFT_LAMBDA_BRACE compstmt RIGHT_BRACE - { - $$ = $2; - } - | LAMBDA_DO compstmt END - { - $$ = $2; - } -; - -do_block: // 1.9 change - BLOCK_DO - { - EnterNestedScope(); - } - block_parameters_opt compstmt END - { - $$ = MakeBlockDefinition($3, $4, @$); - LeaveScope(); - } -; - -block_call: - command do_block - { - if ($1 is YieldCall) { - _tokenizer.ReportError(Errors.BlockGivenToYield); - } - - SetBlock($$ = $1, $2); - } - | block_call DOT operation2 parenthesized_args_opt - { - $$ = MakeMethodCall($1, $3, $4, @$); - } - | block_call SEPARATING_DOUBLE_COLON operation2 parenthesized_args_opt - { - $$ = MakeMethodCall($1, $3, $4, @$); - } -; - -method_call: - operation parenthesized_args - { - $$ = MakeMethodCall(null, $1, $2, @$); - } - | primary DOT operation2 parenthesized_args_opt - { - $$ = MakeMethodCall($1, $3, $4, @$); - } - | primary SEPARATING_DOUBLE_COLON operation2 parenthesized_args - { - $$ = MakeMethodCall($1, $3, $4, @$); - } - | primary SEPARATING_DOUBLE_COLON operation3 - { - $$ = new MethodCall($1, $3, null, @3); - } - | primary DOT parenthesized_args // 1.9 - { - $$ = MakeMethodCall($1, Symbols.Call, $3, @$); - } - | primary SEPARATING_DOUBLE_COLON parenthesized_args // 1.9 - { - $$ = MakeMethodCall($1, Symbols.Call, $3, @$); - } - | primary LEFT_INDEXING_BRACKET call_args_opt closing_bracket // 1.9 - { - $$ = MakeMethodCall($1, Symbols.ArrayItemRead, $3, @$); - } - | SUPER parenthesized_args - { - $$ = MakeSuperCall($2, @1); - } - | SUPER - { - $$ = new SuperCall(null, null, @1); - } -; - -brace_block: - LEFT_BLOCK_BRACE - { - EnterNestedScope(); - } - block_parameters_opt compstmt RIGHT_BRACE - { - $$ = MakeBlockDefinition($3, $4, @$); - LeaveScope(); - } - | DO - { - EnterNestedScope(); - } - block_parameters_opt compstmt END - { - $$ = MakeBlockDefinition($3, $4, @$); - LeaveScope(); - } -; - -when_clauses: - when_clause - { - $$ = CollectionUtils.MakeList($1); - } - | when_clauses when_clause - { - ($$ = $1).Add($2); - } -; - -when_clause: - WHEN args then compstmt - { - $$ = new WhenClause(PopArguments($2), $4, @4); - } -; - -rescue_clauses_opt: - /* empty */ - { - $$ = null; - } - | rescue_clauses -; - -rescue_clauses: - rescue_clause - { - $$ = CollectionUtils.MakeList($1); - } - | rescue_clauses rescue_clause - { - ($$ = $1).Add($2); - } -; - -rescue_clause: - RESCUE exc_var then compstmt - { - $$ = new RescueClause(Expression.EmptyArray, $2, $4, @$); - } - | RESCUE args exc_var then compstmt - { - $$ = new RescueClause(PopArguments($2), $3, $5, @$); - } -; - -exc_var: - /* empty */ - { - $$ = null; - } - | DOUBLE_ARROW lhs - { - $$ = $2; - } -; - -ensure_opt: - /* empty */ - { - $$ = null; - } - | ENSURE compstmt - { - $$ = $2; - } -; - -string_concatenation: - CHARACTER // 1.9 - { - $$ = CollectionUtils.MakeList(MakeStringLiteral($1, @1)); - } - | string - { - $$ = $1; - } - | string_concatenation string - { - ($$ = $1).AddRange($2); - } -; - -string: - STRING_BEGIN string_contents STRING_END - { - $$ = $2; - } -; - -shell_string: - SHELL_STRING_BEGIN string_contents STRING_END - { - $$ = new StringConstructor($2, StringKind.Command, @$); - } -; - -regexp: - REGEXP_BEGIN string_contents REGEXP_END - { - $$ = new RegularExpression($2, $3, @$); - } -; - -words: - WORDS_BEGIN STRING_END - { - $$ = new ArrayConstructor(null, @$); - } - | WORDS_BEGIN word_list word STRING_END - { - $2.Add(new StringConstructor($3, StringKind.Mutable, @3)); - $$ = new ArrayConstructor(new Arguments($2.ToArray()), @$); - } -; - -word_list: - /* empty */ - { - $$ = new List(); - } - | word_list word WORD_SEPARATOR - { - ($$ = $1).Add(new StringConstructor($2, StringKind.Mutable, @2)); - } -; - -word: - string_content - { - $$ = CollectionUtils.MakeList($1); - } - | word string_content - { - ($$ = $1).Add($2); - } -; - -verbatim_words: - VERBATIM_WORDS_BEGIN STRING_END - { - $$ = new ArrayConstructor(null, @$); - } - | VERBATIM_WORDS_BEGIN verbatim_word_list STRING_CONTENT STRING_END - { - $2.Add(MakeStringLiteral($3, @3)); - $$ = MakeVerbatimWords($2, @$); - } -; - -verbatim_word_list: - /* empty */ - { - $$ = new List(); - } - | verbatim_word_list STRING_CONTENT WORD_SEPARATOR - { - ($$ = $1).Add(MakeStringLiteral($2, @2)); - } -; - -string_contents: - /* empty */ - { - $$ = new List(); - } - | string_contents string_content - { - ($$ = $1).Add($2); - } -; - - -string_content: - STRING_CONTENT - { - $$ = MakeStringLiteral($1, @$); - } - | STRING_EMBEDDED_VARIABLE_BEGIN string_embedded_variable - { - $$ = $2; - } - | STRING_EMBEDDED_CODE_BEGIN compstmt STRING_EMBEDDED_CODE_END - { - // STRING_EMBEDDED_CODE_END leaves parenthesised expression, but command_args in compstmt restores it back to the state after - // STRING_EMBEDDED_CODE_BEGIN. So we need to leave it again. - _tokenizer.PopParenthesisedExpressionStack(); - $$ = MakeBlockExpression($2, @2); - } -; - -string_embedded_variable: - GLOBAL_VARIABLE - { - $$ = new GlobalVariable($1, @$); - } - | match_reference - { - $$ = $1; - } - | INSTANCE_VARIABLE - { - $$ = new InstanceVariable($1, @$); - } - | CLASS_VARIABLE - { - $$ = new ClassVariable($1, @$); - } -; - -numeric_literal: - INTEGER - { - // unsigned integer: - $$ = Literal.Integer($1, @$); - } - | BIG_INTEGER - { - $$ = Literal.BigInteger($1, @$); - } - | FLOAT - { - $$ = Literal.Double($1, @$); - } - | NUMBER_NEGATION INTEGER %prec LOWEST - { - // cannot overflow INTEGER is unsigned and Int32.MaxValue < |Int32.MinValue| - $$ = Literal.Integer(-$2, @$); - } - | NUMBER_NEGATION BIG_INTEGER %prec LOWEST - { - // TODO: -|Int32.MinValue| actually ends up here (converted to bigint) instead of being Int32. We should fix that. - $$ = Literal.BigInteger(-$2, @$); - } - | NUMBER_NEGATION FLOAT %prec LOWEST - { - $$ = Literal.Double(-$2, @$); - } -; - -variable: - IDENTIFIER { $$ = VariableFactory.Identifier; $$ = $1; } - | INSTANCE_VARIABLE { $$ = VariableFactory.Instance; $$ = $1; } - | GLOBAL_VARIABLE { $$ = VariableFactory.Global; $$ = $1; } - | CONSTANT_IDENTIFIER { $$ = VariableFactory.Constant; $$ = $1; } - | CLASS_VARIABLE { $$ = VariableFactory.Class; $$ = $1; } - | NIL { $$ = VariableFactory.Nil; $$ = null; } - | SELF { $$ = VariableFactory.Self; $$ = null; } - | TRUE { $$ = VariableFactory.True; $$ = null; } - | FALSE { $$ = VariableFactory.False; $$ = null; } - | FILE { $$ = VariableFactory.File; $$ = null; } - | LINE { $$ = VariableFactory.Line; $$ = null; } - | ENCODING { $$ = VariableFactory.Encoding; $$ = null; } -; - -var_ref: - variable - { - $$ = VariableFactory.MakeRead($1, this, $1, @$); - } -; - -var_lhs: - variable - { - $$ = VariableFactory.MakeLeftValue($1, this, $1, @$); - } -; - -match_reference: - MATCH_REFERENCE - { - $$ = new RegexMatchReference($1, @1); - } -; - -superclass: - term - { - $$ = null; - } - | LESS - { - _tokenizer.LexicalState = LexicalState.EXPR_BEG; - } - expr term - { - $$ = $3; - } - | ERROR term - { - StopErrorRecovery(); - $$ = null; - } -; - -method_parameters: - LEFT_PARENTHESIS parameters closing_parenthesis - { - $$ = $2; - _tokenizer.LexicalState = LexicalState.EXPR_BEG; - _tokenizer.CommandMode = true; - } - | parameters term - { - $$ = $1; - } -; - -parameters: - parameter_list COMMA default_parameter_list COMMA parameter_array block_parameter_opt - { - $$ = new Parameters($1.ToArray(), $1.Count, $3.ToArray(), $5, $6, @$); - } - | parameter_list COMMA default_parameter_list COMMA parameter_array COMMA parameter_list block_parameter_opt // 1.9 - { - $$ = new Parameters(MakeArray($1, $7), $1.Count, $3.ToArray(), $5, $8, @$); - } - | parameter_list COMMA default_parameter_list block_parameter_opt - { - $$ = new Parameters($1.ToArray(), $1.Count, $3.ToArray(), null, $4, @$); - } - | parameter_list COMMA default_parameter_list COMMA parameter_list block_parameter_opt // 1.9 - { - $$ = new Parameters(MakeArray($1, $5), $1.Count, $3.ToArray(), null, $6, @$); - } - | parameter_list COMMA parameter_array block_parameter_opt - { - $$ = new Parameters($1.ToArray(), $1.Count, null, $3, $4, @$); - } - | parameter_list COMMA parameter_array COMMA parameter_list block_parameter_opt - { - $$ = new Parameters(MakeArray($1, $5), $1.Count, null, $3, $6, @$); - } - | parameter_list block_parameter_opt - { - $$ = new Parameters($1.ToArray(), $1.Count, null, null, $2, @$); - } - | default_parameter_list COMMA parameter_array block_parameter_opt - { - $$ = new Parameters(null, 0, $1.ToArray(), $3, $4, @$); - } - | default_parameter_list COMMA parameter_array COMMA parameter_list block_parameter_opt // 1.9 - { - $$ = new Parameters($5.ToArray(), 0, $1.ToArray(), $3, $6, @$); - } - | default_parameter_list block_parameter_opt - { - $$ = new Parameters(null, 0, $1.ToArray(), null, $2, @$); - } - | default_parameter_list COMMA parameter_list block_parameter_opt // 1.9 - { - $$ = new Parameters($3.ToArray(), 0, $1.ToArray(), null, $4, @$); - } - | parameter_array block_parameter_opt - { - $$ = new Parameters(null, 0, null, $1, $2, @$); - } - | parameter_array COMMA parameter_list block_parameter_opt // 1.9 - { - $$ = new Parameters($3.ToArray(), 0, null, $1, $4, @$); - } - | block_parameter - { - $$ = new Parameters(null, 0, null, null, $1, @$); - } - | /* empty */ - { - $$ = Parameters.Empty; - } -; - -parameter: - CONSTANT_IDENTIFIER - { - _tokenizer.ReportError(Errors.FormalArgumentIsConstantVariable); - $$ = DefineParameter(GenerateErrorConstantName(), @$); - } - | INSTANCE_VARIABLE - { - _tokenizer.ReportError(Errors.FormalArgumentIsInstanceVariable); - $$ = DefineParameter(GenerateErrorConstantName(), @$); - } - | GLOBAL_VARIABLE - { - _tokenizer.ReportError(Errors.FormalArgumentIsGlobalVariable); - $$ = DefineParameter(GenerateErrorConstantName(), @$); - } - | CLASS_VARIABLE - { - _tokenizer.ReportError(Errors.FormalArgumentIsClassVariable); - $$ = DefineParameter(GenerateErrorConstantName(), @$); - } - | IDENTIFIER - { - $$ = DefineParameter($1, @$); - } -; - -default_parameter: - IDENTIFIER ASSIGNMENT arg - { - $$ = new SimpleAssignmentExpression(DefineParameter($1, @$), $3, null, @$); - } -; - -// Default block parameter is different from default method parameter -// Block parameter doesn't allow using binary expressions etc. defined by arg due to ambiguity with binary OR operator: lambda { |x=1| } -default_block_parameter: - IDENTIFIER ASSIGNMENT primary - { - $$ = new SimpleAssignmentExpression(DefineParameter($1, @$), $3, null, @$); - } -; - -default_parameter_list: - default_parameter - { - $$ = CollectionUtils.MakeList($1); - } - | default_parameter_list COMMA default_parameter - { - ($$ = $1).Add($3); - } -; - -default_block_parameter_list: - default_block_parameter - { - $$ = CollectionUtils.MakeList($1); - } - | default_block_parameter_list COMMA default_block_parameter - { - ($$ = $1).Add($3); - } -; - -array_parameter_mark: - ASTERISK - | STAR -; - -parameter_array: - array_parameter_mark parameter - { - $$ = $2; - } - | array_parameter_mark - { - $$ = DefineParameter(Symbols.RestArgsLocal, @1); - } -; - -block_parameter_mark: - AMPERSAND - | BLOCK_REFERENCE -; - -block_parameter: - block_parameter_mark parameter - { - $$ = $2; - } -; - -block_parameter_opt: - /* empty */ - { - $$ = null; - } - | COMMA block_parameter - { - $$ = $2; - } -; - -singleton: - var_ref - | LEFT_PARENTHESIS - { - _tokenizer.LexicalState = LexicalState.EXPR_BEG; - } - expr closing_parenthesis - { - $$ = $3; - } -; - -maplets: - maplet - { - $$ = CollectionUtils.MakeList($1); - } - | maplets COMMA maplet - { - ($$ = $1).Add($3); - } -; - -maplet: - arg DOUBLE_ARROW arg - { - $$ = new Maplet($1, $3, @$); - } - | LABEL arg // 1.9 - { - $$ = new Maplet(MakeSymbolLiteral($1, @1), $2, @$); - } -; - -operation: - IDENTIFIER - | CONSTANT_IDENTIFIER - | FUNCTION_IDENTIFIER -; - -operation2: - IDENTIFIER - | CONSTANT_IDENTIFIER - | FUNCTION_IDENTIFIER - | op -; - -operation3: - IDENTIFIER - | FUNCTION_IDENTIFIER - | op -; - -dot_or_colon: - DOT - | SEPARATING_DOUBLE_COLON -; - -terms_opt: - /* empty */ - | terms -; - -new_line_opt: - /* empty */ - | NEW_LINE -; - -closing_parenthesis: - new_line_opt RIGHT_PARENTHESIS -; - -closing_bracket: - new_line_opt RIGHT_BRACKET -; - -trailer: - /* empty */ - | NEW_LINE - | COMMA -; - -term: - SEMICOLON { StopErrorRecovery(); } - | NEW_LINE -; - -terms: - term - | terms SEMICOLON { StopErrorRecovery(); } -; - -%% diff --git a/Src/Ruby/Compiler/Parser/ParserStack.cs b/Src/Ruby/Compiler/Parser/ParserStack.cs deleted file mode 100644 index 1125d51af..000000000 --- a/Src/Ruby/Compiler/Parser/ParserStack.cs +++ /dev/null @@ -1,65 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace IronRuby.Compiler { - public class ParserStack { - // Most Ruby files are around 30, few are around 100 - private const int InitialSize = 50; - - // It's actually faster to keep these as separate arrays rather then wrap entries into a struct. - private TState[]/*!*/ _states = new TState[InitialSize]; - private TLocation[]/*!*/ _locations = new TLocation[InitialSize]; - private TValue[]/*!*/ _values = new TValue[InitialSize]; - - private int _top = 0; - - public void Push(TState state, TValue value, TLocation location) { - int top = _top; - if (top == _states.Length) { - var newStates = new TState[top * 2]; - var newValues = new TValue[top * 2]; - var newLocations = new TLocation[top * 2]; - Array.Copy(_states, newStates, top); - Array.Copy(_values, newValues, top); - Array.Copy(_locations, newLocations, top); - _states = newStates; - _values = newValues; - _locations = newLocations; - } - _states[top] = state; - _values[top] = value; - _locations[top] = location; - _top = top + 1; - } - - public void Pop() { - _top--; - } - - public void Pop(int depth) { - _top -= depth; - } - - public TState PeekState(int depth) { - return _states[_top - depth]; - } - - public TLocation PeekLocation(int depth) { - return _locations[_top - depth]; - } - - public TValue PeekValue(int depth) { - return _values[_top - depth]; - } - - public bool IsEmpty { - get { return _top == 0; } - } - - // debug dump only: - public IEnumerable/*!*/ GetStates() { - return _states; - } - } -} diff --git a/Src/Ruby/Compiler/Parser/TokenSequenceState.cs b/Src/Ruby/Compiler/Parser/TokenSequenceState.cs deleted file mode 100644 index bc63de4d3..000000000 --- a/Src/Ruby/Compiler/Parser/TokenSequenceState.cs +++ /dev/null @@ -1,307 +0,0 @@ -/* **************************************************************************** - * - * Copyright (c) Microsoft Corporation. - * - * This source code is subject to terms and conditions of the Apache License, Version 2.0. A - * copy of the license can be found in the License.html file at the root of this distribution. If - * you cannot locate the Apache License, Version 2.0, please send an email to - * ironruby@microsoft.com. By using this source code in any fashion, you are agreeing to be bound - * by the terms of the Apache License, Version 2.0. - * - * You must not remove this notice, or any other, from this software. - * - * - * ***************************************************************************/ - -using System; -using System.Diagnostics; - -namespace IronRuby.Compiler { - internal class TokenSequenceState { - internal static readonly TokenSequenceState None = new TokenSequenceState(); - - internal virtual Tokens TokenizeAndMark(Tokenizer/*!*/ tokenizer) { - Tokens result = tokenizer.Tokenize(); - tokenizer.CaptureTokenSpan(); - return result; - } - - public override string ToString() { - return ""; - } - } - - [Flags] - public enum StringProperties : byte { - Default = 0, - ExpandsEmbedded = 1, - RegularExpression = 2, - Words = 4, - Symbol = 8, - IndentedHeredoc = 16, - } - - internal sealed class CodeState : TokenSequenceState, IEquatable { - internal readonly LexicalState LexicalState; - - // true if the following identifier is treated as a command name (sets LexicalState.CMDARG): - internal readonly byte CommandMode; - - // true if the previous token is Tokens.Whitespace: - internal readonly byte WhitespaceSeen; - - public CodeState(LexicalState lexicalState, byte commandMode, byte whitespaceSeen) { - LexicalState = lexicalState; - CommandMode = commandMode; - WhitespaceSeen = whitespaceSeen; - } - - public override bool Equals(object other) { - return Equals(other as CodeState); - } - - public bool Equals(CodeState other) { - return ReferenceEquals(other, this) || (other != null - && LexicalState == other.LexicalState - && CommandMode == other.CommandMode - && WhitespaceSeen == other.WhitespaceSeen - ); - } - - public override int GetHashCode() { - return (int)LexicalState - ^ (int)CommandMode - ^ (int)WhitespaceSeen; - } - } - - internal sealed class StringState : TokenSequenceState, IEquatable { - // The number of opening parentheses that need to be closed before the string terminates. - // The level is tracked for all currently opened strings. - // For example, %< .. < .. < #{...} .. > .. > .. > comprises of 3 parts: - // %< .. < .. < - // #{...} - // .. > .. > .. > - // After reading the first part the nested level for the string is set to 2. - private readonly int _nestingLevel; - - private readonly StringProperties _properties; - - // The character terminating the string: - private readonly char _terminator; - - // Parenthesis opening the string; if non-zero parenthesis of this kind is balanced before the string is closed: - private readonly char _openingParenthesis; - - public StringState(StringProperties properties, char terminator) - : this(properties, terminator, '\0', 0) { - } - - public StringState(StringProperties properties, char terminator, char openingParenthesis, int nestingLevel) { - Debug.Assert(!Tokenizer.IsLetterOrDigit(terminator)); - - _properties = properties; - _terminator = terminator; - _openingParenthesis = openingParenthesis; - _nestingLevel = nestingLevel; - } - - public override bool Equals(object other) { - return Equals(other as StringState); - } - - public bool Equals(StringState other) { - return ReferenceEquals(other, this) || (other != null - && _nestingLevel == other._nestingLevel - && _properties == other._properties - && _terminator == other._terminator - && _openingParenthesis == other._openingParenthesis - ); - } - - public override int GetHashCode() { - return _nestingLevel - ^ (int)_properties - ^ (int)_terminator - ^ (int)_openingParenthesis; - } - - public StringState/*!*/ SetNesting(int level) { - return (_nestingLevel == level) ? this : new StringState(_properties, _terminator, _openingParenthesis, level); - } - - public StringProperties Properties { - get { return _properties; } - } - - public int NestingLevel { - get { return _nestingLevel; } - } - - public char TerminatingCharacter { - get { return _terminator; } - } - - public char OpeningParenthesis { - get { return _openingParenthesis; } - } - - public override string ToString() { - return String.Format("StringTerminator({0},{1},{2},{3},{4})", _properties, (int)_terminator, (int)_openingParenthesis, 0, _nestingLevel); - } - - internal override Tokens TokenizeAndMark(Tokenizer/*!*/ tokenizer) { - Tokens result = tokenizer.TokenizeString(this); - tokenizer.CaptureTokenSpan(); - return result; - } - } - - internal abstract class HeredocStateBase : TokenSequenceState { - private readonly StringProperties _properties; - private readonly string/*!*/ _label; - - public HeredocStateBase(StringProperties properties, string/*!*/ label) { - _properties = properties; - _label = label; - } - - protected bool Equals(HeredocStateBase/*!*/ other) { - return _properties == other._properties - && _label == other._label; - } - - protected int GetBaseHashCode() { - return (int)_properties - ^ _label.GetHashCode(); - } - - public StringProperties Properties { - get { return _properties; } - } - - public string Label { - get { return _label; } - } - - internal abstract Tokens Finish(Tokenizer/*!*/ tokenizer, int labelStart); - } - - internal sealed class VerbatimHeredocState : HeredocStateBase, IEquatable { - public VerbatimHeredocState(StringProperties properties, string/*!*/ label) - : base(properties, label) { - } - - public override bool Equals(object other) { - return Equals(other as VerbatimHeredocState); - } - - public bool Equals(VerbatimHeredocState other) { - return ReferenceEquals(other, this) || (other != null - && base.Equals(other) - ); - } - - public override int GetHashCode() { - return GetBaseHashCode(); - } - - internal override Tokens TokenizeAndMark(Tokenizer/*!*/ tokenizer) { - return tokenizer.TokenizeAndMarkHeredoc(this); - } - - internal override Tokens Finish(Tokenizer tokenizer, int labelStart) { - return tokenizer.FinishVerbatimHeredoc(this, labelStart); - } - - public override string ToString() { - return String.Format("VerbatimHeredoc({0},'{1}')", Properties, Label); - } - } - - internal sealed class HeredocState : HeredocStateBase, IEquatable { - private readonly int _resumePosition; - private readonly int _resumeLineLength; - private readonly char[] _resumeLine; - private readonly int _firstLine; - private readonly int _firstLineIndex; - - internal HeredocState(StringProperties properties, string/*!*/ label, int resumePosition, char[] resumeLine, int resumeLineLength, int firstLine, int firstLineIndex) - : base(properties, label) { - _resumePosition = resumePosition; - _resumeLine = resumeLine; - _resumeLineLength = resumeLineLength; - _firstLine = firstLine; - _firstLineIndex = firstLineIndex; - } - - public override bool Equals(object other) { - return Equals(other as HeredocState); - } - - public bool Equals(HeredocState other) { - return ReferenceEquals(other, this) || (other != null - && base.Equals(other) - && _resumePosition == other._resumePosition - // TODO: ??? && _resumeLineLength == other._resumeLineLength - // TODO: ??? && _resumeLine.ValueEquals(other._resumeLine) - && _firstLine == other._firstLine - && _firstLineIndex == other._firstLineIndex - ); - } - - public override int GetHashCode() { - return GetBaseHashCode() - ^ _resumePosition - ^ _firstLine - ^ _firstLineIndex; - } - - public int ResumePosition { - get { return _resumePosition; } - } - - - public char[] ResumeLine { - get { return _resumeLine; } - } - - public int ResumeLineLength { - get { return _resumeLineLength; } - } - - public int FirstLine { - get { return _firstLine; } - } - - public int FirstLineIndex { - get { return _firstLineIndex; } - } - - internal override Tokens TokenizeAndMark(Tokenizer/*!*/ tokenizer) { - return tokenizer.TokenizeAndMarkHeredoc(this); - } - - internal override Tokens Finish(Tokenizer/*!*/ tokenizer, int labelStart) { - return tokenizer.FinishHeredoc(this, labelStart); - } - - public override string ToString() { - return String.Format("Heredoc({0},'{1}',{2},'{3}')", Properties, Label, _resumePosition, new String(_resumeLine)); - } - } - - internal sealed class MultiLineCommentState : TokenSequenceState { - internal static readonly MultiLineCommentState Instance = new MultiLineCommentState(); - - private MultiLineCommentState() { - } - - internal override Tokens TokenizeAndMark(Tokenizer/*!*/ tokenizer) { - tokenizer.MarkTokenStart(); - Tokens token = tokenizer.TokenizeMultiLineComment(false); - tokenizer.CaptureTokenSpan(); - return token; - } - } -} diff --git a/Src/Ruby/Compiler/Parser/Tokenizer.cs b/Src/Ruby/Compiler/Parser/Tokenizer.cs index b8f555f2a..561ae0227 100644 --- a/Src/Ruby/Compiler/Parser/Tokenizer.cs +++ b/Src/Ruby/Compiler/Parser/Tokenizer.cs @@ -29,3351 +29,41 @@ using Microsoft.Scripting.Utils; namespace IronRuby.Compiler { - internal enum LexicalState : byte { - EXPR_BEG, // ignore newline, +/- is a sign. - EXPR_END, // newline significant, +/- is an operator. - EXPR_ARG, // newline significant, +/- is an operator. - EXPR_CMDARG, // newline significant, +/- is an operator, an identifier is a command name, special behavior of do keyword and left parenthesis - EXPR_ENDARG, // newline significant, +/- is an operator, unbound braces. - EXPR_MID, // newline significant, +/- is an operator. - EXPR_FNAME, // ignore newline, no reserved words. - EXPR_ENDFN, // newline significant, +/- is an operator, unbound braces (1.9) - EXPR_DOT, // right after `.' or `::', no reserved words. - EXPR_CLASS, // immediate after `class', no here document. - EXPR_VALUE, // alike EXPR_BEG but label is disallowed (1.9) - }; - - public class Tokenizer : TokenizerService { - private readonly ILexicalVariableResolver/*!*/ _localVariableResolver; - private BignumParser _bigIntParser; - - private const int InitialBufferSize = 80; - - public bool ForceBinaryMultiByte { get; set; } - - public bool AllowNonAsciiIdentifiers { - get { return _multiByteIdentifier < Int32.MaxValue; } - set { _multiByteIdentifier = value ? AllowMultiByteIdentifier : Int32.MaxValue; } - } - - internal RubyEncoding/*!*/ Encoding { - get { return _encoding; } - set { - Assert.NotNull(_encoding); - _encoding = value; - } - } - - public bool Verbatim { - get { return _verbatim; } - set { _verbatim = value; } - } - - private RubyEncoding/*!*/ _encoding; - private TextReader _input; - private SourceLocation _initialLocation; - private RubyCompatibility _compatibility; - - // true if running w/o parser: comments and whitespace tokens are yielded - private bool _verbatim; - - private int _multiByteIdentifier = Int32.MaxValue; - - private SourceUnit _sourceUnit; - private ErrorSink/*!*/ _errorSink; - - #region State - - internal struct NestedTokenSequence : IEquatable { - internal static readonly NestedTokenSequence[] EmptyArray = new NestedTokenSequence[0]; - - public readonly TokenSequenceState State; - public readonly int OpenedBracesInEmbeddedCode; - - public NestedTokenSequence(TokenSequenceState/*!*/ state, int openedBracesInEmbeddedCode) { - State = state; - OpenedBracesInEmbeddedCode = openedBracesInEmbeddedCode; - } - - public override bool Equals(object other) { - return other is NestedTokenSequence && Equals((NestedTokenSequence)other); - } - - public bool Equals(NestedTokenSequence other) { - return ReferenceEquals(State, other.State) || (State != null && State.Equals(other.State) - && OpenedBracesInEmbeddedCode == other.OpenedBracesInEmbeddedCode - ); - } - - public override int GetHashCode() { - return State.GetHashCode() ^ OpenedBracesInEmbeddedCode; - } - } - - internal sealed class State : IEquatable { - internal TokenSequenceState/*!*/ _currentSequence; - internal NestedTokenSequence[]/*!*/ _nestedSequences; - internal int _nestedSequenceCount; - - // Verbatim mode only: a queue of heredocs that were started on the current line. - // The queued heredocs will be pushed to the _nestedSequences stack at the end of the line. - internal List VerbatimHeredocQueue; - - internal LexicalState LexicalState; - - // The number of unmatched left braces since the start of last string embedded code. - internal int OpenedBracesInEmbeddedCode; - - // True (1) if the following identifier is treated as a command name (sets LexicalState.CMDARG). - internal byte _commandMode; - - // True (1) if the previous token is Tokens.Whitespace. - internal byte _whitespaceSeen; - - // True (1) if the previous token is Tokens.StringEmbeddedVariableBegin. - internal byte _inStringEmbeddedVariable; - - // Non-zero => End of the last heredoc that finished reading content. - // While non-zero the current stream position doesn't correspond the current line and line index - // (the stream is ahead, we are reading from a buffer restored by the last heredoc). - internal int HeredocEndLine; - internal int HeredocEndLineIndex; - - internal State(State src) { - if (src != null) { - LexicalState = src.LexicalState; - OpenedBracesInEmbeddedCode = src.OpenedBracesInEmbeddedCode; - _commandMode = src._commandMode; - _whitespaceSeen = src._whitespaceSeen; - _inStringEmbeddedVariable = src._inStringEmbeddedVariable; - HeredocEndLine = src.HeredocEndLine; - HeredocEndLineIndex = src.HeredocEndLineIndex; - _currentSequence = src._currentSequence; - _nestedSequenceCount = src._nestedSequenceCount; - if (_nestedSequenceCount > 0) { - _nestedSequences = new NestedTokenSequence[_nestedSequenceCount]; - Array.Copy(src._nestedSequences, 0, _nestedSequences, 0, _nestedSequenceCount); - } else { - _nestedSequences = NestedTokenSequence.EmptyArray; - } - } else { - LexicalState = LexicalState.EXPR_BEG; - _commandMode = 1; - HeredocEndLineIndex = -1; - _currentSequence = TokenSequenceState.None; - _nestedSequences = NestedTokenSequence.EmptyArray; - } - } - - public override bool Equals(object other) { - return Equals(other as State); - } - - public bool Equals(State other) { - return ReferenceEquals(this, other) || (other != null - && _currentSequence == other._currentSequence - && Utils.ValueEquals(_nestedSequences, _nestedSequenceCount, other._nestedSequences, other._nestedSequenceCount) - && LexicalState == other.LexicalState - && OpenedBracesInEmbeddedCode == other.OpenedBracesInEmbeddedCode - && _commandMode == other._commandMode - && _whitespaceSeen == other._whitespaceSeen - && _inStringEmbeddedVariable == other._inStringEmbeddedVariable - && HeredocEndLine == other.HeredocEndLine - && HeredocEndLineIndex == other.HeredocEndLineIndex - ); - } - - public override int GetHashCode() { - return _currentSequence.GetHashCode() - ^ _nestedSequences.GetValueHashCode(0, _nestedSequenceCount) - ^ _nestedSequenceCount - ^ (int)LexicalState - ^ OpenedBracesInEmbeddedCode - ^ _commandMode - ^ _whitespaceSeen - ^ _inStringEmbeddedVariable - ^ HeredocEndLine - ^ HeredocEndLineIndex; - } - - internal TokenSequenceState/*!*/ CurrentSequence { - get { return _currentSequence; } - set { - Assert.NotNull(value); - _currentSequence = value; - } - } - - private void PushNestedSequence(NestedTokenSequence sequence) { - if (_nestedSequences.Length == _nestedSequenceCount) { - Array.Resize(ref _nestedSequences, _nestedSequences.Length * 2 + 1); - } - _nestedSequences[_nestedSequenceCount++] = sequence; - } - - private NestedTokenSequence PopNestedSequence() { - Debug.Assert(_nestedSequenceCount > 0); - var result = _nestedSequences[_nestedSequenceCount - 1]; - _nestedSequences[_nestedSequenceCount - 1] = default(NestedTokenSequence); - _nestedSequenceCount--; - return result; - } - - internal void StartStringEmbeddedCode() { - PushNestedSequence(new NestedTokenSequence(_currentSequence, OpenedBracesInEmbeddedCode)); - OpenedBracesInEmbeddedCode = 0; - _currentSequence = TokenSequenceState.None; - } - - internal void EndStringEmbeddedCode() { - var nestedSeq = PopNestedSequence(); - _currentSequence = nestedSeq.State; - OpenedBracesInEmbeddedCode = nestedSeq.OpenedBracesInEmbeddedCode; - Debug.Assert(OpenedBracesInEmbeddedCode >= 0); - } - - internal void EnqueueVerbatimHeredoc(VerbatimHeredocState/*!*/ heredoc) { - if (VerbatimHeredocQueue == null) { - VerbatimHeredocQueue = new List(); - } - VerbatimHeredocQueue.Add(heredoc); - } - - internal void DequeueVerbatimHeredocs() { - Debug.Assert(VerbatimHeredocQueue != null && VerbatimHeredocQueue.Count > 0); - // TODO: - if (_currentSequence == TokenSequenceState.None) { - PushNestedSequence(new NestedTokenSequence(new CodeState(LexicalState, _commandMode, _whitespaceSeen), OpenedBracesInEmbeddedCode)); - } else { - PushNestedSequence(new NestedTokenSequence(_currentSequence, OpenedBracesInEmbeddedCode)); - } - - for (int i = VerbatimHeredocQueue.Count - 1; i > 0; i--) { - PushNestedSequence(new NestedTokenSequence(VerbatimHeredocQueue[i], OpenedBracesInEmbeddedCode)); - } - _currentSequence = VerbatimHeredocQueue[0]; - VerbatimHeredocQueue = null; - } - - internal void FinishVerbatimHeredoc() { - var nestedSeq = PopNestedSequence(); - // TODO: - CodeState codeState = nestedSeq.State as CodeState; - if (codeState != null) { - LexicalState = codeState.LexicalState; - _commandMode = codeState.CommandMode; - _whitespaceSeen = codeState.WhitespaceSeen; - _currentSequence = TokenSequenceState.None; - } else { - _currentSequence = nestedSeq.State; - } - OpenedBracesInEmbeddedCode = nestedSeq.OpenedBracesInEmbeddedCode; - Debug.Assert(OpenedBracesInEmbeddedCode >= 0); - } - } - - private bool InStringEmbeddedCode { get { return _state._nestedSequenceCount > 0; } } - private bool InStringEmbeddedVariable { get { return _state._inStringEmbeddedVariable == 1; } set { _state._inStringEmbeddedVariable = value ? (byte)1 : (byte)0; } } - private bool WhitespaceSeen { get { return _state._whitespaceSeen == 1; } set { _state._whitespaceSeen = value ? (byte)1 : (byte)0; } } - - // TODO: (verbatim mode) is this ok to be set by parser? - public bool CommandMode { get { return _state._commandMode == 1; } set { _state._commandMode = value ? (byte)1 : (byte)0; } } - - private State _state; - - #endregion - - // The number of unmatched left parentheses, brackets, braces and lambda parameter definitions (->). - // Used to find the begining of a lambda body. - // The value is insignificant in verbatim mode. - internal int _openingCount; - - // The value of _openingCount at the begining of a lambda definition. - // Zeroed at the start of lambda body definition. - // The value is insignificant in verbatim mode. - internal int _lambdaOpenings; - - // track command arguments state - used for DO/BLOCK_DO disambiguation; always 0 in verbatim mode: - private int _commandArgsStateStack; - - // track conditional expression state - used for LOOP_DO/DO/BLOCK_DO disambiguation; always 0 in verbatim mode: - private int _loopConditionStateStack; - - // Entire line that is currently being tokenized. - // Includes \r, \n, \r\n if there was eoln in input. - private char[] _lineBuffer; - - // Portion of _lineBuffer that contains valid data. - private int _lineLength; - - // index in the current buffer/line: - private int _bufferPos; - - // current line no: - private int _currentLine; - private int _currentLineIndex; - - // out: whether the last token terminated - private bool _unterminatedToken; - private bool _eofReached; - // out: offset data following __END__ token - private int _dataOffset; - // out: token value: - private TokenValue _tokenValue; - - // token positions set during tokenization (TODO: to be replaced by tokenizer buffer): - private SourceLocation _currentTokenStart; - private SourceLocation _currentTokenEnd; - - [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] - private int _currentTokenStartIndex; - - // last token span: - private SourceSpan _tokenSpan; - - #region Initialization - - public Tokenizer() - : this(true) { - } - - public Tokenizer(bool verbatim) - : this(verbatim, DummyVariableResolver.AllMethodNames) { - } - - public Tokenizer(bool verbatim, ILexicalVariableResolver/*!*/ localVariableResolver) { - ContractUtils.RequiresNotNull(localVariableResolver, "localVariableResolver"); - - _errorSink = ErrorSink.Null; - _localVariableResolver = localVariableResolver; - _verbatim = verbatim; - _encoding = RubyEncoding.Binary; - } - - public void Initialize(SourceUnit/*!*/ sourceUnit) { - ContractUtils.RequiresNotNull(sourceUnit, "sourceUnit"); - Initialize(null, sourceUnit.GetReader(), sourceUnit, SourceLocation.MinValue); - } - - public void Initialize(TextReader/*!*/ reader) { - Initialize(null, reader, null, SourceLocation.MinValue); - } - - public override void Initialize(object state, TextReader/*!*/ reader, SourceUnit sourceUnit, SourceLocation initialLocation) { - ContractUtils.RequiresNotNull(reader, "reader"); - - _sourceUnit = sourceUnit; - _initialLocation = initialLocation; - _currentLine = _initialLocation.Line; - _currentLineIndex = _initialLocation.Index; - _tokenSpan = new SourceSpan(initialLocation, initialLocation); - - _state = new State(state as State); - _commandArgsStateStack = 0; - _loopConditionStateStack = 0; - _openingCount = 0; - _input = reader; - _lineBuffer = null; - _lineLength = 0; - _bufferPos = 0; - _currentTokenStart = SourceLocation.Invalid; - _currentTokenEnd = SourceLocation.Invalid; - _currentTokenStartIndex = -1; - - _tokenValue = new TokenValue(); - _eofReached = false; - _unterminatedToken = false; - _dataOffset = -1; - - DumpBeginningOfUnit(); - } - - #endregion - - #region Debug Logging - -#if DEBUG - private int _logVerbosity; // 0 means logging disabled - private TextWriter _log; -#endif - [Conditional("DEBUG")] - public void EnableLogging(int verbosity, TextWriter/*!*/ output) { - Debug.Assert(verbosity > 0 && verbosity <= 2); - Assert.NotNull(output); -#if DEBUG - _logVerbosity = verbosity; - _log = output; -#endif - } - - [Conditional("DEBUG")] - public void DisableLogging() { -#if DEBUG - _logVerbosity = 0; - _log = null; -#endif - } - - [Conditional("DEBUG")] - private void Log(string/*!*/ format, params object[] args) { -#if DEBUG - if (_logVerbosity > 0) { - _log.WriteLine(format, args); - } -#endif - } - - [Conditional("DEBUG")] - private void DumpBeginningOfUnit() { - Log("--- Source unit: '{0}' ---", _sourceUnit != null ? _sourceUnit.Path : "N/A"); - } - - [Conditional("DEBUG")] - private void DumpToken(Tokens token) { -#if DEBUG - Log("{0,-25} {1,-25} {2}", - Parser.GetTerminalName((int)token), - _tokenValue.ToString(), - LexicalState); -#endif - } - - #endregion - - #region Parser Driven State - - internal LexicalState LexicalState { - get { return _state.LexicalState; } - set { _state.LexicalState = value; } - } - - private bool IsEndLexicalState { - get { - return _state.LexicalState == LexicalState.EXPR_END - || _state.LexicalState == LexicalState.EXPR_ENDARG - || _state.LexicalState == LexicalState.EXPR_ENDFN; // 1.9 - } - } - - private bool IsBeginLexicalState { - get { - return _state.LexicalState == LexicalState.EXPR_BEG - || _state.LexicalState == LexicalState.EXPR_MID - || _state.LexicalState == LexicalState.EXPR_CLASS - || _state.LexicalState == LexicalState.EXPR_VALUE; // 1.9 - } - } - - private bool InArgs { - get { return _state.LexicalState == LexicalState.EXPR_ARG || _state.LexicalState == LexicalState.EXPR_CMDARG; } - } - - private bool InArgsNoSpace(int c) { - return InArgs && WhitespaceSeen && !IsWhiteSpace(c); - } - - // Push(n) - private void BitStackPush(ref int stack, int n) { - stack = (stack << 1) | ((n) & 1); - } - - // Pop() - private int BitStackPop(ref int stack) { - return (stack >>= 1); - } - - // x = Pop(), Top |= x - private void BitStackOrPop(ref int stack) { - stack = (stack >> 1) | (stack & 1); - } - - // Peek() != 0 - private bool BitStackPeek(int stack) { - return (stack & 1) != 0; - } - - private bool InCommandArgs { - get { return BitStackPeek(_commandArgsStateStack); } - } - - private bool InLoopCondition { - get { return BitStackPeek(_loopConditionStateStack); } - } - - internal int EnterCommandArguments() { - int old = _commandArgsStateStack; - BitStackPush(ref _commandArgsStateStack, 1); - return old; - } - - internal void LeaveCommandArguments(int state) { - _commandArgsStateStack = state; - } - - internal void EnterLoopCondition() { - BitStackPush(ref _loopConditionStateStack, 1); - } - - internal void LeaveLoopCondition() { - BitStackPop(ref _loopConditionStateStack); - } - - private void EnterParenthesisedExpression() { - _openingCount++; - BitStackPush(ref _loopConditionStateStack, 0); - BitStackPush(ref _commandArgsStateStack, 0); - } - - internal void LeaveParenthesisedExpression() { - _openingCount--; - PopParenthesisedExpressionStack(); - } - - internal void PopParenthesisedExpressionStack() { - BitStackOrPop(ref _commandArgsStateStack); - - // was: BitStackOrPop(ref _loopConditionStateStack); - // this case cannot happen, since it would require closing parenthesis not matching opening - // ( ... while [[ ... ) ... do ]] - BitStackPop(ref _loopConditionStateStack); - } - - private Tokens StringEmbeddedVariableBegin() { - InStringEmbeddedVariable = true; - LexicalState = LexicalState.EXPR_BEG; - return Tokens.StringEmbeddedVariableBegin; - } - - private Tokens StringEmbeddedCodeBegin() { - _state.StartStringEmbeddedCode(); - LexicalState = LexicalState.EXPR_BEG; - EnterParenthesisedExpression(); - return Tokens.StringEmbeddedCodeBegin; - } - - internal int EnterLambdaDefinition() { - int old = _lambdaOpenings; - _lambdaOpenings = ++_openingCount; - return old; - } - - internal void LeaveLambdaDefinition(int oldLambdaOpenings) { - _lambdaOpenings = oldLambdaOpenings; - } - - #endregion - - #region Error Reporting - - private void Report(string/*!*/ message, int errorCode, SourceSpan location, Severity severity) { - Debug.Assert(severity != Severity.FatalError); - _errorSink.Add(_sourceUnit, message, location, errorCode, severity); - } - - internal void ReportError(ErrorInfo info) { - Report(info.GetMessage(), info.Code, GetCurrentSpan(), Severity.Error); - } - - internal void ReportError(ErrorInfo info, params object[] args) { - Report(info.GetMessage(args), info.Code, GetCurrentSpan(), Severity.Error); - } - - internal void ReportError(ErrorInfo info, SourceSpan location, params object[] args) { - Report(info.GetMessage(args), info.Code, location, Severity.Error); - } - - internal void ReportWarning(ErrorInfo info) { - Report(info.GetMessage(), info.Code, GetCurrentSpan(), Severity.Warning); - } - - internal void ReportWarning(ErrorInfo info, params object[] args) { - Report(info.GetMessage(args), info.Code, GetCurrentSpan(), Severity.Warning); - } - - // TODO: - private void WarnBalanced(string p, string p_2) { - // 1.9 - } - - #endregion - - #region Buffer Operations - - // Populates the line buffer by the next line. - // Returns false if no characters were read. - private bool LoadLine() { - int size = 0; - - if (_lineBuffer == null) { - _lineBuffer = new char[InitialBufferSize]; - } - - while (true) { - int c; - try { - c = _input.Read(); - } catch (DecoderFallbackException e) { - ReportError(Errors.InvalidMultibyteCharacter, BitConverter.ToString(e.BytesUnknown).Replace('-', ' '), _encoding.Name); - c = -1; - } - - if (c == -1) { - if (size > 0) { - if (size < _lineBuffer.Length) { - _lineBuffer[size] = '\0'; - } - break; - } else { - return false; - } - } - - if (size == _lineBuffer.Length) { - Array.Resize(ref _lineBuffer, size * 2); - } - _lineBuffer[size++] = (char)c; - - if (c == '\n') break; - if (c == '\r' && _input.Peek() != '\n') break; - } - - _lineLength = size; - _bufferPos = 0; - return true; - } - - private int Read() { - if (!RefillBuffer()) { - return -1; - } - - Debug.Assert(0 <= _bufferPos && _bufferPos < _lineLength); - - return _lineBuffer[_bufferPos++]; - } - - private bool Read(int c) { - if (Peek() == c) { - Skip(); - return true; - } else { - return false; - } - } - - private void Skip(int c) { - Debug.Assert(c != -1 && _lineBuffer[_bufferPos] == c); - _bufferPos += 1; - } - - private void Skip() { - _bufferPos += 1; - } - - private void SeekRelative(int disp) { - Debug.Assert(_bufferPos + disp >= 0); - Debug.Assert(_bufferPos + disp <= _lineLength); - _bufferPos += disp; - } - - private void Back(int c) { - if (c != -1) { - Debug.Assert(_lineBuffer[_bufferPos - 1] == c); - _bufferPos--; - } else { - Debug.Assert(_bufferPos == _lineLength); - } - } - - private int Peek() { - return Peek(0); - } - - private int Peek(int disp) { - if (_lineBuffer == null) { - if (!RefillBuffer()) { - return -1; - } - } - - if (_bufferPos + disp < _lineLength) { - return _lineBuffer[_bufferPos + disp]; - } - - return -1; - } - - private bool RefillBuffer() { - Debug.Assert(_lineBuffer == null || 0 <= _bufferPos && _bufferPos <= _lineLength); - - if (_lineBuffer == null || _bufferPos == _lineLength) { - bool wasBufferNull = _lineBuffer == null; - int oldLineLength = _lineLength; - - // end of stream: - if (!LoadLine()) { - return false; - } - - // skips lines of heredoc content (only number, real bits has already been read): - if (_state.HeredocEndLine > 0) { - _currentLine = _state.HeredocEndLine; - _currentLineIndex = _state.HeredocEndLineIndex; - _state.HeredocEndLine = 0; - _state.HeredocEndLineIndex = -1; - } else { - - // TODO: initial column - if (wasBufferNull) { - _currentLine = _initialLocation.Line; - _currentLineIndex = _initialLocation.Index; - } else { - _currentLine++; - _currentLineIndex += oldLineLength; - } - } - } - - return true; - } - - private bool AtEndOfLine { - get { return _bufferPos == _lineLength && _bufferPos > 0 && _lineBuffer[_bufferPos - 1] == '\n'; } - } - - private bool is_bol() { - return _bufferPos == 0; - } - - private bool was_bol() { - return _bufferPos == 1; - } - - private bool LineContentEquals(string str, bool skipWhitespace) { - int strStart; - return LineContentEquals(str, skipWhitespace, out strStart); - } - - private bool LineContentEquals(string str, bool skipWhitespace, out int strStart) { - int p = 0; - int n; - - if (skipWhitespace) { - while (p < _lineLength && IsWhiteSpace(_lineBuffer[p])) { - p++; - } - } - - strStart = p; - n = _lineLength - (p + str.Length); - if (n < 0 || (n > 0 && _lineBuffer[p + str.Length] != '\n' && _lineBuffer[p + str.Length] != '\r')) { - return false; - } - - return StringEquals(str, _lineBuffer, p, _lineLength); - } - - private static bool StringEquals(string/*!*/ str, char[]/*!*/ chars, int offset, int count) { - if (str.Length > count - offset) { - return false; - } - for (int i = 0; i < str.Length; i++) { - if (str[i] != chars[offset + i]) { - return false; - } - } - - return true; - } - - #endregion - - #region Token Spans - - internal void CaptureTokenSpan() { - _tokenSpan = new SourceSpan(_currentTokenStart, _currentTokenEnd); - } - - private void MarkTokenEnd(bool isMultiLine) { - if (isMultiLine) { - MarkMultiLineTokenEnd(); - } else { - MarkSingleLineTokenEnd(); - } - } - - private void MarkSingleLineTokenEnd() { - Debug.Assert(_lineBuffer == null || Array.IndexOf(_lineBuffer, '\n', _currentTokenStartIndex, _bufferPos - _currentTokenStartIndex) == -1); - _currentTokenEnd = GetCurrentLocation(); - } - - private void MarkMultiLineTokenEnd() { - _currentTokenEnd = GetCurrentLocation(); - } - - private Tokens MarkSingleLineTokenEnd(Tokens token) { - MarkSingleLineTokenEnd(); - return token; - } - - private Tokens MarkMultiLineTokenEnd(Tokens token) { - MarkMultiLineTokenEnd(); - return token; - } - - internal void MarkTokenStart() { - _currentTokenStart = GetCurrentLocation(); - _currentTokenStartIndex = _bufferPos; - } - - private SourceLocation GetCurrentLocation() { - if (_lineBuffer == null) { - return _initialLocation; - } else if (AtEndOfLine) { - return new SourceLocation(_currentLineIndex + _bufferPos, _currentLine + 1, 1); - } else { - return new SourceLocation( - _currentLineIndex + _bufferPos, - _currentLine, - (_currentLine == _initialLocation.Line ? _initialLocation.Column : 1) + _bufferPos - ); - } - } - - private SourceSpan GetCurrentSpan() { - SourceLocation loc = GetCurrentLocation(); - return new SourceSpan(loc, loc); - } - - #endregion - - #region Main Tokenization - - public Tokens GetNextToken() { - if (_input == null) { - throw new InvalidOperationException("Uninitialized"); - } - - while (true) { - // TODO: - RefillBuffer(); - - Tokens token = _state.CurrentSequence.TokenizeAndMark(this); - DumpToken(token); - - // Do not set WhitespaceSeen and CommandMode states as they already were set by FinishVerbatimHeredoc. - if (token == Tokens.VerbatimHeredocEnd) { - // no heredoc can start on the current line: - Debug.Assert(_state.VerbatimHeredocQueue == null); - return token; - } - - // - // Skip whitespace and set/clear CommandMode for the next token. - // - - WhitespaceSeen = token == Tokens.Whitespace; - switch (token) { - case Tokens.MultiLineComment: - case Tokens.SingleLineComment: - case Tokens.EndOfLine: - case Tokens.Whitespace: - // whitespace doesn't affect CommandMode - // ignore the token unless in verbatim mode - if (_verbatim) { - break; - } else { - continue; - } - - case Tokens.EndOfFile: - _eofReached = true; - CommandMode = false; - break; - - case Tokens.NewLine: - case Tokens.Semicolon: - case Tokens.Do: - case Tokens.LeftBlockArgBrace: - case Tokens.LeftBlockBrace: - CommandMode = true; - break; - - // parser also sets CommandMode = true after - // block_parameters |...| <<< - // method_parameters (...) <<< - - default: - CommandMode = false; - break; - } - - if (_verbatim && _state.VerbatimHeredocQueue != null && AtEndOfLine) { - _state.DequeueVerbatimHeredocs(); - } - - return token; - } - } - - internal Tokens Tokenize() { - MarkTokenStart(); - int c = Read(); - - switch (c) { - case '\0': // null terminates the input - // if tokenizer is asked for the next token it returns EOF again: - Back('\0'); - MarkSingleLineTokenEnd(); - return Tokens.EndOfFile; - - case -1: // end of stream - MarkSingleLineTokenEnd(); - return Tokens.EndOfFile; - - // whitespace - case ' ': - case '\t': - case '\f': - return MarkSingleLineTokenEnd(ReadNonEolnWhiteSpace()); - - case '\n': - return MarkMultiLineTokenEnd(GetEndOfLineToken()); - - case '\r': - if (Read('\n')) { - return MarkMultiLineTokenEnd(GetEndOfLineToken()); - } else { - return MarkSingleLineTokenEnd(ReadNonEolnWhiteSpace()); - } - - case '\\': - return TokenizeBackslash(); - - case '#': - return MarkSingleLineTokenEnd(ReadSingleLineComment()); - - case '*': - return MarkSingleLineTokenEnd(ReadStar()); - - case '!': - return MarkSingleLineTokenEnd(ReadBang()); - - case '=': - if (was_bol() && PeekMultiLineCommentBegin()) { - return TokenizeMultiLineComment(true); - } - - return MarkSingleLineTokenEnd(ReadEquals()); - - case '<': - return TokenizeLessThan(); - - case '>': - return MarkSingleLineTokenEnd(ReadGreaterThan()); - - case '"': - return MarkSingleLineTokenEnd(ReadDoubleQuote()); - - case '\'': - return MarkSingleLineTokenEnd(ReadSingleQuote()); - - case '`': - return MarkSingleLineTokenEnd(ReadBacktick()); - - case '?': - return TokenizeQuestionmark(); - - case '&': - return MarkSingleLineTokenEnd(ReadAmpersand()); - - case '|': - return MarkSingleLineTokenEnd(ReadPipe()); - - case '+': - return MarkSingleLineTokenEnd(ReadPlus()); - - case '-': - return MarkSingleLineTokenEnd(ReadMinus()); - - case '.': - return MarkSingleLineTokenEnd(ReadDot()); - - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - return MarkSingleLineTokenEnd(ReadUnsignedNumber(c)); - - case ':': - return MarkSingleLineTokenEnd(ReadColon()); - - case '/': - return MarkSingleLineTokenEnd(ReadSlash()); - - case '^': - return MarkSingleLineTokenEnd(ReadCaret()); - - case ';': - LexicalState = LexicalState.EXPR_BEG; - MarkSingleLineTokenEnd(); - return Tokens.Semicolon; - - case ',': - LexicalState = LexicalState.EXPR_BEG; - MarkSingleLineTokenEnd(); - return Tokens.Comma; - - case '~': - return MarkSingleLineTokenEnd(ReadTilde()); - - case '(': - return MarkSingleLineTokenEnd(ReadLeftParenthesis()); - - case '[': - return MarkSingleLineTokenEnd(ReadLeftBracket()); - - case '{': - return MarkSingleLineTokenEnd(ReadLeftBrace()); - - case ')': - return TokenizeClosing(Tokens.RightParenthesis); - - case ']': - return TokenizeClosing(Tokens.RightBracket); - - case '}': - return TokenizeClosingBrace(); - - case '%': - return TokenizePercent(); - - case '$': - return MarkSingleLineTokenEnd(ReadGlobalVariable()); - - case '@': - return MarkSingleLineTokenEnd(ReadInstanceOrClassVariable()); - - case '_': - if (was_bol() && LineContentEquals("__END__", false)) { - // if tokenizer is asked for the next token it returns EOF again: - Back('_'); - MarkSingleLineTokenEnd(); - _dataOffset = _currentLineIndex + _lineLength; - return Tokens.EndOfFile; - } - return MarkSingleLineTokenEnd(ReadIdentifier(c)); - - default: - if (!IsIdentifierInitial(c, _multiByteIdentifier)) { - ReportError(Errors.InvalidCharacterInExpression, (char)c); - MarkSingleLineTokenEnd(); - return Tokens.InvalidCharacter; - } - - return MarkSingleLineTokenEnd(ReadIdentifier(c)); - } - } - - #endregion - - #region End-Of-Line - - private Tokens ReadNonEolnWhiteSpace() { - while (true) { - int c = Peek(); - if (c == ' ' || c == '\t' || c == '\f') { - Skip(c); - continue; - } - if (c == '\r' && Peek(1) != '\n') { - Skip(c); - continue; - } - break; - } - - return Tokens.Whitespace; - } - - private Tokens GetEndOfLineToken() { - if (LexicalState == LexicalState.EXPR_BEG || - LexicalState == LexicalState.EXPR_FNAME || - LexicalState == LexicalState.EXPR_DOT || - LexicalState == LexicalState.EXPR_CLASS || - LexicalState == LexicalState.EXPR_VALUE) { - - return Tokens.EndOfLine; - } - - // TODO: don't do this in verbatim mode in heredoc: - if (!_verbatim || _state.VerbatimHeredocQueue == null) { - // foo - // .bar - RefillBuffer(); - int start = _bufferPos; - int c; - do { - c = Read(); - if (c == '.') { - if (Peek() != '.') { - _bufferPos = start; - return Tokens.EndOfLine; - } - break; - } - } while (IsWhiteSpace(c)); - _bufferPos = start; - } - - LexicalState = LexicalState.EXPR_BEG; - return Tokens.NewLine; - } - - private Tokens TokenizeBackslash() { - // escaped eoln is considered whitespace: - if (TryReadEndOfLine()) { - MarkMultiLineTokenEnd(); - return Tokens.Whitespace; - } - - MarkSingleLineTokenEnd(); - return Tokens.Backslash; - } - - private Tokens ReadSingleLineComment() { - while (true) { - int c = Peek(); - - if (c == -1 || c == '\n') { - return Tokens.SingleLineComment; - } - - Skip(c); - } - } - - private bool TryReadEndOfLine() { - int c = Peek(); - if (c == '\n') { - Skip(c); - return true; - } - - if (c == '\r' && Peek(1) == '\n') { - SeekRelative(2); - return true; - } - - return false; - } - - private int ReadNormalizeEndOfLine() { - int c = Read(); - - if (c == '\r' && Peek() == '\n') { - Skip('\n'); - return '\n'; - } - - return c; - } - - private int ReadNormalizeEndOfLine(out int eolnWidth) { - int c = Read(); - - if (c == '\r' && Peek() == '\n') { - Skip('\n'); - eolnWidth = 2; - return '\n'; - } - - eolnWidth = 1; - return c; - } - - #endregion - - #region Identifiers and Keywords - - // Identifiers: - // [:alpha:_][:identifier:]+ - // Method names: - // [:alpha:_][:identifier:]+[?][^=] - // [:alpha:_][:identifier:]+[!][^=] - // [:alpha:_][:identifier:]+[=][^=~>] - // [:alpha:_][:identifier:]+[=] immediately followed by => - // Keywords - private Tokens ReadIdentifier(int firstCharacter) { - // the first character already read: - int start = _bufferPos - 1; - SkipVariableName(); - - // reads token suffix (!, ?, =) and returns the the token kind based upon the suffix: - Tokens result = ReadIdentifierSuffix(firstCharacter); - - // TODO: possible optimization: ~15% are keywords, ~15% are existing local variables -> we can save allocations - string identifier = new String(_lineBuffer, start, _bufferPos - start); - - // 1.9 label: - if (InArgs || LexicalState == LexicalState.EXPR_BEG && !CommandMode) { - if (Peek(0) == ':' && Peek(1) != ':') { - Skip(':'); - LexicalState = LexicalState.EXPR_BEG; - SetStringToken(identifier); - return Tokens.Label; - } - } - - // keyword: - if (LexicalState != LexicalState.EXPR_DOT) { - if (LexicalState == LexicalState.EXPR_FNAME) { - SetStringToken(identifier); - } - - Tokens keyword = StringToKeyword(identifier); - if (keyword != Tokens.None) { - return keyword; - } - } - - if (IsBeginLexicalState || InArgs || LexicalState == LexicalState.EXPR_DOT) { - // TODO: test LexState == DOT!! - if (LexicalState != LexicalState.EXPR_DOT && _localVariableResolver.IsLocalVariable(identifier)) { - LexicalState = LexicalState.EXPR_END; - } else if (CommandMode) { - LexicalState = LexicalState.EXPR_CMDARG; - } else { - LexicalState = LexicalState.EXPR_ARG; - } - } else if (LexicalState == LexicalState.EXPR_FNAME) { - LexicalState = LexicalState.EXPR_ENDFN; - } else { - LexicalState = LexicalState.EXPR_END; - } - - SetStringToken(identifier); - return result; - } - - private Tokens ReadIdentifierSuffix(int firstCharacter) { - int suffix = Peek(0); - int c = Peek(1); - if ((suffix == '!' || suffix == '?') && c != '=') { - Skip(suffix); - return Tokens.FunctionIdentifier; - } - - if (LexicalState == LexicalState.EXPR_FNAME && - suffix == '=' && c != '~' && c != '>' && (c != '=' || Peek(2) == '>')) { - // include '=' into the token: - Skip(suffix); - // TODO: FunctionIdentifier might be better, seems to not matter because the rules that use it accept FtnIdf as well - return Tokens.Identifier; - } - - // no suffix: - return IsUpperLetter(firstCharacter) ? Tokens.ConstantIdentifier : Tokens.Identifier; - } - - private Tokens StringToKeyword(string/*!*/ identifier) { - switch (identifier) { - case "if": return ReturnKeyword(Tokens.If, Tokens.IfMod, LexicalState.EXPR_BEG); - case "in": return ReturnKeyword(Tokens.In, LexicalState.EXPR_BEG); - case "do": return ReturnDoKeyword(); - case "or": return ReturnKeyword(Tokens.Or, LexicalState.EXPR_BEG); - - case "and": return ReturnKeyword(Tokens.And, LexicalState.EXPR_BEG); - case "end": return ReturnKeyword(Tokens.End, LexicalState.EXPR_END); - case "def": return ReturnKeyword(Tokens.Def, LexicalState.EXPR_FNAME); - case "for": return ReturnKeyword(Tokens.For, LexicalState.EXPR_BEG); - case "not": return ReturnKeyword(Tokens.Not, LexicalState.EXPR_ARG); - case "nil": return ReturnKeyword(Tokens.Nil, LexicalState.EXPR_END); - case "END": return ReturnKeyword(Tokens.UppercaseEnd, LexicalState.EXPR_END); - - case "else": return ReturnKeyword(Tokens.Else, LexicalState.EXPR_BEG); - case "then": return ReturnKeyword(Tokens.Then, LexicalState.EXPR_BEG); - case "case": return ReturnKeyword(Tokens.Case, LexicalState.EXPR_BEG); - case "self": return ReturnKeyword(Tokens.Self, LexicalState.EXPR_END); - case "true": return ReturnKeyword(Tokens.True, LexicalState.EXPR_END); - case "next": return ReturnKeyword(Tokens.Next, LexicalState.EXPR_MID); - case "when": return ReturnKeyword(Tokens.When, LexicalState.EXPR_BEG); - case "redo": return ReturnKeyword(Tokens.Redo, LexicalState.EXPR_END); - - case "alias": return ReturnKeyword(Tokens.Alias, LexicalState.EXPR_FNAME); - case "begin": return ReturnKeyword(Tokens.Begin, LexicalState.EXPR_BEG); - case "break": return ReturnKeyword(Tokens.Break, LexicalState.EXPR_MID); - case "BEGIN": return ReturnKeyword(Tokens.UppercaseBegin, LexicalState.EXPR_END); - case "class": return ReturnKeyword(Tokens.Class, LexicalState.EXPR_CLASS); - case "elsif": return ReturnKeyword(Tokens.Elsif, LexicalState.EXPR_BEG); - case "false": return ReturnKeyword(Tokens.False, LexicalState.EXPR_END); - case "retry": return ReturnKeyword(Tokens.Retry, LexicalState.EXPR_END); - case "super": return ReturnKeyword(Tokens.Super, LexicalState.EXPR_ARG); - case "until": return ReturnKeyword(Tokens.Until, Tokens.UntilMod, LexicalState.EXPR_BEG); - case "undef": return ReturnKeyword(Tokens.Undef, LexicalState.EXPR_FNAME); - case "while": return ReturnKeyword(Tokens.While, Tokens.WhileMod, LexicalState.EXPR_BEG); - case "yield": return ReturnKeyword(Tokens.Yield, LexicalState.EXPR_ARG); - - case "ensure": return ReturnKeyword(Tokens.Ensure, LexicalState.EXPR_BEG); - case "module": return ReturnKeyword(Tokens.Module, LexicalState.EXPR_BEG); - case "rescue": return ReturnKeyword(Tokens.Rescue, Tokens.RescueMod, LexicalState.EXPR_MID); - case "return": return ReturnKeyword(Tokens.Return, LexicalState.EXPR_MID); - case "unless": return ReturnKeyword(Tokens.Unless, Tokens.UnlessMod, LexicalState.EXPR_BEG); - - case "defined?": return ReturnKeyword(Tokens.Defined, LexicalState.EXPR_ARG); - case "__LINE__": return ReturnKeyword(Tokens.Line, LexicalState.EXPR_END); - case "__FILE__": return ReturnKeyword(Tokens.File, LexicalState.EXPR_END); - case "__ENCODING__": - return ReturnKeyword(Tokens.Encoding, LexicalState.EXPR_END); - - default: return Tokens.None; - } - } - - private Tokens ReturnKeyword(Tokens keyword, LexicalState state) { - LexicalState = state; - return keyword; - } - - private Tokens ReturnKeyword(Tokens keywordInExpression, Tokens keywordModifier, LexicalState state) { - Debug.Assert(keywordInExpression != keywordModifier); - - if (LexicalState == LexicalState.EXPR_BEG || LexicalState == LexicalState.EXPR_VALUE) { - LexicalState = state; - return keywordInExpression; - } else { - LexicalState = LexicalState.EXPR_BEG; - return keywordModifier; - } - } - - private Tokens ReturnDoKeyword() { - // 1.9 lambda - if (_lambdaOpenings > 0 && _lambdaOpenings == _openingCount) { - _lambdaOpenings = 0; - _openingCount--; - return Tokens.LambdaDo; - } - - LexicalState oldState = LexicalState; - LexicalState = LexicalState.EXPR_BEG; - // if last conditional opening is a parenthesis: - if (InLoopCondition) { - return Tokens.LoopDo; - } - - if (InCommandArgs && oldState != LexicalState.EXPR_CMDARG || oldState == LexicalState.EXPR_ENDARG || oldState == LexicalState.EXPR_BEG) { - return Tokens.BlockDo; - } - - return Tokens.Do; - } - - #endregion - - #region Comments - - // =begin - // ... - // =end - internal Tokens TokenizeMultiLineComment(bool started) { - while (true) { - // skip current line: - if (started) { - _bufferPos = _lineLength; - } else { - started = true; - } - - // read the first character of the next line: - int c = Read(); - if (c == -1) { - _unterminatedToken = true; - if (_verbatim) { - _state.CurrentSequence = MultiLineCommentState.Instance; - MarkMultiLineTokenEnd(); - return _currentTokenStart.Index == _currentTokenEnd.Index ? Tokens.EndOfFile : Tokens.MultiLineComment; - } else { - ReportError(Errors.UnterminatedEmbeddedDocument); - break; - } - } - - if (c != '=') { - continue; - } - - if (PeekMultiLineCommentEnd()) { - break; - } - } - - _state.CurrentSequence = TokenSequenceState.None; - _bufferPos = _lineLength; - MarkMultiLineTokenEnd(); - return Tokens.MultiLineComment; - } - - private bool PeekMultiLineCommentBegin() { - int minLength = _bufferPos + 5; - return minLength <= _lineLength && - _lineBuffer[_bufferPos + 0] == 'b' && - _lineBuffer[_bufferPos + 1] == 'e' && - _lineBuffer[_bufferPos + 2] == 'g' && - _lineBuffer[_bufferPos + 3] == 'i' && - _lineBuffer[_bufferPos + 4] == 'n' && - (minLength == _lineLength || IsWhiteSpace(_lineBuffer[minLength])); - } - - private bool PeekMultiLineCommentEnd() { - int minLength = _bufferPos + 3; - return minLength <= _lineLength && - _lineBuffer[_bufferPos + 0] == 'e' && - _lineBuffer[_bufferPos + 1] == 'n' && - _lineBuffer[_bufferPos + 2] == 'd' && - (minLength == _lineLength || IsWhiteSpace(_lineBuffer[minLength])); - } - - #endregion - - #region Tokens - - // Assignment: = - // Operators: == === =~ => - private Tokens ReadEquals() { - switch (LexicalState) { - case LexicalState.EXPR_FNAME: - case LexicalState.EXPR_DOT: - LexicalState = LexicalState.EXPR_ARG; - break; - - default: - LexicalState = LexicalState.EXPR_BEG; - break; - } - - switch (Peek()) { - case '=': - Skip('='); - return Read('=') ? Tokens.StrictEqual : Tokens.Equal; - - case '~': - Skip('~'); - return Tokens.Match; - - case '>': - Skip('>'); - return Tokens.DoubleArrow; - - default: - return Tokens.Assignment; - } - } - - // Operators: + +@ - // Assignments: += - // Literals: +[:number:] - private Tokens ReadPlus() { - int c = Peek(); - if (LexicalState == LexicalState.EXPR_FNAME || LexicalState == LexicalState.EXPR_DOT) { - - LexicalState = LexicalState.EXPR_ARG; - if (c == '@') { - Skip('@'); - return Tokens.UnaryPlus; - } - - return Tokens.Plus; - } - - if (c == '=') { - Skip('='); - SetAsciiStringToken(Symbols.Plus); - LexicalState = LexicalState.EXPR_BEG; - return Tokens.OpAssignment; - } - - bool nospace = false; - if (IsBeginLexicalState || (nospace = InArgsNoSpace(c))) { - if (nospace) { - ReportWarning(Errors.AmbiguousFirstArgument); - } - - LexicalState = LexicalState.EXPR_BEG; - if (IsDecimalDigit(c)) { - Skip(c); - return ReadUnsignedNumber(c); - } - - return Tokens.UnaryPlus; - } - - WarnBalanced("+", "unary operator"); - LexicalState = LexicalState.EXPR_BEG; - return Tokens.Plus; - } - - // Parentheses: ( - private Tokens ReadLeftParenthesis() { - Tokens result = Tokens.LeftParenthesis; - - if (IsBeginLexicalState) { - result = Tokens.LeftExprParenthesis; - } else if (InArgs && WhitespaceSeen) { - result = Tokens.LeftArgParenthesis; - } - - EnterParenthesisedExpression(); - LexicalState = LexicalState.EXPR_BEG; - return result; - } - - // Instance variables: - // @[:alpha:_][:identifier:]* - // Class variables: - // @@[:alpha:_][:identifier:]* - // At: - // @ - private Tokens ReadInstanceOrClassVariable() { - Tokens result; - - // start right before @/@@, the resulting symbol starts with @/@@ - int start = _bufferPos - 1; - - int c = Peek(0); - if (c == '@') { - c = Peek(1); - result = Tokens.ClassVariable; - } else { - result = Tokens.InstanceVariable; - } - - // c follows @ or @@ - if (IsDecimalDigit(c)) { - ReportError(result == Tokens.InstanceVariable ? Errors.InvalidInstanceVariableName : Errors.InvalidClassVariableName, (char)c); - } else if (IsIdentifierInitial(c)) { - if (result == Tokens.ClassVariable) { - Skip('@'); - } - Skip(c); - - SkipVariableName(); - SetStringToken(start, _bufferPos - start); - LexicalState = LexicalState.EXPR_END; - return result; - } - - return Tokens.At; - } - - // Global variables: - // $[_~*$?!@/\;,.=:<>"] - // $-[:identifier:] - // $[:identifier:] - // Match references: - // $[&`'+] - // $[1-9][0-9]+ - // Dollar: - // $ - private Tokens ReadGlobalVariable() { - LexicalState = LexicalState.EXPR_END; - - // start right after $, the resulting symbol doesn't contain $ - int start = _bufferPos; - - int c = Read(); - switch (c) { - case '_': - if (IsIdentifier(Peek())) { - SkipVariableName(); - SetStringToken(start, _bufferPos - start); - return Tokens.GlobalVariable; - } - return GlobalVariableToken(Symbols.LastInputLine); - - // exceptions: - case '!': return GlobalVariableToken(Symbols.CurrentException); - case '@': return GlobalVariableToken(Symbols.CurrentExceptionBacktrace); - - // options: - case '-': - if (IsIdentifier(Peek())) { - Read(); - SetStringToken(start, 2); - } else { - SetAsciiStringToken("-"); - } - return Tokens.GlobalVariable; - - // others: - case ',': return GlobalVariableToken(Symbols.ItemSeparator); - case ';': return GlobalVariableToken(Symbols.StringSeparator); - case '/': return GlobalVariableToken(Symbols.InputSeparator); - case '\\': return GlobalVariableToken(Symbols.OutputSeparator); - case '*': return GlobalVariableToken(Symbols.CommandLineArguments); - case '$': return GlobalVariableToken(Symbols.CurrentProcessId); - case '?': return GlobalVariableToken(Symbols.ChildProcessExitStatus); - case '=': return GlobalVariableToken(Symbols.IgnoreCaseComparator); - case ':': return GlobalVariableToken(Symbols.LoadPath); - case '"': return GlobalVariableToken(Symbols.LoadedFiles); - case '<': return GlobalVariableToken(Symbols.InputContent); - case '>': return GlobalVariableToken(Symbols.OutputStream); - case '.': return GlobalVariableToken(Symbols.LastInputLineNumber); - - // regex: - case '~': - return GlobalVariableToken(Symbols.MatchData); - - case '&': - _tokenValue.SetInteger(RegexMatchReference.EntireMatch); - return Tokens.MatchReference; - - case '`': - _tokenValue.SetInteger(RegexMatchReference.PreMatch); - return Tokens.MatchReference; - - case '\'': - _tokenValue.SetInteger(RegexMatchReference.PostMatch); - return Tokens.MatchReference; - - case '+': - _tokenValue.SetInteger(RegexMatchReference.MatchLastGroup); - return Tokens.MatchReference; - - case '0': - if (IsIdentifier(Peek())) { - // $0[A-Za-z0-9_] are invalid: - SkipVariableName(); - ReportError(Errors.InvalidGlobalVariableName, new String(_lineBuffer, start - 1, _bufferPos - start)); - SetAsciiStringToken(Symbols.ErrorVariable); - return Tokens.GlobalVariable; - } - - return GlobalVariableToken(Symbols.CommandLineProgramPath); - - default: - if (IsDecimalDigit(c)) { - return ReadMatchGroupReferenceVariable(c); - } - - if (IsIdentifier(c)) { - SkipVariableName(); - SetStringToken(start, _bufferPos - start); - return Tokens.GlobalVariable; - } - - Back(c); - return Tokens.Dollar; - } - } - - private Tokens ReadMatchGroupReferenceVariable(int c) { - int start = _bufferPos - 1; - int value = c - '0'; - bool overflow = false; - - while (true) { - c = Peek(); - - if (!IsDecimalDigit(c)) { - break; - } - - Skip(c); - value = unchecked(value * 10 + (c - '0')); - overflow |= (value < 0); - } - - if (overflow) { - ReportError(Errors.MatchGroupReferenceOverflow, new String(_lineBuffer, start, _bufferPos - start)); - } - - _tokenValue.SetInteger(value); - return Tokens.MatchReference; - } - - private Tokens GlobalVariableToken(string/*!*/ symbol) { - SetAsciiStringToken(symbol); - return Tokens.GlobalVariable; - } - - // Assignments: %= - // Operators: % - // Literals: %{... (quotation start) - private Tokens TokenizePercent() { - if (IsBeginLexicalState) { - return TokenizeQuotationStart(); - } - - int c = Peek(); - if (c == '=') { - Skip(c); - SetAsciiStringToken(Symbols.Mod); - LexicalState = LexicalState.EXPR_BEG; - MarkSingleLineTokenEnd(); - return Tokens.OpAssignment; - } - - if (InArgsNoSpace(c)) { - return TokenizeQuotationStart(); - } - - switch (LexicalState) { - case LexicalState.EXPR_FNAME: - case LexicalState.EXPR_DOT: - LexicalState = LexicalState.EXPR_ARG; - break; - - default: - LexicalState = LexicalState.EXPR_BEG; - break; - } - - WarnBalanced("%%", "string literal"); - MarkSingleLineTokenEnd(); - return Tokens.Percent; - } - - // Closing tokens: ), ], } - private Tokens TokenizeClosing(Tokens token) { - LeaveParenthesisedExpression(); - LexicalState = token == Tokens.RightParenthesis ? LexicalState.EXPR_ENDFN : LexicalState.EXPR_ENDARG; // 1.8: EXPR_END (all cases) - MarkSingleLineTokenEnd(); - return token; - } - - // Closing tokens: }, StringEmbeddedCodeEnd - private Tokens TokenizeClosingBrace() { - if (_state.OpenedBracesInEmbeddedCode > 0) { - _state.OpenedBracesInEmbeddedCode--; - return TokenizeClosing(Tokens.RightBrace); - } - - if (InStringEmbeddedCode) { - _state.EndStringEmbeddedCode(); - return TokenizeClosing(Tokens.StringEmbeddedCodeEnd); - } - - // unmatched brace: - return TokenizeClosing(Tokens.RightBrace); - } - - // Braces: { - private Tokens ReadLeftBrace() { - Tokens result; - - if (_lambdaOpenings > 0 && _lambdaOpenings == _openingCount) { - result = Tokens.LeftLambdaBrace; // 1.9 lambda body opening - _lambdaOpenings = 0; - _openingCount--; - } else if (InArgs || LexicalState == LexicalState.EXPR_END || LexicalState == LexicalState.EXPR_ENDFN) { - result = Tokens.LeftBlockBrace; // block (primary) - } else if (LexicalState == LexicalState.EXPR_ENDARG) { - result = Tokens.LeftBlockArgBrace; // block (expr) - } else { - result = Tokens.LeftBrace; // hash - } - - _state.OpenedBracesInEmbeddedCode++; - EnterParenthesisedExpression(); - LexicalState = LexicalState.EXPR_BEG; - return result; - } - - // Brackets: [ - // Operators: [] []= - private Tokens ReadLeftBracket() { - if (LexicalState == LexicalState.EXPR_FNAME || LexicalState == LexicalState.EXPR_DOT) { - LexicalState = LexicalState.EXPR_ARG; - - return Read(']') ? (Read('=') ? Tokens.ItemSetter : Tokens.ItemGetter) : Tokens.LeftIndexingBracket; - } - - Tokens result; - if (IsBeginLexicalState) { - result = Tokens.LeftBracket; - } else if (InArgs && WhitespaceSeen) { - result = Tokens.LeftBracket; - } else { - result = Tokens.LeftIndexingBracket; - } - - LexicalState = LexicalState.EXPR_BEG; - EnterParenthesisedExpression(); - return result; - } - - // Operators: ~ ~@ - private Tokens ReadTilde() { - if (LexicalState == LexicalState.EXPR_FNAME || LexicalState == LexicalState.EXPR_DOT) { - // ~@ - Read('@'); - LexicalState = LexicalState.EXPR_ARG; - } else { - LexicalState = LexicalState.EXPR_BEG; - } - - return Tokens.Tilde; - } - - // Assignments: ^= - // Operators: ^ - private Tokens ReadCaret() { - if (Read('=')) { - SetAsciiStringToken(Symbols.Xor); - LexicalState = LexicalState.EXPR_BEG; - return Tokens.OpAssignment; - } - - switch (LexicalState) { - case LexicalState.EXPR_FNAME: - case LexicalState.EXPR_DOT: - LexicalState = LexicalState.EXPR_ARG; - break; - - default: - LexicalState = LexicalState.EXPR_BEG; - break; - } - - return Tokens.Caret; - } - - // Operators: / - // Assignments: /= - // Literals: /... (regex start) - private Tokens ReadSlash() { - if (IsBeginLexicalState) { - _state.CurrentSequence = new StringState(StringProperties.RegularExpression | StringProperties.ExpandsEmbedded, '/'); - return Tokens.RegexpBegin; - } - - int c = Peek(); - if (c == '=') { - Skip(c); - SetAsciiStringToken(Symbols.Divide); - LexicalState = LexicalState.EXPR_BEG; - return Tokens.OpAssignment; - } - - if (InArgsNoSpace(c)) { - ReportWarning(Errors.AmbiguousFirstArgument); - _state.CurrentSequence = new StringState(StringProperties.RegularExpression | StringProperties.ExpandsEmbedded, '/'); - return Tokens.RegexpBegin; - } - - switch (LexicalState) { - case LexicalState.EXPR_FNAME: - case LexicalState.EXPR_DOT: - LexicalState = LexicalState.EXPR_ARG; - break; - - default: - LexicalState = LexicalState.EXPR_BEG; - break; - } - - WarnBalanced("/", "regexp literal"); - return Tokens.Slash; - } - - // Operators: :: : - // Literals: :... (symbol start) - private Tokens ReadColon() { - int c = Peek(); - if (c == ':') { - Skip(c); - if (IsBeginLexicalState || InArgs && WhitespaceSeen) { - LexicalState = LexicalState.EXPR_BEG; - return Tokens.LeadingDoubleColon; - } - - LexicalState = LexicalState.EXPR_DOT; - return Tokens.SeparatingDoubleColon; - } - - if (IsEndLexicalState || IsWhiteSpace(c)) { - WarnBalanced(":", "symbol literal"); - LexicalState = LexicalState.EXPR_BEG; - return Tokens.Colon; - } - - switch (c) { - case '\'': - Skip(c); - _state.CurrentSequence = new StringState(StringProperties.Symbol, '\''); - break; - - case '"': - Skip(c); - _state.CurrentSequence = new StringState(StringProperties.Symbol | StringProperties.ExpandsEmbedded, '"'); - break; - - default: - Debug.Assert(_state.CurrentSequence == TokenSequenceState.None); - break; - } - - LexicalState = LexicalState.EXPR_FNAME; - return Tokens.SymbolBegin; - } - - // Assignments: **= *= - // Operators: ** * splat - private Tokens ReadStar() { - Tokens result; - - int c = Peek(); - if (c == '*') { - Skip(c); - if (Read('=')) { - SetAsciiStringToken(Symbols.Power); - LexicalState = LexicalState.EXPR_BEG; - - return Tokens.OpAssignment; - } - - result = Tokens.Pow; - } else if (c == '=') { - Skip(c); - - SetAsciiStringToken(Symbols.Multiply); - LexicalState = LexicalState.EXPR_BEG; - return Tokens.OpAssignment; - } else if (InArgsNoSpace(c)) { - ReportWarning(Errors.StarInterpretedAsSplatArgument); - result = Tokens.Star; - } else if (IsBeginLexicalState) { - result = Tokens.Star; - } else { - WarnBalanced("*", "argument prefix"); - result = Tokens.Asterisk; - } - - switch (LexicalState) { - case LexicalState.EXPR_FNAME: - case LexicalState.EXPR_DOT: - LexicalState = LexicalState.EXPR_ARG; - break; - - default: - LexicalState = LexicalState.EXPR_BEG; - break; - } - - return result; - } - - // Operators: ! != !~ !@ - private Tokens ReadBang() { - int c = Peek(); - if (LexicalState == LexicalState.EXPR_FNAME || LexicalState == LexicalState.EXPR_DOT) { - LexicalState = LexicalState.EXPR_ARG; - if (c == '@') { - Skip(c); - return Tokens.Bang; - } - } else { - LexicalState = LexicalState.EXPR_BEG; - } - - if (c == '=') { - Skip(c); - return Tokens.NotEqual; - } - - if (c == '~') { - Skip(c); - return Tokens.Nmatch; - } - - return Tokens.Bang; - } - - // String: < < - private Tokens TokenizeLessThan() { - int c = Read(); - - if (c == '<' && - LexicalState != LexicalState.EXPR_DOT && - LexicalState != LexicalState.EXPR_CLASS && - !IsEndLexicalState && - (!InArgs || WhitespaceSeen)) { - - Tokens token = TokenizeHeredocLabel(); - if (token != Tokens.None) { - return token; - } - } - - switch (LexicalState) { - case LexicalState.EXPR_FNAME: - case LexicalState.EXPR_DOT: - LexicalState = LexicalState.EXPR_ARG; - break; - - default: - LexicalState = LexicalState.EXPR_BEG; - break; - } - - if (c == '=') { - if (Read('>')) { - MarkSingleLineTokenEnd(); - return Tokens.Cmp; - } - MarkSingleLineTokenEnd(); - return Tokens.LessOrEqual; - } - - if (c == '<') { - if (Read('=')) { - SetAsciiStringToken(Symbols.LeftShift); - LexicalState = LexicalState.EXPR_BEG; - MarkSingleLineTokenEnd(); - return Tokens.OpAssignment; - } - WarnBalanced("<<", "here document"); - MarkSingleLineTokenEnd(); - return Tokens.Lshft; - } - - Back(c); - MarkSingleLineTokenEnd(); - return Tokens.Less; - } - - // Assignment: >>= - // Operators: > >= >> - private Tokens ReadGreaterThan() { - switch (LexicalState) { - case LexicalState.EXPR_FNAME: - case LexicalState.EXPR_DOT: - LexicalState = LexicalState.EXPR_ARG; - break; - - default: - LexicalState = LexicalState.EXPR_BEG; - break; - } - - int c = Peek(); - if (c == '=') { - Skip(c); - return Tokens.GreaterOrEqual; - } - - if (c == '>') { - Skip(c); - if (Read('=')) { - SetAsciiStringToken(Symbols.RightShift); - LexicalState = LexicalState.EXPR_BEG; - return Tokens.OpAssignment; - } - return Tokens.Rshft; - } - - return Tokens.Greater; - } - - // String: `... - // Operator: ` - private Tokens ReadBacktick() { - if (LexicalState == LexicalState.EXPR_FNAME) { - LexicalState = LexicalState.EXPR_ENDFN; // 1.8 : EXPR_END - return Tokens.Backtick; - } - - if (LexicalState == LexicalState.EXPR_DOT) { - // This used to check if we are in command. There seems to be no way how we could get there. - // The lexical state is EXPR_BEG after CommandMode is set for the next non-whitespace token. Whitespace tokens don't change the state. - // The lexical state is EXPR_DOT after Token.SeparatingDoubleColon and Token.Dot none of which change the command state. - // LexicalState = (_commandMode) ? LexicalState.EXPR_CMDARG : LexicalState.EXPR_ARG; - Debug.Assert(!CommandMode); - LexicalState = LexicalState.EXPR_ARG; - return Tokens.Backtick; - } - - _state.CurrentSequence = new StringState(StringProperties.ExpandsEmbedded, '`'); - return Tokens.ShellStringBegin; - } - - // Operators: ? (conditional) - // Literals: ?[:char:] ?{escape} - // Errors: ?[:EOF:] - private Tokens TokenizeQuestionmark() { - if (IsEndLexicalState) { - LexicalState = LexicalState.EXPR_VALUE; // 1.8: EXPR_BEG - MarkSingleLineTokenEnd(); - return Tokens.QuestionMark; - } - - // ?[:EOF:] - int c = Peek(); - if (c == -1) { - _unterminatedToken = true; - MarkSingleLineTokenEnd(); - ReportError(Errors.IncompleteCharacter); - return Tokens.EndOfFile; - } - - // ?[:whitespace:] - if (IsWhiteSpace(c)) { - if (!InArgs) { - int c2 = 0; - switch (c) { - case ' ': c2 = 's'; break; - case '\n': c2 = 'n'; break; - case '\t': c2 = 't'; break; - case '\v': c2 = 'v'; break; - case '\r': c2 = (Peek(1) == '\n') ? 'n' : 'r'; break; - case '\f': c2 = 'f'; break; - } - - if (c2 != 0) { - ReportWarning(Errors.InvalidCharacterSyntax, (char)c2); - } - } - LexicalState = LexicalState.EXPR_VALUE; // 1.8: EXPR_BEG - MarkSingleLineTokenEnd(); - return Tokens.QuestionMark; - } - - // ?{identifier} - if ((IsLetterOrDigit(c) || c == '_') && IsIdentifier(Peek(1))) { - LexicalState = LexicalState.EXPR_BEG; - MarkSingleLineTokenEnd(); - return Tokens.QuestionMark; - } - - Skip(c); - - object content; - RubyEncoding encoding; - - // ?\{escape} - if (c == '\\') { - c = Peek(); - if (c == 'u') { - // \uFFFF, \u{xxxxxx} - Skip(c); - int codepoint = Peek() == '{' ? ReadUnicodeEscape6() : ReadUnicodeEscape4(); - content = UnicodeCodePointToString(codepoint); - encoding = (codepoint <= 0x7f) ? _encoding : RubyEncoding.UTF8; - MarkSingleLineTokenEnd(); - } else { - // \xXX, \M-x, ... - c = ReadEscape(); - if (c <= 0x7f) { - content = new String((char)c, 1); - encoding = _encoding; - } else { - Debug.Assert(c <= 0xff); - content = new[] { (byte)c }; - encoding = (_encoding == RubyEncoding.Ascii) ? RubyEncoding.Binary : _encoding; - } - - // \M-{eoln} eats the eoln: - MarkMultiLineTokenEnd(); - } - } else { - int d; - if (IsHighSurrogate(c) && IsLowSurrogate(d = Peek())) { - Skip(d); - content = new String(new[] { (char)c, (char)d }); - } else { - content = new String((char)c, 1); - } - encoding = _encoding; - MarkSingleLineTokenEnd(); - } - - LexicalState = LexicalState.EXPR_END; - _tokenValue.StringContent = content; - _tokenValue.Encoding = encoding; - return Tokens.Character; - } - - // Operators: & && - // Assignments: &= - private Tokens ReadAmpersand() { - int c = Peek(); - - if (c == '&') { - Skip(c); - LexicalState = LexicalState.EXPR_BEG; - - if (Read('=')) { - SetAsciiStringToken(Symbols.And); - return Tokens.OpAssignment; - } - - return Tokens.LogicalAnd; - } - - if (c == '=') { - Skip(c); - LexicalState = LexicalState.EXPR_BEG; - SetAsciiStringToken(Symbols.BitwiseAnd); - return Tokens.OpAssignment; - } - - Tokens result; - if (InArgsNoSpace(c)) { - // we are in command argument and there is a whitespace between ampersand: "foo &bar" - ReportWarning(Errors.AmpersandInterpretedAsProcArgument); - result = Tokens.BlockReference; - } else if (IsBeginLexicalState) { - result = Tokens.BlockReference; - } else { - WarnBalanced("&", "argument prefix"); - result = Tokens.Ampersand; - } - - switch (LexicalState) { - case LexicalState.EXPR_FNAME: - case LexicalState.EXPR_DOT: - LexicalState = LexicalState.EXPR_ARG; - break; - - default: - LexicalState = LexicalState.EXPR_BEG; - break; - } - - return result; - } - - // Operators: | || - // Assignments: |= ||= - private Tokens ReadPipe() { - int c = Peek(); - - if (c == '|') { - Skip(c); - LexicalState = LexicalState.EXPR_BEG; - - if (Read('=')) { - SetAsciiStringToken(Symbols.Or); - LexicalState = LexicalState.EXPR_BEG; - return Tokens.OpAssignment; - } - return Tokens.LogicalOr; - } - - if (c == '=') { - Skip(c); - SetAsciiStringToken(Symbols.BitwiseOr); - LexicalState = LexicalState.EXPR_BEG; - return Tokens.OpAssignment; - } - - if (LexicalState == LexicalState.EXPR_FNAME || LexicalState == LexicalState.EXPR_DOT) { - LexicalState = LexicalState.EXPR_ARG; - } else { - LexicalState = LexicalState.EXPR_BEG; - } - - return Tokens.Pipe; - } - - // Operators: . .. ... - // Errors: .[:digit:] - private Tokens ReadDot() { - LexicalState = LexicalState.EXPR_BEG; - - int c = Peek(); - if (c == '.') { - Skip(c); - return Read('.') ? Tokens.TripleDot : Tokens.DoubleDot; - } - - if (IsDecimalDigit(c)) { - ReportError(Errors.NoFloatingLiteral); - } - - LexicalState = LexicalState.EXPR_DOT; - return Tokens.Dot; - } - - // Operators: - -@ -> - // Assignments: -= - // Literals: -... (negative number sign) - private Tokens ReadMinus() { - if (LexicalState == LexicalState.EXPR_FNAME || LexicalState == LexicalState.EXPR_DOT) { - LexicalState = LexicalState.EXPR_ARG; - return Read('@') ? Tokens.UnaryMinus : Tokens.Minus; - } - - int c = Peek(); - if (c == '=') { - Skip(c); - SetAsciiStringToken(Symbols.Minus); - LexicalState = LexicalState.EXPR_BEG; - return Tokens.OpAssignment; - } - - if (c == '>') { - Skip(c); - LexicalState = LexicalState.EXPR_ARG; - return Tokens.Lambda; - } - - bool nospace = false; - if (IsBeginLexicalState || (nospace = InArgsNoSpace(c))) { - if (nospace) { - ReportWarning(Errors.AmbiguousFirstArgument); - } - - LexicalState = LexicalState.EXPR_BEG; - return IsDecimalDigit(c) ? Tokens.NumberNegation : Tokens.UnaryMinus; - } - - LexicalState = LexicalState.EXPR_BEG; - WarnBalanced("-", "unary operator"); - return Tokens.Minus; - } - - // Reads - // [:letter:]* - // and converts it to RegEx options. - private RubyRegexOptions ReadRegexOptions() { - RubyRegexOptions encoding = 0; - RubyRegexOptions options = 0; - - while (true) { - int c = Peek(); - if (!IsLetter(c)) { - break; - } - - Skip(c); - switch (c) { - case 'i': options |= RubyRegexOptions.IgnoreCase; break; - case 'x': options |= RubyRegexOptions.Extended; break; - case 'm': options |= RubyRegexOptions.Multiline; break; - case 'o': options |= RubyRegexOptions.Once; break; - - case 'n': encoding = RubyRegexOptions.FIXED; break; - case 'e': encoding = RubyRegexOptions.EUC; break; - case 's': encoding = RubyRegexOptions.SJIS; break; - case 'u': encoding = RubyRegexOptions.UTF8; break; - - default: - ReportError(Errors.UnknownRegexOption, (char)c); - break; - } - } - - return options | encoding; - } - - #endregion - - #region Character Escapes - - // \\ \n \t \r \f \v \a \b \s - // \[:octal:] \x[:hexa:] \M-\[:escape:] \M-[:char:] \C-[:escape:] \C-[:char:] \c[:escape:] \c[:char:] \[:char:] - private int ReadEscape() { - int c = Read(); - switch (c) { - case '\\': return '\\'; - case 'n': return '\n'; - case 't': return '\t'; - case 'r': return '\r'; - case 'f': return '\f'; - case 'v': return '\v'; - case 'a': return '\a'; - case 'e': return 27; - case 'b': return '\b'; - case 's': return ' '; - - case 'x': return ReadHexEscape(); - - case 'M': - if (!Read('-')) { - return InvalidEscapeCharacter(); - } - - c = ReadNormalizeEndOfLine(); - if (c == '\\') { - return ReadEscape() | 0x80; - } - - if (c == -1) { - return InvalidEscapeCharacter(); - } - - return (c & 0xff) | 0x80; - - case 'C': - if (!Read('-')) { - return InvalidEscapeCharacter(); - } - goto case 'c'; - - case 'c': - c = ReadNormalizeEndOfLine(); - - if (c == '?') { - return 0177; - } - - if (c == -1) { - return InvalidEscapeCharacter(); - } - - if (c == '\\') { - c = ReadEscape(); - } - - return c & 0x9f; - - case -1: - return InvalidEscapeCharacter(); - - default: - if (IsOctalDigit(c)) { - return ReadOctalEscape(c - '0'); - } - - // ReadEscape is not called if the backslash is followed by an eoln: - Debug.Assert(c != '\n' && (c != '\r' || Peek() != '\n')); - return c; - } - } - - private int InvalidEscapeCharacter() { - ReportError(Errors.InvalidEscapeCharacter); - // return != 0 so that additional errors (\0 in a symbol) are not invoked - return '?'; - } - - // Appends escaped regex escape sequence. - private void AppendEscapedRegexEscape(MutableStringBuilder/*!*/ content, int term) { - int c = Read(); - - switch (c) { - case 'x': - content.AppendAscii('\\'); - AppendEscapedHexEscape(content); - break; - - case 'M': - if (!Read('-')) { - InvalidEscapeCharacter(); - break; - } - - content.AppendAscii('\\'); - content.AppendAscii('M'); - content.AppendAscii('-'); - - // escaped: - AppendRegularExpressionCompositeEscape(content, term); - break; - - case 'C': - if (!Read('-')) { - InvalidEscapeCharacter(); - break; - } - - content.AppendAscii('\\'); - content.AppendAscii('C'); - content.AppendAscii('-'); - - AppendRegularExpressionCompositeEscape(content, term); - break; - - case 'c': - content.AppendAscii('\\'); - content.AppendAscii('c'); - AppendRegularExpressionCompositeEscape(content, term); - break; - - case -1: - InvalidEscapeCharacter(); - break; - - default: - if (IsOctalDigit(c)) { - content.AppendAscii('\\'); - AppendEscapedOctalEscape(content); - break; - } - - if (c != '\\' || c != term) { - content.AppendAscii('\\'); - } - - // ReadEscape is not called if the backslash is followed by an eoln: - Debug.Assert(c != '\n' && (c != '\r' || Peek() != '\n')); - AppendCharacter(content, c); - break; - } - } - - private void AppendRegularExpressionCompositeEscape(MutableStringBuilder/*!*/ content, int term) { - int c = ReadNormalizeEndOfLine(); - if (c == '\\') { - AppendEscapedRegexEscape(content, term); - } else if (c == -1) { - InvalidEscapeCharacter(); - } else { - AppendCharacter(content, c); - } - } - - private void AppendEscapedOctalEscape(MutableStringBuilder/*!*/ content) { - int start = _bufferPos - 1; - ReadOctalEscape(0); - - Debug.Assert(IsOctalDigit(_lineBuffer[start])); // first digit - content.AppendAscii(_lineBuffer, start, _bufferPos - start); - } - - private void AppendEscapedHexEscape(MutableStringBuilder/*!*/ content) { - int start = _bufferPos - 1; - ReadHexEscape(); - - Debug.Assert(_lineBuffer[start] == 'x'); - content.AppendAscii(_lineBuffer, start, _bufferPos - start); - } - - // returns true if any escaped codepoint is non-ascii - private bool AppendEscapedUnicode(MutableStringBuilder/*!*/ content) { - bool isNonAscii = false; - int start = _bufferPos - 1; - if (Peek() == '{') { - // \u{codepoint codepoint ... codepoint} - isNonAscii = AppendUnicodeCodePoints(null); - } else { - // \uFFFF - isNonAscii = ReadUnicodeEscape4() >= 0x80; - } - Debug.Assert(_lineBuffer[start] == 'u'); - content.AppendAscii(_lineBuffer, start, _bufferPos - start); - return isNonAscii; - } - - // Reads octal number of at most 3 digits. - // Reads at most 2 octal digits as the value of the first digit is in "value". - private int ReadOctalEscape(int value) { - int c; - if (IsOctalDigit(c = Peek())) { - Skip(c); - value = (value << 3) | (c - '0'); - - if (IsOctalDigit(c = Peek())) { - Skip(c); - value = (value << 3) | (c - '0'); - } - } - return value; - } - - // Reads hexadecimal number of at most 2 digits. - private int ReadHexEscape() { - int c; - int value = ToDigit(c = Peek()); - if (value < 16) { - Skip(c); - int digit = ToDigit(c = Peek()); - if (digit < 16) { - Skip(c); - value = (value << 4) | digit; - } - - return value; - } else { - return InvalidEscapeCharacter(); - } - } - - // Peeks exactly 4 hexadecimal characters (\uFFFF). - private int ReadUnicodeEscape4() { - int d4 = ToDigit(Peek(0)); - int d3 = ToDigit(Peek(1)); - int d2 = ToDigit(Peek(2)); - int d1 = ToDigit(Peek(3)); - - if (d1 >= 16 || d2 >= 16 || d3 >= 16 || d4 >= 16) { - return InvalidEscapeCharacter(); - } - - SeekRelative(4); - return (d4 << 12) | (d3 << 8) | (d2 << 4) | d1; - } - - // Reads {at-most-six-hexa-digits} - private int ReadUnicodeEscape6() { - int c = Read(); - Debug.Assert(c == '{'); - - bool isEmpty; - int codepoint = ReadUnicodeCodePoint(out isEmpty); - - if (Peek() == '}') { - Skip(); - } else { - ReportError(Errors.UntermintedUnicodeEscape); - isEmpty = false; - } - - if (isEmpty) { - ReportError(Errors.InvalidUnicodeEscape); - } - - return codepoint; - } - - // Parses [0-9A-F]{1,6} - private int ReadUnicodeCodePoint(out bool isEmpty) { - int codepoint = 0; - int i = 0; - while (true) { - int digit = ToDigit(Peek()); - if (digit >= 16) { - break; - } - - if (i < 7) { - codepoint = (codepoint << 4) | digit; - } - - i++; - Skip(); - } - - if (codepoint > 0x10ffff) { - ReportError(Errors.TooLargeUnicodeCodePoint); - codepoint = (int)'?'; - } - - isEmpty = i == 0; - return codepoint; - } - - // returns true if any codepoint represents a non-ascii character - private bool AppendUnicodeCodePoints(MutableStringBuilder content) { - bool isAscii = true; - bool isEmpty; - Skip('{'); - while (true) { - int codepoint = ReadUnicodeCodePoint(out isEmpty); - if (content != null && !isEmpty) { - AppendUnicodeCodePoint(content, codepoint); - } - isAscii &= codepoint <= 0x7f; - - int c = Peek(); - if (c == '}') { - Skip(); - break; - } - if (c != ' ') { - ReportError(Errors.UntermintedUnicodeEscape); - isEmpty = false; - break; - } - Skip(); - } - if (isEmpty) { - ReportError(Errors.InvalidUnicodeEscape); - } - return !isAscii; - } - - // Reads \uFFFF or \u{FFFFFF} and appends the character to the string content: - private void AppendUnicodeCodePoint(MutableStringBuilder/*!*/ content, int codepoint) { - if (codepoint >= 0x80) { - SwitchToUtf8(content); - } - content.AppendUnicodeCodepoint(codepoint); - } - - private void SwitchToUtf8(MutableStringBuilder/*!*/ content) { - if (content.IsAscii) { - content.Encoding = RubyEncoding.UTF8; - } else if (content.Encoding != RubyEncoding.UTF8) { - ReportError(Errors.EncodingsMixed, content.Encoding, RubyEncoding.UTF8.Name); - } - } - - private void AppendByte(MutableStringBuilder/*!*/ content, int b) { - if (b >= 0x80 && content.Encoding == RubyEncoding.Ascii) { - content.Encoding = RubyEncoding.Binary; - } - content.Append((byte)b); - } - - private void AppendCharacter(MutableStringBuilder/*!*/ content, int c) { - // c is encoded via the current source encoding (__ENCODING__): - if (c >= 0x80 && !content.IsAscii && content.Encoding != _encoding) { - ReportError(Errors.EncodingsMixed, content.Encoding, _encoding); - } - content.Append((char)c); - } - - /// - /// Converts all codepoints in range [0, 0x10ffff] to a string. - /// Undefined for codepoint greater than 0x10ffff. - /// - public static string/*!*/ UnicodeCodePointToString(int codepoint) { - if (codepoint < 0x10000) { - // code-points [0xd800 .. 0xdfff] are not treated as invalid - return new String((char)codepoint, 1); - } else { - codepoint -= 0x10000; - return new String(new char[] { (char)((codepoint / 0x400) + 0xd800), (char)((codepoint % 0x400) + 0xdc00) }); - } - } - - public static int ToCodePoint(int highSurrogate, int lowSurrogate) { - return (highSurrogate - 0xd800) * 0x400 + (lowSurrogate - 0xdc00) + 0x10000; - } - - public static bool IsHighSurrogate(int c) { - return unchecked((uint)c - 0xd800 <= (uint)0xdbff - 0xd800); - } - - public static bool IsLowSurrogate(int c) { - return unchecked((uint)c - 0xdc00 <= (uint)0xdfff - 0xdc00); - } - - public static bool IsSurrogate(int c) { - return unchecked((uint)c - 0xd800 <= (uint)0xdfff - 0xd800); - } - - #endregion - - #region Strings - - internal void SetStringToken(string/*!*/ value) { - _tokenValue.SetString(value); - } - - internal void SetAsciiStringToken(string/*!*/ symbol) { - _tokenValue.SetString(symbol); - } - - internal void SetStringToken(int start, int length) { - SetStringToken(new String(_lineBuffer, start, length)); - } - - // String: "... - private Tokens ReadDoubleQuote() { - _state.CurrentSequence = new StringState(StringProperties.ExpandsEmbedded, '"'); - return Tokens.StringBegin; - } - - // String: '... - private Tokens ReadSingleQuote() { - _state.CurrentSequence = new StringState(StringProperties.Default, '\''); - return Tokens.StringBegin; - } - - // returns last character read - private int ReadStringContent(MutableStringBuilder/*!*/ content, StringProperties stringType, int terminator, int openingParenthesis, - ref int nestingLevel) { - - while (true) { - int eolnWidth; - int c = ReadNormalizeEndOfLine(out eolnWidth); - if (c == -1) { - return -1; - } - - if (openingParenthesis != 0 && c == openingParenthesis) { - nestingLevel++; - } else if (c == terminator) { - if (nestingLevel == 0) { - SeekRelative(-eolnWidth); - return c; - } - nestingLevel--; - } else if (((stringType & StringProperties.ExpandsEmbedded) != 0) && c == '#' && _bufferPos < _lineLength) { - int c2 = _lineBuffer[_bufferPos]; - if (c2 == '$' || c2 == '@' || c2 == '{') { - SeekRelative(-eolnWidth); - return c; - } - } else if ((stringType & StringProperties.Words) != 0 && IsWhiteSpace(c)) { - SeekRelative(-eolnWidth); - return c; - } else if (c == '\\') { - c = ReadNormalizeEndOfLine(out eolnWidth); - - if (c == '\n') { - if ((stringType & StringProperties.Words) == 0) { - if ((stringType & StringProperties.ExpandsEmbedded) != 0) { - continue; - } - content.AppendAscii('\\'); - } - } else if (c == '\\') { - if ((stringType & StringProperties.RegularExpression) != 0) { - content.AppendAscii('\\'); - } - } else if ((stringType & StringProperties.RegularExpression) != 0) { - // \uFFFF, \u{codepoint} - if (c == 'u') { - content.AppendAscii('\\'); - if (AppendEscapedUnicode(content)) { - SwitchToUtf8(content); - } - } else { - SeekRelative(-eolnWidth); - AppendEscapedRegexEscape(content, terminator); - } - continue; - } else if ((stringType & StringProperties.ExpandsEmbedded) != 0) { - if (c == 'u') { - if (Peek() == '{') { - // \u{codepoint codepoint ... codepoint} - if (AppendUnicodeCodePoints(content)) { - SwitchToUtf8(content); - } - } else { - // \uFFFF - int codepoint = ReadUnicodeEscape4(); - AppendUnicodeCodePoint(content, codepoint); - if (codepoint >= 0x80) { - SwitchToUtf8(content); - } - } - } else { - // other escapes: - SeekRelative(-eolnWidth); - AppendByte(content, ReadEscape()); - } - continue; - } else if ((stringType & StringProperties.Words) != 0 && IsWhiteSpace(c)) { - // ignore backslashed spaces in %w - } else if (c != terminator && !(openingParenthesis != 0 && c == openingParenthesis)) { - content.AppendAscii('\\'); - } - } - - AppendCharacter(content, c); - } - } - - // - // returns tokens: - // - StringEnd/RegexEnd ... string/regex closed - // - WordSeparator ... whitespace in a word list - // - StringEmbeddedVariableBegin ... #$, #@ (start of an embedded global/instance variable) - // - StringEmbeddedCodeBegin ... #{ (start of an embedded expression) - // - StringContent ... string data - // - internal Tokens TokenizeString(StringState/*!*/ info) { - // global or instance variable in a string: - if (InStringEmbeddedVariable) { - InStringEmbeddedVariable = false; - return Tokenize(); - } - - StringProperties properties = info.Properties; - bool whitespaceSeen = false; - - MarkTokenStart(); - - int eolnWidth; - int c = ReadNormalizeEndOfLine(out eolnWidth); - - // unterminated string: - if (c == -1) { - _unterminatedToken = true; - MarkSingleLineTokenEnd(); - if (_verbatim) { - return Tokens.EndOfFile; - } else { - ReportError(Errors.UnterminatedString); - return FinishString(Tokens.StringEnd); - } - } - - bool isMultiline = c == '\n'; - - // skip whitespace in word list: - if ((properties & StringProperties.Words) != 0 && IsWhiteSpace(c)) { - isMultiline |= SkipWhitespace(); - c = Read(); - whitespaceSeen = true; - } - - // end of the top-level string: - if (c == info.TerminatingCharacter && info.NestingLevel == 0) { - - // end of words: - if ((properties & StringProperties.Words) != 0) { - MarkTokenEnd(isMultiline); - return FinishString(Tokens.StringEnd); - } - - // end of regex: - if ((properties & StringProperties.RegularExpression) != 0) { - _tokenValue.SetRegexOptions(ReadRegexOptions()); - MarkTokenEnd(isMultiline); - return FinishString(Tokens.RegexpEnd); - } - - // end of string/symbol: - MarkTokenEnd(isMultiline); - return FinishString(Tokens.StringEnd); - } - - // word separator: - if (whitespaceSeen) { - Debug.Assert(!IsWhiteSpace(c)); - Back(c); - MarkTokenEnd(isMultiline); - return Tokens.WordSeparator; - } - - MutableStringBuilder content; - - // start of #$variable, #@variable, #{expression} in a string: - if ((properties & StringProperties.ExpandsEmbedded) != 0 && c == '#') { - switch (Peek()) { - case '$': - case '@': - MarkSingleLineTokenEnd(); - return StringEmbeddedVariableBegin(); - - case '{': - Skip('{'); - MarkSingleLineTokenEnd(); - return StringEmbeddedCodeBegin(); - } - content = new MutableStringBuilder(_encoding); - content.AppendAscii('#'); - } else { - content = new MutableStringBuilder(_encoding); - SeekRelative(-eolnWidth); - } - - int nestingLevel = info.NestingLevel; - ReadStringContent(content, properties, info.TerminatingCharacter, info.OpeningParenthesis, ref nestingLevel); - _state.CurrentSequence = info.SetNesting(nestingLevel); - - _tokenValue.SetStringContent(content); - MarkMultiLineTokenEnd(); - return Tokens.StringContent; - } - - private Tokens FinishString(Tokens endToken) { - _state.CurrentSequence = TokenSequenceState.None; - LexicalState = LexicalState.EXPR_END; - return endToken; - } - - #endregion - - #region Heredoc - - private Tokens TokenizeHeredocLabel() { - int term; - StringProperties stringType = StringProperties.Default; - - int prefixWidth; - int c = ReadNormalizeEndOfLine(out prefixWidth); - if (c == '-') { - c = ReadNormalizeEndOfLine(out prefixWidth); - prefixWidth++; - stringType = StringProperties.IndentedHeredoc; - } - - string label; - if (c == '\'' || c == '"' || c == '`') { - if (c != '\'') { - stringType |= StringProperties.ExpandsEmbedded; - } - - // do not include quotes: - int start = _bufferPos; - term = c; - - while (true) { - c = Read(); - if (c == -1) { - _unterminatedToken = true; - ReportError(Errors.UnterminatedHereDocIdentifier); - c = term; - break; - } - - if (c == term) { - break; - } - - // MRI doesn't do this, it continues reading the label and includes \n into it. - // The label cannot be matched with the end label (only single-line comparison is done), so it's better to report error here - // Allowing \n in label requires the token to be multi-line. - // Note we can ignore \r followed by \n here since it will fail in the next iteration. - if (c == '\n') { - Back('\n'); - ReportError(Errors.UnterminatedHereDocIdentifier); - c = term; - break; - } - } - - label = new String(_lineBuffer, start, _bufferPos - start - 1); - } else if (IsIdentifier(c)) { - term = '"'; - stringType |= StringProperties.ExpandsEmbedded; - - int start = _bufferPos - 1; - SkipVariableName(); - label = new String(_lineBuffer, start, _bufferPos - start); - } else { - SeekRelative(-prefixWidth); - return Tokens.None; - } - - // note that if we allow \n in the label we must change this to multi-line token! - MarkSingleLineTokenEnd(); - - if (_verbatim) { - // enqueue a new verbatim heredoc state, it will be dequeued at the end of the current line: - _state.EnqueueVerbatimHeredoc(new VerbatimHeredocState(stringType, label)); - return Tokens.VerbatimHeredocBegin; - } else { - // skip the rest of the line (the content is stored in heredoc string terminal and tokenized upon restore) - int resume = _bufferPos; - _bufferPos = _lineLength; - _state.CurrentSequence = new HeredocState(stringType, label, resume, _lineBuffer, _lineLength, _currentLine, _currentLineIndex); - _lineBuffer = new char[InitialBufferSize]; - return term == '`' ? Tokens.ShellStringBegin : Tokens.StringBegin; - } - } - - private void MarkHeredocEnd(HeredocStateBase/*!*/ heredoc, int labelStart) { - if (labelStart < 0) { - MarkTokenStart(); - MarkSingleLineTokenEnd(); - } else { - SeekRelative(labelStart); - MarkTokenStart(); - SeekRelative(heredoc.Label.Length); - if (TryReadEndOfLine()) { - MarkMultiLineTokenEnd(); - } else { - MarkSingleLineTokenEnd(); - } - } - } - - internal Tokens FinishVerbatimHeredoc(VerbatimHeredocState/*!*/ heredoc, int labelStart) { - Debug.Assert(_verbatim); - MarkHeredocEnd(heredoc, labelStart); - _state.FinishVerbatimHeredoc(); - CaptureTokenSpan(); - return Tokens.VerbatimHeredocEnd; - } - - // - // The heredoc end label is the token that we return as StringEnd. - // After marking the label the buffer is restored so that we can continue reading tokens following the heredoc opening label. - // - // [<|... other tokens ... - // ... heredoc content tokens ... - // END - // - internal Tokens FinishHeredoc(HeredocState/*!*/ heredoc, int labelStart) { - Debug.Assert(!_verbatim); - - MarkHeredocEnd(heredoc, labelStart); - _state.HeredocEndLine = _currentTokenEnd.Line; - _state.HeredocEndLineIndex = _currentTokenEnd.Index; - _state.CurrentSequence = TokenSequenceState.None; - LexicalState = LexicalState.EXPR_END; - - // restore buffer: - _lineBuffer = heredoc.ResumeLine; - _lineLength = heredoc.ResumeLineLength; - _bufferPos = heredoc.ResumePosition; - _currentLine = heredoc.FirstLine; - _currentLineIndex = heredoc.FirstLineIndex; - - // We pretend the end token is zero-width and immediately follows the opening heredoc token. - // This makes locations merging in the parser work w/o introducing an additional complexity. - MarkTokenStart(); - MarkSingleLineTokenEnd(); - CaptureTokenSpan(); - return Tokens.StringEnd; - } - - internal Tokens TokenizeAndMarkHeredoc(HeredocStateBase/*!*/ heredoc) { - // global or instance variable in heredoc: - if (InStringEmbeddedVariable) { - InStringEmbeddedVariable = false; - CaptureTokenSpan(); - return Tokenize(); - } - - StringProperties stringKind = heredoc.Properties; - bool isIndented = (stringKind & StringProperties.IndentedHeredoc) != 0; - - if (Peek() == -1) { - ReportError(Errors.UnterminatedHereDoc, heredoc.Label); - _unterminatedToken = true; - return heredoc.Finish(this, -1); - } - - // label reached - it becomes a string-end token: - // (note that label is single line, MRI allows multiline, but such label is never matched) - int labelStart; - if (is_bol() && LineContentEquals(heredoc.Label, isIndented, out labelStart)) { - return heredoc.Finish(this, labelStart); - } - - MarkTokenStart(); - - if ((stringKind & StringProperties.ExpandsEmbedded) == 0) { - - StringBuilder str = ReadNonexpandingHeredocContent(heredoc); - - // do not restore buffer, the next token query will invoke 'if (EOF)' or 'if (line contains label)' above: - SetStringToken(str.ToString()); - MarkMultiLineTokenEnd(); - CaptureTokenSpan(); - return Tokens.StringContent; - } - - Tokens result = TokenizeExpandingHeredocContent(heredoc); - CaptureTokenSpan(); - return result; - } - - private StringBuilder/*!*/ ReadNonexpandingHeredocContent(HeredocStateBase/*!*/ heredoc) { - bool isIndented = (heredoc.Properties & StringProperties.IndentedHeredoc) != 0; - var result = new StringBuilder(); - - // reads lines until the line contains heredoc label - do { - int end = _lineLength; - if (end > 0) { - switch (_lineBuffer[end - 1]) { - case '\n': - if (--end == 0 || _lineBuffer[end - 1] != '\r') { - end++; - break; - } - --end; - break; - - case '\r': - --end; - break; - } - } - - result.Append(_lineBuffer, 0, end); - - if (end < _lineLength) { - result.Append('\n'); - } - - _bufferPos = _lineLength; - - // force new line load: - RefillBuffer(); - - if (Peek() == -1) { - // eof reached before end of heredoc: - return result; - } - - } while (!LineContentEquals(heredoc.Label, isIndented)); - - // return to the end of line, next token will be StringEnd spanning over the end-of-heredoc label: - _bufferPos = 0; - return result; - } - - private Tokens TokenizeExpandingHeredocContent(HeredocStateBase/*!*/ heredoc) { - MutableStringBuilder content; - - int c = Peek(); - if (c == '#') { - Skip(c); - - switch (Peek()) { - case '$': - case '@': - MarkSingleLineTokenEnd(); - return StringEmbeddedVariableBegin(); - - case '{': - Skip('{'); - MarkSingleLineTokenEnd(); - return StringEmbeddedCodeBegin(); - } - - content = new MutableStringBuilder(_encoding); - content.AppendAscii('#'); - } else { - content = new MutableStringBuilder(_encoding); - } - - bool isIndented = (heredoc.Properties & StringProperties.IndentedHeredoc) != 0; - - do { - // read string content upto the end of the line: - int tmp = 0; - c = ReadStringContent(content, heredoc.Properties, '\n', 0, ref tmp); - - // stop reading on end-of-file or just before an embedded expression: #$, #$, #{ - if (c != '\n') { - break; - } - - // append \n - content.AppendAscii((char)ReadNormalizeEndOfLine()); - - // if we are in verbatim mode we need to yield to heredocs that were defined on the current line: - if (c == '\n' && _verbatim && _state.VerbatimHeredocQueue != null) { - break; - } - - // TODO: - RefillBuffer(); - - // first char on the next line: - if (Peek() == -1) { - break; - } - - } while (!LineContentEquals(heredoc.Label, isIndented)); - - _tokenValue.SetStringContent(content); - MarkMultiLineTokenEnd(); - return Tokens.StringContent; - } - - #endregion - - #region String Quotations - - // Quotation start: - // %[QqWwxrs]?[^:alpha-numeric:] - private Tokens TokenizeQuotationStart() { - StringProperties type; - Tokens token; - int terminator; - - // c is the character following % - // note that it could be eoln in which case it needs to be normalized: - int c = ReadNormalizeEndOfLine(); - switch (c) { - case 'Q': - type = StringProperties.ExpandsEmbedded; - token = Tokens.StringBegin; - terminator = ReadNormalizeEndOfLine(); - break; - - case 'q': - type = StringProperties.Default; - token = Tokens.StringBegin; - terminator = ReadNormalizeEndOfLine(); - break; - - case 'W': - type = StringProperties.Words | StringProperties.ExpandsEmbedded; - token = Tokens.WordsBegin; - // if the terminator is a whitespace the end will never be matched and syntax error will be reported - terminator = ReadNormalizeEndOfLine(); - break; - - case 'w': - type = StringProperties.Words; - token = Tokens.VerbatimWordsBegin; - // if the terminator is a whitespace the end will never be matched and syntax error will be reported - terminator = ReadNormalizeEndOfLine(); - break; - - case 'x': - type = StringProperties.ExpandsEmbedded; - token = Tokens.ShellStringBegin; - terminator = ReadNormalizeEndOfLine(); - break; - - case 'r': - type = StringProperties.RegularExpression | StringProperties.ExpandsEmbedded; - token = Tokens.RegexpBegin; - terminator = ReadNormalizeEndOfLine(); - break; - - case 's': - type = StringProperties.Symbol; - token = Tokens.SymbolBegin; - terminator = ReadNormalizeEndOfLine(); - LexicalState = LexicalState.EXPR_FNAME; - break; - - default: - type = StringProperties.ExpandsEmbedded; - token = Tokens.StringBegin; - terminator = c; - break; - } - - int parenthesis = terminator; - switch (terminator) { - case -1: - _unterminatedToken = true; - MarkSingleLineTokenEnd(); - ReportError(Errors.UnterminatedString); - return Tokens.EndOfFile; - - case '(': terminator = ')'; break; - case '{': terminator = '}'; break; - case '[': terminator = ']'; break; - case '<': terminator = '>'; break; - - default: - if (IsLetterOrDigit(terminator)) { - Back(terminator); - MarkSingleLineTokenEnd(); - ReportError(Errors.UnknownQuotedStringType); - return Tokens.Percent; - } - - parenthesis = 0; - break; - } - - bool isMultiline = terminator == '\n'; - - if ((type & StringProperties.Words) != 0) { - isMultiline |= SkipWhitespace(); - } - - if (isMultiline) { - MarkMultiLineTokenEnd(); + /// + /// What is left of the 1.9-era lexer now that prism is the only parser: the rules for + /// Ruby names, digits and number literals, and the encoding magic comment, which the + /// runtime asks about strings and symbols at run time. + /// + public static class Tokenizer { + /// + /// Converts all codepoints in range [0, 0x10ffff] to a string. + /// Undefined for codepoint greater than 0x10ffff. + /// + public static string/*!*/ UnicodeCodePointToString(int codepoint) { + if (codepoint < 0x10000) { + // code-points [0xd800 .. 0xdfff] are not treated as invalid + return new String((char)codepoint, 1); } else { - MarkSingleLineTokenEnd(); + codepoint -= 0x10000; + return new String(new char[] { (char)((codepoint / 0x400) + 0xd800), (char)((codepoint % 0x400) + 0xdc00) }); } + } + + public static int ToCodePoint(int highSurrogate, int lowSurrogate) { + return (highSurrogate - 0xd800) * 0x400 + (lowSurrogate - 0xdc00) + 0x10000; + } - _state.CurrentSequence = new StringState(type, (char)terminator, (char)parenthesis, 0); - return token; + public static bool IsHighSurrogate(int c) { + return unchecked((uint)c - 0xd800 <= (uint)0xdbff - 0xd800); } - #endregion + public static bool IsLowSurrogate(int c) { + return unchecked((uint)c - 0xdc00 <= (uint)0xdfff - 0xdc00); + } - #region Numbers + public static bool IsSurrogate(int c) { + return unchecked((uint)c - 0xd800 <= (uint)0xdfff - 0xd800); + } public sealed class BignumParser : UnsignedBigIntegerParser { private char[] _buffer; @@ -3405,368 +95,6 @@ protected override int ReadDigit() { } } - private enum NumericCharKind { - None, - Digit, - Underscore - } - - // INTEGER: - // [1-9]([0-9_]*[1-9])? - // 0([0-7_]*[0-7])? - // 0[xX][0-9a-fA-F]([0-9a-fA-F_]*[0-9a-fA-F])? - // 0[dD][0-9]([0-9_]*[0-9])? - // 0[bB][01]([01_]*[01])? - // 0[oO][0-7]([0-7_]*[0-7])? - // - // FLOAT: - // (0|[1-9]([0-9_]*[0-9])?)[.][0-9_]*[0-9]([eE][+-]?[0-9]([0-9_]*[0-9])?) - // - // Takes the first decimal digit of the number. - // - private Tokens ReadUnsignedNumber(int c) { - LexicalState = LexicalState.EXPR_END; - - if (c == '0') { - switch (Peek()) { - case 'x': - case 'X': - Skip(); - return ReadInteger(16, NumericCharKind.None); - - case 'b': - case 'B': - Skip(); - return ReadInteger(2, NumericCharKind.None); - - case 'o': - case 'O': - Skip(); - return ReadInteger(8, NumericCharKind.None); - - case 'd': - case 'D': - Skip(); - return ReadInteger(10, NumericCharKind.None); - - case 'e': - case 'E': { - // 0e[+-]... - int sign; - int start = _bufferPos - 1; - - if (TryReadExponentSign(1, out sign)) { - return ReadDoubleExponent(start, sign); - } - - _tokenValue.SetInteger(0); - return Tokens.Integer; - } - - case '.': - // 0. - if (IsDecimalDigit(Peek(1))) { - Skip('.'); - return ReadDouble(_bufferPos - 2); - } - - _tokenValue.SetInteger(0); - return Tokens.Integer; - - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '_': - // the previous character is '0' digit: - return ReadInteger(8, NumericCharKind.Digit); - - case '8': - case '9': - ReportError(Errors.IllegalOctalDigit); - // treat the number as decimal - return ReadInteger(10, NumericCharKind.Digit); - - default: - _tokenValue.SetInteger(0); - return Tokens.Integer; - } - } - - return ReadDecimalNumber(c); - } - - // OCTAL: [0-7]([0-7_]*[0-7])? - // HEXA: [0-9a-fA-F]([0-9a-fA-F_]*[0-9a-fA-F])? - // BINARY: [01]([01_]*[01])? - // DECIMAL: [0-9]([0-9_]*[0-9])? - // - // prev ... previous character: either '0' for octals or -1 for 0[xbdo] - private Tokens ReadInteger(int @base, NumericCharKind prev) { - Debug.Assert(prev == NumericCharKind.None || prev == NumericCharKind.Digit); - Debug.Assert(@base <= 16); - long integer = 0; - int numberStartIndex = _bufferPos; - int underscoreCount = 0; - - while (true) { - int c = Peek(); - int digit = ToDigit(c); - - if (digit < @base) { - Skip(c); - - integer = integer * @base + digit; - prev = NumericCharKind.Digit; - - if (integer > Int32.MaxValue) { - return ReadBigNumber(integer, @base, numberStartIndex, underscoreCount, false); - } - - } else { - if (prev != NumericCharKind.Digit) { - if (prev == NumericCharKind.Underscore) { - ReportError(Errors.TrailingUnderscoreInNumber); - } else { - ReportError(Errors.NumericLiteralWithoutDigits); - } - } else if (c == '_') { - Skip(c); - prev = NumericCharKind.Underscore; - underscoreCount++; - continue; - } - - if (c == '.' && IsDecimalDigit(Peek(1))) { - ReportWarning(Errors.NoFloatingLiteral); - } - - _tokenValue.SetInteger((int)integer); - return Tokens.Integer; - } - } - } - - // INTEGER: - // [1-9]([0-9_]*[1-9])? - // - // FLOAT: - // [1-9]([0-9_]*[0-9])?[.][0-9_]*[0-9]([eE][+-]?[0-9]([0-9_]*[0-9])?) - private Tokens ReadDecimalNumber(int c) { - Debug.Assert(IsDecimalDigit(c) && c != '0'); - - // the first character of the number already read: - int numberStartIndex = _bufferPos - 1; - - int underscoreCount = 0; - NumericCharKind prev = NumericCharKind.Digit; - long integer = c - '0'; - - while (true) { - int sign; - c = Peek(); - - if (IsDecimalDigit(c)) { - Skip(c); - prev = NumericCharKind.Digit; - integer = integer * 10 + (c - '0'); - if (integer > Int32.MaxValue) { - return ReadBigNumber(integer, 10, numberStartIndex, underscoreCount, true); - } - - } else if (prev == NumericCharKind.Underscore) { - - ReportError(Errors.TrailingUnderscoreInNumber); - _tokenValue.SetInteger((int)integer); - return Tokens.Integer; - - } else if ((c == 'e' || c == 'E') && TryReadExponentSign(1, out sign)) { - - return ReadDoubleExponent(numberStartIndex, sign); - - } else if (c == '_') { - - Skip(c); - underscoreCount++; - prev = NumericCharKind.Underscore; - - } else { - - if (c == '.' && IsDecimalDigit(Peek(1))) { - Skip('.'); - return ReadDouble(numberStartIndex); - } - - _tokenValue.SetInteger((int)integer); - return Tokens.Integer; - } - } - } - - private bool TryReadExponentSign(int offset, out int sign) { - int s = Peek(offset); - if (s == '-') { - offset++; - sign = -1; - } else if (s == '+') { - offset++; - sign = +1; - } else { - sign = +1; - } - - if (IsDecimalDigit(Peek(offset))) { - SeekRelative(offset); - return true; - } - - if (s == '-') { - ReportError(Errors.TrailingMinusInNumber); - } else if (s == '+') { - ReportError(Errors.TrailingPlusInNumber); - } else { - ReportError(Errors.TrailingEInNumber); - } - - return false; - } - - // OCTAL: [0-7]([0-7_]*[0-7])? - // HEXA: [0-9a-fA-F]([0-9a-fA-F_]*[0-9a-fA-F])? - // BINARY: [01]([01_]*[01])? - // DECIMAL: [0-9]([0-9_]*[0-9])? - // FLOAT: [1-9]([0-9_]*[0-9])?[.][0-9_]*[0-9]([eE][+-]?[0-9]([0-9_]*[0-9])?) - // - // Previous digit caused an integer overflow. - // numberStartIndex ... index of the first (most significant) digit - // underscoreCount ... number of underscores already read - private Tokens ReadBigNumber(long value, int @base, int numberStartIndex, int underscoreCount, bool allowDouble) { - Debug.Assert(!allowDouble || @base == 10, "Only decimal based doubles supported"); - Debug.Assert(@base <= 16); - - // the previous char is a digit: - NumericCharKind prev = NumericCharKind.Digit; - - while (true) { - int c = Peek(); - int digit = ToDigit(c); - - if (digit < @base) { - prev = NumericCharKind.Digit; - Skip(c); - } else { - - if (prev == NumericCharKind.Underscore) { - ReportError(Errors.TrailingUnderscoreInNumber); - } else if (c == '_') { - Skip(c); - prev = NumericCharKind.Underscore; - underscoreCount++; - continue; - } else if (allowDouble) { - int sign; - if ((c == 'e' || c == 'E') && TryReadExponentSign(1, out sign)) { - return ReadDoubleExponent(numberStartIndex, sign); - } else if (c == '.') { - if (IsDecimalDigit(Peek(1))) { - Skip('.'); - return ReadDouble(numberStartIndex); - } - } - } - - // TODO: store only the digit count, the actual value will be parsed later: - // TODO: skip initial zeros - if (_bigIntParser == null) { - _bigIntParser = new BignumParser(); - } - - _bigIntParser.Position = numberStartIndex; - _bigIntParser.Buffer = _lineBuffer; - - BigInteger result = _bigIntParser.Parse(_bufferPos - numberStartIndex - underscoreCount, @base); - - Debug.Assert(value > 0, "Cannot be zero since we are parsing a number greater than Int32.MaxValue"); - - _tokenValue.SetBigInteger(result); - return Tokens.BigInteger; - } - } - } - - // FLOAT - decimal and exponent - // {value.}[0-9_]*[0-9])([eE][+-]?[0-9]([0-9_]*[0-9])?) - private Tokens ReadDouble(int numberStartIndex) { - Debug.Assert(IsDecimalDigit(Peek())); - - NumericCharKind prev = NumericCharKind.None; - while (true) { - int sign; - int c = Peek(); - - if (IsDecimalDigit(c)) { - prev = NumericCharKind.Digit; - Skip(c); - } else if ((c == 'e' || c == 'E') && TryReadExponentSign(1, out sign)) { - return ReadDoubleExponent(numberStartIndex, sign); - } else { - if (prev == NumericCharKind.Underscore) { - ReportError(Errors.TrailingUnderscoreInNumber); - } else if (c == '_') { - Skip(c); - prev = NumericCharKind.Underscore; - continue; - } - - return DecodeDouble(numberStartIndex, _bufferPos); - } - } - } - - // FLOAT - exponent - // [+-]?[0-9]([0-9_]*[0-9])? - private Tokens ReadDoubleExponent(int numberStartIndex, int sign) { - int exponent = 0; - NumericCharKind prev = NumericCharKind.None; - while (true) { - int c = Peek(); - - if (IsDecimalDigit(c)) { - Skip(c); - prev = NumericCharKind.Digit; - - // greater exponents evaluate to infinity/zero, we need to keep parsing though: - if (exponent < 10000) { - exponent = exponent * 10 + (c - '0'); - } - } else { - if (prev != NumericCharKind.Digit) { - Debug.Assert(prev == NumericCharKind.Underscore); - ReportError(Errors.TrailingUnderscoreInNumber); - } else if (c == '_') { - Skip(c); - prev = NumericCharKind.Underscore; - continue; - } - - exponent *= sign; - - // some MRI arbitrary restrictions on the exponent: - if (exponent <= -1021 || exponent >= 1025) { - // TODO: - int start = _currentTokenStart.Column - 1; - ReportWarning(Errors.FloatOutOfRange, new String(_lineBuffer, start, _bufferPos - start).Replace("_", "")); - } - - return DecodeDouble(numberStartIndex, _bufferPos); - } - } - } - private static bool TryDecodeDouble(char[]/*!*/ str, int first, int end, out double result) { StringBuilder sb = new StringBuilder(end - first); sb.Length = end - first; @@ -3797,20 +125,6 @@ private static bool TryDecodeDouble(string/*!*/ str, int first, int end, out dou return Double.TryParse(sb.ToString(), NumberStyles.Float, CultureInfo.InvariantCulture, out result); } - private Tokens DecodeDouble(int first, int end) { - double result; - if (!TryDecodeDouble(_lineBuffer, first, end, out result)) { - result = Double.PositiveInfinity; - } - - _tokenValue.SetDouble(result); - return Tokens.Float; - } - - #endregion - - #region Character Categories - public static bool IsDecimalDigit(int c) { return unchecked((uint)c - '0' <= (uint)'9' - '0'); } @@ -3847,18 +161,10 @@ public static int ToDigit(int c) { // Surrogate pairs are composed to a single character that is also considered an identifier. private const int AllowMultiByteIdentifier = 0x07f; - private bool IsIdentifier(int c) { - return IsIdentifier(c, _multiByteIdentifier); - } - public static bool IsIdentifier(int c, int multiByteIdentifier) { return IsIdentifierInitial(c, multiByteIdentifier) || IsDecimalDigit(c); } - private bool IsIdentifierInitial(int c) { - return IsIdentifierInitial(c, _multiByteIdentifier); - } - public static bool IsIdentifierInitial(int c, int multiByteIdentifier) { return IsLetter(c) || c == '_' || c > multiByteIdentifier; } @@ -3903,69 +209,6 @@ private static bool IsMethodNameSuffix(int c, int multiByteIdentifier) { return IsIdentifier(c, multiByteIdentifier) || c == '!' || c == '?' || c == '='; } - private void SkipVariableName() { - while (true) { - int c = Peek(); - if (IsIdentifier(c)) { - Skip(); - } else { - break; - } - } - } - - // returns true if an end of line has been skipped: - private bool SkipWhitespace() { - bool eolnSkipped = false; - while (true) { - RefillBuffer(); - int c = Peek(); - if (c == '\n') { - eolnSkipped = true; - Skip(); - } else if (IsWhiteSpace(c)) { - Skip(); - } else { - return eolnSkipped; - } - } - } - - #endregion - - #region Public API - - public SourceUnit SourceUnit { - get { return _sourceUnit; } - } - - public int DataOffset { - get { return _dataOffset; } - } - - public RubyCompatibility Compatibility { - get { return _compatibility; } - set { _compatibility = value; } - } - - public SourceSpan TokenSpan { - get { return _tokenSpan; } - } - - public TokenValue TokenValue { - get { return _tokenValue; } - } - - public bool EndOfFileReached { - get { return _eofReached; } - } - - public bool UnterminatedToken { - get { return _unterminatedToken; } - } - - #region ParseInteger - private static int NextChar(string/*!*/ str, ref int i) { return i == str.Length ? -1 : str[i++]; } @@ -4074,10 +317,6 @@ public static IntegerValue ParseInteger(string/*!*/ str, int @base, ref int i) { } } - #endregion - - #region TryParseDouble - private static int Read(string/*!*/ str, ref int i) { i++; return (i < str.Length) ? str[i] : -1; @@ -4153,10 +392,6 @@ public static bool TryParseDouble(string/*!*/ str, out double result, out bool c return success; } - #endregion - - #region TryParseEncodingHeader - private const string EncodingHeaderPattern = @"^[#].*?coding\s*[:=]\s*(?[a-z0-9_-]+)"; // reads case insensitively, doesn't rewind the reader if the content doesn't match, doesn't read a line unless it starts with '#': @@ -4191,10 +426,6 @@ internal static bool TryParseEncodingHeader(TextReader/*!*/ reader, out string e return false; } - #endregion - - #region Names - public static bool IsConstantName(string name) { return !String.IsNullOrEmpty(name) && (IsUpperLetter(name[0]) || IsNonAsciiConstantInitial(name, 0)) @@ -4281,425 +512,5 @@ public static bool IsOperatorName(string/*!*/ name) { return false; } - #endregion - - #endregion - - #region Tokenizer Service - - public override object CurrentState { - get { return _state; } - } - - public override ErrorSink/*!*/ ErrorSink { - get { return _errorSink; } - set { - ContractUtils.RequiresNotNull(value, "value"); - _errorSink = value; - } - } - - public override bool IsRestartable { - get { return true; } - } - - public override SourceLocation CurrentPosition { - get { return _tokenSpan.End; } - } - - public override bool SkipToken() { - return GetNextToken() != Tokens.EndOfFile; - } - - public override TokenInfo ReadToken() { - Tokens token = GetNextToken(); - TokenInfo result = GetTokenInfo(token); - result.SourceSpan = TokenSpan; - return result; - } - - internal static TokenInfo GetTokenInfo(Tokens token) { - TokenInfo result = new TokenInfo(); - switch (token) { - case Tokens.Undef: - case Tokens.Rescue: - case Tokens.Ensure: - case Tokens.If: - case Tokens.Unless: - case Tokens.Then: - case Tokens.Elsif: - case Tokens.Else: - case Tokens.Case: - case Tokens.When: - case Tokens.While: - case Tokens.Until: - case Tokens.For: - case Tokens.Break: - case Tokens.Next: - case Tokens.Redo: - case Tokens.Retry: - case Tokens.In: - case Tokens.Return: - case Tokens.Yield: - case Tokens.Super: - case Tokens.Self: - case Tokens.Nil: - case Tokens.True: - case Tokens.False: - case Tokens.And: - case Tokens.Or: - case Tokens.Not: - case Tokens.IfMod: - case Tokens.UnlessMod: - case Tokens.WhileMod: - case Tokens.UntilMod: - case Tokens.RescueMod: - case Tokens.Alias: - case Tokens.Defined: - case Tokens.Line: - case Tokens.File: - case Tokens.Encoding: - result.Category = TokenCategory.Keyword; - break; - - case Tokens.Def: - case Tokens.Class: - case Tokens.Module: - case Tokens.End: - case Tokens.Begin: - case Tokens.UppercaseBegin: - case Tokens.UppercaseEnd: - case Tokens.Do: - case Tokens.LoopDo: - case Tokens.BlockDo: - case Tokens.LambdaDo: - result.Category = TokenCategory.Keyword; - result.Trigger = TokenTriggers.MatchBraces; - break; - - case Tokens.Plus: // + - case Tokens.UnaryPlus: // +@ - case Tokens.Minus: // - - case Tokens.UnaryMinus: // -@ - case Tokens.NumberNegation: // - - case Tokens.Pow: // ** - case Tokens.Cmp: // <=> - case Tokens.Equal: // == - case Tokens.StrictEqual: // === - case Tokens.NotEqual: // != - case Tokens.Greater: // > - case Tokens.GreaterOrEqual: // >= - case Tokens.Less: // < - case Tokens.LessOrEqual: // <= - case Tokens.LogicalAnd: // && - case Tokens.LogicalOr: // || - case Tokens.Match: // =~ - case Tokens.Nmatch: // !~ - case Tokens.DoubleDot: // .. - case Tokens.TripleDot: // ... - case Tokens.ItemGetter: // [] - case Tokens.ItemSetter: // []= - case Tokens.Lshft: // << - case Tokens.Rshft: // >> - case Tokens.DoubleArrow: // => - case Tokens.Lambda: // -> - case Tokens.Star: // * - case Tokens.Asterisk: // * - case Tokens.BlockReference: // & - case Tokens.Ampersand: // & - case Tokens.Percent: // % - case Tokens.Assignment: // = - case Tokens.OpAssignment: // +=, -=, ... - case Tokens.Caret: // ^ - case Tokens.Colon: // : - case Tokens.QuestionMark: // ? - case Tokens.Bang: // ! - case Tokens.Slash: // / - case Tokens.Tilde: // ~ - case Tokens.Backtick: // ` - result.Category = TokenCategory.Operator; - break; - - case Tokens.SeparatingDoubleColon: // :: - case Tokens.LeadingDoubleColon: // :: - result.Category = TokenCategory.Delimiter; - result.Trigger = TokenTriggers.MemberSelect; - break; - - case Tokens.LeftBracket: // [ - case Tokens.LeftIndexingBracket: // [ - case Tokens.RightBracket: // ] - case Tokens.LeftBrace: // { - case Tokens.LeftBlockArgBrace: // { - case Tokens.LeftBlockBrace: // { - case Tokens.LeftLambdaBrace: // { - case Tokens.RightBrace: // } - case Tokens.Pipe: // | - case Tokens.StringEmbeddedCodeBegin: // #{ in string - case Tokens.StringEmbeddedCodeEnd: // } in string - result.Category = TokenCategory.Grouping; - result.Trigger = TokenTriggers.MatchBraces; - break; - - case Tokens.LeftParenthesis: // ( - case Tokens.LeftArgParenthesis: // ( in argument - result.Category = TokenCategory.Grouping; - result.Trigger = TokenTriggers.MatchBraces | TokenTriggers.ParameterStart; - break; - - case Tokens.LeftExprParenthesis: // ( in expression - result.Category = TokenCategory.Grouping; - result.Trigger = TokenTriggers.MatchBraces; - break; - - case Tokens.RightParenthesis: // ) - result.Category = TokenCategory.Grouping; - result.Trigger = TokenTriggers.MatchBraces | TokenTriggers.ParameterEnd; - break; - - case Tokens.Comma: // , - result.Category = TokenCategory.Delimiter; - result.Trigger = TokenTriggers.ParameterNext; - break; - - case Tokens.Dot: // . - result.Category = TokenCategory.Delimiter; - result.Trigger = TokenTriggers.MemberSelect; - break; - - case Tokens.Character: - case Tokens.StringEnd: - case Tokens.VerbatimHeredocBegin: - case Tokens.VerbatimHeredocEnd: - result.Category = TokenCategory.StringLiteral; - break; - - case Tokens.StringEmbeddedVariableBegin: // # in string followed by @ or $ - case Tokens.Semicolon: // ; - case Tokens.WordSeparator: // - result.Category = TokenCategory.Delimiter; - break; - - case Tokens.SymbolBegin: - case Tokens.Label: - case Tokens.Identifier: - case Tokens.FunctionIdentifier: - case Tokens.GlobalVariable: - case Tokens.InstanceVariable: - case Tokens.ConstantIdentifier: - case Tokens.ClassVariable: - case Tokens.MatchReference: - result.Category = TokenCategory.Identifier; - break; - - case Tokens.Integer: - case Tokens.Float: - case Tokens.BigInteger: - result.Category = TokenCategory.NumericLiteral; - break; - - case Tokens.StringContent: - case Tokens.StringBegin: - case Tokens.ShellStringBegin: - case Tokens.WordsBegin: - case Tokens.VerbatimWordsBegin: - case Tokens.RegexpBegin: - case Tokens.RegexpEnd: - // TODO: distingush various kinds of string content (regex, string, heredoc, symbols, words) - result.Category = TokenCategory.StringLiteral; - break; - - case Tokens.Pound: - result.Category = TokenCategory.LineComment; - break; - - case Tokens.EndOfFile: - result.Category = TokenCategory.EndOfStream; - break; - - case Tokens.NewLine: - case Tokens.EndOfLine: - case Tokens.Whitespace: - result.Category = TokenCategory.WhiteSpace; - break; - - case Tokens.SingleLineComment: - result.Category = TokenCategory.LineComment; - break; - - case Tokens.MultiLineComment: - result.Category = TokenCategory.Comment; - break; - - case Tokens.Error: - case Tokens.Backslash: - case Tokens.At: - case Tokens.Dollar: - case Tokens.InvalidCharacter: - result.Category = TokenCategory.Error; - break; - - default: - throw Assert.Unreachable; - } - - return result; - } - - internal static string/*!*/ GetTokenDescription(Tokens token) { - switch (token) { - case Tokens.Undef: return "`undef'"; - case Tokens.Rescue: - case Tokens.RescueMod: return "`rescue'"; - case Tokens.Ensure: return "`ensure'"; - case Tokens.If: - case Tokens.IfMod: return "`if'"; - case Tokens.Unless: - case Tokens.UnlessMod: return "`unless'"; - case Tokens.Then: return "`then'"; - case Tokens.Elsif: return "`elsif'"; - case Tokens.Else: return "`else'"; - case Tokens.Case: return "`case'"; - case Tokens.When: return "`when'"; - case Tokens.While: - case Tokens.WhileMod: return "`while'"; - case Tokens.Until: - case Tokens.UntilMod: return "`until'"; - case Tokens.For: return "`for'"; - case Tokens.Break: return "`break'"; - case Tokens.Next: return "`next'"; - case Tokens.Redo: return "`redo'"; - case Tokens.Retry: return "`retry'"; - case Tokens.In: return "`in'"; - case Tokens.Return: return "`return'"; - case Tokens.Yield: return "`yield'"; - case Tokens.Super: return "`super'"; - case Tokens.Self: return "`self'"; - case Tokens.Nil: return "`nil'"; - case Tokens.True: return "`true'"; - case Tokens.False: return "`false'"; - case Tokens.And: return "`and'"; - case Tokens.Or: return "`or'"; - case Tokens.Not: return "`not'"; - case Tokens.Alias: return "`alias'"; - case Tokens.Defined: return "`defined'"; - case Tokens.Line: return "`__LINE__'"; - case Tokens.File: return "`__FILE__'"; - case Tokens.Encoding: return "`__ENCODING__'"; - case Tokens.Def: return "`def'"; - case Tokens.Class: return "`class'"; - case Tokens.Module: return "`module'"; - case Tokens.End: return "`end'"; - case Tokens.Begin: return "`begin'"; - case Tokens.UppercaseBegin: return "`BEGIN'"; - case Tokens.UppercaseEnd: return "`END'"; - case Tokens.Do: - case Tokens.LoopDo: - case Tokens.BlockDo: - case Tokens.LambdaDo: return "`do'"; - case Tokens.Plus: return "`+'"; - case Tokens.UnaryPlus: return "`+@'"; - case Tokens.Minus: return "`-'"; - case Tokens.UnaryMinus: return "`-@'"; - case Tokens.Pow: return "`**'"; - case Tokens.Cmp: return "`<=>'"; - case Tokens.Equal: return "`=='"; - case Tokens.StrictEqual: return "`==='"; - case Tokens.NotEqual: return "`!='"; - case Tokens.Greater: return "`>'"; - case Tokens.GreaterOrEqual: return "`>='"; - case Tokens.Less: return "`<'"; - case Tokens.LessOrEqual: return "`<'"; - case Tokens.LogicalAnd: return "`&&'"; - case Tokens.LogicalOr: return "`||'"; - case Tokens.Match: return "`=~'"; - case Tokens.Nmatch: return "`!~'"; - case Tokens.DoubleDot: return "`..'"; - case Tokens.TripleDot: return "`...'"; - case Tokens.ItemGetter: return "`[]'"; - case Tokens.ItemSetter: return "`[]='"; - case Tokens.Lshft: return "`<<'"; - case Tokens.Rshft: return "`>>'"; - case Tokens.DoubleArrow: return "`=>'"; - case Tokens.Lambda: return "`->'"; - case Tokens.Star: - case Tokens.Asterisk: return "`*'"; - case Tokens.BlockReference: - case Tokens.Ampersand: return "`&'"; - case Tokens.Percent: return "`%'"; - case Tokens.Assignment: return "`='"; - case Tokens.Caret: return "`^'"; - case Tokens.Colon: return "`:'"; - case Tokens.QuestionMark: return "`?'"; - case Tokens.Bang: return "`!'"; - case Tokens.Slash: return "`/'"; - case Tokens.Tilde: return "`~'"; - case Tokens.Backtick: return "`"; - case Tokens.SeparatingDoubleColon: - case Tokens.LeadingDoubleColon: return "`::'"; - case Tokens.LeftBracket: - case Tokens.LeftIndexingBracket: return "`['"; - case Tokens.RightBracket: return "`]'"; - case Tokens.LeftBrace: - case Tokens.LeftBlockArgBrace: - case Tokens.LeftBlockBrace: - case Tokens.LeftLambdaBrace: return "`{'"; - case Tokens.RightBrace: return "`}'"; - case Tokens.Pipe: return "`|'"; - case Tokens.LeftParenthesis: - case Tokens.LeftArgParenthesis: - case Tokens.LeftExprParenthesis: return "`('"; - case Tokens.RightParenthesis: return "`)'"; - case Tokens.Comma: return "`,'"; - case Tokens.Dot: return "`.'"; - case Tokens.Semicolon: return "`;'"; - - case Tokens.Character: return "character escape (?...)"; - case Tokens.NumberNegation: return "negative number"; - case Tokens.OpAssignment: return "assignment with operation"; - case Tokens.StringEmbeddedVariableBegin: return "`#@' or `#$'"; - case Tokens.StringEmbeddedCodeBegin: return "`#{'"; - case Tokens.StringEmbeddedCodeEnd: return "`}'"; - case Tokens.Label: return "label"; - case Tokens.Identifier: return "identifier"; - case Tokens.FunctionIdentifier: return "function name"; - case Tokens.GlobalVariable: return "global variable"; - case Tokens.InstanceVariable: return "instance variable"; - case Tokens.ConstantIdentifier: return "constant"; - case Tokens.ClassVariable: return "class variable"; - case Tokens.MatchReference: return "$&, $`, $', $+, or $1-9"; - case Tokens.Integer: return "integer"; - case Tokens.BigInteger: return "big integer"; - case Tokens.Float: return "float"; - case Tokens.StringBegin: return "quote"; - case Tokens.VerbatimHeredocBegin: return "heredoc start"; - case Tokens.StringContent: return "string content"; - case Tokens.StringEnd: return "string terminator"; - case Tokens.VerbatimHeredocEnd: return "heredoc terminator"; - case Tokens.ShellStringBegin: return "shell command (`...`)"; - case Tokens.SymbolBegin: return "symbol"; - case Tokens.WordsBegin: return "`%W'"; - case Tokens.VerbatimWordsBegin: return "`%w'"; - case Tokens.WordSeparator: return "word separator"; - case Tokens.RegexpBegin: return "regex start"; - case Tokens.RegexpEnd: return "regex end"; - case Tokens.Pound: return "`#'"; - case Tokens.EndOfFile: return "end of file"; - case Tokens.NewLine: - case Tokens.EndOfLine: return "end of line"; - case Tokens.Whitespace: return "space"; - case Tokens.SingleLineComment: return "# comment"; - case Tokens.MultiLineComment: return "=begin ... =end"; - case Tokens.Error: return "error"; - case Tokens.Backslash: return "`\\'"; - case Tokens.At: return "`@'"; - case Tokens.Dollar: return "`$'"; - case Tokens.InvalidCharacter: return "invalid character"; - default: - throw Assert.Unreachable; - } - } - - #endregion } } diff --git a/Src/Ruby/Compiler/Parser/VariableFactory.cs b/Src/Ruby/Compiler/Parser/VariableFactory.cs deleted file mode 100644 index faa00d51e..000000000 --- a/Src/Ruby/Compiler/Parser/VariableFactory.cs +++ /dev/null @@ -1,120 +0,0 @@ -/* **************************************************************************** - * - * Copyright (c) Microsoft Corporation. - * - * This source code is subject to terms and conditions of the Apache License, Version 2.0. A - * copy of the license can be found in the License.html file at the root of this distribution. If - * you cannot locate the Apache License, Version 2.0, please send an email to - * ironruby@microsoft.com. By using this source code in any fashion, you are agreeing to be bound - * by the terms of the Apache License, Version 2.0. - * - * You must not remove this notice, or any other, from this software. - * - * - * ***************************************************************************/ - -using System.Dynamic; -using Microsoft.Scripting; -using Microsoft.Scripting.Utils; -using IronRuby.Compiler.Ast; - -namespace IronRuby.Compiler { - internal static class VariableFactory { - public const int Identifier = 0; - public const int Instance = 1; - public const int Global = 2; - public const int Constant = 3; - public const int Class = 4; - public const int Nil = 5; - public const int Self = 6; - public const int True = 7; - public const int False = 8; - public const int File = 9; - public const int Line = 10; - public const int Encoding = 11; - - internal static Expression/*!*/ MakeRead(int kind, Parser/*!*/ parser, string name, SourceSpan location) { - switch (kind) { - case Identifier: - return (Expression)parser.CurrentScope.ResolveVariable(name) ?? new MethodCall(null, name, null, null, location); - - case Instance: - return new InstanceVariable(name, location); - - case Global: - return new GlobalVariable(name, location); - - case Constant: - return new ConstantVariable(name, location); - - case Class: - return new ClassVariable(name, location); - - case Nil: - return Literal.Nil(location); - - case Self: - return new SelfReference(location); - - case True: - return Literal.True(location); - - case False: - return Literal.False(location); - - case File: - return new FileLiteral(location); - - case Line: - return Literal.Integer(parser.Tokenizer.TokenSpan.Start.Line, location); - - case Encoding: - return new EncodingExpression(location); - } - - throw Assert.Unreachable; - } - - internal static LeftValue/*!*/ MakeLeftValue(int kind, Parser/*!*/ parser, string name, SourceSpan location) { - switch (kind) { - case Identifier: - return parser.CurrentScope.ResolveOrAddVariable(name, location); - - case Instance: - return new InstanceVariable(name, location); - - case Global: - return new GlobalVariable(name, location); - - case Constant: - return new ConstantVariable(name, location); - - case Class: - return new ClassVariable(name, location); - - case Nil: - return parser.CannotAssignError("nil", location); - - case Self: - return parser.CannotAssignError("self", location); - - case True: - return parser.CannotAssignError("true", location); - - case False: - return parser.CannotAssignError("false", location); - - case File: - return parser.CannotAssignError("__FILE__", location); - - case Line: - return parser.CannotAssignError("__LINE__", location); - - case Encoding: - return parser.CannotAssignError("__ENCODING__", location); - } - - return null; - } - } -} diff --git a/Src/Ruby/GlobalSuppressions.cs b/Src/Ruby/GlobalSuppressions.cs index a55a7404a..ba7b47351 100644 --- a/Src/Ruby/GlobalSuppressions.cs +++ b/Src/Ruby/GlobalSuppressions.cs @@ -15,4 +15,3 @@ [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1020:AvoidNamespacesWithFewTypes", Scope = "namespace", Target = "IronRuby")] [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1020:AvoidNamespacesWithFewTypes", Scope = "namespace", Target = "IronRuby.Hosting")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity", Scope = "member", Target = "IronRuby.Compiler.Parser.#DoAction(System.Int32)")] diff --git a/Src/Ruby/Hosting/RubyCommandLine.cs b/Src/Ruby/Hosting/RubyCommandLine.cs index d680f4642..54a264ebc 100644 --- a/Src/Ruby/Hosting/RubyCommandLine.cs +++ b/Src/Ruby/Hosting/RubyCommandLine.cs @@ -157,17 +157,6 @@ protected override int RunFile(string fileName) { return 1; } - if (options.LoopOverInput && RubyContext.UsesLegacyParser) { - // The program has to be read rather than handed to the compiler as a path, so - // that the -n loop can be wrapped around it. - string path = RubyUtils.CanonicalizePath(fileName); - string source = File.ReadAllText(path, GetSourceCodeEncoding()); - return RunFile(Engine.CreateScriptSource( - new BinaryContentProvider(GetSourceCodeEncoding().GetBytes(WrapInInputLoop(source, options))), - path, GetSourceCodeEncoding(), SourceCodeKind.File - )); - } - return RunFile(Engine.CreateScriptSourceFromFile(RubyUtils.CanonicalizePath(fileName), GetSourceCodeEncoding())); } @@ -184,7 +173,7 @@ private static bool HasRubyScript(string/*!*/ path, bool skipToRubyShebang) { if (!skipToRubyShebang) { return true; } - } else if (line.IndexOf("ruby", StringComparison.Ordinal) >= 0) { + } else if (line.IndexOf("ruby", StringComparison.Ordinal) >= 0 || RubyUtils.ShebangNamesIronRuby(line)) { return true; } while ((line = reader.ReadLine()) != null) { @@ -201,37 +190,6 @@ private static bool HasRubyScript(string/*!*/ path, bool skipToRubyShebang) { } } - /// - /// -n and -p run the program once per input line, as `while gets; ...; end`; -a splits the - /// line into $F and -l chomps it first. - /// - /// The loop header sits on the same line as the first line of the program rather than on a - /// line of its own, so that every line of the program keeps the number it has in the file - /// and backtraces still point at the right place. - /// - /// A BEGIN or END block in the program is rejected by the parser as "permitted only at - /// toplevel", because after the wrapping it no longer is one. MRI wraps the parsed program - /// instead, where the two have already been hoisted out; doing the same here needs the - /// same hoisting in the prism bridge. - /// - private static string/*!*/ WrapInInputLoop(string/*!*/ source, RubyOptions/*!*/ options) { - var header = new StringBuilder("while gets;"); - if (options.ChopLines) { - header.Append("$_.chomp!($/);"); - } - if (options.AutoSplit) { - header.Append("$F=$_.split;"); - } - - var footer = new StringBuilder(); - if (options.PrintEachLine) { - footer.Append(";print $_"); - } - footer.Append(";end"); - - return header.ToString() + source + footer.ToString(); - } - protected override ScriptCodeParseResult GetCommandProperties(string code) { return CreateCommandSource(code, SourceCodeKind.InteractiveCode, "(ir)").GetCodeProperties(Engine.GetCompilerOptions(ScriptScope)); } @@ -241,14 +199,8 @@ protected override void ExecuteCommand(string/*!*/ command) { } protected override int RunCommand(string/*!*/ command) { - var options = ((RubyContext)Language).RubyOptions; - // prism wraps the loop around the parsed program itself (PrismAstBridge). - bool wrap = options.LoopOverInput && RubyContext.UsesLegacyParser; - if (wrap) { - command = WrapInInputLoop(command, options); - } - - byte[] raw = wrap ? null : GetRawCommandBytes(command); + // -n and -p: prism wraps the loop around the parsed program itself (PrismAstBridge). + byte[] raw = GetRawCommandBytes(command); if (raw != null) { return RunFile(Engine.CreateScriptSource(new BinaryContentProvider(raw), "-e", GetSourceCodeEncoding(), SourceCodeKind.Statements)); } diff --git a/Src/Ruby/Hosting/RubyConsoleHost.cs b/Src/Ruby/Hosting/RubyConsoleHost.cs index d61fab877..774323464 100644 --- a/Src/Ruby/Hosting/RubyConsoleHost.cs +++ b/Src/Ruby/Hosting/RubyConsoleHost.cs @@ -75,6 +75,45 @@ private sealed class RubyPlatformAdaptationLayer : PlatformAdaptationLayer { public override Stream OpenInputFileStream(string path, FileMode mode, FileAccess access, FileShare share, int bufferSize) { return base.OpenInputFileStream(path, mode, access, share | FileShare.ReadWrite | FileShare.Delete, bufferSize); } + + /// + /// MRI's Dir.pwd is getcwd(): the directory as it was set. .NET's GetCurrentDirectory + /// expands an 8.3 short name ("C:\Users\ABCDEF~1") to the long one, so after + /// Dir.chdir(Dir.tmpdir) Dir.pwd was not the directory just changed into, and a path + /// built from the one did not start with the other - rubocop, for one, then cannot + /// show a file relative to the current directory. + /// + public override string CurrentDirectory { + get { + if (Path.DirectorySeparatorChar == '\\') { + var buffer = new System.Text.StringBuilder(260); + uint length = GetCurrentDirectoryW((uint)buffer.Capacity, buffer); + if (length > buffer.Capacity) { + buffer = new System.Text.StringBuilder((int)length); + length = GetCurrentDirectoryW(length, buffer); + } + if (length > 0 && length <= buffer.Capacity) { + return buffer.ToString(); + } + } + return base.CurrentDirectory; + } + set { + // .NET checks the directory - its errors are what Dir.chdir turns into Errno - + // but sets it through Path.GetFullPath, which expands short names too; MRI's + // SetCurrentDirectory takes the path as given. + base.CurrentDirectory = value; + if (Path.DirectorySeparatorChar == '\\') { + SetCurrentDirectoryW(value); + } + } + } + + [System.Runtime.InteropServices.DllImport("kernel32", CharSet = System.Runtime.InteropServices.CharSet.Unicode, SetLastError = true)] + private static extern uint GetCurrentDirectoryW(uint bufferLength, System.Text.StringBuilder buffer); + + [System.Runtime.InteropServices.DllImport("kernel32", CharSet = System.Runtime.InteropServices.CharSet.Unicode, SetLastError = true)] + private static extern bool SetCurrentDirectoryW(string path); } private static void SetHomeEnvironmentVariable() { diff --git a/Src/Ruby/Runtime/Attributes.cs b/Src/Ruby/Runtime/Attributes.cs index 766669fd3..1ae153056 100644 --- a/Src/Ruby/Runtime/Attributes.cs +++ b/Src/Ruby/Runtime/Attributes.cs @@ -118,6 +118,15 @@ public RubyMethodAttribute(string/*!*/ name, RubyMethodAttributes methodAttribut /// [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] public sealed class RubyNotImplementedAttribute : Attribute { + /// + /// Not implemented on Windows only, where MRI defines it as the stub too (IO#ioctl); the + /// same build runs on Unix, where the method works. + /// + public bool OnWindowsOnly { get; set; } + + internal bool AppliesHere { + get { return !OnWindowsOnly || System.IO.Path.DirectorySeparatorChar == '\\'; } + } } [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] diff --git a/Src/Ruby/Runtime/Calls/RubyLibraryMethodInfo.cs b/Src/Ruby/Runtime/Calls/RubyLibraryMethodInfo.cs index 7b7312c86..7e71975c6 100644 --- a/Src/Ruby/Runtime/Calls/RubyLibraryMethodInfo.cs +++ b/Src/Ruby/Runtime/Calls/RubyLibraryMethodInfo.cs @@ -102,7 +102,8 @@ public bool IsNotImplemented { if (_notImplemented == 0) { bool result = true; foreach (var member in GetMembers()) { - if (!member.IsDefined(typeof(RubyNotImplementedAttribute), false)) { + var notImplemented = (RubyNotImplementedAttribute)Attribute.GetCustomAttribute(member, typeof(RubyNotImplementedAttribute), false); + if (notImplemented == null || !notImplemented.AppliesHere) { result = false; break; } diff --git a/Src/Ruby/Runtime/RubyContext.cs b/Src/Ruby/Runtime/RubyContext.cs index ef900657b..42d4d471b 100644 --- a/Src/Ruby/Runtime/RubyContext.cs +++ b/Src/Ruby/Runtime/RubyContext.cs @@ -602,8 +602,12 @@ public RubyContext(ScriptDomainManager/*!*/ manager, IDictionary _namespaceCache = new Dictionary(); _referenceTypeInstanceData = new System.Runtime.CompilerServices.ConditionalWeakTable(); _valueTypeInstanceData = new Dictionary(); - _inputProvider = new RubyInputProvider(this, _options.Arguments, _options.LocaleEncoding); - _defaultExternalEncoding = _options.DefaultEncoding ?? _options.LocaleEncoding; + // MRI 3.0+ on Windows: the default external encoding is UTF-8 whatever the console's + // code page, which stays the locale encoding - and ARGV is in it too; a .NET argument + // is Unicode, so nothing is lost. + bool windows = Path.DirectorySeparatorChar == '\\'; + _inputProvider = new RubyInputProvider(this, _options.Arguments, windows ? RubyEncoding.UTF8 : _options.LocaleEncoding); + _defaultExternalEncoding = _options.DefaultEncoding ?? (windows ? RubyEncoding.UTF8 : _options.LocaleEncoding); // -E / --encoding, resolved here rather than in the options parser because looking an // encoding up by its Ruby name needs a context. It overrides both -K and the locale: // that is the whole point of the option. @@ -3536,18 +3540,24 @@ internal bool TryGetCurrentSourceLocation(out string path, out int line) { // "file:line:in `method'", read from the right: a file name can hold colons of // its own - an eval inside an eval is called "(eval at file:line)" - so the line // number is the last thing before ":in", not the first thing after the path. - string first = backtrace[0].ToString(); - int inIndex = first.LastIndexOf(":in ", StringComparison.Ordinal); - string head = (inIndex >= 0) ? first.Substring(0, inIndex) : first; + // A frame without a file (":0:in ..." - a library method, or a CLR frame when + // backtraces show them) is not where the code was written: the first one that + // names a file is. + foreach (var entry in backtrace) { + string frame = entry.ToString(); + int inIndex = frame.LastIndexOf(":in ", StringComparison.Ordinal); + string head = (inIndex >= 0) ? frame.Substring(0, inIndex) : frame; + + int colon = head.LastIndexOf(':'); + if (colon <= 0 || !Int32.TryParse(head.Substring(colon + 1), out line)) { + continue; + } - int colon = head.LastIndexOf(':'); - if (colon < 0 || !Int32.TryParse(head.Substring(colon + 1), out line)) { - line = 0; - return false; + path = head.Substring(0, colon); + return true; } - - path = head.Substring(0, colon); - return true; + line = 0; + return false; } catch (Exception) { path = null; line = 0; @@ -3567,6 +3577,13 @@ internal bool TryGetCurrentSourceLocation(out string path, out int line) { // Encoding::UTF_16BE is that every path operation raises // Encoding::CompatibilityError, which this layer has no way to report), and neither // can ASCII-8BIT, which rejects every character above U+00FF. + // + // On Windows file names are Unicode and MRI's filesystem encoding is UTF-8 whatever + // the console's code page: under code page 850 a path holding a character CP850 has + // no byte for was an Errno::EINVAL here. + if (Path.DirectorySeparatorChar == '\\') { + return RubyEncoding.UTF8; + } var external = _defaultExternalEncoding; if (external == null || !external.IsAsciiIdentity || external == RubyEncoding.Binary) { return RubyEncoding.UTF8; @@ -3711,47 +3728,31 @@ public override ScriptCode CompileSourceCode(SourceUnit/*!*/ sourceUnit, Compile #endif /// - /// The front end a host chose, or null for the default. The default is the prism bridge - /// whenever IronRuby.Prism can be loaded - it is what ir, irubyc's hosts and the test suite's - /// prism mode use, and the only front end that parses Ruby 3 and 4 (ruby4.rb included) - and the - /// legacy 1.9-era parser only when it cannot. Before, null meant the legacy parser, so a host - /// that embedded IronRuby with Ruby.CreateEngine() and set nothing got a 1.9 parser without - /// any sign of it. Set this to to ask for the old parser explicitly. + /// The front end a host chose, or null for prism (IronRuby.Prism's bridge), which is the + /// only parser IronRuby has: the 1.9-era LALR parser that used to be the fallback is gone. /// public static Func AlternativeParser; - /// The built-in 1.9-era parser, for hosts (and the legacy test mode) that want it. - public static readonly Func LegacyParser = - (sourceUnit, options, errorSink) => new Parser().Parse(sourceUnit, options, errorSink); - private static Func _defaultParser; - /// The front end in effect: the one a host set, or else the default. + /// The front end in effect: the one a host set, or else prism. public static Func EffectiveParser { get { return AlternativeParser ?? (_defaultParser ?? (_defaultParser = ResolveDefaultParser())); } } - /// True when source is parsed by the legacy parser (which cannot wrap -n/-p itself). - public static bool UsesLegacyParser { - get { return EffectiveParser == LegacyParser; } - } - // IronRuby.Prism references IronRuby, so IronRuby cannot reference it back: find it by name. - // A missing IronRuby.Prism means the legacy parser; a present one whose native libprism is - // missing fails at the first parse with DllNotFoundException - a deployment error that is - // better reported than papered over with a parser that cannot read the prelude. + // Without it there is nothing to parse with, which is a deployment error and is reported as + // one; a present IronRuby.Prism whose native libprism is missing fails at the first parse + // with DllNotFoundException. private static Func ResolveDefaultParser() { - try { - Type bridge = Type.GetType("IronRuby.Prism.PrismAstBridge, IronRuby.Prism", false); - MethodInfo parse = (bridge != null) ? bridge.GetMethod("Parse", BindingFlags.Public | BindingFlags.Static, null, - new[] { typeof(SourceUnit), typeof(RubyCompilerOptions), typeof(ErrorSink) }, null) : null; - if (parse != null) { - return (Func)parse.CreateDelegate(typeof(Func)); - } - } catch (Exception) { - // not deployed, or not loadable here: fall back below + Type bridge = Type.GetType("IronRuby.Prism.PrismAstBridge, IronRuby.Prism", false); + MethodInfo parse = (bridge != null) ? bridge.GetMethod("Parse", BindingFlags.Public | BindingFlags.Static, null, + new[] { typeof(SourceUnit), typeof(RubyCompilerOptions), typeof(ErrorSink) }, null) : null; + if (parse == null) { + throw new InvalidOperationException( + "IronRuby.Prism.dll could not be loaded: it is IronRuby's parser and has to be deployed next to IronRuby.dll."); } - return LegacyParser; + return (Func)parse.CreateDelegate(typeof(Func)); } @@ -4374,12 +4375,10 @@ private void AppendExceptionReport(StringBuilder/*!*/ sb, Exception/*!*/ excepti public override TService GetService(params object[] args) { if (typeof(TService) == typeof(RubyService)) { return (TService)(object)(_rubyService ?? (_rubyService = new RubyService(this, (Microsoft.Scripting.Hosting.ScriptEngine)args[0]))); - } - - if (typeof(TService) == typeof(TokenizerService)) { - return (TService)(object)new Tokenizer(); } + // There is no TokenizerService (the DLR's colouring tokenizer) any more: it was the + // 1.9-era lexer of the legacy parser. return base.GetService(args); } diff --git a/Src/Ruby/Runtime/RubyOps.cs b/Src/Ruby/Runtime/RubyOps.cs index 73b820962..84f9e40cc 100644 --- a/Src/Ruby/Runtime/RubyOps.cs +++ b/Src/Ruby/Runtime/RubyOps.cs @@ -1547,10 +1547,15 @@ private static object ResolveQualifiedConstant(RubyScope/*!*/ scope, string/*!*/ missingConstantOwner = topModule; } + // defined?(A::B::C) never calls const_missing (MRI): a name that is not there makes the + // whole path undefined. Only the get does what evaluating A::B would. object result; if (missingConstantOwner == null) { result = storage.Value; anyMissing = ReportConstantDeprecation(context, firstOwner, name); + } else if (!isGet) { + anyMissing = true; + return null; } else { anyMissing = true; using (context.ClassHierarchyUnlocker()) { @@ -1575,6 +1580,9 @@ private static object ResolveQualifiedConstant(RubyScope/*!*/ scope, string/*!*/ } result = storage.Value; + } else if (!isGet) { + anyMissing = true; + return null; } else { anyMissing = true; using (context.ClassHierarchyUnlocker()) { @@ -2823,27 +2831,40 @@ private static void AppendInterpolatedPart(MutableString/*!*/ result, MutableStr [Emitted] public static RubySymbol/*!*/ CreateSymbolM(MutableString str1, RubyEncoding/*!*/ encoding, RubyScope/*!*/ scope) { - return scope.RubyContext.CreateSymbol(CreateMutableStringM(str1, encoding), false); + return CreateInterpolatedSymbol(scope.RubyContext, CreateMutableStringM(str1, encoding)); } [Emitted] public static RubySymbol/*!*/ CreateSymbolLM(string/*!*/ str1, MutableString str2, RubyEncoding/*!*/ encoding, RubyScope/*!*/ scope) { - return scope.RubyContext.CreateSymbol(CreateMutableStringLM(str1, str2, encoding), false); + return CreateInterpolatedSymbol(scope.RubyContext, CreateMutableStringLM(str1, str2, encoding)); } [Emitted] public static RubySymbol/*!*/ CreateSymbolML(MutableString str1, string/*!*/ str2, RubyEncoding/*!*/ encoding, RubyScope/*!*/ scope) { - return scope.RubyContext.CreateSymbol(CreateMutableStringML(str1, str2, encoding), false); + return CreateInterpolatedSymbol(scope.RubyContext, CreateMutableStringML(str1, str2, encoding)); } - + [Emitted] public static RubySymbol/*!*/ CreateSymbolMM(MutableString str1, MutableString str2, RubyEncoding/*!*/ encoding, RubyScope/*!*/ scope) { - return scope.RubyContext.CreateSymbol(CreateMutableStringMM(str1, str2, encoding), false); + return CreateInterpolatedSymbol(scope.RubyContext, CreateMutableStringMM(str1, str2, encoding)); } [Emitted] public static RubySymbol/*!*/ CreateSymbolN(MutableString[]/*!*/ strings, RubyScope/*!*/ scope) { - return scope.RubyContext.CreateSymbol(CreateMutableStringN(strings), false); + return CreateInterpolatedSymbol(scope.RubyContext, CreateMutableStringN(strings)); + } + + /// + /// :"#{...}" and %I[#{...}] are String#to_sym of what was interpolated: bytes that are not + /// valid in the string's encoding cannot name a symbol (MRI's rb_str_intern), where an + /// ASCII byte means itself. + /// + private static RubySymbol/*!*/ CreateInterpolatedSymbol(RubyContext/*!*/ context, MutableString/*!*/ str) { + if (str.Encoding.IsAsciiIdentity && str.ContainsInvalidCharacters()) { + throw new EncodingError(RubyExceptions.FormatMessage("invalid symbol in encoding {0} :{1}", + str.Encoding.Name, context.Inspect(str).ToString())); + } + return context.CreateSymbol(str, false); } #endregion diff --git a/Src/Ruby/Runtime/RubyUtils.cs b/Src/Ruby/Runtime/RubyUtils.cs index a1c348be0..1255c24f6 100644 --- a/Src/Ruby/Runtime/RubyUtils.cs +++ b/Src/Ruby/Runtime/RubyUtils.cs @@ -1967,6 +1967,28 @@ public static bool IsRubyThreadExit(Exception e) { #region Paths + /// + /// Whether the first line of a script is a #! line that runs IronRuby's own launcher. MRI + /// and prism take a #! line without "ruby" in it as the start of some other program and + /// look further down for the Ruby one; but RubyGems and Rails write binstubs from + /// RbConfig's ruby_install_name, which is "ir", so `rails new` starts bin/rails with + /// "#!/usr/bin/env ir.exe" - a Ruby script that does not say "ruby". + /// + public static bool ShebangNamesIronRuby(string/*!*/ code) { + if (code == null || !code.StartsWith("#!", StringComparison.Ordinal)) { + return false; + } + int end = code.IndexOf('\n'); + string shebang = (end < 0) ? code.Substring(2) : code.Substring(2, end - 2); + foreach (string word in shebang.Split(new[] { ' ', '\t', '\r', '/', '\\', '"', '\'' }, StringSplitOptions.RemoveEmptyEntries)) { + switch (word.ToLowerInvariant()) { + case "ir": case "ir.exe": case "ir.cmd": case "ir.sh": + return true; + } + } + return false; + } + // '\' is only a path separator on Windows. On Unix it is an ordinary character in a // file name, and rewriting it silently loses files: mspec's own rm_r expands the path // first, so a fixture called "special/\a" was never found, never deleted, and every diff --git a/Src/StdLib/ironruby/ironruby/gem_compat.rb b/Src/StdLib/ironruby/ironruby/gem_compat.rb index 4f35d073c..40ac53dec 100644 --- a/Src/StdLib/ironruby/ironruby/gem_compat.rb +++ b/Src/StdLib/ironruby/ironruby/gem_compat.rb @@ -130,6 +130,27 @@ def initialize(*args, &block) end end +# bindex (skiptrace): it gives every exception the Bindings of the frames it +# was raised through, from a C extension on CRuby and from VM internals on JRuby +# and Rubinius; for any other engine it defines nothing, and Exception#bindings +# is a NoMethodError. web-console, in every `rails new` Gemfile, asks for it +# while rendering the development error page - so on IronRuby each error page, +# a plain 404 for a missing record included, became a 500. +# +# The bindings themselves need the runtime to capture them at raise time, which +# IronRuby does not do yet. Until it does, Exception#bindings answers what it +# answers on those engines for an exception nobody captured bindings for, and +# the error page renders; its console has no frame to evaluate in. +IronRuby::GemCompat.on_require("bindex") do + unless ::Exception.method_defined?(:bindings) + ::Exception.class_eval do + def bindings + @bindings || [] + end + end + end +end + # power_assert: Parser#valid_syntax? checks a line with # RubyVM::InstructionSequence.compile, and PowerAssert::Parser builds one at # load time, so on an engine without RubyVM the require dies with a NameError. @@ -237,4 +258,39 @@ def which(executable) end ::Bundler.singleton_class.prepend(rubypath_which) end + + # `gem "tzinfo-data", platforms: %i[windows jruby]`, which every `rails new` + # Gemfile has: Bundler keeps a platform-restricted gem only for the lockfile + # platforms whose *generic* platform the restriction names, and to it + # IronRuby's universal-dotnet is generic `ruby` - on Windows as everywhere. + # So tzinfo-data was never installed, and a Rails app on Windows, which has + # no zoneinfo, died in its first initializer with TZInfo::DataSourceNotFound. + # + # The .NET platform is the same on every OS, so for it the restriction is + # answered the way `current_platform?` answers it - by the Ruby running now. + if ::Bundler::Dependency.method_defined?(:gem_platforms) && + !::Bundler::Dependency.method_defined?(:ironruby_dotnet_platforms) + dotnet_platforms = Module.new do + # The dotnet platforms, and - since Bundler filters what it installs and + # loads by the *generic* local platform, which for dotnet is `ruby` - that + # one too when it stands for the dotnet platform this process runs on. + def ironruby_dotnet_platforms(valid_platforms) # :nodoc: + dotnet = ->(p) { p.respond_to?(:os) && p.os == "dotnet" } + local_is_dotnet = dotnet.call(::Bundler.local_platform) + valid_platforms.select do |p| + dotnet.call(p) || (local_is_dotnet && p == ::Bundler.generic_local_platform) + end + end + + # Same order as valid_platforms, which is what Bundler's comment promises. + def gem_platforms(valid_platforms) + found = super + return found if platforms.empty? || force_ruby_platform || !current_platform? + dotnet = ironruby_dotnet_platforms(valid_platforms) + return found if dotnet.empty? + valid_platforms.select { |p| found.include?(p) || dotnet.include?(p) } + end + end + ::Bundler::Dependency.prepend(dotnet_platforms) + end end diff --git a/Src/StdLib/ironruby/ripper/sexp_builder.rb b/Src/StdLib/ironruby/ripper/sexp_builder.rb index 0e78dc0e5..98d87660a 100644 --- a/Src/StdLib/ironruby/ripper/sexp_builder.rb +++ b/Src/StdLib/ironruby/ripper/sexp_builder.rb @@ -391,14 +391,14 @@ def visit_InterpolatedMatchLastLineNode(node) visit_InterpolatedRegularExpressio def visit_SymbolNode(node) opening = node['opening_loc'] ? text(node['opening_loc']) : nil return [:dyna_symbol, list(:string, symbol_content(node))] if opening.nil? ? false : opening.size > 1 - value = fname_token(node['value_loc']) + value = fname_token(node['content_loc']) return value if opening.nil? [:symbol_literal, [:symbol, value]] end # `:""` and `%s()` have no content event at all. def symbol_content(node) - location = node['value_loc'] + location = node['content_loc'] return [] if location.nil? || location[1] == 0 [[:add, [:@tstring_content, text(location), pos(location[0])]]] end @@ -425,7 +425,7 @@ def word_element(node, interpolating = false) token = string_content_token(node) interpolating ? list(:word, [[:add, token]]) : token when 'SymbolNode' - token = [:@tstring_content, text(node['value_loc']), pos(node['value_loc'][0])] + token = [:@tstring_content, text(node['content_loc']), pos(node['content_loc'][0])] interpolating ? list(:word, [[:add, token]]) : token when 'InterpolatedStringNode', 'InterpolatedSymbolNode' list(:word, node['parts'].map { |part| [:add, string_part(part)] }) @@ -1278,7 +1278,7 @@ def global_name(node) end def alias_name(node) - return [:symbol_literal, fname_token(node['value_loc'])] if node['type'] == 'SymbolNode' && node['opening_loc'].nil? + return [:symbol_literal, fname_token(node['content_loc'])] if node['type'] == 'SymbolNode' && node['opening_loc'].nil? visit(node) end diff --git a/Src/StdLib/ironruby/ruby4.rb b/Src/StdLib/ironruby/ruby4.rb index 783cc35a4..34da99feb 100644 --- a/Src/StdLib/ironruby/ruby4.rb +++ b/Src/StdLib/ironruby/ruby4.rb @@ -4463,13 +4463,23 @@ class << Dir def home(user = nil) if user.nil? dir = ENV['HOME'] + if dir.nil? && File::ALT_SEPARATOR + # MRI's rb_w32_home_dir: HOME, then USERPROFILE, then HOMEDRIVE + HOMEPATH, then the + # profile folder Windows reports. + dir = ENV['USERPROFILE'] + dir ||= ENV['HOMEDRIVE'] + ENV['HOMEPATH'] if ENV['HOMEDRIVE'] && ENV['HOMEPATH'] + dir ||= System::Environment.GetFolderPath(System::Environment::SpecialFolder.UserProfile).to_s + dir = nil if dir.empty? + end unless dir require 'etc' pw = (Etc.getpwuid(Process.uid) rescue nil) dir = pw && pw.dir end raise ArgumentError, "couldn't find HOME environment -- expanding `~'" unless dir - return dir.dup + # MRI on Windows: the home directory is written with forward slashes, like every path it + # makes, whatever HOME holds ("C:\Users\x" from Git Bash, for one). ENV keeps its value. + return File::ALT_SEPARATOR ? dir.tr("\\", "/") : dir.dup end raise TypeError, "no implicit conversion of #{user.class} into String" unless user.is_a?(String) @@ -8590,13 +8600,19 @@ module Process # passing them to a syscall later gets the right value. { WNOHANG: 1, WUNTRACED: 2, + }.each { |name, value| const_set(name, value) unless const_defined?(name) } + + # CRuby on Windows has neither priorities nor resource limits, and portable code asks + # for the constant before it calls the function: net-http-persistent, which Bundler + # vendors, calls getrlimit whenever RLIMIT_NOFILE is defined. + { PRIO_PROCESS: 0, PRIO_PGRP: 1, PRIO_USER: 2, RLIMIT_CPU: 0, RLIMIT_FSIZE: 1, RLIMIT_DATA: 2, RLIMIT_STACK: 3, RLIMIT_CORE: 4, RLIMIT_RSS: 5, RLIMIT_NPROC: 6, RLIMIT_NOFILE: 7, RLIMIT_MEMLOCK: 8, RLIMIT_AS: 9, RLIMIT_LOCKS: 10, RLIMIT_SIGPENDING: 11, RLIMIT_MSGQUEUE: 12, RLIMIT_NICE: 13, RLIMIT_RTPRIO: 14, RLIMIT_RTTIME: 15, RLIM_INFINITY: 2**64 - 1, RLIM_SAVED_CUR: 2**64 - 1, RLIM_SAVED_MAX: 2**64 - 1, - }.each { |name, value| const_set(name, value) unless const_defined?(name) } + }.each { |name, value| const_set(name, value) unless const_defined?(name) } unless ::File::ALT_SEPARATOR == "\\" # Process.times returns this; MRI names the struct under Process as well as Struct. Tms = Struct::Tms unless const_defined?(:Tms) @@ -9439,7 +9455,20 @@ def self.waitall # on platforms that cannot do it too, as the function that raises NotImplementedError, # and that function is exactly the case respond_to? answers false for - so portable # code asks whether the feature is there rather than whether the name is. - NOT_IMPLEMENTED_METHODS = [:daemon, :fork, :_fork].freeze unless const_defined?(:NOT_IMPLEMENTED_METHODS) + # On Windows the resource-limit and priority functions are the same kind of stub in + # MRI; the libc behind ours is not there to call. + WINDOWS_NOT_IMPLEMENTED_METHODS__ = [:getrlimit, :setrlimit, :getpriority, :setpriority].freeze unless const_defined?(:WINDOWS_NOT_IMPLEMENTED_METHODS__) + unless const_defined?(:NOT_IMPLEMENTED_METHODS) + NOT_IMPLEMENTED_METHODS = (::File::ALT_SEPARATOR == "\\" ? + [:daemon, :fork, :_fork] + WINDOWS_NOT_IMPLEMENTED_METHODS__ : [:daemon, :fork, :_fork]).freeze + end + + if ::File::ALT_SEPARATOR == "\\" + WINDOWS_NOT_IMPLEMENTED_METHODS__.each do |name| + define_method(name) { |*| raise NotImplementedError, "#{name}() function is unimplemented on this machine" } + module_function name + end + end unless respond_to?(:daemon) def daemon(nochdir = nil, noclose = nil) diff --git a/Src/StdLib/ruby/4.0/bundled_gems.rb b/Src/StdLib/ruby/4.0/bundled_gems.rb index c5893a241..6de30483d 100644 --- a/Src/StdLib/ruby/4.0/bundled_gems.rb +++ b/Src/StdLib/ruby/4.0/bundled_gems.rb @@ -122,6 +122,15 @@ def self.warning?(name, specs: nil) false end + # IronRuby: fiddle, syslog, nkf, win32ole and bigdecimal are IronRuby's own, + # in its archdir (Src/StdLib/ironruby) where CRuby keeps C extensions, and no + # gem can replace them. They are not leaving anything, so there is nothing to + # warn of. + if RUBY_ENGINE == "ironruby" + resolved = $LOAD_PATH.resolve_feature_path(feature) rescue nil + return if resolved && resolved[1].start_with?(ARCHDIR) + end + if suppress_list = Thread.current[:__bundled_gems_warning_suppression] return if suppress_list.include?(name) || suppress_list.include?(feature) end diff --git a/Src/StdLib/ruby/4.0/rubygems/defaults/ironruby.rb b/Src/StdLib/ruby/4.0/rubygems/defaults/ironruby.rb index 1691bed9f..e60d2c1a4 100644 --- a/Src/StdLib/ruby/4.0/rubygems/defaults/ironruby.rb +++ b/Src/StdLib/ruby/4.0/rubygems/defaults/ironruby.rb @@ -227,8 +227,8 @@ def self.path end ## - # RbConfig.ruby names the `ir` apphost, which starts without the -X:UsePrism - # and -X:StdLib arguments that make it a Ruby 4 interpreter. RubyGems and + # RbConfig.ruby names the `ir` apphost, which starts without the -X:StdLib + # argument that gives it Ruby 4's standard library. RubyGems and # Bundler shell out to Gem.ruby to run binstubs and extconf.rb, so point it # at the ir.sh (ir.cmd on Windows) wrapper next to the source tree when there # is one. @@ -554,13 +554,58 @@ def build_extensions end end + ## + # Gems that are C extensions upstream and that IronRuby has exactly one of, + # built in, at a newer major version than some popular gems were released + # for. Such a gem cannot get the version it asks for here - there is no + # compiler for the C one - and the one here does what it uses, so a + # requirement on an older major version is read with its upper bound lifted - + # "~> 1.7" as ">= 1.7" - for these names only, from the given major version + # on, and only where the built-in version then satisfies it. + # + # prism: IronRuby parses with it, at 2.x since it follows prism 2.0's + # serialization; its FFI backend would need a libprism 1.x beside that. + # rubocop-ast (~> 1.7), so rubocop and standard, and minitest 6 (~> 1.5), + # which every Rails app's tests pull in, ask for 1.x and use the Ruby API, + # which 2.0 kept for what they call: their exercises in Util/gems give the + # same output as on CRuby with prism 1.9. 0.x is an API from before 1.0. + # + # bigdecimal: the C# one in Src/Libraries presents as 4.0.1 and passes + # ruby/spec's library/bigdecimal. ttfunk, so prawn, asks for ~> 3.1 and + # only tells a BigDecimal operand from the others by its class. 2.0 removed + # BigDecimal.new, so a requirement for 1.x is left alone. + IRONRUBY_LIFTED_REQUIREMENTS = { "prism" => 1, "bigdecimal" => 2 }.freeze # :nodoc: + + module IronRubyBuiltInRequirement # :nodoc: + def requirement + requirement = super + from_major = IRONRUBY_LIFTED_REQUIREMENTS[name] + return requirement unless from_major + built_in = Gem.ironruby_pinned_gems[name] + return requirement if built_in.nil? || requirement.satisfied_by?(built_in) + return requirement if requirement.requirements.any? { |_, version| version.segments.first < from_major } + + lifted = requirement.requirements.filter_map do |op, version| + case op + when "~>" then ">= #{version}" + when "<", "<=" then nil + else "#{op} #{version}" + end + end + lifted = Gem::Requirement.new(lifted) + lifted.satisfied_by?(built_in) ? lifted : requirement + end + end + def self.const_added(name) # :nodoc: super # Registering an autoload fires this too; only a real class is prepended to. Installer.prepend(IronRubyNoExtensionBuild) if name == :Installer && !autoload?(:Installer) + Dependency.prepend(IronRubyBuiltInRequirement) if name == :Dependency && !autoload?(:Dependency) end Installer.prepend(IronRubyNoExtensionBuild) if const_defined?(:Installer, false) && !autoload?(:Installer) + Dependency.prepend(IronRubyBuiltInRequirement) if const_defined?(:Dependency, false) && !autoload?(:Dependency) class BasicSpecification; end diff --git a/Util/aot/NativeAot/Program.cs b/Util/aot/NativeAot/Program.cs index ac149d460..541b17847 100644 --- a/Util/aot/NativeAot/Program.cs +++ b/Util/aot/NativeAot/Program.cs @@ -102,10 +102,11 @@ static int Main(string[] args) { } Console.WriteLine("IsDynamicCodeSupported: " + System.Runtime.CompilerServices.RuntimeFeature.IsDynamicCodeSupported); } + // Prism is the only parser; -X:UsePrism, which used to choose it, is accepted and ignored. if (Array.IndexOf(args, "-X:UsePrism") >= 0) { args = Array.FindAll(args, a => a != "-X:UsePrism"); - RubyContext.AlternativeParser = IronRuby.Prism.PrismAstBridge.Parse; } + RubyContext.AlternativeParser = IronRuby.Prism.PrismAstBridge.Parse; return new Host().Run(args); } } diff --git a/Util/aot/NativeAot/ir-native.sh b/Util/aot/NativeAot/ir-native.sh index 4d349ee5f..24b76a283 100755 --- a/Util/aot/NativeAot/ir-native.sh +++ b/Util/aot/NativeAot/ir-native.sh @@ -9,5 +9,5 @@ S="$IR_ROOT/Src/StdLib" # interpreter-only paths (dotnet build ir-native.csproj -p:PublishAot=false -o DIR). : "${IR_NATIVE_BIN:=$HERE/bin/Release/net10.0/linux-x64/publish/ir}" export DOTNET_ROOT="${DOTNET_ROOT:-/usr/local/dotnet}" -exec "$IR_NATIVE_BIN" -X:UsePrism \ +exec "$IR_NATIVE_BIN" \ "-X:StdLib=$S/ironruby:$S/ruby/4.0" "$@" diff --git a/Util/gems/POPULAR.md b/Util/gems/POPULAR.md index b5bd1edfb..e8691e588 100644 --- a/Util/gems/POPULAR.md +++ b/Util/gems/POPULAR.md @@ -146,7 +146,7 @@ Named in the brief, further down the list: | chunky_png | 1.4.0 | **WORKS** | draws into an image, encodes it, decodes it again and compares the pixels | | standard | 1.56.0 | **WORKS** | `Standard::Cli` over a file with a real offence; it is RuboCop underneath | | yard | 0.9.45 | **BROKEN** | `require "yard"` succeeds; parsing Ruby does not. `YARD::Parser::Ruby::RipperParser` builds its handlers from `Ripper::PARSER_EVENT_TABLE` at load, and IronRuby's Ripper is a prism tree translator with `Ripper.sexp` and the scanner events, not an event parser | -| prawn | 2.5.0 | **BROKEN** | pins `bigdecimal ~> 3.1`; IronRuby's built-in bigdecimal presents as 4.0.1, so RubyGems tries to build the C one and fails. CRuby installs the C gem instead | +| prawn | 2.5.0 | **WORKS** | two A4 pages with text, shapes, a text box and page numbers, rendered to the same bytes. ttfunk pins `bigdecimal ~> 3.1`; IronRuby's built-in bigdecimal is 4.0.1, and RubyGems now reads a 2.x or 3.x requirement on it as `>=` (`rubygems/defaults/ironruby.rb`) | | rb-inotify | 0.11.1 | **WORKS** | on IronRuby's ffi; create/modify/delete events match CRuby | | bcrypt | 3.1.22 | **IMPOSSIBLE as a gem** | C extension: the Blowfish KDF. A port, not a shim - `BCrypt.Net` already exists on NuGet | | oj | 3.17.6 | **IMPOSSIBLE as a gem** | C extension. Use `json`, which IronRuby implements | diff --git a/Util/gems/catalog.rb b/Util/gems/catalog.rb index 49ac18462..cdc7ae230 100644 --- a/Util/gems/catalog.rb +++ b/Util/gems/catalog.rb @@ -241,8 +241,8 @@ module GemCatalog 'sawyer' => { require: 'sawyer', gem: true, exercise: 'sawyer', status: :works }, 'listen' => { require: 'listen', gem: true, exercise: 'listen', status: :works }, 'chunky_png' => { require: 'chunky_png', gem: true, exercise: 'chunky_png', status: :works }, - 'prawn' => { require: 'prawn', gem: true, status: :broken, - note: 'pins bigdecimal ~> 3.1; IronRuby has 4.0.1 built in, so RubyGems builds the C one' }, + 'prawn' => { require: 'prawn', gem: true, exercise: 'prawn', status: :works, + note: 'ttfunk pins bigdecimal ~> 3.1; read as >= 3.1 against the built-in 4.0.1' }, 'standard' => { require: 'standard', gem: true, exercise: 'standard', status: :works }, 'bcrypt' => { require: 'bcrypt', gem: true, status: :impossible, note: 'C extension (the Blowfish KDF); a .NET port is a real project' }, diff --git a/Util/gems/exercises/listen.rb b/Util/gems/exercises/listen.rb index 92d2fe960..025b25001 100644 --- a/Util/gems/exercises/listen.rb +++ b/Util/gems/exercises/listen.rb @@ -16,14 +16,24 @@ listener.start puts listener.processing? -File.write(File.join(dir, 'a.txt'), 'one') +# Listen builds its first snapshot of the directory on a thread of its own after #start, so a +# file written at once may already be in it, and then no "added" event comes - on any Ruby, +# just more often on a slower or busier one. Writing it again with other content makes a +# "modified" event in that case, so the answer does not depend on who won the race. +file = File.join(dir, 'a.txt') +File.write(file, 'one') deadline = Time.now + 10 events = [] +rewritten_at = Time.now while Time.now < deadline begin events << seen.pop(true) rescue ThreadError sleep 0.1 + if Time.now - rewritten_at > 0.5 + File.write(file, "one #{Time.now.to_f}") + rewritten_at = Time.now + end end break if events.flatten.include?('a.txt') end diff --git a/Util/gems/exercises/prawn.rb b/Util/gems/exercises/prawn.rb new file mode 100644 index 000000000..867b34742 --- /dev/null +++ b/Util/gems/exercises/prawn.rb @@ -0,0 +1,26 @@ +require 'prawn' +require 'digest' + +# prawn depends on ttfunk, which asks for bigdecimal ~> 3.1: activating it at +# all is half of what this checks (see POPULAR.md), the PDF is the other half. +puts Gem.loaded_specs.key?('ttfunk') + +pdf = Prawn::Document.new(page_size: 'A4', info: { Title: 'Exercise', CreationDate: Time.utc(2026, 1, 2) }) +pdf.font 'Helvetica' +pdf.text 'Hello from prawn', size: 18, style: :bold +pdf.move_down 10 +pdf.text 'Line two, ' * 20 +pdf.stroke_rectangle [0, 600], 200, 100 +pdf.fill_color 'FF8000' +pdf.fill_circle [300, 550], 40 +pdf.start_new_page +pdf.font 'Courier' +pdf.text_box 'In a box', at: [50, 700], width: 100, height: 40 +pdf.number_pages '/', at: [pdf.bounds.right - 50, 0] + +puts pdf.page_count +puts pdf.width_of('Hello', size: 12).round(3) +data = pdf.render +puts data[0, 8] +puts data.include?('/Title') +puts Digest::SHA256.hexdigest(data) diff --git a/Util/gen-internal-methods.rb b/Util/gen-internal-methods.rb new file mode 100644 index 000000000..94ae91c98 --- /dev/null +++ b/Util/gen-internal-methods.rb @@ -0,0 +1,55 @@ +# frozen_string_literal: true +# +# Regenerates Src/Libraries/Builtins/InternalMethods.Generated.cs: the core methods CRuby +# itself writes in Ruby (kernel.rb, numeric.rb, ... compiled into the interpreter), with the +# "" file Method#source_location names for each. +# +# Run it with CRuby 4.0 - the oracle - from the root of the source tree: +# +# ruby --disable-gems Util/gen-internal-methods.rb +# +# Why this exists +# --------------- +# IronRuby implements a good part of core in its own Ruby prelude (Src/StdLib/ironruby/ruby4.rb +# and friends), Kernel#puts among them, where CRuby's are C. A C method has no source location: +# Method#source_location is nil, and code relies on that - method_source raises its own +# SourceNotFoundError for one, and pry and friends show "C method" instead of opening a file. +# So a prelude method answers nil unless CRuby's own is written in Ruby too, and then it is +# located where CRuby's is: "" for Kernel#tap, "" for +# Integer#times. (--disable-gems keeps RubyGems' Kernel#require, which is a library, out.) + +abort "run this with CRuby 4.0, not #{RUBY_ENGINE} #{RUBY_VERSION}" unless RUBY_ENGINE == "ruby" && RUBY_VERSION.start_with?("4.0") + +entries = {} +ObjectSpace.each_object(Module) do |mod| + name = mod.name + next if name.nil? || mod.singleton_class? + [[mod, "#"], [mod.singleton_class, "."]].each do |owner, sep| + (owner.instance_methods(false) + owner.private_instance_methods(false)).each do |meth| + location = owner.instance_method(meth).source_location + next unless location && location[0].start_with?("/*!*/ SourceFiles = new Dictionary { +HEADER +entries.sort.each { |key, file| out << " { #{key.dump}, #{file.dump} },\n" } +out << <<~FOOTER + }; + } + } +FOOTER + +path = File.expand_path("../Src/Libraries/Builtins/InternalMethods.Generated.cs", __dir__) +File.binwrite(path, out.gsub("\n", "\r\n")) +puts "#{entries.size} methods -> #{path.sub(File.expand_path("..", __dir__) + "/", "")}" diff --git a/default.mspec b/default.mspec index 1143a250b..486903478 100644 --- a/default.mspec +++ b/default.mspec @@ -1,6 +1,6 @@ # MSpec configuration for running ruby/spec against IronRuby. # -# ir -X:UsePrism -X:StdLib= -Imspec/lib mspec/bin/mspec-run spec/language +# ir -X:StdLib= -Imspec/lib mspec/bin/mspec-run spec/language # class MSpecScript ir_root = File.expand_path(File.dirname(__FILE__)) @@ -20,7 +20,6 @@ class MSpecScript set :target, File.join(bin, exe) set :flags, [ - "-X:UsePrism", # -X:StdLib rather than -I: the library goes on $LOAD_PATH after the -I paths a spec # passes, as MRI's does "-X:StdLib=#{stdlib}", diff --git a/ir.cmd b/ir.cmd index b17cd80ac..fe51087d0 100644 --- a/ir.cmd +++ b/ir.cmd @@ -42,5 +42,5 @@ if "%RUBYPATH%"=="" (set "RUBYPATH=%S%\bin;%IR_BINDIR%") else (set "RUBYPATH=%S% rem -X:StdLib is split on Path.PathSeparator, which is ';' on Windows - a ':' list would rem be cut apart at every drive letter. -"%IR_BIN%" -X:UsePrism "-X:StdLib=%S%\ironruby;%S%\ruby\4.0" %* +"%IR_BIN%" "-X:StdLib=%S%\ironruby;%S%\ruby\4.0" %* exit /b %ERRORLEVEL% diff --git a/ir.sh b/ir.sh index a985bd136..1ab7f70f6 100755 --- a/ir.sh +++ b/ir.sh @@ -70,5 +70,5 @@ fi RUBYPATH="$S/bin:$(dirname "$IR_BIN")${RUBYPATH:+:$RUBYPATH}" export RUBYPATH -exec "$IR_BIN" -X:UsePrism \ +exec "$IR_BIN" \ "-X:StdLib=$S/ironruby:$S/ruby/4.0" "$@" From d5a23cacf370235df8ad5b8ed9e2a456412ab018 Mon Sep 17 00:00:00 2001 From: Largo Date: Wed, 28 Oct 2026 09:27:35 +0100 Subject: [PATCH 8/9] Address review: relative chdir, ~ order, kept upper bounds - Dir.chdir with a relative path moved twice on Windows ("..": up two levels): the directory was set through .NET and then again through SetCurrentDirectoryW, each resolving it from where the last left off. It is set once now, with .NET only for the failure and its exception. - File.expand_path("~") looks at USERPROFILE before HOMEDRIVE + HOMEPATH, as CRuby and Dir.home do. - Lifting a prism/bigdecimal requirement removes only the bound "~>" implies; an explicit "< 4" stays. - defined? clears the private-constant reference that #const_missing would otherwise have consumed. - The nested-BEGIN walk runs on a fresh stack when the current one is low. - Tests: Dir_ChdirRelative1, File_ExpandTildeOrder1. --- Src/IronRuby.Tests/RubyTests.cs | 2 + Src/IronRuby.Tests/Runtime/MiscTests.cs | 61 +++++++++++++++++-- Src/Libraries/Builtins/FileOps.cs | 9 +-- Src/Prism/PrismAstBridge.cs | 5 ++ Src/Ruby/Hosting/RubyConsoleHost.cs | 13 ++-- Src/Ruby/Runtime/RubyContext.cs | 8 +++ Src/Ruby/Runtime/RubyOps.cs | 2 + .../ruby/4.0/rubygems/defaults/ironruby.rb | 11 ++-- 8 files changed, 89 insertions(+), 22 deletions(-) diff --git a/Src/IronRuby.Tests/RubyTests.cs b/Src/IronRuby.Tests/RubyTests.cs index f245e49c9..162c4ad37 100644 --- a/Src/IronRuby.Tests/RubyTests.cs +++ b/Src/IronRuby.Tests/RubyTests.cs @@ -730,6 +730,8 @@ public Tests(Driver/*!*/ driver) { Zlib_Streams1, Process_SpawnKill1, File_DriveLetters1, + Dir_ChdirRelative1, + File_ExpandTildeOrder1, File_FlockReadpartialRlimit1, Json_ControlCharacters1, NetHttp_Tls1, diff --git a/Src/IronRuby.Tests/Runtime/MiscTests.cs b/Src/IronRuby.Tests/Runtime/MiscTests.cs index d18b78205..e41885611 100644 --- a/Src/IronRuby.Tests/Runtime/MiscTests.cs +++ b/Src/IronRuby.Tests/Runtime/MiscTests.cs @@ -925,11 +925,8 @@ p got } /// - /// What RubyGems and Bundler need from the file system on Windows, where each of these - /// used to P/Invoke libc or raise: File#flock (RubyGems locks every binstub it writes), - /// IO#readpartial after IO#eof? has filled the buffer (Bundler checksums every .gem that - /// way), and Process's resource limits, which MRI does not define on Windows at all - - /// net-http-persistent calls getrlimit whenever RLIMIT_NOFILE is defined. + /// A drive-relative name's dirname is "C:." on Windows, as in MRI - which is how CRuby's own + /// pathname_builtin.rb recognises drive letters, so Pathname#absolute? depends on it. /// public void File_DriveLetters1() { TestOutput(@" @@ -948,6 +945,60 @@ p Pathname.new('C:/x/y').absolute? == windows, Pathname.new('/x').absolute? "); } + /// + /// A relative Dir.chdir is resolved once, from the directory in force - Dir.pwd keeping + /// 8.3 short names once made it twice, so ".." went up two levels. + /// + public void Dir_ChdirRelative1() { + TestOutput(@" +require 'tmpdir' +require 'fileutils' +root = File.join(Dir.tmpdir, ""ir-chdir-#{Process.pid}"") +FileUtils.mkdir_p(File.join(root, 'a', 'a', 'a')) +Dir.chdir(File.join(root, 'a', 'a')) do + Dir.chdir('..') + p File.basename(File.dirname(Dir.pwd)) == File.basename(root) + Dir.chdir('a') + p File.basename(File.dirname(File.dirname(Dir.pwd))) == File.basename(root) +end +FileUtils.rm_rf(root) +", @" +true +true +"); + } + + /// + /// Without HOME, "~" and Dir.home both come from USERPROFILE before HOMEDRIVE + HOMEPATH, + /// as in CRuby on Windows. + /// + public void File_ExpandTildeOrder1() { + TestOutput(@" +require 'ruby4' +saved = %w[HOME USERPROFILE HOMEDRIVE HOMEPATH].to_h { |k| [k, ENV[k]] } +begin + ENV.delete('HOME') + ENV['USERPROFILE'] = 'Y:\\profile' + ENV['HOMEDRIVE'], ENV['HOMEPATH'] = 'X:', '\\homepath' + windows = File::ALT_SEPARATOR == '\\' + p File.expand_path('~') == (windows ? 'Y:/profile' : File.expand_path('~')) + p Dir.home == File.expand_path('~') || !windows +ensure + saved.each { |k, v| ENV[k] = v } +end +", @" +true +true +"); + } + + /// + /// What RubyGems and Bundler need from the file system on Windows, where each of these + /// used to P/Invoke libc or raise: File#flock (RubyGems locks every binstub it writes), + /// IO#readpartial after IO#eof? has filled the buffer (Bundler checksums every .gem that + /// way), and Process's resource limits, which MRI does not define on Windows at all - + /// net-http-persistent calls getrlimit whenever RLIMIT_NOFILE is defined. + /// public void File_FlockReadpartialRlimit1() { TestOutput(@" require 'ruby4' diff --git a/Src/Libraries/Builtins/FileOps.cs b/Src/Libraries/Builtins/FileOps.cs index d259acbdb..5b851bd6f 100644 --- a/Src/Libraries/Builtins/FileOps.cs +++ b/Src/Libraries/Builtins/FileOps.cs @@ -901,7 +901,8 @@ private static string StripPathCharacters(string path) { /// /// "~" on Windows, where there is no user database to ask. MRI looks at $HOME, then at - /// $HOMEDRIVE + $HOMEPATH, then at $USERPROFILE, and refuses "~name" outright. Leaving + /// $USERPROFILE, then at $HOMEDRIVE + $HOMEPATH, as Dir.home does, and refuses "~name" + /// outright. Leaving /// the tilde alone - which is what this used to do - made Dir.home, Gem's user directory /// and every "~/.somethingrc" resolve inside the working directory. /// @@ -915,6 +916,9 @@ private static string StripPathCharacters(string path) { } string home = RubyEnvironment.GetVariable(context.Platform, "HOME"); + if (home == null) { + home = RubyEnvironment.GetVariable(context.Platform, "USERPROFILE"); + } if (home == null) { string drive = RubyEnvironment.GetVariable(context.Platform, "HOMEDRIVE"); string tail = RubyEnvironment.GetVariable(context.Platform, "HOMEPATH"); @@ -922,9 +926,6 @@ private static string StripPathCharacters(string path) { home = (drive ?? "") + tail; } } - if (home == null) { - home = RubyEnvironment.GetVariable(context.Platform, "USERPROFILE"); - } if (home == null) { throw RubyExceptions.CreateArgumentError("couldn't find HOME environment -- expanding `~'"); } diff --git a/Src/Prism/PrismAstBridge.cs b/Src/Prism/PrismAstBridge.cs index e3a26f3f9..e5ede4f19 100644 --- a/Src/Prism/PrismAstBridge.cs +++ b/Src/Prism/PrismAstBridge.cs @@ -430,6 +430,11 @@ private static Pm.PmNode HoistPreExecution(Pm.PmNode statementsNode) { /// first, and then a without the inner block. /// private static void CollectPreExecution(Pm.PreExecutionNode/*!*/ node, List/*!*/ into) { + // Nested BEGINs recurse through here rather than through Expr (see StackGuard). + if (!StackGuard.IsSufficient) { + StackGuard.RunOnFreshStack(() => CollectPreExecution(node, into)); + return; + } if (node.Statements is Pm.StatementsNode body && Array.Exists(body.Body, n => n is Pm.PreExecutionNode)) { var rest = new List(); foreach (var n in body.Body) { diff --git a/Src/Ruby/Hosting/RubyConsoleHost.cs b/Src/Ruby/Hosting/RubyConsoleHost.cs index 774323464..52edb9f9e 100644 --- a/Src/Ruby/Hosting/RubyConsoleHost.cs +++ b/Src/Ruby/Hosting/RubyConsoleHost.cs @@ -99,13 +99,14 @@ public override string CurrentDirectory { return base.CurrentDirectory; } set { - // .NET checks the directory - its errors are what Dir.chdir turns into Errno - - // but sets it through Path.GetFullPath, which expands short names too; MRI's - // SetCurrentDirectory takes the path as given. - base.CurrentDirectory = value; - if (Path.DirectorySeparatorChar == '\\') { - SetCurrentDirectoryW(value); + // .NET sets it through Path.GetFullPath, which expands short names too; MRI's + // SetCurrentDirectory takes the path as given. Set once - a relative path set + // twice would be resolved twice - and leave a failure to .NET, whose + // exceptions are what Dir.chdir turns into Errno. + if (Path.DirectorySeparatorChar == '\\' && SetCurrentDirectoryW(value)) { + return; } + base.CurrentDirectory = value; } } diff --git a/Src/Ruby/Runtime/RubyContext.cs b/Src/Ruby/Runtime/RubyContext.cs index 42d4d471b..739c68e56 100644 --- a/Src/Ruby/Runtime/RubyContext.cs +++ b/Src/Ruby/Runtime/RubyContext.cs @@ -2142,6 +2142,14 @@ internal static void SetPrivateConstantReference(RubyModule/*!*/ owner) { _privateConstantReference = owner; } + /// + /// For a lookup that reports a constant missing without calling #const_missing, which + /// would otherwise consume the reference: defined? does that. + /// + internal static void ClearPrivateConstantReference() { + _privateConstantReference = null; + } + // thread-safe: // Task::Factory is a static property, not a constant: say how to get it (Task.Factory). Only CLR const and // static readonly fields are constants (RubyModule.TryGetClrConstantField) - a constant is cached where it is diff --git a/Src/Ruby/Runtime/RubyOps.cs b/Src/Ruby/Runtime/RubyOps.cs index 84f9e40cc..be3a9c0c3 100644 --- a/Src/Ruby/Runtime/RubyOps.cs +++ b/Src/Ruby/Runtime/RubyOps.cs @@ -1555,6 +1555,7 @@ private static object ResolveQualifiedConstant(RubyScope/*!*/ scope, string/*!*/ anyMissing = ReportConstantDeprecation(context, firstOwner, name); } else if (!isGet) { anyMissing = true; + RubyContext.ClearPrivateConstantReference(); return null; } else { anyMissing = true; @@ -1582,6 +1583,7 @@ private static object ResolveQualifiedConstant(RubyScope/*!*/ scope, string/*!*/ result = storage.Value; } else if (!isGet) { anyMissing = true; + RubyContext.ClearPrivateConstantReference(); return null; } else { anyMissing = true; diff --git a/Src/StdLib/ruby/4.0/rubygems/defaults/ironruby.rb b/Src/StdLib/ruby/4.0/rubygems/defaults/ironruby.rb index e60d2c1a4..de29bea5b 100644 --- a/Src/StdLib/ruby/4.0/rubygems/defaults/ironruby.rb +++ b/Src/StdLib/ruby/4.0/rubygems/defaults/ironruby.rb @@ -561,7 +561,8 @@ def build_extensions # compiler for the C one - and the one here does what it uses, so a # requirement on an older major version is read with its upper bound lifted - # "~> 1.7" as ">= 1.7" - for these names only, from the given major version - # on, and only where the built-in version then satisfies it. + # on, and only where the built-in version then satisfies it. Only the bound + # "~>" implies is lifted: "< 4" written out is a gem saying 4 does not work. # # prism: IronRuby parses with it, at 2.x since it follows prism 2.0's # serialization; its FFI backend would need a libprism 1.x beside that. @@ -585,12 +586,8 @@ def requirement return requirement if built_in.nil? || requirement.satisfied_by?(built_in) return requirement if requirement.requirements.any? { |_, version| version.segments.first < from_major } - lifted = requirement.requirements.filter_map do |op, version| - case op - when "~>" then ">= #{version}" - when "<", "<=" then nil - else "#{op} #{version}" - end + lifted = requirement.requirements.map do |op, version| + op == "~>" ? ">= #{version}" : "#{op} #{version}" end lifted = Gem::Requirement.new(lifted) lifted.satisfied_by?(built_in) ? lifted : requirement From 40e05286d434d525e77b93f4ab9ea97f94e8266e Mon Sep 17 00:00:00 2001 From: Largo Date: Wed, 28 Oct 2026 10:48:23 +0100 Subject: [PATCH 9/9] Tests: turn off .NET's file-locking emulation, as ir does On Unix .NET emulates FileShare with a flock(2) of its own on every file it opens. ir turns that off (Ruby.Console.csproj), the test host did not, so File_FlockReadpartialRlimit1 - File#flock(LOCK_EX) with a second File.open of the same file - waited forever behind the hidden shared lock and hung the Linux CI jobs. Checked on Ubuntu 24.04: the test hangs without this and passes with it, and so does the whole suite. --- Src/IronRuby.Tests/IronRuby.Tests.csproj | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Src/IronRuby.Tests/IronRuby.Tests.csproj b/Src/IronRuby.Tests/IronRuby.Tests.csproj index 63913b409..2ea5afc81 100644 --- a/Src/IronRuby.Tests/IronRuby.Tests.csproj +++ b/Src/IronRuby.Tests/IronRuby.Tests.csproj @@ -9,6 +9,10 @@ + +