Skip to content

Commit

Permalink
Merge pull request #46 from KQMATH/develop
Browse files Browse the repository at this point in the history
v1.3.0
  • Loading branch information
andstor authored Sep 21, 2019
2 parents dff9225 + f3e83a5 commit 4103c8a
Show file tree
Hide file tree
Showing 6 changed files with 171 additions and 31 deletions.
14 changes: 7 additions & 7 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "tex2max",
"version": "1.2.2",
"version": "1.3.0",
"description": "LaTeX math to Maxima code converter",
"main": "lib/tex2max.common.js",
"unpkg": "lib/tex2max.js",
Expand Down
20 changes: 20 additions & 0 deletions src/parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,22 @@ export function parseLatex(tokens) {
}
}

function parseDecimalSeparator() {
logger.debug('Parsing decimal number: ' + getCurrentChar());
let nextToken = peekType();
let previousStructureType = lookBack(1);

if (previousStructureType !== 'number') {
// TODO review if this should be allowed ".2" instead of "0.2".
throw new Error('Leading decimal separators are not allowed');
}

return {
type: 'decimal_separator',
value: consume(),
};
}

function parseWord() {
logger.debug('- Found letter \"' + getCurrentChar() + '\"');

Expand Down Expand Up @@ -503,6 +519,10 @@ export function parseLatex(tokens) {
logger.debug('Found NUMBER_LITERAL \"' + getCurrentChar() + '\"');
parsedResult = parseNumber();
break;
case TOKEN_TYPES.PERIOD:
logger.debug('Found PERIOD\"' + getCurrentChar() + '\"');
parsedResult = parseDecimalSeparator();
break;
case TOKEN_TYPES.BACKSLASH:
logger.debug('Found BACKSLASH \"' + getCurrentChar() + '\"');
parsedResult = handleBackslash();
Expand Down
90 changes: 67 additions & 23 deletions src/post-parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,10 @@ export function postParse(parsedLatex) {
logger.debug('Found bracket \"' + value + '\"');
node = parseGroup();
break;

case 'number':
logger.debug('Found number \"' + value + '\"');
node = parseNumber();
break;
default:
node = item;
break;
Expand Down Expand Up @@ -100,34 +103,24 @@ export function postParse(parsedLatex) {
}

function peekItem(position) {
return parsedLatex[index + position]
? parsedLatex[index + 1]
: null;
if (typeof parsedLatex[index + position] === 'undefined') {
return null;
}
return parsedLatex[index + position];
}

function peekType(position) {
return parsedLatex[index + position]
? parsedLatex[index + 1].type
: null;
if (typeof parsedLatex[index + position] === 'undefined') {
return null;
}
return parsedLatex[index + position].type;
}

function peekValue(position) {
return parsedLatex[index + position] ? parsedLatex[index +
position].value : null;
}

function lookBack(position) {
return parsedLatex[index - position];
}

function lookBackValue() {
let previousToken = parsedLatex[index - 1];
return previousToken ? previousToken.value : null;
}

function lookBackType(position) {
let previousToken = parsedLatex[index - position];
return previousToken ? previousToken.type : null;
if (typeof parsedLatex[index + position] === 'undefined') {
return null;
}
return parsedLatex[index + position].value;
}

function parseGroup() {
Expand All @@ -149,6 +142,57 @@ export function postParse(parsedLatex) {
};
}

function parseNumber() {
let node;

if (peekType(1) === 'decimal_separator') {
node = parseFloat();
} else {
node = getCurrentItem();
}
return node;
}

function parseFloat() {
let node;
let float;

if (decimalSeparatorQuantityInNumber() > 1) {
throw new Error('Only one decimal separator is allowed');
}

if (peekType(2) === 'number') {
logger.debug("- Found fractional part decimal part\"" + getCurrentValue() + "\", continuing parsing");
let decimal_separator = peekValue(1);
float = getCurrentValue() + decimal_separator + peekValue(2);

} else {
throw new Error('Trailing decimal separator isn\'t allowed');
}
index += 2;

node = {
type: 'number',
value: float,
};
return node;
}

function decimalSeparatorQuantityInNumber() {
let i = 0;
let isNumber = true;
let quantity = 0;
while (isNumber) {
if (peekType(i) === 'decimal_separator') {
quantity++;
} else if (peekType(i) !== 'number'){
isNumber = false
}
i++;
}
return quantity;
}

function parseDelimiter() {
let nodes = null;
let node, groupNode;
Expand Down
71 changes: 71 additions & 0 deletions src/tests/decimal.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/**
* @author André Storhaug <[email protected]>
* @copyright 2019 NTNU
*/

import test from 'ava';
import TeX2Max from '../index';

test.beforeEach(t => {
t.context.TeX2Max = new TeX2Max();
});

function transpilation(t, input, expected) {
let maximaCode = t.context.TeX2Max.toMaxima(input);
t.is(maximaCode, expected);
}
transpilation.title = (
providedTitle = '', input, expected) => `${providedTitle} ${input}`.trim();

function singleVars(t, input, expected) {
t.context.TeX2Max.updateOptions({
onlySingleVariables: true,
addTimesSign: true,
});
transpilation(t, input, expected);
}
singleVars.title = (
providedTitle = '', input,
expected) => `SingleVars: ${providedTitle} ${input}`.trim();

function transpilationError(t, input) {
t.throws(() => {
let maximaCode = t.context.TeX2Max.toMaxima(input);
}, Error);
}
transpilationError.title = (
providedTitle = '', input) => `${providedTitle} ${input}`.trim();


// Point type "." decimal numbers
test('Short point type decimal number with leading zero',
[transpilation, singleVars],
'0.2', '0.2');

test('Long point type decimal number with leading zero',
[transpilation, singleVars],
'1234.1234', '1234.1234');

test('Short point type decimal number with leading zero in simple function',
[transpilation, singleVars],
'\\sin(0.2)', 'sin(0.2)');

test('Long point type decimal number with leading zero in simple function',
[transpilation, singleVars],
'\\sin(1234.1234)', 'sin(1234.1234)');

test('point type decimal number with leading decimal separator that should throw an error',
[transpilationError],
'.2');

test('Point type decimal number with trailing decimal separator that should throw an error',
[transpilationError],
'.2');

test('Point type decimal number with more than one decimal separator that should throw an error',
[transpilationError],
'1.2.3');

test('Point type decimal number with trailing decimal separator in simple function that should throw an error',
[transpilationError],
'\\sin(.2)');
5 changes: 5 additions & 0 deletions src/tokens/tokens.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,11 @@ export const TOKEN_TYPES = {
symbol: null,
regex: /^[0-9]+$/i
},
PERIOD: {
name: "PERIOD",
symbol: ".",
regex: /^[.]$/
},
STRING_LITERAL: {
name: "STRING_LITERAL",
symbol: null,
Expand Down

0 comments on commit 4103c8a

Please sign in to comment.