antlr4 icon indicating copy to clipboard operation
antlr4 copied to clipboard

Generated Dart code for Flutter web contains integer literals that exceed JavaScript's safe integer limit (2^53)

Open limexp opened this issue 4 months ago • 3 comments

Description

The generated Dart code for ANTLR grammars, when targeting web platforms, can produce integer literals that exceed the maximum safe integer limit in JavaScript ($2^{53}-1$). This leads to runtime errors because JavaScript cannot represent these large integers exactly.

This issue specifically affects web builds and is a direct result of the difference between 64-bit integer representation in most native environments and the 53-bit safe integer limit in JavaScript's number type.


Error Message

Error: The integer literal 1295065285207669298 can't be represented exactly in JavaScript. Try changing the literal to something that can be represented in JavaScript. In JavaScript 1295065285207669248 is the nearest value that can be represented exactly.


Affected Grammar

This issue is consistently reproducible with the objc grammar from the antlr/grammars-v4 repository.


Steps to Reproduce

To reproduce this issue, run the following commands (just generate dart-parser and import it or add checkVersion call to prevent unused import warning):

# Clone the repository with the grammars
git clone https://github.com/antlr/grammars-v4.git

# Create a new Flutter project for web
flutter create --platforms web flutter_web_error
cd flutter_web_error/

# Add the antlr4 package
flutter pub add antlr4

# Generate Dart code from the objc grammar
antlr4 -visitor -o lib/antlr4 -Xexact-output-dir -Dlanguage=Dart ../grammars-v4/objc/ObjectiveCParser.g4 ../grammars-v4/objc/ObjectiveCLexer.g4

# Add ANTLR generated parser import to main.dart to trigger the error on run
printf "import 'package:flutter_web_error/antlr4/ObjectiveCParser.dart';\n$(cat lib/main.dart)" > lib/main.dart

# Run the web application
flutter run

limexp avatar Sep 09 '25 07:09 limexp

I checked other grammars from antlr/grammars-v4: 225 are fine with Flutter web, 133 generate JavaScript integer literal errors. The most simple are: Alloy and RobotWar.

The full list of grammars that fail to be used in Flutter web:

acme, ada/ada2005, ada/ada2012, ada/ada83, ada/ada95, agc, alef, alloy, amazon-states-language, angelscript, antlr/antlr2, antlr/antlr3, antlr/antlr4, apex, arden, argus, asl, asm/asm6502, asm/asm8086, asm/masm, asm/nasm, asm/ptx/ptx-isa-1.0, asm/ptx/ptx-isa-2.1, atl, awk, basic, bcpl, bicep, bison, c, cpp, cql3, css3, cypher, dart2, edif300, eiffel, elixir, fortran/fortran90, fusion-tables, gdscript, golang, graphql, gvpr, haskell, hexpat, hypertalk, icalendar, idl, informix, iri, java/java, java/java20, java/java8, java/java9, javacc, javascript/ecmascript, javascript/javascript, javascript/jsx, javascript/typescript, joss, kirikiri-tjs, kquery, kuka, limbo, llvm-ir, modula2pim4, oberon, objc, pascal, pcre, peoplecode, pf, php, pike, plucid, powerbuilder, powerquery, protobuf/protobuf2, protobuf/protobuf3, python/python, python/python2, python/python2_7_18, python/python2-js, python/python3, python/python3_13, redis, rexx, robotwars, ruleworks, rust, scala, scss, sharc, smiles, smtlibv2, solidity, sparql, spass, sql/clickhouse, sql/derby, sql/drill, sql/hive/v4, sql/informix-sql, sql/mariadb, sql/mysql/Oracle, sql/mysql/Positive-Technologies, sql/phoenix, sql/plsql, sql/postgresql, sql/snowflake, sql/sqlite, sql/starrocks, sql/trino, sql/tsql, swift/swift2, swift/swift3, swift/swift5, teal, tinymud, tinyos_nesc, turing, unreal_angelscript, v, vaxscan, vb6, vba/vba6, velocity, vhdl, wavefront, wren, xpath/xpath20, xpath/xpath31

limexp avatar Sep 09 '25 14:09 limexp

I checked other grammars from antlr/grammars-v4: 225 are fine with Flutter web, 133 generate JavaScript integer literal errors. The most simple are: Alloy and RobotWar.

The full list of grammars that fail to be used in Flutter web:

..., antlr/antlr2, antlr/antlr3, ..., apex, ..., bcpl, ...

We don't test the grammars in grammars-v4 against Flutter Web, but it sounds like it's a "target" to add to testing. NB: I use "target" to mean both the generated code language and the environment that it runs in. We do test native executable Dart apps (templates here: https://github.com/antlr/grammars-v4/tree/a5754dd907b434d161213b729178c8fbbd128c2c/_scripts/templates/Dart).

Of those mentioned above, many don't work for native Dart apps as well. The full list is found by searching the desc.xml, which is the only way to know whether a grammar works for the target or not. In the past, people wrote the code for that target, but it never actually worked!

09/10-06:43:33 ~/issues/g4-current
$ for d in `find . -name desc.xml | grep -v Generated`; do trxml2 $d | grep Dart > /dev/null; if [ $? -ne 0 ]; then echo `dirname $d`
; fi; done
./antlr/antlr2
./antlr/antlr3
./apex
./asn/asn_3gpp
./bcpl
./bencoding
./clif
./csharp
./databank
./eiffel
./gdscript
./gff3
./haskell
./hexpat
./html
./icalendar
./java/java
./javadoc
./javascript/ecmascript
./javascript/javascript
./javascript/jsx
./javascript/typescript
./kirikiri-tjs
./langium
./logo/logo
./logo/ucb-logo
./lpc
./ocl
./pdn
./pegen
./pgn
./php
./pike
./protobuf/protobuf3
./python/python
./python/python2
./python/python2-js
./python/python2_7_18
./python/python3
./python/python3_13
./quakemap
./r
./restructuredtext
./rexx
./rust
./scss
./solidity
./sql/starrocks
./sql/teradata
./sql/tsql
./stringtemplate
./swift/swift2
./swift/swift3
./swift/swift5
./thrift
./tinymud
./tinyos_nesc
./v
./velocity
./webidl
./xpath/xpath20
./xpath/xpath31
./z
09/10-06:46:42 ~/issues/g4-current
$

kaby76 avatar Sep 10 '25 11:09 kaby76

Thanks so much for the comment!

I first ran into this error on my own grammar, but for the example, I decided to grab something from grammars-v4. I was lucky that the very first one I tried (objc) threw an error, which is why I created this issue.

After that, I decided to test some other grammars to find a simpler one for debugging. I chose ones where the flutter build web log contained "be represented exactly in JavaScript."

Today, I decided to try to fix the error, and I managed to do so with a minimal tweak to the Dart template. I'm currently using a patched version of antlr4 locally.

limexp avatar Sep 10 '25 12:09 limexp