mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 19:37:35 +00:00
JSSpecCompiler: Parse arbitrarily large rational numbers in xspec mode
This commit is contained in:
parent
2a2e31f2ed
commit
86d54a8684
9 changed files with 64 additions and 8 deletions
|
@ -10,6 +10,7 @@
|
||||||
#include <AK/RefCounted.h>
|
#include <AK/RefCounted.h>
|
||||||
#include <AK/RefPtr.h>
|
#include <AK/RefPtr.h>
|
||||||
#include <AK/Vector.h>
|
#include <AK/Vector.h>
|
||||||
|
#include <LibCrypto/BigFraction/BigFraction.h>
|
||||||
|
|
||||||
#include "Forward.h"
|
#include "Forward.h"
|
||||||
|
|
||||||
|
@ -208,16 +209,16 @@ protected:
|
||||||
|
|
||||||
class MathematicalConstant : public Expression {
|
class MathematicalConstant : public Expression {
|
||||||
public:
|
public:
|
||||||
MathematicalConstant(i64 number)
|
MathematicalConstant(Crypto::BigFraction number)
|
||||||
: m_number(number)
|
: m_number(number)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: This should be able to hold arbitrary number
|
|
||||||
i64 m_number;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void dump_tree(StringBuilder& builder) override;
|
void dump_tree(StringBuilder& builder) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Crypto::BigFraction m_number;
|
||||||
};
|
};
|
||||||
|
|
||||||
class StringLiteral : public Expression {
|
class StringLiteral : public Expression {
|
||||||
|
|
|
@ -62,7 +62,12 @@ void ControlFlowBranch::dump_tree(StringBuilder& builder)
|
||||||
|
|
||||||
void MathematicalConstant::dump_tree(StringBuilder& builder)
|
void MathematicalConstant::dump_tree(StringBuilder& builder)
|
||||||
{
|
{
|
||||||
dump_node(builder, "MathematicalConstant {}", m_number);
|
String representation;
|
||||||
|
if (Crypto::UnsignedBigInteger { 1000 }.divided_by(m_number.denominator()).remainder == 0)
|
||||||
|
representation = MUST(String::from_byte_string(m_number.to_byte_string(3)));
|
||||||
|
else
|
||||||
|
representation = MUST(String::formatted("{}/{}", MUST(m_number.numerator().to_base(10)), MUST(m_number.denominator().to_base(10))));
|
||||||
|
dump_node(builder, "MathematicalConstant {}", representation);
|
||||||
}
|
}
|
||||||
|
|
||||||
void StringLiteral::dump_tree(StringBuilder& builder)
|
void StringLiteral::dump_tree(StringBuilder& builder)
|
||||||
|
|
|
@ -21,6 +21,6 @@ set(SOURCES
|
||||||
main.cpp
|
main.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
lagom_tool(JSSpecCompiler LIBS LibCpp LibMain LibXML)
|
lagom_tool(JSSpecCompiler LIBS LibCpp LibMain LibXML LibCrypto)
|
||||||
target_include_directories(JSSpecCompiler PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
|
target_include_directories(JSSpecCompiler PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
target_compile_options(JSSpecCompiler PRIVATE -Wno-missing-field-initializers)
|
target_compile_options(JSSpecCompiler PRIVATE -Wno-missing-field-initializers)
|
||||||
|
|
|
@ -126,7 +126,8 @@ template<>
|
||||||
NullableTree CppASTConverter::convert_node(Cpp::NumericLiteral const& literal)
|
NullableTree CppASTConverter::convert_node(Cpp::NumericLiteral const& literal)
|
||||||
{
|
{
|
||||||
// TODO: Numerical literals are not limited to i64.
|
// TODO: Numerical literals are not limited to i64.
|
||||||
return make_ref_counted<MathematicalConstant>(literal.value().to_number<i64>().value());
|
VERIFY(literal.value().to_number<i64>().has_value());
|
||||||
|
return make_ref_counted<MathematicalConstant>(MUST(Crypto::BigFraction::from_string(literal.value())));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
|
|
|
@ -299,7 +299,7 @@ TextParseErrorOr<Tree> TextParser::parse_expression()
|
||||||
if (token.type == TokenType::Identifier) {
|
if (token.type == TokenType::Identifier) {
|
||||||
expression = make_ref_counted<UnresolvedReference>(token.data);
|
expression = make_ref_counted<UnresolvedReference>(token.data);
|
||||||
} else if (token.type == TokenType::Number) {
|
} else if (token.type == TokenType::Number) {
|
||||||
expression = make_ref_counted<MathematicalConstant>(token.data.to_number<i64>().value());
|
expression = make_ref_counted<MathematicalConstant>(MUST(Crypto::BigFraction::from_string(token.data)));
|
||||||
} else if (token.type == TokenType::String) {
|
} else if (token.type == TokenType::String) {
|
||||||
expression = make_ref_counted<StringLiteral>(token.data);
|
expression = make_ref_counted<StringLiteral>(token.data);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
<!DOCTYPE inline_dtd[<!ENTITY nbsp " ">]>
|
||||||
|
<specification>
|
||||||
|
<emu-clause id="1" aoid="ArbitrarilyLargeNumbers">
|
||||||
|
<h1><span class="secnum">1</span> ArbitrarilyLargeNumbers ( <var>a</var> )</h1>
|
||||||
|
<emu-alg>
|
||||||
|
<ol>
|
||||||
|
<li>Let <var>a</var> be 1.</li>
|
||||||
|
<li>Let <var>b</var> be 3.6.</li>
|
||||||
|
<li>Let <var>c</var> be -3.6.</li>
|
||||||
|
<li>Let <var>d</var> be -1000000000000000000000.</li>
|
||||||
|
<li>Let <var>e</var> be 1.0000001.</li>
|
||||||
|
<li>Return <var>a</var>+<var>b</var>+<var>c</var>+<var>d</var>+<var>e</var>.</li>
|
||||||
|
</ol>
|
||||||
|
</emu-alg>
|
||||||
|
</emu-clause>
|
||||||
|
</specification>
|
|
@ -0,0 +1,29 @@
|
||||||
|
===== AST after reference-resolving =====
|
||||||
|
ArbitrarilyLargeNumbers(a):
|
||||||
|
TreeList
|
||||||
|
BinaryOperation Assignment
|
||||||
|
Var a
|
||||||
|
MathematicalConstant 1
|
||||||
|
BinaryOperation Assignment
|
||||||
|
Var b
|
||||||
|
MathematicalConstant 3.6
|
||||||
|
BinaryOperation Assignment
|
||||||
|
Var c
|
||||||
|
MathematicalConstant -3.6
|
||||||
|
BinaryOperation Assignment
|
||||||
|
Var d
|
||||||
|
MathematicalConstant -1000000000000000000000
|
||||||
|
BinaryOperation Assignment
|
||||||
|
Var e
|
||||||
|
MathematicalConstant 10000001/10000000
|
||||||
|
ReturnNode
|
||||||
|
BinaryOperation Plus
|
||||||
|
Var a
|
||||||
|
BinaryOperation Plus
|
||||||
|
Var b
|
||||||
|
BinaryOperation Plus
|
||||||
|
Var c
|
||||||
|
BinaryOperation Plus
|
||||||
|
Var d
|
||||||
|
Var e
|
||||||
|
|
|
@ -50,6 +50,7 @@ const Array regression_tests = {
|
||||||
TestDescription {
|
TestDescription {
|
||||||
.sources = {
|
.sources = {
|
||||||
"spec-no-new-line-after-dot.xml"sv,
|
"spec-no-new-line-after-dot.xml"sv,
|
||||||
|
"spec-parsing.xml"sv,
|
||||||
"spec-single-function-simple.xml"sv,
|
"spec-single-function-simple.xml"sv,
|
||||||
},
|
},
|
||||||
.flags = { dump_after_frontend },
|
.flags = { dump_after_frontend },
|
||||||
|
|
|
@ -58,6 +58,9 @@ public:
|
||||||
ByteString to_byte_string(unsigned rounding_threshold) const;
|
ByteString to_byte_string(unsigned rounding_threshold) const;
|
||||||
double to_double() const;
|
double to_double() const;
|
||||||
|
|
||||||
|
Crypto::SignedBigInteger const& numerator() const& { return m_numerator; }
|
||||||
|
Crypto::UnsignedBigInteger const& denominator() const& { return m_denominator; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void reduce();
|
void reduce();
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue