Сообщение Re[15]: Простой скрипт внутри приложения (в виде строки) от 24.11.2021 13:06
Изменено 24.11.2021 13:16 Pauel
Re[15]: Простой скрипт внутри приложения (в виде строки)
Здравствуйте, Sinclair, Вы писали:
S>Эмм. А что там особенно извратного? Пишется всё примерно так же, как и слышится. Стоит один раз увидеть реализацию, как всё становится предельно очевидно. По одной продукции на приоритет:
S>
S>Всё. Вот вам выражения стремя четырьмя приоритетами, 7 операторов. Хотите, чтобы я дописал семантические действия? И сравним, что проще — Пратт или PEG.
А ты не мог бы выдать этот пег для сравнения?
Накидал recursive descent парсер, только мне пришлось изменить немного грамматику, а то у меня не хотело есть например 2+2+2+2+2. Не уверен, насколько это эквивалентно твоей
S>Эмм. А что там особенно извратного? Пишется всё примерно так же, как и слышится. Стоит один раз увидеть реализацию, как всё становится предельно очевидно. По одной продукции на приоритет:
S>
S>expr = add
S>add = mul '+' mul | mul '-' mul | mul
S>mul = power '*' power | power '/' power | power '%' power | power
S>power = atom '^' atom | atom
S>atom = number | var | '-' atom | '(' expr ')'
S>number = [0-9]+
S>var = [a-zA-Z][a-zA-Z0-9]*
S>
S>Всё. Вот вам выражения с
А ты не мог бы выдать этот пег для сравнения?
Накидал recursive descent парсер, только мне пришлось изменить немного грамматику, а то у меня не хотело есть например 2+2+2+2+2. Не уверен, насколько это эквивалентно твоей
/*
expr = add
add = mul (('+'|'-') mul)*
mul = power (('*'|'/'|'%') power)*
power = atom ('^' atom)*
atom = number | var | '-' atom | '(' expr ')'
number = [0-9]+
var = [a-zA-Z][a-zA-Z0-9]*
*/
const digit = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];
const letterLower = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'];
const letterUpper = letterLower.map(x => x.toUpperCase());
const letter = [...letterLower, ...letterUpper];
const letterOrDigit = [...letter, ...digit];
function parse(source) {
let currentPosition = 0;
function next(...tokens) {
const t = peek(...tokens);
if (t != null) {
currentPosition += t.length;
return t;
}
return null;
}
function peek(...tokens) {
for (const t of tokens) {
if (source.startsWith(t, currentPosition)) {
return t;
}
}
return null;
}
function revert(toPosition) {
currentPosition = toPosition;
}
function expr() {
return add();
}
function add() {
let left = mul();
while (true) {
let operator = next('+', '-');
if (operator == null) {
break;
}
const right = mul();
left = {type: 'add', operator, left, right};
}
return left;
}
function mul() {
let left = power();
while (true) {
let operator = next('*', '/', '%');
if (operator == null) {
break;
}
const right = power();
left = {type: 'mul', operator, left, right};
}
return left;
}
function power() {
let left = atom();
while (true) {
let operator = next('^');
if (operator == null) {
break;
}
const right = atom();
left = {type: 'power', operator, left, right};
}
return left;
}
function atom() {
return number() || variable() || negation() || grouping();
}
function grouping() {
const savePosition = currentPosition;
if (peek('(') == null) {
return null;
}
next('(');
const e = expr();
if (e == null) {
revert(savePosition);
return null;
}
if (next(')') == null) {
revert(savePosition);
}
return e;
}
function negation() {
if (peek('-')) {
next('-');
const right = atom();
return {type: 'negation', right};
}
return null;
}
function variable() {
const input = [];
const start = next(...letter);
if (start == null) {
return null;
}
input.push(start);
while (true) {
const x = next(...letterOrDigit);
if (x == null) {
break;
}
input.push(x);
}
return input.length === 0 ? null : {type: 'variable', name: input.join('')};
}
function number() {
const input = [];
while (true) {
const d = next(...digit);
if (d == null) {
break;
}
input.push(d);
}
return input.length === 0 ? null : {type: 'number', value: input.join('')};
}
return expr();
}
console.log(JSON.stringify(parse(process.argv[2]), null, 4));
Re[15]: Простой скрипт внутри приложения (в виде строки)
Здравствуйте, Sinclair, Вы писали:
S>Эмм. А что там особенно извратного? Пишется всё примерно так же, как и слышится. Стоит один раз увидеть реализацию, как всё становится предельно очевидно. По одной продукции на приоритет:
S>
S>Всё. Вот вам выражения стремя четырьмя приоритетами, 7 операторов. Хотите, чтобы я дописал семантические действия? И сравним, что проще — Пратт или PEG.
А ты не мог бы выдать этот пег для сравнения?
Накидал recursive descent парсер, только мне пришлось изменить немного грамматику, а то у меня не хотело есть например 2+2+2+2+2. Не уверен, насколько это эквивалентно твоей
S>Эмм. А что там особенно извратного? Пишется всё примерно так же, как и слышится. Стоит один раз увидеть реализацию, как всё становится предельно очевидно. По одной продукции на приоритет:
S>
S>expr = add
S>add = mul '+' mul | mul '-' mul | mul
S>mul = power '*' power | power '/' power | power '%' power | power
S>power = atom '^' atom | atom
S>atom = number | var | '-' atom | '(' expr ')'
S>number = [0-9]+
S>var = [a-zA-Z][a-zA-Z0-9]*
S>
S>Всё. Вот вам выражения с
А ты не мог бы выдать этот пег для сравнения?
Накидал recursive descent парсер, только мне пришлось изменить немного грамматику, а то у меня не хотело есть например 2+2+2+2+2. Не уверен, насколько это эквивалентно твоей
/*
expr = add
add = mul (('+'|'-') mul)*
mul = power (('*'|'/'|'%') power)*
power = atom ('^' atom)*
atom = number | var | '-' atom | '(' expr ')'
number = [0-9]+
var = [a-zA-Z][a-zA-Z0-9]*
*/
const digit = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];
const letterLower = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'];
const letterUpper = letterLower.map(x => x.toUpperCase());
const letter = [...letterLower, ...letterUpper];
const letterOrDigit = [...letter, ...digit];
function parse(source) {
let currentPosition = 0;
function next(...tokens) {
const t = peek(...tokens);
if (t != null) {
currentPosition += t.length;
return t;
}
return null;
}
function peek(...tokens) {
for (const t of tokens) {
if (source.startsWith(t, currentPosition)) {
return t;
}
}
return null;
}
function revert(toPosition) {
currentPosition = toPosition;
}
function expr() {
return add();
}
function add() {
const savePosition = currentPosition;
let left = mul();
while (true) {
let operator = next('+', '-');
if (operator == null) {
break;
}
const right = mul();
if (right == null) {
revert(savePosition);
return null;
}
left = {type: 'add', operator, left, right};
}
return left;
}
function mul() {
const savePosition = currentPosition;
let left = power();
while (true) {
let operator = next('*', '/', '%');
if (operator == null) {
break;
}
const right = power();
if (right == null) {
revert(savePosition);
return null;
}
left = {type: 'mul', operator, left, right};
}
return left;
}
function power() {
const savePosition = currentPosition;
let left = atom();
while (true) {
let operator = next('^');
if (operator == null) {
break;
}
const right = atom();
if (right == null) {
revert(savePosition);
return null;
}
left = {type: 'power', operator, left, right};
}
return left;
}
function atom() {
return number() || variable() || negation() || grouping();
}
function grouping() {
const savePosition = currentPosition;
if (peek('(') == null) {
return null;
}
next('(');
const e = expr();
if (e == null) {
revert(savePosition);
return null;
}
if (next(')') == null) {
revert(savePosition);
}
return e;
}
function negation() {
if (peek('-')) {
next('-');
const right = atom();
return {type: 'negation', right};
}
return null;
}
function variable() {
const input = [];
const start = next(...letter);
if (start == null) {
return null;
}
input.push(start);
while (true) {
const x = next(...letterOrDigit);
if (x == null) {
break;
}
input.push(x);
}
return input.length === 0 ? null : {type: 'variable', name: input.join('')};
}
function number() {
const input = [];
while (true) {
const d = next(...digit);
if (d == null) {
break;
}
input.push(d);
}
return input.length === 0 ? null : {type: 'number', value: input.join('')};
}
return expr();
}
console.log(JSON.stringify(parse(process.argv[2]), null, 4));