Введение

Документ подробно описывает API для построения LR-автоматов по заданной грамматике. Интерактивную страницу OpenAPI спецификации можно посмотреть здесь.

API является версионируемым. Версия задается в пути запроса (во 2 сегменте).

POST api/{v1+}/build/lr0 (json)

Строит LR(0)-автомат. Результат возвращает в формате json.

Заголовки запроса

Имя Описание

Accept

application/json

Параметры пути

Имя Описание

version

версия API

Тело запроса

Поле Тип Обязательное Описание

.grammar

Object

Да

Грамматика, по которой требуется построить LR-автомат

.grammar.terminals

Array

Да

Список терминалов грамматики.

.grammar.nonTerminals

Array

Да

Список нетерминалов грамматики

.grammar.rules

Array

Да

Список правил грамматики

.grammar.rules[].left

String

Да

Нетерминал левой части правила грамматики

.grammar.rules[].right

String

Да

Символы правой части правила грамматики

.grammar.startSymbol

String

Да

Аксиома грамматики (нетерминал)

.buildOptions

Object

Нет

Параметры построения LR-автомата

.buildOptions.namesGenerationStrategy

String

Нет

Стратегия генерации имен состояний при построении автомата

.buildOptions.enableBuildLog

Boolean

Нет

Передавать ли в ответе лог построения

Заголовки ответа

Имя Описание

Content-Type

application/json

Тело ответа

Поле Тип Обязательное Описание

.automaton

Object

Да

Построенный LR-автомат

.automaton.states

Array

Да

Состояния автомата

.automaton.states[].name

String

Да

Имя состояния

.automaton.states[].items

Array

Да

LR(0)-пункты в состоянии

.automaton.states[].items[].rule

Object

Да

Правило грамматики пункта

.automaton.states[].items[].rule.left

String

Да

Левая часть правила

.automaton.states[].items[].rule.right

String

Да

Правая часть правила

.automaton.states[].items[].dotIndex

Number

Да

Позиция точки в правой части правила

.automaton.transitions

Array

Да

Переходы между состояниями автомата

.automaton.transitions[].from

String

Да

Исходное состояние

.automaton.transitions[].to

String

Да

Целевое состояние

.automaton.transitions[].through

String

Да

Символ перехода

.buildLog

Object

Нет

Лог построения LR-автомата (если указана соответствующая опция)

.buildLog.operations

Array

Да

Последовательность операций построения

.buildLog.operations[].message

String

Да

Человекочитаемое описание операции

.buildLog.operations[].level

String

Да

Тип операции

.buildLog.operations[].name

String

Да

Имя операции

.buildLog.operations[].stateName

String

Нет

Имя состояния

.buildLog.operations[].state

String

Нет

Состояние, к которому применяется операция

.buildLog.operations[].item

Object

Нет

LR-пункт, связанный с операцией

.buildLog.operations[].item.rule.left

String

Нет

Левая часть правила пункта

.buildLog.operations[].item.rule.right

String

Нет

Правая часть правила пункта

.buildLog.operations[].item.dotIndex

Number

Нет

Позиция точки

.buildLog.operations[].from

String

Нет

Исходное состояние перехода

.buildLog.operations[].to

String

Нет

Целевое состояние перехода

.buildLog.operations[].through

String

Нет

Символ перехода

curl

$ curl 'http://localhost:8080/api/v1/build/lr0' -i -X POST \
    -H 'Content-Type: application/json' \
    -H 'Accept: application/json' \
    -d '{
  "grammar" : {
    "terminals" : [ "(", ")" ],
    "nonTerminals" : [ "S" ],
    "rules" : [ {
      "left" : "S",
      "right" : "(S)"
    }, {
      "left" : "S",
      "right" : ""
    } ],
    "startSymbol" : "S"
  },
  "buildOptions" : {
    "enableBuildLog" : true
  }
}'
Примеры

Пример запроса

POST /api/v1/build/lr0 HTTP/1.1
Content-Type: application/json
Accept: application/json
Content-Length: 280
Host: localhost:8080

{
  "grammar" : {
    "terminals" : [ "(", ")" ],
    "nonTerminals" : [ "S" ],
    "rules" : [ {
      "left" : "S",
      "right" : "(S)"
    }, {
      "left" : "S",
      "right" : ""
    } ],
    "startSymbol" : "S"
  },
  "buildOptions" : {
    "enableBuildLog" : true
  }
}

Пример ответа

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 7577

{
  "automaton" : {
    "states" : [ {
      "name" : "S1",
      "items" : [ {
        "rule" : {
          "left" : "S'",
          "right" : "S"
        },
        "dotIndex" : 1
      } ]
    }, {
      "name" : "S2",
      "items" : [ {
        "rule" : {
          "left" : "S",
          "right" : "(S)"
        },
        "dotIndex" : 2
      } ]
    }, {
      "name" : "(1",
      "items" : [ {
        "rule" : {
          "left" : "S",
          "right" : "(S)"
        },
        "dotIndex" : 1
      }, {
        "rule" : {
          "left" : "S",
          "right" : ""
        },
        "dotIndex" : 0
      }, {
        "rule" : {
          "left" : "S",
          "right" : "(S)"
        },
        "dotIndex" : 0
      } ]
    }, {
      "name" : ")1",
      "items" : [ {
        "rule" : {
          "left" : "S",
          "right" : "(S)"
        },
        "dotIndex" : 3
      } ]
    }, {
      "name" : "∇",
      "items" : [ {
        "rule" : {
          "left" : "S'",
          "right" : "S"
        },
        "dotIndex" : 0
      }, {
        "rule" : {
          "left" : "S",
          "right" : ""
        },
        "dotIndex" : 0
      }, {
        "rule" : {
          "left" : "S",
          "right" : "(S)"
        },
        "dotIndex" : 0
      } ]
    } ],
    "transitions" : [ {
      "from" : "(1",
      "to" : "S2",
      "through" : "S"
    }, {
      "from" : "∇",
      "to" : "S1",
      "through" : "S"
    }, {
      "from" : "S2",
      "to" : ")1",
      "through" : ")"
    }, {
      "from" : "(1",
      "to" : "(1",
      "through" : "("
    }, {
      "from" : "∇",
      "to" : "(1",
      "through" : "("
    } ]
  },
  "buildLog" : {
    "operations" : [ {
      "message" : "Построим LR-автомат lr(0)",
      "level" : "comment",
      "name" : "buildLrAutomaton"
    }, {
      "message" : "Расширяем исходную грамматику.",
      "level" : "comment",
      "name" : "extendGrammar"
    }, {
      "message" : "Добавляем состояние '∇'.",
      "stateName" : "∇",
      "level" : "action",
      "name" : "addState"
    }, {
      "message" : "Добавляем в состояние '∇' пункт '[S'→•S]'.",
      "state" : "∇",
      "item" : {
        "rule" : {
          "left" : "S'",
          "right" : "S"
        },
        "dotIndex" : 0
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем в состояние '∇' пункт '[S→•]'.",
      "state" : "∇",
      "item" : {
        "rule" : {
          "left" : "S",
          "right" : ""
        },
        "dotIndex" : 0
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем в состояние '∇' пункт '[S→•(S)]'.",
      "state" : "∇",
      "item" : {
        "rule" : {
          "left" : "S",
          "right" : "(S)"
        },
        "dotIndex" : 0
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Просматриваем состояние '∇'",
      "level" : "comment",
      "name" : "startAddNewTransitions"
    }, {
      "message" : "Добавляем состояние 'S1'.",
      "stateName" : "S1",
      "level" : "action",
      "name" : "addState"
    }, {
      "message" : "Добавляем в состояние 'S1' пункт '[S'→S•]'.",
      "state" : "S1",
      "item" : {
        "rule" : {
          "left" : "S'",
          "right" : "S"
        },
        "dotIndex" : 1
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем переход из состояния '∇' в состояние 'S1' по символу 'S'.",
      "from" : "∇",
      "to" : "S1",
      "through" : "S",
      "level" : "action",
      "name" : "addTransition"
    }, {
      "message" : "Добавляем состояние '(1'.",
      "stateName" : "(1",
      "level" : "action",
      "name" : "addState"
    }, {
      "message" : "Добавляем в состояние '(1' пункт '[S→(•S)]'.",
      "state" : "(1",
      "item" : {
        "rule" : {
          "left" : "S",
          "right" : "(S)"
        },
        "dotIndex" : 1
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем в состояние '(1' пункт '[S→•]'.",
      "state" : "(1",
      "item" : {
        "rule" : {
          "left" : "S",
          "right" : ""
        },
        "dotIndex" : 0
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем в состояние '(1' пункт '[S→•(S)]'.",
      "state" : "(1",
      "item" : {
        "rule" : {
          "left" : "S",
          "right" : "(S)"
        },
        "dotIndex" : 0
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем переход из состояния '∇' в состояние '(1' по символу '('.",
      "from" : "∇",
      "to" : "(1",
      "through" : "(",
      "level" : "action",
      "name" : "addTransition"
    }, {
      "message" : "Просматриваем состояние 'S1'",
      "level" : "comment",
      "name" : "startAddNewTransitions"
    }, {
      "message" : "Просматриваем состояние '(1'",
      "level" : "comment",
      "name" : "startAddNewTransitions"
    }, {
      "message" : "Добавляем состояние 'S2'.",
      "stateName" : "S2",
      "level" : "action",
      "name" : "addState"
    }, {
      "message" : "Добавляем в состояние 'S2' пункт '[S→(S•)]'.",
      "state" : "S2",
      "item" : {
        "rule" : {
          "left" : "S",
          "right" : "(S)"
        },
        "dotIndex" : 2
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем переход из состояния '(1' в состояние 'S2' по символу 'S'.",
      "from" : "(1",
      "to" : "S2",
      "through" : "S",
      "level" : "action",
      "name" : "addTransition"
    }, {
      "message" : "Добавляем переход из состояния '(1' в состояние '(1' по символу '('.",
      "from" : "(1",
      "to" : "(1",
      "through" : "(",
      "level" : "action",
      "name" : "addTransition"
    }, {
      "message" : "Просматриваем состояние 'S2'",
      "level" : "comment",
      "name" : "startAddNewTransitions"
    }, {
      "message" : "Добавляем состояние ')1'.",
      "stateName" : ")1",
      "level" : "action",
      "name" : "addState"
    }, {
      "message" : "Добавляем в состояние ')1' пункт '[S→(S)•]'.",
      "state" : ")1",
      "item" : {
        "rule" : {
          "left" : "S",
          "right" : "(S)"
        },
        "dotIndex" : 3
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем переход из состояния 'S2' в состояние ')1' по символу ')'.",
      "from" : "S2",
      "to" : ")1",
      "through" : ")",
      "level" : "action",
      "name" : "addTransition"
    }, {
      "message" : "Просматриваем состояние ')1'",
      "level" : "comment",
      "name" : "startAddNewTransitions"
    } ]
  }
}

POST api/{v1+}/build/lr0 (png)

Строит LR(0)-автомат. Результат возвращает в формате png.

Заголовки запроса

Имя Описание

Accept

image/png

Параметры пути

Имя Описание

version

версия API

Тело запроса

Поле Тип Обязательное Описание

.grammar

Object

Да

Грамматика, по которой требуется построить LR-автомат

.grammar.terminals

Array

Да

Список терминалов грамматики.

.grammar.nonTerminals

Array

Да

Список нетерминалов грамматики

.grammar.rules

Array

Да

Список правил грамматики

.grammar.rules[].left

String

Да

Нетерминал левой части правила грамматики

.grammar.rules[].right

String

Да

Символы правой части правила грамматики

.grammar.startSymbol

String

Да

Аксиома грамматики (нетерминал)

.buildOptions

Object

Нет

Параметры построения LR-автомата

.buildOptions.namesGenerationStrategy

String

Нет

Стратегия генерации имен состояний при построении автомата

visualizeOperations.colorizeTransitions

Boolean

Нет

Нужно ли окрашивать переходы автомата. По умолчанию не окрашиваются.

visualizeOperations.colorizeStateNames

Boolean

Нет

Окрашивать ли имена состояний. По умолчанию не окрашиваются.

visualizeOperations.stateNameStyle

String

Нет

Стиль оформления названия состояния. По умолчанию 'onBlackBackground'.

Заголовки ответа

Имя Описание

Content-Type

image/png

curl

$ curl 'http://localhost:8080/api/v1/build/lr0' -i -X POST \
    -H 'Content-Type: application/json' \
    -H 'Accept: image/png' \
    -d '{
  "grammar" : {
    "terminals" : [ "a", "b", "c", "d" ],
    "nonTerminals" : [ "S", "A" ],
    "rules" : [ {
      "left" : "S",
      "right" : "Aa"
    }, {
      "left" : "S",
      "right" : "bAc"
    }, {
      "left" : "S",
      "right" : "bc"
    }, {
      "left" : "S",
      "right" : "bda"
    }, {
      "left" : "A",
      "right" : "d"
    } ],
    "startSymbol" : "S"
  }
}'

Пример запроса

POST /api/v1/build/lr0 HTTP/1.1
Content-Type: application/json
Accept: image/png
Content-Length: 393
Host: localhost:8080

{
  "grammar" : {
    "terminals" : [ "a", "b", "c", "d" ],
    "nonTerminals" : [ "S", "A" ],
    "rules" : [ {
      "left" : "S",
      "right" : "Aa"
    }, {
      "left" : "S",
      "right" : "bAc"
    }, {
      "left" : "S",
      "right" : "bc"
    }, {
      "left" : "S",
      "right" : "bda"
    }, {
      "left" : "A",
      "right" : "d"
    } ],
    "startSymbol" : "S"
  }
}

Пример ответа

Пример построения lr(0)

POST api/{v1+}/build/lr0 (zip)

Строит LR(0)-автомат. Лог построения возвращает в zip архиве с изображениями автомата.

Заголовки запроса

Имя Описание

Accept

application/octet-stream

Параметры пути

Имя Описание

version

версия API

Тело запроса

Поле Тип Обязательное Описание

.grammar

Object

Да

Грамматика, по которой требуется построить LR-автомат

.grammar.terminals

Array

Да

Список терминалов грамматики.

.grammar.nonTerminals

Array

Да

Список нетерминалов грамматики

.grammar.rules

Array

Да

Список правил грамматики

.grammar.rules[].left

String

Да

Нетерминал левой части правила грамматики

.grammar.rules[].right

String

Да

Символы правой части правила грамматики

.grammar.startSymbol

String

Да

Аксиома грамматики (нетерминал)

.buildOptions

Object

Нет

Параметры построения LR-автомата

.buildOptions.namesGenerationStrategy

String

Нет

Стратегия генерации имен состояний при построении автомата

visualizeOperations.visualizeOperations

Array

Нет

Номера операций, которые нужно визуализировать. Если не указаны, то визуализируются все операции

visualizeOperations.colorizeTransitions

Boolean

Нет

Нужно ли окрашивать переходы автомата. По умолчанию не окрашиваются.

visualizeOperations.colorizeStateNames

Boolean

Нет

Окрашивать ли имена состояний. По умолчанию не окрашиваются.

visualizeOperations.stateNameStyle

String

Нет

Стиль оформления названия состояния. По умолчанию 'onBlackBackground'.

Заголовки ответа

Имя Описание

Content-Type

application/octet-stream (zip)

curl

$ curl 'http://localhost:8080/api/v1/build/lr0' -i -X POST \
    -H 'Content-Type: application/json' \
    -H 'Accept: application/octet-stream' \
    -d '{
  "grammar" : {
    "terminals" : [ "u", "z", "v", "w", "y", "x" ],
    "nonTerminals" : [ "S", "B", "D", "E", "F" ],
    "rules" : [ {
      "left" : "S",
      "right" : "uBDz"
    }, {
      "left" : "B",
      "right" : "Bv"
    }, {
      "left" : "B",
      "right" : "w"
    }, {
      "left" : "D",
      "right" : "EF"
    }, {
      "left" : "E",
      "right" : "y"
    }, {
      "left" : "E",
      "right" : ""
    }, {
      "left" : "F",
      "right" : "x"
    }, {
      "left" : "F",
      "right" : ""
    } ],
    "startSymbol" : "S"
  }
}'

Пример запроса

POST /api/v1/build/lr0 HTTP/1.1
Content-Type: application/json
Accept: application/octet-stream
Content-Length: 562
Host: localhost:8080

{
  "grammar" : {
    "terminals" : [ "u", "z", "v", "w", "y", "x" ],
    "nonTerminals" : [ "S", "B", "D", "E", "F" ],
    "rules" : [ {
      "left" : "S",
      "right" : "uBDz"
    }, {
      "left" : "B",
      "right" : "Bv"
    }, {
      "left" : "B",
      "right" : "w"
    }, {
      "left" : "D",
      "right" : "EF"
    }, {
      "left" : "E",
      "right" : "y"
    }, {
      "left" : "E",
      "right" : ""
    }, {
      "left" : "F",
      "right" : "x"
    }, {
      "left" : "F",
      "right" : ""
    } ],
    "startSymbol" : "S"
  }
}

POST api/{v1+}/build/lalr1 (json)

Строит LALR(1)-автомат. Результат возвращает в формате json.

Заголовки запроса

Имя Описание

Accept

application/json

Параметры пути

Имя Описание

version

версия API

Тело запроса

Поле Тип Обязательное Описание

.grammar

Object

Да

Грамматика, по которой требуется построить LR-автомат

.grammar.terminals

Array

Да

Список терминалов грамматики.

.grammar.nonTerminals

Array

Да

Список нетерминалов грамматики

.grammar.rules

Array

Да

Список правил грамматики

.grammar.rules[].left

String

Да

Нетерминал левой части правила грамматики

.grammar.rules[].right

String

Да

Символы правой части правила грамматики

.grammar.startSymbol

String

Да

Аксиома грамматики (нетерминал)

.buildOptions

Object

Нет

Параметры построения LR-автомата

.buildOptions.namesGenerationStrategy

String

Нет

Стратегия генерации имен состояний при построении автомата

.buildOptions.lalr1BuildAlgorithm

String

Нет

Алгоритм построения LALR(1)-автомата

.buildOptions.enableBuildLog

Boolean

Нет

Передавать ли в ответе лог построения

Заголовки ответа

Имя Описание

Content-Type

application/json

Тело ответа

Поле Тип Обязательное Описание

.automaton

Object

Да

Построенный LR-автомат

.automaton.states

Array

Да

Состояния автомата

.automaton.states[].name

String

Да

Имя состояния

.automaton.states[].items

Array

Да

LR(0)-пункты в состоянии

.automaton.states[].items[].rule

Object

Да

Правило грамматики пункта

.automaton.states[].items[].rule.left

String

Да

Левая часть правила

.automaton.states[].items[].rule.right

String

Да

Правая часть правила

.automaton.states[].items[].dotIndex

Number

Да

Позиция точки в правой части правила

.automaton.transitions

Array

Да

Переходы между состояниями автомата

.automaton.transitions[].from

String

Да

Исходное состояние

.automaton.transitions[].to

String

Да

Целевое состояние

.automaton.transitions[].through

String

Да

Символ перехода

.buildLog

Object

Нет

Лог построения LR-автомата (если указана соответствующая опция)

.buildLog.operations

Array

Да

Последовательность операций построения

.buildLog.operations[].message

String

Да

Человекочитаемое описание операции

.buildLog.operations[].level

String

Да

Тип операции

.buildLog.operations[].name

String

Да

Имя операции

.buildLog.operations[].stateName

String

Нет

Имя состояния

.buildLog.operations[].state

String

Нет

Состояние, к которому применяется операция

.buildLog.operations[].item

Object

Нет

LR-пункт, связанный с операцией

.buildLog.operations[].item.rule.left

String

Нет

Левая часть правила пункта

.buildLog.operations[].item.rule.right

String

Нет

Правая часть правила пункта

.buildLog.operations[].item.dotIndex

Number

Нет

Позиция точки

.buildLog.operations[].from

String

Нет

Исходное состояние перехода

.buildLog.operations[].to

String

Нет

Целевое состояние перехода

.buildLog.operations[].through

String

Нет

Символ перехода

.automaton.states[].items[].lookAheadSymbol

String

Нет

Символ предпросмотра

.buildLog.operations[].item.lookAheadSymbol

String

Нет

Символ предпросмотра

.automaton.states[].items[].lookAheadSymbols

Array

Нет

Символы предпросмотра (при построении через канальный алгоритм)

curl

$ curl 'http://localhost:8080/api/v1/build/lalr1' -i -X POST \
    -H 'Content-Type: application/json' \
    -H 'Accept: application/json' \
    -d '{
  "grammar" : {
    "terminals" : [ "x", "*", "=" ],
    "nonTerminals" : [ "S", "L", "R" ],
    "rules" : [ {
      "left" : "S",
      "right" : "L=R"
    }, {
      "left" : "S",
      "right" : "R"
    }, {
      "left" : "L",
      "right" : "*R"
    }, {
      "left" : "L",
      "right" : "x"
    }, {
      "left" : "R",
      "right" : "L"
    } ],
    "startSymbol" : "S"
  },
  "buildOptions" : {
    "enableBuildLog" : true
  }
}'
Примеры

Пример запроса

POST /api/v1/build/lalr1 HTTP/1.1
Content-Type: application/json
Accept: application/json
Content-Length: 444
Host: localhost:8080

{
  "grammar" : {
    "terminals" : [ "x", "*", "=" ],
    "nonTerminals" : [ "S", "L", "R" ],
    "rules" : [ {
      "left" : "S",
      "right" : "L=R"
    }, {
      "left" : "S",
      "right" : "R"
    }, {
      "left" : "L",
      "right" : "*R"
    }, {
      "left" : "L",
      "right" : "x"
    }, {
      "left" : "R",
      "right" : "L"
    } ],
    "startSymbol" : "S"
  },
  "buildOptions" : {
    "enableBuildLog" : true
  }
}

Пример ответа

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 41323

{
  "automaton" : {
    "states" : [ {
      "name" : "R3",
      "items" : [ {
        "rule" : {
          "left" : "S",
          "right" : "L=R"
        },
        "dotIndex" : 3,
        "lookAheadSymbol" : "⊣"
      } ]
    }, {
      "name" : "=1",
      "items" : [ {
        "rule" : {
          "left" : "S",
          "right" : "L=R"
        },
        "dotIndex" : 2,
        "lookAheadSymbol" : "⊣"
      }, {
        "rule" : {
          "left" : "R",
          "right" : "L"
        },
        "dotIndex" : 0,
        "lookAheadSymbol" : "⊣"
      }, {
        "rule" : {
          "left" : "L",
          "right" : "*R"
        },
        "dotIndex" : 0,
        "lookAheadSymbol" : "⊣"
      }, {
        "rule" : {
          "left" : "L",
          "right" : "x"
        },
        "dotIndex" : 0,
        "lookAheadSymbol" : "⊣"
      } ]
    }, {
      "name" : "L1",
      "items" : [ {
        "rule" : {
          "left" : "S",
          "right" : "L=R"
        },
        "dotIndex" : 1,
        "lookAheadSymbol" : "⊣"
      }, {
        "rule" : {
          "left" : "R",
          "right" : "L"
        },
        "dotIndex" : 1,
        "lookAheadSymbol" : "⊣"
      } ]
    }, {
      "name" : "R2;R4",
      "items" : [ {
        "rule" : {
          "left" : "L",
          "right" : "*R"
        },
        "dotIndex" : 2,
        "lookAheadSymbol" : "="
      }, {
        "rule" : {
          "left" : "L",
          "right" : "*R"
        },
        "dotIndex" : 2,
        "lookAheadSymbol" : "⊣"
      } ]
    }, {
      "name" : "∇",
      "items" : [ {
        "rule" : {
          "left" : "S'",
          "right" : "S"
        },
        "dotIndex" : 0,
        "lookAheadSymbol" : "⊣"
      }, {
        "rule" : {
          "left" : "S",
          "right" : "R"
        },
        "dotIndex" : 0,
        "lookAheadSymbol" : "⊣"
      }, {
        "rule" : {
          "left" : "S",
          "right" : "L=R"
        },
        "dotIndex" : 0,
        "lookAheadSymbol" : "⊣"
      }, {
        "rule" : {
          "left" : "R",
          "right" : "L"
        },
        "dotIndex" : 0,
        "lookAheadSymbol" : "⊣"
      }, {
        "rule" : {
          "left" : "L",
          "right" : "x"
        },
        "dotIndex" : 0,
        "lookAheadSymbol" : "="
      }, {
        "rule" : {
          "left" : "L",
          "right" : "*R"
        },
        "dotIndex" : 0,
        "lookAheadSymbol" : "="
      }, {
        "rule" : {
          "left" : "L",
          "right" : "*R"
        },
        "dotIndex" : 0,
        "lookAheadSymbol" : "⊣"
      }, {
        "rule" : {
          "left" : "L",
          "right" : "x"
        },
        "dotIndex" : 0,
        "lookAheadSymbol" : "⊣"
      } ]
    }, {
      "name" : "L2;L3",
      "items" : [ {
        "rule" : {
          "left" : "R",
          "right" : "L"
        },
        "dotIndex" : 1,
        "lookAheadSymbol" : "⊣"
      }, {
        "rule" : {
          "left" : "R",
          "right" : "L"
        },
        "dotIndex" : 1,
        "lookAheadSymbol" : "="
      } ]
    }, {
      "name" : "*1;*2",
      "items" : [ {
        "rule" : {
          "left" : "L",
          "right" : "*R"
        },
        "dotIndex" : 1,
        "lookAheadSymbol" : "⊣"
      }, {
        "rule" : {
          "left" : "L",
          "right" : "*R"
        },
        "dotIndex" : 1,
        "lookAheadSymbol" : "="
      }, {
        "rule" : {
          "left" : "R",
          "right" : "L"
        },
        "dotIndex" : 0,
        "lookAheadSymbol" : "⊣"
      }, {
        "rule" : {
          "left" : "R",
          "right" : "L"
        },
        "dotIndex" : 0,
        "lookAheadSymbol" : "="
      }, {
        "rule" : {
          "left" : "L",
          "right" : "*R"
        },
        "dotIndex" : 0,
        "lookAheadSymbol" : "⊣"
      }, {
        "rule" : {
          "left" : "L",
          "right" : "x"
        },
        "dotIndex" : 0,
        "lookAheadSymbol" : "⊣"
      }, {
        "rule" : {
          "left" : "L",
          "right" : "x"
        },
        "dotIndex" : 0,
        "lookAheadSymbol" : "="
      }, {
        "rule" : {
          "left" : "L",
          "right" : "*R"
        },
        "dotIndex" : 0,
        "lookAheadSymbol" : "="
      } ]
    }, {
      "name" : "x1;x2",
      "items" : [ {
        "rule" : {
          "left" : "L",
          "right" : "x"
        },
        "dotIndex" : 1,
        "lookAheadSymbol" : "⊣"
      }, {
        "rule" : {
          "left" : "L",
          "right" : "x"
        },
        "dotIndex" : 1,
        "lookAheadSymbol" : "="
      } ]
    }, {
      "name" : "S1",
      "items" : [ {
        "rule" : {
          "left" : "S'",
          "right" : "S"
        },
        "dotIndex" : 1,
        "lookAheadSymbol" : "⊣"
      } ]
    }, {
      "name" : "R1",
      "items" : [ {
        "rule" : {
          "left" : "S",
          "right" : "R"
        },
        "dotIndex" : 1,
        "lookAheadSymbol" : "⊣"
      } ]
    } ],
    "transitions" : [ {
      "from" : "∇",
      "to" : "L1",
      "through" : "L"
    }, {
      "from" : "=1",
      "to" : "x1;x2",
      "through" : "x"
    }, {
      "from" : "*1;*2",
      "to" : "x1;x2",
      "through" : "x"
    }, {
      "from" : "∇",
      "to" : "*1;*2",
      "through" : "*"
    }, {
      "from" : "∇",
      "to" : "S1",
      "through" : "S"
    }, {
      "from" : "*1;*2",
      "to" : "L2;L3",
      "through" : "L"
    }, {
      "from" : "∇",
      "to" : "R1",
      "through" : "R"
    }, {
      "from" : "*1;*2",
      "to" : "R2;R4",
      "through" : "R"
    }, {
      "from" : "∇",
      "to" : "x1;x2",
      "through" : "x"
    }, {
      "from" : "=1",
      "to" : "*1;*2",
      "through" : "*"
    }, {
      "from" : "*1;*2",
      "to" : "*1;*2",
      "through" : "*"
    }, {
      "from" : "=1",
      "to" : "L2;L3",
      "through" : "L"
    }, {
      "from" : "L1",
      "to" : "=1",
      "through" : "="
    }, {
      "from" : "=1",
      "to" : "R3",
      "through" : "R"
    } ]
  },
  "buildLog" : {
    "operations" : [ {
      "message" : "Построим LR-автомат lalr(1)",
      "level" : "comment",
      "name" : "buildLrAutomaton"
    }, {
      "message" : "Построим LR-автомат lr(1)",
      "level" : "comment",
      "name" : "buildLrAutomaton"
    }, {
      "message" : "Расширяем исходную грамматику.",
      "level" : "comment",
      "name" : "extendGrammar"
    }, {
      "message" : "Добавляем состояние '∇'.",
      "stateName" : "∇",
      "level" : "action",
      "name" : "addState"
    }, {
      "message" : "Добавляем в состояние '∇' пункт '[S'→•S, ⊣]'.",
      "state" : "∇",
      "item" : {
        "rule" : {
          "left" : "S'",
          "right" : "S"
        },
        "dotIndex" : 0,
        "lookAheadSymbol" : "⊣"
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем в состояние '∇' пункт '[S→•R, ⊣]'.",
      "state" : "∇",
      "item" : {
        "rule" : {
          "left" : "S",
          "right" : "R"
        },
        "dotIndex" : 0,
        "lookAheadSymbol" : "⊣"
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем в состояние '∇' пункт '[S→•L=R, ⊣]'.",
      "state" : "∇",
      "item" : {
        "rule" : {
          "left" : "S",
          "right" : "L=R"
        },
        "dotIndex" : 0,
        "lookAheadSymbol" : "⊣"
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем в состояние '∇' пункт '[R→•L, ⊣]'.",
      "state" : "∇",
      "item" : {
        "rule" : {
          "left" : "R",
          "right" : "L"
        },
        "dotIndex" : 0,
        "lookAheadSymbol" : "⊣"
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем в состояние '∇' пункт '[L→•x, =]'.",
      "state" : "∇",
      "item" : {
        "rule" : {
          "left" : "L",
          "right" : "x"
        },
        "dotIndex" : 0,
        "lookAheadSymbol" : "="
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем в состояние '∇' пункт '[L→•*R, =]'.",
      "state" : "∇",
      "item" : {
        "rule" : {
          "left" : "L",
          "right" : "*R"
        },
        "dotIndex" : 0,
        "lookAheadSymbol" : "="
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем в состояние '∇' пункт '[L→•*R, ⊣]'.",
      "state" : "∇",
      "item" : {
        "rule" : {
          "left" : "L",
          "right" : "*R"
        },
        "dotIndex" : 0,
        "lookAheadSymbol" : "⊣"
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем в состояние '∇' пункт '[L→•x, ⊣]'.",
      "state" : "∇",
      "item" : {
        "rule" : {
          "left" : "L",
          "right" : "x"
        },
        "dotIndex" : 0,
        "lookAheadSymbol" : "⊣"
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Просматриваем состояние '∇'",
      "level" : "comment",
      "name" : "startAddNewTransitions"
    }, {
      "message" : "Добавляем состояние 'S1'.",
      "stateName" : "S1",
      "level" : "action",
      "name" : "addState"
    }, {
      "message" : "Добавляем в состояние 'S1' пункт '[S'→S•, ⊣]'.",
      "state" : "S1",
      "item" : {
        "rule" : {
          "left" : "S'",
          "right" : "S"
        },
        "dotIndex" : 1,
        "lookAheadSymbol" : "⊣"
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем переход из состояния '∇' в состояние 'S1' по символу 'S'.",
      "from" : "∇",
      "to" : "S1",
      "through" : "S",
      "level" : "action",
      "name" : "addTransition"
    }, {
      "message" : "Добавляем состояние 'R1'.",
      "stateName" : "R1",
      "level" : "action",
      "name" : "addState"
    }, {
      "message" : "Добавляем в состояние 'R1' пункт '[S→R•, ⊣]'.",
      "state" : "R1",
      "item" : {
        "rule" : {
          "left" : "S",
          "right" : "R"
        },
        "dotIndex" : 1,
        "lookAheadSymbol" : "⊣"
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем переход из состояния '∇' в состояние 'R1' по символу 'R'.",
      "from" : "∇",
      "to" : "R1",
      "through" : "R",
      "level" : "action",
      "name" : "addTransition"
    }, {
      "message" : "Добавляем состояние 'L1'.",
      "stateName" : "L1",
      "level" : "action",
      "name" : "addState"
    }, {
      "message" : "Добавляем в состояние 'L1' пункт '[S→L•=R, ⊣]'.",
      "state" : "L1",
      "item" : {
        "rule" : {
          "left" : "S",
          "right" : "L=R"
        },
        "dotIndex" : 1,
        "lookAheadSymbol" : "⊣"
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем в состояние 'L1' пункт '[R→L•, ⊣]'.",
      "state" : "L1",
      "item" : {
        "rule" : {
          "left" : "R",
          "right" : "L"
        },
        "dotIndex" : 1,
        "lookAheadSymbol" : "⊣"
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем переход из состояния '∇' в состояние 'L1' по символу 'L'.",
      "from" : "∇",
      "to" : "L1",
      "through" : "L",
      "level" : "action",
      "name" : "addTransition"
    }, {
      "message" : "Добавляем состояние 'x1'.",
      "stateName" : "x1",
      "level" : "action",
      "name" : "addState"
    }, {
      "message" : "Добавляем в состояние 'x1' пункт '[L→x•, ⊣]'.",
      "state" : "x1",
      "item" : {
        "rule" : {
          "left" : "L",
          "right" : "x"
        },
        "dotIndex" : 1,
        "lookAheadSymbol" : "⊣"
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем в состояние 'x1' пункт '[L→x•, =]'.",
      "state" : "x1",
      "item" : {
        "rule" : {
          "left" : "L",
          "right" : "x"
        },
        "dotIndex" : 1,
        "lookAheadSymbol" : "="
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем переход из состояния '∇' в состояние 'x1' по символу 'x'.",
      "from" : "∇",
      "to" : "x1",
      "through" : "x",
      "level" : "action",
      "name" : "addTransition"
    }, {
      "message" : "Добавляем состояние '*1'.",
      "stateName" : "*1",
      "level" : "action",
      "name" : "addState"
    }, {
      "message" : "Добавляем в состояние '*1' пункт '[L→*•R, ⊣]'.",
      "state" : "*1",
      "item" : {
        "rule" : {
          "left" : "L",
          "right" : "*R"
        },
        "dotIndex" : 1,
        "lookAheadSymbol" : "⊣"
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем в состояние '*1' пункт '[L→*•R, =]'.",
      "state" : "*1",
      "item" : {
        "rule" : {
          "left" : "L",
          "right" : "*R"
        },
        "dotIndex" : 1,
        "lookAheadSymbol" : "="
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем в состояние '*1' пункт '[R→•L, ⊣]'.",
      "state" : "*1",
      "item" : {
        "rule" : {
          "left" : "R",
          "right" : "L"
        },
        "dotIndex" : 0,
        "lookAheadSymbol" : "⊣"
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем в состояние '*1' пункт '[R→•L, =]'.",
      "state" : "*1",
      "item" : {
        "rule" : {
          "left" : "R",
          "right" : "L"
        },
        "dotIndex" : 0,
        "lookAheadSymbol" : "="
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем в состояние '*1' пункт '[L→•*R, ⊣]'.",
      "state" : "*1",
      "item" : {
        "rule" : {
          "left" : "L",
          "right" : "*R"
        },
        "dotIndex" : 0,
        "lookAheadSymbol" : "⊣"
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем в состояние '*1' пункт '[L→•x, ⊣]'.",
      "state" : "*1",
      "item" : {
        "rule" : {
          "left" : "L",
          "right" : "x"
        },
        "dotIndex" : 0,
        "lookAheadSymbol" : "⊣"
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем в состояние '*1' пункт '[L→•x, =]'.",
      "state" : "*1",
      "item" : {
        "rule" : {
          "left" : "L",
          "right" : "x"
        },
        "dotIndex" : 0,
        "lookAheadSymbol" : "="
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем в состояние '*1' пункт '[L→•*R, =]'.",
      "state" : "*1",
      "item" : {
        "rule" : {
          "left" : "L",
          "right" : "*R"
        },
        "dotIndex" : 0,
        "lookAheadSymbol" : "="
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем переход из состояния '∇' в состояние '*1' по символу '*'.",
      "from" : "∇",
      "to" : "*1",
      "through" : "*",
      "level" : "action",
      "name" : "addTransition"
    }, {
      "message" : "Просматриваем состояние 'S1'",
      "level" : "comment",
      "name" : "startAddNewTransitions"
    }, {
      "message" : "Просматриваем состояние 'R1'",
      "level" : "comment",
      "name" : "startAddNewTransitions"
    }, {
      "message" : "Просматриваем состояние 'L1'",
      "level" : "comment",
      "name" : "startAddNewTransitions"
    }, {
      "message" : "Добавляем состояние '=1'.",
      "stateName" : "=1",
      "level" : "action",
      "name" : "addState"
    }, {
      "message" : "Добавляем в состояние '=1' пункт '[S→L=•R, ⊣]'.",
      "state" : "=1",
      "item" : {
        "rule" : {
          "left" : "S",
          "right" : "L=R"
        },
        "dotIndex" : 2,
        "lookAheadSymbol" : "⊣"
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем в состояние '=1' пункт '[R→•L, ⊣]'.",
      "state" : "=1",
      "item" : {
        "rule" : {
          "left" : "R",
          "right" : "L"
        },
        "dotIndex" : 0,
        "lookAheadSymbol" : "⊣"
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем в состояние '=1' пункт '[L→•*R, ⊣]'.",
      "state" : "=1",
      "item" : {
        "rule" : {
          "left" : "L",
          "right" : "*R"
        },
        "dotIndex" : 0,
        "lookAheadSymbol" : "⊣"
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем в состояние '=1' пункт '[L→•x, ⊣]'.",
      "state" : "=1",
      "item" : {
        "rule" : {
          "left" : "L",
          "right" : "x"
        },
        "dotIndex" : 0,
        "lookAheadSymbol" : "⊣"
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем переход из состояния 'L1' в состояние '=1' по символу '='.",
      "from" : "L1",
      "to" : "=1",
      "through" : "=",
      "level" : "action",
      "name" : "addTransition"
    }, {
      "message" : "Просматриваем состояние 'x1'",
      "level" : "comment",
      "name" : "startAddNewTransitions"
    }, {
      "message" : "Просматриваем состояние '*1'",
      "level" : "comment",
      "name" : "startAddNewTransitions"
    }, {
      "message" : "Добавляем состояние 'R2'.",
      "stateName" : "R2",
      "level" : "action",
      "name" : "addState"
    }, {
      "message" : "Добавляем в состояние 'R2' пункт '[L→*R•, =]'.",
      "state" : "R2",
      "item" : {
        "rule" : {
          "left" : "L",
          "right" : "*R"
        },
        "dotIndex" : 2,
        "lookAheadSymbol" : "="
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем в состояние 'R2' пункт '[L→*R•, ⊣]'.",
      "state" : "R2",
      "item" : {
        "rule" : {
          "left" : "L",
          "right" : "*R"
        },
        "dotIndex" : 2,
        "lookAheadSymbol" : "⊣"
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем переход из состояния '*1' в состояние 'R2' по символу 'R'.",
      "from" : "*1",
      "to" : "R2",
      "through" : "R",
      "level" : "action",
      "name" : "addTransition"
    }, {
      "message" : "Добавляем состояние 'L2'.",
      "stateName" : "L2",
      "level" : "action",
      "name" : "addState"
    }, {
      "message" : "Добавляем в состояние 'L2' пункт '[R→L•, ⊣]'.",
      "state" : "L2",
      "item" : {
        "rule" : {
          "left" : "R",
          "right" : "L"
        },
        "dotIndex" : 1,
        "lookAheadSymbol" : "⊣"
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем в состояние 'L2' пункт '[R→L•, =]'.",
      "state" : "L2",
      "item" : {
        "rule" : {
          "left" : "R",
          "right" : "L"
        },
        "dotIndex" : 1,
        "lookAheadSymbol" : "="
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем переход из состояния '*1' в состояние 'L2' по символу 'L'.",
      "from" : "*1",
      "to" : "L2",
      "through" : "L",
      "level" : "action",
      "name" : "addTransition"
    }, {
      "message" : "Добавляем переход из состояния '*1' в состояние '*1' по символу '*'.",
      "from" : "*1",
      "to" : "*1",
      "through" : "*",
      "level" : "action",
      "name" : "addTransition"
    }, {
      "message" : "Добавляем переход из состояния '*1' в состояние 'x1' по символу 'x'.",
      "from" : "*1",
      "to" : "x1",
      "through" : "x",
      "level" : "action",
      "name" : "addTransition"
    }, {
      "message" : "Просматриваем состояние '=1'",
      "level" : "comment",
      "name" : "startAddNewTransitions"
    }, {
      "message" : "Добавляем состояние 'R3'.",
      "stateName" : "R3",
      "level" : "action",
      "name" : "addState"
    }, {
      "message" : "Добавляем в состояние 'R3' пункт '[S→L=R•, ⊣]'.",
      "state" : "R3",
      "item" : {
        "rule" : {
          "left" : "S",
          "right" : "L=R"
        },
        "dotIndex" : 3,
        "lookAheadSymbol" : "⊣"
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем переход из состояния '=1' в состояние 'R3' по символу 'R'.",
      "from" : "=1",
      "to" : "R3",
      "through" : "R",
      "level" : "action",
      "name" : "addTransition"
    }, {
      "message" : "Добавляем состояние 'L3'.",
      "stateName" : "L3",
      "level" : "action",
      "name" : "addState"
    }, {
      "message" : "Добавляем в состояние 'L3' пункт '[R→L•, ⊣]'.",
      "state" : "L3",
      "item" : {
        "rule" : {
          "left" : "R",
          "right" : "L"
        },
        "dotIndex" : 1,
        "lookAheadSymbol" : "⊣"
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем переход из состояния '=1' в состояние 'L3' по символу 'L'.",
      "from" : "=1",
      "to" : "L3",
      "through" : "L",
      "level" : "action",
      "name" : "addTransition"
    }, {
      "message" : "Добавляем состояние '*2'.",
      "stateName" : "*2",
      "level" : "action",
      "name" : "addState"
    }, {
      "message" : "Добавляем в состояние '*2' пункт '[L→*•R, ⊣]'.",
      "state" : "*2",
      "item" : {
        "rule" : {
          "left" : "L",
          "right" : "*R"
        },
        "dotIndex" : 1,
        "lookAheadSymbol" : "⊣"
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем в состояние '*2' пункт '[R→•L, ⊣]'.",
      "state" : "*2",
      "item" : {
        "rule" : {
          "left" : "R",
          "right" : "L"
        },
        "dotIndex" : 0,
        "lookAheadSymbol" : "⊣"
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем в состояние '*2' пункт '[L→•*R, ⊣]'.",
      "state" : "*2",
      "item" : {
        "rule" : {
          "left" : "L",
          "right" : "*R"
        },
        "dotIndex" : 0,
        "lookAheadSymbol" : "⊣"
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем в состояние '*2' пункт '[L→•x, ⊣]'.",
      "state" : "*2",
      "item" : {
        "rule" : {
          "left" : "L",
          "right" : "x"
        },
        "dotIndex" : 0,
        "lookAheadSymbol" : "⊣"
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем переход из состояния '=1' в состояние '*2' по символу '*'.",
      "from" : "=1",
      "to" : "*2",
      "through" : "*",
      "level" : "action",
      "name" : "addTransition"
    }, {
      "message" : "Добавляем состояние 'x2'.",
      "stateName" : "x2",
      "level" : "action",
      "name" : "addState"
    }, {
      "message" : "Добавляем в состояние 'x2' пункт '[L→x•, ⊣]'.",
      "state" : "x2",
      "item" : {
        "rule" : {
          "left" : "L",
          "right" : "x"
        },
        "dotIndex" : 1,
        "lookAheadSymbol" : "⊣"
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем переход из состояния '=1' в состояние 'x2' по символу 'x'.",
      "from" : "=1",
      "to" : "x2",
      "through" : "x",
      "level" : "action",
      "name" : "addTransition"
    }, {
      "message" : "Просматриваем состояние 'R2'",
      "level" : "comment",
      "name" : "startAddNewTransitions"
    }, {
      "message" : "Просматриваем состояние 'L2'",
      "level" : "comment",
      "name" : "startAddNewTransitions"
    }, {
      "message" : "Просматриваем состояние 'R3'",
      "level" : "comment",
      "name" : "startAddNewTransitions"
    }, {
      "message" : "Просматриваем состояние 'L3'",
      "level" : "comment",
      "name" : "startAddNewTransitions"
    }, {
      "message" : "Просматриваем состояние '*2'",
      "level" : "comment",
      "name" : "startAddNewTransitions"
    }, {
      "message" : "Добавляем состояние 'R4'.",
      "stateName" : "R4",
      "level" : "action",
      "name" : "addState"
    }, {
      "message" : "Добавляем в состояние 'R4' пункт '[L→*R•, ⊣]'.",
      "state" : "R4",
      "item" : {
        "rule" : {
          "left" : "L",
          "right" : "*R"
        },
        "dotIndex" : 2,
        "lookAheadSymbol" : "⊣"
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем переход из состояния '*2' в состояние 'R4' по символу 'R'.",
      "from" : "*2",
      "to" : "R4",
      "through" : "R",
      "level" : "action",
      "name" : "addTransition"
    }, {
      "message" : "Добавляем переход из состояния '*2' в состояние 'L3' по символу 'L'.",
      "from" : "*2",
      "to" : "L3",
      "through" : "L",
      "level" : "action",
      "name" : "addTransition"
    }, {
      "message" : "Добавляем переход из состояния '*2' в состояние '*2' по символу '*'.",
      "from" : "*2",
      "to" : "*2",
      "through" : "*",
      "level" : "action",
      "name" : "addTransition"
    }, {
      "message" : "Добавляем переход из состояния '*2' в состояние 'x2' по символу 'x'.",
      "from" : "*2",
      "to" : "x2",
      "through" : "x",
      "level" : "action",
      "name" : "addTransition"
    }, {
      "message" : "Просматриваем состояние 'x2'",
      "level" : "comment",
      "name" : "startAddNewTransitions"
    }, {
      "message" : "Просматриваем состояние 'R4'",
      "level" : "comment",
      "name" : "startAddNewTransitions"
    }, {
      "message" : "Уплотняем полученный LR-автомат",
      "level" : "comment",
      "name" : "compactLRAutomaton"
    }, {
      "message" : "Удаляем переход из состояния '∇' в состояние '*1' по символу '*'.",
      "from" : "∇",
      "to" : "*1",
      "through" : "*",
      "level" : "action",
      "name" : "deleteTransition"
    }, {
      "message" : "Удаляем переход из состояния '*2' в состояние 'L3' по символу 'L'.",
      "from" : "*2",
      "to" : "L3",
      "through" : "L",
      "level" : "action",
      "name" : "deleteTransition"
    }, {
      "message" : "Удаляем переход из состояния '*1' в состояние 'L2' по символу 'L'.",
      "from" : "*1",
      "to" : "L2",
      "through" : "L",
      "level" : "action",
      "name" : "deleteTransition"
    }, {
      "message" : "Удаляем переход из состояния '*1' в состояние '*1' по символу '*'.",
      "from" : "*1",
      "to" : "*1",
      "through" : "*",
      "level" : "action",
      "name" : "deleteTransition"
    }, {
      "message" : "Удаляем переход из состояния '*2' в состояние 'R4' по символу 'R'.",
      "from" : "*2",
      "to" : "R4",
      "through" : "R",
      "level" : "action",
      "name" : "deleteTransition"
    }, {
      "message" : "Удаляем переход из состояния '*1' в состояние 'x1' по символу 'x'.",
      "from" : "*1",
      "to" : "x1",
      "through" : "x",
      "level" : "action",
      "name" : "deleteTransition"
    }, {
      "message" : "Удаляем переход из состояния '*2' в состояние '*2' по символу '*'.",
      "from" : "*2",
      "to" : "*2",
      "through" : "*",
      "level" : "action",
      "name" : "deleteTransition"
    }, {
      "message" : "Удаляем переход из состояния '*2' в состояние 'x2' по символу 'x'.",
      "from" : "*2",
      "to" : "x2",
      "through" : "x",
      "level" : "action",
      "name" : "deleteTransition"
    }, {
      "message" : "Удаляем переход из состояния '*1' в состояние 'R2' по символу 'R'.",
      "from" : "*1",
      "to" : "R2",
      "through" : "R",
      "level" : "action",
      "name" : "deleteTransition"
    }, {
      "message" : "Удаляем переход из состояния '∇' в состояние 'x1' по символу 'x'.",
      "from" : "∇",
      "to" : "x1",
      "through" : "x",
      "level" : "action",
      "name" : "deleteTransition"
    }, {
      "message" : "Удаляем переход из состояния '=1' в состояние '*2' по символу '*'.",
      "from" : "=1",
      "to" : "*2",
      "through" : "*",
      "level" : "action",
      "name" : "deleteTransition"
    }, {
      "message" : "Удаляем переход из состояния '=1' в состояние 'x2' по символу 'x'.",
      "from" : "=1",
      "to" : "x2",
      "through" : "x",
      "level" : "action",
      "name" : "deleteTransition"
    }, {
      "message" : "Удаляем переход из состояния '=1' в состояние 'L3' по символу 'L'.",
      "from" : "=1",
      "to" : "L3",
      "through" : "L",
      "level" : "action",
      "name" : "deleteTransition"
    }, {
      "message" : "Удаляем состояние 'R2'.",
      "stateName" : "R2",
      "level" : "action",
      "name" : "deleteState"
    }, {
      "message" : "Удаляем состояние 'R4'.",
      "stateName" : "R4",
      "level" : "action",
      "name" : "deleteState"
    }, {
      "message" : "Удаляем состояние 'L2'.",
      "stateName" : "L2",
      "level" : "action",
      "name" : "deleteState"
    }, {
      "message" : "Удаляем состояние '*1'.",
      "stateName" : "*1",
      "level" : "action",
      "name" : "deleteState"
    }, {
      "message" : "Удаляем состояние 'L3'.",
      "stateName" : "L3",
      "level" : "action",
      "name" : "deleteState"
    }, {
      "message" : "Удаляем состояние '*2'.",
      "stateName" : "*2",
      "level" : "action",
      "name" : "deleteState"
    }, {
      "message" : "Удаляем состояние 'x1'.",
      "stateName" : "x1",
      "level" : "action",
      "name" : "deleteState"
    }, {
      "message" : "Удаляем состояние 'x2'.",
      "stateName" : "x2",
      "level" : "action",
      "name" : "deleteState"
    }, {
      "message" : "Добавляем состояние 'R2;R4'.",
      "stateName" : "R2;R4",
      "level" : "action",
      "name" : "addState"
    }, {
      "message" : "Добавляем в состояние 'R2;R4' пункт '[L→*R•, =]'.",
      "state" : "R2;R4",
      "item" : {
        "rule" : {
          "left" : "L",
          "right" : "*R"
        },
        "dotIndex" : 2,
        "lookAheadSymbol" : "="
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем в состояние 'R2;R4' пункт '[L→*R•, ⊣]'.",
      "state" : "R2;R4",
      "item" : {
        "rule" : {
          "left" : "L",
          "right" : "*R"
        },
        "dotIndex" : 2,
        "lookAheadSymbol" : "⊣"
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем состояние 'L2;L3'.",
      "stateName" : "L2;L3",
      "level" : "action",
      "name" : "addState"
    }, {
      "message" : "Добавляем в состояние 'L2;L3' пункт '[R→L•, ⊣]'.",
      "state" : "L2;L3",
      "item" : {
        "rule" : {
          "left" : "R",
          "right" : "L"
        },
        "dotIndex" : 1,
        "lookAheadSymbol" : "⊣"
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем в состояние 'L2;L3' пункт '[R→L•, =]'.",
      "state" : "L2;L3",
      "item" : {
        "rule" : {
          "left" : "R",
          "right" : "L"
        },
        "dotIndex" : 1,
        "lookAheadSymbol" : "="
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем состояние '*1;*2'.",
      "stateName" : "*1;*2",
      "level" : "action",
      "name" : "addState"
    }, {
      "message" : "Добавляем в состояние '*1;*2' пункт '[L→*•R, ⊣]'.",
      "state" : "*1;*2",
      "item" : {
        "rule" : {
          "left" : "L",
          "right" : "*R"
        },
        "dotIndex" : 1,
        "lookAheadSymbol" : "⊣"
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем в состояние '*1;*2' пункт '[L→*•R, =]'.",
      "state" : "*1;*2",
      "item" : {
        "rule" : {
          "left" : "L",
          "right" : "*R"
        },
        "dotIndex" : 1,
        "lookAheadSymbol" : "="
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем в состояние '*1;*2' пункт '[R→•L, ⊣]'.",
      "state" : "*1;*2",
      "item" : {
        "rule" : {
          "left" : "R",
          "right" : "L"
        },
        "dotIndex" : 0,
        "lookAheadSymbol" : "⊣"
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем в состояние '*1;*2' пункт '[R→•L, =]'.",
      "state" : "*1;*2",
      "item" : {
        "rule" : {
          "left" : "R",
          "right" : "L"
        },
        "dotIndex" : 0,
        "lookAheadSymbol" : "="
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем в состояние '*1;*2' пункт '[L→•*R, ⊣]'.",
      "state" : "*1;*2",
      "item" : {
        "rule" : {
          "left" : "L",
          "right" : "*R"
        },
        "dotIndex" : 0,
        "lookAheadSymbol" : "⊣"
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем в состояние '*1;*2' пункт '[L→•x, ⊣]'.",
      "state" : "*1;*2",
      "item" : {
        "rule" : {
          "left" : "L",
          "right" : "x"
        },
        "dotIndex" : 0,
        "lookAheadSymbol" : "⊣"
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем в состояние '*1;*2' пункт '[L→•x, =]'.",
      "state" : "*1;*2",
      "item" : {
        "rule" : {
          "left" : "L",
          "right" : "x"
        },
        "dotIndex" : 0,
        "lookAheadSymbol" : "="
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем в состояние '*1;*2' пункт '[L→•*R, =]'.",
      "state" : "*1;*2",
      "item" : {
        "rule" : {
          "left" : "L",
          "right" : "*R"
        },
        "dotIndex" : 0,
        "lookAheadSymbol" : "="
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем состояние 'x1;x2'.",
      "stateName" : "x1;x2",
      "level" : "action",
      "name" : "addState"
    }, {
      "message" : "Добавляем в состояние 'x1;x2' пункт '[L→x•, ⊣]'.",
      "state" : "x1;x2",
      "item" : {
        "rule" : {
          "left" : "L",
          "right" : "x"
        },
        "dotIndex" : 1,
        "lookAheadSymbol" : "⊣"
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем в состояние 'x1;x2' пункт '[L→x•, =]'.",
      "state" : "x1;x2",
      "item" : {
        "rule" : {
          "left" : "L",
          "right" : "x"
        },
        "dotIndex" : 1,
        "lookAheadSymbol" : "="
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем переход из состояния '=1' в состояние 'L2;L3' по символу 'L'.",
      "from" : "=1",
      "to" : "L2;L3",
      "through" : "L",
      "level" : "action",
      "name" : "addTransition"
    }, {
      "message" : "Добавляем переход из состояния '*1;*2' в состояние 'L2;L3' по символу 'L'.",
      "from" : "*1;*2",
      "to" : "L2;L3",
      "through" : "L",
      "level" : "action",
      "name" : "addTransition"
    }, {
      "message" : "Добавляем переход из состояния '*1;*2' в состояние 'R2;R4' по символу 'R'.",
      "from" : "*1;*2",
      "to" : "R2;R4",
      "through" : "R",
      "level" : "action",
      "name" : "addTransition"
    }, {
      "message" : "Добавляем переход из состояния '=1' в состояние 'x1;x2' по символу 'x'.",
      "from" : "=1",
      "to" : "x1;x2",
      "through" : "x",
      "level" : "action",
      "name" : "addTransition"
    }, {
      "message" : "Добавляем переход из состояния '*1;*2' в состояние 'x1;x2' по символу 'x'.",
      "from" : "*1;*2",
      "to" : "x1;x2",
      "through" : "x",
      "level" : "action",
      "name" : "addTransition"
    }, {
      "message" : "Добавляем переход из состояния '∇' в состояние 'x1;x2' по символу 'x'.",
      "from" : "∇",
      "to" : "x1;x2",
      "through" : "x",
      "level" : "action",
      "name" : "addTransition"
    }, {
      "message" : "Добавляем переход из состояния '∇' в состояние '*1;*2' по символу '*'.",
      "from" : "∇",
      "to" : "*1;*2",
      "through" : "*",
      "level" : "action",
      "name" : "addTransition"
    }, {
      "message" : "Добавляем переход из состояния '*1;*2' в состояние '*1;*2' по символу '*'.",
      "from" : "*1;*2",
      "to" : "*1;*2",
      "through" : "*",
      "level" : "action",
      "name" : "addTransition"
    }, {
      "message" : "Добавляем переход из состояния '=1' в состояние '*1;*2' по символу '*'.",
      "from" : "=1",
      "to" : "*1;*2",
      "through" : "*",
      "level" : "action",
      "name" : "addTransition"
    } ]
  }
}

POST api/{v1+}/build/lalr1 (png)

Строит LALR(1)-автомат. Результат возвращает в формате png.

Заголовки запроса

Имя Описание

Content-Type

image/png

Параметры пути

Имя Описание

version

версия API

Тело запроса

Поле Тип Обязательное Описание

.grammar

Object

Да

Грамматика, по которой требуется построить LR-автомат

.grammar.terminals

Array

Да

Список терминалов грамматики.

.grammar.nonTerminals

Array

Да

Список нетерминалов грамматики

.grammar.rules

Array

Да

Список правил грамматики

.grammar.rules[].left

String

Да

Нетерминал левой части правила грамматики

.grammar.rules[].right

String

Да

Символы правой части правила грамматики

.grammar.startSymbol

String

Да

Аксиома грамматики (нетерминал)

.buildOptions

Object

Нет

Параметры построения LR-автомата

.buildOptions.namesGenerationStrategy

String

Нет

Стратегия генерации имен состояний при построении автомата

.buildOptions.lalr1BuildAlgorithm

String

Нет

Алгоритм построения LALR(1)-автомата

visualizeOperations.colorizeTransitions

Boolean

Нет

Нужно ли окрашивать переходы автомата. По умолчанию не окрашиваются.

visualizeOperations.colorizeStateNames

Boolean

Нет

Окрашивать ли имена состояний. По умолчанию не окрашиваются.

visualizeOperations.stateNameStyle

String

Нет

Стиль оформления названия состояния. По умолчанию 'onBlackBackground'.

Заголовки ответа

Имя Описание

Content-Type

application/json

curl

$ curl 'http://localhost:8080/api/v1/build/lalr1' -i -X POST \
    -H 'Content-Type: application/json' \
    -H 'Accept: image/png' \
    -d '{
  "grammar" : {
    "terminals" : [ "i", "+", "(", ")" ],
    "nonTerminals" : [ "E", "T" ],
    "rules" : [ {
      "left" : "E",
      "right" : "T"
    }, {
      "left" : "E",
      "right" : "E+T"
    }, {
      "left" : "T",
      "right" : "i"
    }, {
      "left" : "T",
      "right" : "(E)"
    } ],
    "startSymbol" : "E"
  }
}'

Пример запроса

POST /api/v1/build/lalr1 HTTP/1.1
Content-Type: application/json
Accept: image/png
Content-Length: 342
Host: localhost:8080

{
  "grammar" : {
    "terminals" : [ "i", "+", "(", ")" ],
    "nonTerminals" : [ "E", "T" ],
    "rules" : [ {
      "left" : "E",
      "right" : "T"
    }, {
      "left" : "E",
      "right" : "E+T"
    }, {
      "left" : "T",
      "right" : "i"
    }, {
      "left" : "T",
      "right" : "(E)"
    } ],
    "startSymbol" : "E"
  }
}

Пример ответа

Пример построения lalr(1)

POST api/{v1+}/build/lalr1 (zip)

Строит LALR(1)-автомат. Лог построения возвращает в zip архиве с изображениями автомата.

Заголовки запроса

Имя Описание

Accept

application/octet-stream

Параметры пути

Имя Описание

version

версия API

Тело запроса

Поле Тип Обязательное Описание

.grammar

Object

Да

Грамматика, по которой требуется построить LR-автомат

.grammar.terminals

Array

Да

Список терминалов грамматики.

.grammar.nonTerminals

Array

Да

Список нетерминалов грамматики

.grammar.rules

Array

Да

Список правил грамматики

.grammar.rules[].left

String

Да

Нетерминал левой части правила грамматики

.grammar.rules[].right

String

Да

Символы правой части правила грамматики

.grammar.startSymbol

String

Да

Аксиома грамматики (нетерминал)

.buildOptions

Object

Нет

Параметры построения LR-автомата

.buildOptions.namesGenerationStrategy

String

Нет

Стратегия генерации имен состояний при построении автомата

.buildOptions.lalr1BuildAlgorithm

String

Нет

Алгоритм построения LALR(1)-автомата

visualizeOperations.visualizeOperations

Array

Нет

Номера операций, которые нужно визуализировать. Если не указаны, то визуализируются все операции

visualizeOperations.colorizeTransitions

Boolean

Нет

Нужно ли окрашивать переходы автомата. По умолчанию не окрашиваются.

visualizeOperations.colorizeStateNames

Boolean

Нет

Окрашивать ли имена состояний. По умолчанию не окрашиваются.

visualizeOperations.stateNameStyle

String

Нет

Стиль оформления названия состояния. По умолчанию 'onBlackBackground'.

Заголовки ответа

Имя Описание

Content-Type

application/octet-stream (zip)

curl

$ curl 'http://localhost:8080/api/v1/build/lalr1' -i -X POST \
    -H 'Content-Type: application/json' \
    -H 'Accept: application/octet-stream' \
    -d '{
  "grammar" : {
    "terminals" : [ "a", "b", "c", "d" ],
    "nonTerminals" : [ "S", "A" ],
    "rules" : [ {
      "left" : "S",
      "right" : "Aa"
    }, {
      "left" : "S",
      "right" : "bAc"
    }, {
      "left" : "S",
      "right" : "bc"
    }, {
      "left" : "S",
      "right" : "bda"
    }, {
      "left" : "A",
      "right" : "d"
    } ],
    "startSymbol" : "S"
  }
}'

Пример запроса

POST /api/v1/build/lalr1 HTTP/1.1
Content-Type: application/json
Accept: application/octet-stream
Content-Length: 393
Host: localhost:8080

{
  "grammar" : {
    "terminals" : [ "a", "b", "c", "d" ],
    "nonTerminals" : [ "S", "A" ],
    "rules" : [ {
      "left" : "S",
      "right" : "Aa"
    }, {
      "left" : "S",
      "right" : "bAc"
    }, {
      "left" : "S",
      "right" : "bc"
    }, {
      "left" : "S",
      "right" : "bda"
    }, {
      "left" : "A",
      "right" : "d"
    } ],
    "startSymbol" : "S"
  }
}

POST api/{v1+}/build/lr1 (json)

Строит LR(1)-автомат. Результат возвращает в формате json.

Заголовки запроса

Имя Описание

Accept

application/json

Параметры пути

Имя Описание

version

версия API

Тело запроса

Поле Тип Обязательное Описание

.grammar

Object

Да

Грамматика, по которой требуется построить LR-автомат

.grammar.terminals

Array

Да

Список терминалов грамматики.

.grammar.nonTerminals

Array

Да

Список нетерминалов грамматики

.grammar.rules

Array

Да

Список правил грамматики

.grammar.rules[].left

String

Да

Нетерминал левой части правила грамматики

.grammar.rules[].right

String

Да

Символы правой части правила грамматики

.grammar.startSymbol

String

Да

Аксиома грамматики (нетерминал)

.buildOptions

Object

Нет

Параметры построения LR-автомата

.buildOptions.namesGenerationStrategy

String

Нет

Стратегия генерации имен состояний при построении автомата

.buildOptions.lalr1BuildAlgorithm

String

Нет

Алгоритм построения LALR(1)-автомата

.buildOptions.enableBuildLog

Boolean

Нет

Передавать ли в ответе лог построения

Заголовки ответа

Имя Описание

Content-Type

application/json

Тело ответа

Поле Тип Обязательное Описание

.automaton

Object

Да

Построенный LR-автомат

.automaton.states

Array

Да

Состояния автомата

.automaton.states[].name

String

Да

Имя состояния

.automaton.states[].items

Array

Да

LR(0)-пункты в состоянии

.automaton.states[].items[].rule

Object

Да

Правило грамматики пункта

.automaton.states[].items[].rule.left

String

Да

Левая часть правила

.automaton.states[].items[].rule.right

String

Да

Правая часть правила

.automaton.states[].items[].dotIndex

Number

Да

Позиция точки в правой части правила

.automaton.transitions

Array

Да

Переходы между состояниями автомата

.automaton.transitions[].from

String

Да

Исходное состояние

.automaton.transitions[].to

String

Да

Целевое состояние

.automaton.transitions[].through

String

Да

Символ перехода

.buildLog

Object

Нет

Лог построения LR-автомата (если указана соответствующая опция)

.buildLog.operations

Array

Да

Последовательность операций построения

.buildLog.operations[].message

String

Да

Человекочитаемое описание операции

.buildLog.operations[].level

String

Да

Тип операции

.buildLog.operations[].name

String

Да

Имя операции

.buildLog.operations[].stateName

String

Нет

Имя состояния

.buildLog.operations[].state

String

Нет

Состояние, к которому применяется операция

.buildLog.operations[].item

Object

Нет

LR-пункт, связанный с операцией

.buildLog.operations[].item.rule.left

String

Нет

Левая часть правила пункта

.buildLog.operations[].item.rule.right

String

Нет

Правая часть правила пункта

.buildLog.operations[].item.dotIndex

Number

Нет

Позиция точки

.buildLog.operations[].from

String

Нет

Исходное состояние перехода

.buildLog.operations[].to

String

Нет

Целевое состояние перехода

.buildLog.operations[].through

String

Нет

Символ перехода

.automaton.states[].items[].lookAheadSymbol

String

Нет

Символ предпросмотра

.buildLog.operations[].item.lookAheadSymbol

String

Нет

Символ предпросмотра

.automaton.states[].items[].lookAheadSymbols

Array

Нет

Символы предпросмотра (при построении через канальный алгоритм)

curl

$ curl 'http://localhost:8080/api/v1/build/lalr1' -i -X POST \
    -H 'Content-Type: application/json' \
    -H 'Accept: application/json' \
    -d '{
  "grammar" : {
    "terminals" : [ "x", "*", "=" ],
    "nonTerminals" : [ "S", "L", "R" ],
    "rules" : [ {
      "left" : "S",
      "right" : "L=R"
    }, {
      "left" : "S",
      "right" : "R"
    }, {
      "left" : "L",
      "right" : "*R"
    }, {
      "left" : "L",
      "right" : "x"
    }, {
      "left" : "R",
      "right" : "L"
    } ],
    "startSymbol" : "S"
  },
  "buildOptions" : {
    "enableBuildLog" : true
  }
}'
Примеры

Пример запроса

POST /api/v1/build/lalr1 HTTP/1.1
Content-Type: application/json
Accept: application/json
Content-Length: 444
Host: localhost:8080

{
  "grammar" : {
    "terminals" : [ "x", "*", "=" ],
    "nonTerminals" : [ "S", "L", "R" ],
    "rules" : [ {
      "left" : "S",
      "right" : "L=R"
    }, {
      "left" : "S",
      "right" : "R"
    }, {
      "left" : "L",
      "right" : "*R"
    }, {
      "left" : "L",
      "right" : "x"
    }, {
      "left" : "R",
      "right" : "L"
    } ],
    "startSymbol" : "S"
  },
  "buildOptions" : {
    "enableBuildLog" : true
  }
}

Пример ответа

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 41323

{
  "automaton" : {
    "states" : [ {
      "name" : "R3",
      "items" : [ {
        "rule" : {
          "left" : "S",
          "right" : "L=R"
        },
        "dotIndex" : 3,
        "lookAheadSymbol" : "⊣"
      } ]
    }, {
      "name" : "=1",
      "items" : [ {
        "rule" : {
          "left" : "S",
          "right" : "L=R"
        },
        "dotIndex" : 2,
        "lookAheadSymbol" : "⊣"
      }, {
        "rule" : {
          "left" : "R",
          "right" : "L"
        },
        "dotIndex" : 0,
        "lookAheadSymbol" : "⊣"
      }, {
        "rule" : {
          "left" : "L",
          "right" : "*R"
        },
        "dotIndex" : 0,
        "lookAheadSymbol" : "⊣"
      }, {
        "rule" : {
          "left" : "L",
          "right" : "x"
        },
        "dotIndex" : 0,
        "lookAheadSymbol" : "⊣"
      } ]
    }, {
      "name" : "L1",
      "items" : [ {
        "rule" : {
          "left" : "S",
          "right" : "L=R"
        },
        "dotIndex" : 1,
        "lookAheadSymbol" : "⊣"
      }, {
        "rule" : {
          "left" : "R",
          "right" : "L"
        },
        "dotIndex" : 1,
        "lookAheadSymbol" : "⊣"
      } ]
    }, {
      "name" : "R2;R4",
      "items" : [ {
        "rule" : {
          "left" : "L",
          "right" : "*R"
        },
        "dotIndex" : 2,
        "lookAheadSymbol" : "="
      }, {
        "rule" : {
          "left" : "L",
          "right" : "*R"
        },
        "dotIndex" : 2,
        "lookAheadSymbol" : "⊣"
      } ]
    }, {
      "name" : "∇",
      "items" : [ {
        "rule" : {
          "left" : "S'",
          "right" : "S"
        },
        "dotIndex" : 0,
        "lookAheadSymbol" : "⊣"
      }, {
        "rule" : {
          "left" : "S",
          "right" : "R"
        },
        "dotIndex" : 0,
        "lookAheadSymbol" : "⊣"
      }, {
        "rule" : {
          "left" : "S",
          "right" : "L=R"
        },
        "dotIndex" : 0,
        "lookAheadSymbol" : "⊣"
      }, {
        "rule" : {
          "left" : "R",
          "right" : "L"
        },
        "dotIndex" : 0,
        "lookAheadSymbol" : "⊣"
      }, {
        "rule" : {
          "left" : "L",
          "right" : "x"
        },
        "dotIndex" : 0,
        "lookAheadSymbol" : "="
      }, {
        "rule" : {
          "left" : "L",
          "right" : "*R"
        },
        "dotIndex" : 0,
        "lookAheadSymbol" : "="
      }, {
        "rule" : {
          "left" : "L",
          "right" : "*R"
        },
        "dotIndex" : 0,
        "lookAheadSymbol" : "⊣"
      }, {
        "rule" : {
          "left" : "L",
          "right" : "x"
        },
        "dotIndex" : 0,
        "lookAheadSymbol" : "⊣"
      } ]
    }, {
      "name" : "L2;L3",
      "items" : [ {
        "rule" : {
          "left" : "R",
          "right" : "L"
        },
        "dotIndex" : 1,
        "lookAheadSymbol" : "⊣"
      }, {
        "rule" : {
          "left" : "R",
          "right" : "L"
        },
        "dotIndex" : 1,
        "lookAheadSymbol" : "="
      } ]
    }, {
      "name" : "*1;*2",
      "items" : [ {
        "rule" : {
          "left" : "L",
          "right" : "*R"
        },
        "dotIndex" : 1,
        "lookAheadSymbol" : "⊣"
      }, {
        "rule" : {
          "left" : "L",
          "right" : "*R"
        },
        "dotIndex" : 1,
        "lookAheadSymbol" : "="
      }, {
        "rule" : {
          "left" : "R",
          "right" : "L"
        },
        "dotIndex" : 0,
        "lookAheadSymbol" : "⊣"
      }, {
        "rule" : {
          "left" : "R",
          "right" : "L"
        },
        "dotIndex" : 0,
        "lookAheadSymbol" : "="
      }, {
        "rule" : {
          "left" : "L",
          "right" : "*R"
        },
        "dotIndex" : 0,
        "lookAheadSymbol" : "⊣"
      }, {
        "rule" : {
          "left" : "L",
          "right" : "x"
        },
        "dotIndex" : 0,
        "lookAheadSymbol" : "⊣"
      }, {
        "rule" : {
          "left" : "L",
          "right" : "x"
        },
        "dotIndex" : 0,
        "lookAheadSymbol" : "="
      }, {
        "rule" : {
          "left" : "L",
          "right" : "*R"
        },
        "dotIndex" : 0,
        "lookAheadSymbol" : "="
      } ]
    }, {
      "name" : "x1;x2",
      "items" : [ {
        "rule" : {
          "left" : "L",
          "right" : "x"
        },
        "dotIndex" : 1,
        "lookAheadSymbol" : "⊣"
      }, {
        "rule" : {
          "left" : "L",
          "right" : "x"
        },
        "dotIndex" : 1,
        "lookAheadSymbol" : "="
      } ]
    }, {
      "name" : "S1",
      "items" : [ {
        "rule" : {
          "left" : "S'",
          "right" : "S"
        },
        "dotIndex" : 1,
        "lookAheadSymbol" : "⊣"
      } ]
    }, {
      "name" : "R1",
      "items" : [ {
        "rule" : {
          "left" : "S",
          "right" : "R"
        },
        "dotIndex" : 1,
        "lookAheadSymbol" : "⊣"
      } ]
    } ],
    "transitions" : [ {
      "from" : "∇",
      "to" : "L1",
      "through" : "L"
    }, {
      "from" : "=1",
      "to" : "x1;x2",
      "through" : "x"
    }, {
      "from" : "*1;*2",
      "to" : "x1;x2",
      "through" : "x"
    }, {
      "from" : "∇",
      "to" : "*1;*2",
      "through" : "*"
    }, {
      "from" : "∇",
      "to" : "S1",
      "through" : "S"
    }, {
      "from" : "*1;*2",
      "to" : "L2;L3",
      "through" : "L"
    }, {
      "from" : "∇",
      "to" : "R1",
      "through" : "R"
    }, {
      "from" : "*1;*2",
      "to" : "R2;R4",
      "through" : "R"
    }, {
      "from" : "∇",
      "to" : "x1;x2",
      "through" : "x"
    }, {
      "from" : "=1",
      "to" : "*1;*2",
      "through" : "*"
    }, {
      "from" : "*1;*2",
      "to" : "*1;*2",
      "through" : "*"
    }, {
      "from" : "=1",
      "to" : "L2;L3",
      "through" : "L"
    }, {
      "from" : "L1",
      "to" : "=1",
      "through" : "="
    }, {
      "from" : "=1",
      "to" : "R3",
      "through" : "R"
    } ]
  },
  "buildLog" : {
    "operations" : [ {
      "message" : "Построим LR-автомат lalr(1)",
      "level" : "comment",
      "name" : "buildLrAutomaton"
    }, {
      "message" : "Построим LR-автомат lr(1)",
      "level" : "comment",
      "name" : "buildLrAutomaton"
    }, {
      "message" : "Расширяем исходную грамматику.",
      "level" : "comment",
      "name" : "extendGrammar"
    }, {
      "message" : "Добавляем состояние '∇'.",
      "stateName" : "∇",
      "level" : "action",
      "name" : "addState"
    }, {
      "message" : "Добавляем в состояние '∇' пункт '[S'→•S, ⊣]'.",
      "state" : "∇",
      "item" : {
        "rule" : {
          "left" : "S'",
          "right" : "S"
        },
        "dotIndex" : 0,
        "lookAheadSymbol" : "⊣"
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем в состояние '∇' пункт '[S→•R, ⊣]'.",
      "state" : "∇",
      "item" : {
        "rule" : {
          "left" : "S",
          "right" : "R"
        },
        "dotIndex" : 0,
        "lookAheadSymbol" : "⊣"
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем в состояние '∇' пункт '[S→•L=R, ⊣]'.",
      "state" : "∇",
      "item" : {
        "rule" : {
          "left" : "S",
          "right" : "L=R"
        },
        "dotIndex" : 0,
        "lookAheadSymbol" : "⊣"
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем в состояние '∇' пункт '[R→•L, ⊣]'.",
      "state" : "∇",
      "item" : {
        "rule" : {
          "left" : "R",
          "right" : "L"
        },
        "dotIndex" : 0,
        "lookAheadSymbol" : "⊣"
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем в состояние '∇' пункт '[L→•x, =]'.",
      "state" : "∇",
      "item" : {
        "rule" : {
          "left" : "L",
          "right" : "x"
        },
        "dotIndex" : 0,
        "lookAheadSymbol" : "="
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем в состояние '∇' пункт '[L→•*R, =]'.",
      "state" : "∇",
      "item" : {
        "rule" : {
          "left" : "L",
          "right" : "*R"
        },
        "dotIndex" : 0,
        "lookAheadSymbol" : "="
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем в состояние '∇' пункт '[L→•*R, ⊣]'.",
      "state" : "∇",
      "item" : {
        "rule" : {
          "left" : "L",
          "right" : "*R"
        },
        "dotIndex" : 0,
        "lookAheadSymbol" : "⊣"
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем в состояние '∇' пункт '[L→•x, ⊣]'.",
      "state" : "∇",
      "item" : {
        "rule" : {
          "left" : "L",
          "right" : "x"
        },
        "dotIndex" : 0,
        "lookAheadSymbol" : "⊣"
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Просматриваем состояние '∇'",
      "level" : "comment",
      "name" : "startAddNewTransitions"
    }, {
      "message" : "Добавляем состояние 'S1'.",
      "stateName" : "S1",
      "level" : "action",
      "name" : "addState"
    }, {
      "message" : "Добавляем в состояние 'S1' пункт '[S'→S•, ⊣]'.",
      "state" : "S1",
      "item" : {
        "rule" : {
          "left" : "S'",
          "right" : "S"
        },
        "dotIndex" : 1,
        "lookAheadSymbol" : "⊣"
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем переход из состояния '∇' в состояние 'S1' по символу 'S'.",
      "from" : "∇",
      "to" : "S1",
      "through" : "S",
      "level" : "action",
      "name" : "addTransition"
    }, {
      "message" : "Добавляем состояние 'R1'.",
      "stateName" : "R1",
      "level" : "action",
      "name" : "addState"
    }, {
      "message" : "Добавляем в состояние 'R1' пункт '[S→R•, ⊣]'.",
      "state" : "R1",
      "item" : {
        "rule" : {
          "left" : "S",
          "right" : "R"
        },
        "dotIndex" : 1,
        "lookAheadSymbol" : "⊣"
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем переход из состояния '∇' в состояние 'R1' по символу 'R'.",
      "from" : "∇",
      "to" : "R1",
      "through" : "R",
      "level" : "action",
      "name" : "addTransition"
    }, {
      "message" : "Добавляем состояние 'L1'.",
      "stateName" : "L1",
      "level" : "action",
      "name" : "addState"
    }, {
      "message" : "Добавляем в состояние 'L1' пункт '[S→L•=R, ⊣]'.",
      "state" : "L1",
      "item" : {
        "rule" : {
          "left" : "S",
          "right" : "L=R"
        },
        "dotIndex" : 1,
        "lookAheadSymbol" : "⊣"
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем в состояние 'L1' пункт '[R→L•, ⊣]'.",
      "state" : "L1",
      "item" : {
        "rule" : {
          "left" : "R",
          "right" : "L"
        },
        "dotIndex" : 1,
        "lookAheadSymbol" : "⊣"
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем переход из состояния '∇' в состояние 'L1' по символу 'L'.",
      "from" : "∇",
      "to" : "L1",
      "through" : "L",
      "level" : "action",
      "name" : "addTransition"
    }, {
      "message" : "Добавляем состояние 'x1'.",
      "stateName" : "x1",
      "level" : "action",
      "name" : "addState"
    }, {
      "message" : "Добавляем в состояние 'x1' пункт '[L→x•, ⊣]'.",
      "state" : "x1",
      "item" : {
        "rule" : {
          "left" : "L",
          "right" : "x"
        },
        "dotIndex" : 1,
        "lookAheadSymbol" : "⊣"
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем в состояние 'x1' пункт '[L→x•, =]'.",
      "state" : "x1",
      "item" : {
        "rule" : {
          "left" : "L",
          "right" : "x"
        },
        "dotIndex" : 1,
        "lookAheadSymbol" : "="
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем переход из состояния '∇' в состояние 'x1' по символу 'x'.",
      "from" : "∇",
      "to" : "x1",
      "through" : "x",
      "level" : "action",
      "name" : "addTransition"
    }, {
      "message" : "Добавляем состояние '*1'.",
      "stateName" : "*1",
      "level" : "action",
      "name" : "addState"
    }, {
      "message" : "Добавляем в состояние '*1' пункт '[L→*•R, ⊣]'.",
      "state" : "*1",
      "item" : {
        "rule" : {
          "left" : "L",
          "right" : "*R"
        },
        "dotIndex" : 1,
        "lookAheadSymbol" : "⊣"
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем в состояние '*1' пункт '[L→*•R, =]'.",
      "state" : "*1",
      "item" : {
        "rule" : {
          "left" : "L",
          "right" : "*R"
        },
        "dotIndex" : 1,
        "lookAheadSymbol" : "="
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем в состояние '*1' пункт '[R→•L, ⊣]'.",
      "state" : "*1",
      "item" : {
        "rule" : {
          "left" : "R",
          "right" : "L"
        },
        "dotIndex" : 0,
        "lookAheadSymbol" : "⊣"
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем в состояние '*1' пункт '[R→•L, =]'.",
      "state" : "*1",
      "item" : {
        "rule" : {
          "left" : "R",
          "right" : "L"
        },
        "dotIndex" : 0,
        "lookAheadSymbol" : "="
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем в состояние '*1' пункт '[L→•*R, ⊣]'.",
      "state" : "*1",
      "item" : {
        "rule" : {
          "left" : "L",
          "right" : "*R"
        },
        "dotIndex" : 0,
        "lookAheadSymbol" : "⊣"
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем в состояние '*1' пункт '[L→•x, ⊣]'.",
      "state" : "*1",
      "item" : {
        "rule" : {
          "left" : "L",
          "right" : "x"
        },
        "dotIndex" : 0,
        "lookAheadSymbol" : "⊣"
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем в состояние '*1' пункт '[L→•x, =]'.",
      "state" : "*1",
      "item" : {
        "rule" : {
          "left" : "L",
          "right" : "x"
        },
        "dotIndex" : 0,
        "lookAheadSymbol" : "="
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем в состояние '*1' пункт '[L→•*R, =]'.",
      "state" : "*1",
      "item" : {
        "rule" : {
          "left" : "L",
          "right" : "*R"
        },
        "dotIndex" : 0,
        "lookAheadSymbol" : "="
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем переход из состояния '∇' в состояние '*1' по символу '*'.",
      "from" : "∇",
      "to" : "*1",
      "through" : "*",
      "level" : "action",
      "name" : "addTransition"
    }, {
      "message" : "Просматриваем состояние 'S1'",
      "level" : "comment",
      "name" : "startAddNewTransitions"
    }, {
      "message" : "Просматриваем состояние 'R1'",
      "level" : "comment",
      "name" : "startAddNewTransitions"
    }, {
      "message" : "Просматриваем состояние 'L1'",
      "level" : "comment",
      "name" : "startAddNewTransitions"
    }, {
      "message" : "Добавляем состояние '=1'.",
      "stateName" : "=1",
      "level" : "action",
      "name" : "addState"
    }, {
      "message" : "Добавляем в состояние '=1' пункт '[S→L=•R, ⊣]'.",
      "state" : "=1",
      "item" : {
        "rule" : {
          "left" : "S",
          "right" : "L=R"
        },
        "dotIndex" : 2,
        "lookAheadSymbol" : "⊣"
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем в состояние '=1' пункт '[R→•L, ⊣]'.",
      "state" : "=1",
      "item" : {
        "rule" : {
          "left" : "R",
          "right" : "L"
        },
        "dotIndex" : 0,
        "lookAheadSymbol" : "⊣"
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем в состояние '=1' пункт '[L→•*R, ⊣]'.",
      "state" : "=1",
      "item" : {
        "rule" : {
          "left" : "L",
          "right" : "*R"
        },
        "dotIndex" : 0,
        "lookAheadSymbol" : "⊣"
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем в состояние '=1' пункт '[L→•x, ⊣]'.",
      "state" : "=1",
      "item" : {
        "rule" : {
          "left" : "L",
          "right" : "x"
        },
        "dotIndex" : 0,
        "lookAheadSymbol" : "⊣"
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем переход из состояния 'L1' в состояние '=1' по символу '='.",
      "from" : "L1",
      "to" : "=1",
      "through" : "=",
      "level" : "action",
      "name" : "addTransition"
    }, {
      "message" : "Просматриваем состояние 'x1'",
      "level" : "comment",
      "name" : "startAddNewTransitions"
    }, {
      "message" : "Просматриваем состояние '*1'",
      "level" : "comment",
      "name" : "startAddNewTransitions"
    }, {
      "message" : "Добавляем состояние 'R2'.",
      "stateName" : "R2",
      "level" : "action",
      "name" : "addState"
    }, {
      "message" : "Добавляем в состояние 'R2' пункт '[L→*R•, =]'.",
      "state" : "R2",
      "item" : {
        "rule" : {
          "left" : "L",
          "right" : "*R"
        },
        "dotIndex" : 2,
        "lookAheadSymbol" : "="
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем в состояние 'R2' пункт '[L→*R•, ⊣]'.",
      "state" : "R2",
      "item" : {
        "rule" : {
          "left" : "L",
          "right" : "*R"
        },
        "dotIndex" : 2,
        "lookAheadSymbol" : "⊣"
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем переход из состояния '*1' в состояние 'R2' по символу 'R'.",
      "from" : "*1",
      "to" : "R2",
      "through" : "R",
      "level" : "action",
      "name" : "addTransition"
    }, {
      "message" : "Добавляем состояние 'L2'.",
      "stateName" : "L2",
      "level" : "action",
      "name" : "addState"
    }, {
      "message" : "Добавляем в состояние 'L2' пункт '[R→L•, ⊣]'.",
      "state" : "L2",
      "item" : {
        "rule" : {
          "left" : "R",
          "right" : "L"
        },
        "dotIndex" : 1,
        "lookAheadSymbol" : "⊣"
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем в состояние 'L2' пункт '[R→L•, =]'.",
      "state" : "L2",
      "item" : {
        "rule" : {
          "left" : "R",
          "right" : "L"
        },
        "dotIndex" : 1,
        "lookAheadSymbol" : "="
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем переход из состояния '*1' в состояние 'L2' по символу 'L'.",
      "from" : "*1",
      "to" : "L2",
      "through" : "L",
      "level" : "action",
      "name" : "addTransition"
    }, {
      "message" : "Добавляем переход из состояния '*1' в состояние '*1' по символу '*'.",
      "from" : "*1",
      "to" : "*1",
      "through" : "*",
      "level" : "action",
      "name" : "addTransition"
    }, {
      "message" : "Добавляем переход из состояния '*1' в состояние 'x1' по символу 'x'.",
      "from" : "*1",
      "to" : "x1",
      "through" : "x",
      "level" : "action",
      "name" : "addTransition"
    }, {
      "message" : "Просматриваем состояние '=1'",
      "level" : "comment",
      "name" : "startAddNewTransitions"
    }, {
      "message" : "Добавляем состояние 'R3'.",
      "stateName" : "R3",
      "level" : "action",
      "name" : "addState"
    }, {
      "message" : "Добавляем в состояние 'R3' пункт '[S→L=R•, ⊣]'.",
      "state" : "R3",
      "item" : {
        "rule" : {
          "left" : "S",
          "right" : "L=R"
        },
        "dotIndex" : 3,
        "lookAheadSymbol" : "⊣"
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем переход из состояния '=1' в состояние 'R3' по символу 'R'.",
      "from" : "=1",
      "to" : "R3",
      "through" : "R",
      "level" : "action",
      "name" : "addTransition"
    }, {
      "message" : "Добавляем состояние 'L3'.",
      "stateName" : "L3",
      "level" : "action",
      "name" : "addState"
    }, {
      "message" : "Добавляем в состояние 'L3' пункт '[R→L•, ⊣]'.",
      "state" : "L3",
      "item" : {
        "rule" : {
          "left" : "R",
          "right" : "L"
        },
        "dotIndex" : 1,
        "lookAheadSymbol" : "⊣"
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем переход из состояния '=1' в состояние 'L3' по символу 'L'.",
      "from" : "=1",
      "to" : "L3",
      "through" : "L",
      "level" : "action",
      "name" : "addTransition"
    }, {
      "message" : "Добавляем состояние '*2'.",
      "stateName" : "*2",
      "level" : "action",
      "name" : "addState"
    }, {
      "message" : "Добавляем в состояние '*2' пункт '[L→*•R, ⊣]'.",
      "state" : "*2",
      "item" : {
        "rule" : {
          "left" : "L",
          "right" : "*R"
        },
        "dotIndex" : 1,
        "lookAheadSymbol" : "⊣"
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем в состояние '*2' пункт '[R→•L, ⊣]'.",
      "state" : "*2",
      "item" : {
        "rule" : {
          "left" : "R",
          "right" : "L"
        },
        "dotIndex" : 0,
        "lookAheadSymbol" : "⊣"
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем в состояние '*2' пункт '[L→•*R, ⊣]'.",
      "state" : "*2",
      "item" : {
        "rule" : {
          "left" : "L",
          "right" : "*R"
        },
        "dotIndex" : 0,
        "lookAheadSymbol" : "⊣"
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем в состояние '*2' пункт '[L→•x, ⊣]'.",
      "state" : "*2",
      "item" : {
        "rule" : {
          "left" : "L",
          "right" : "x"
        },
        "dotIndex" : 0,
        "lookAheadSymbol" : "⊣"
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем переход из состояния '=1' в состояние '*2' по символу '*'.",
      "from" : "=1",
      "to" : "*2",
      "through" : "*",
      "level" : "action",
      "name" : "addTransition"
    }, {
      "message" : "Добавляем состояние 'x2'.",
      "stateName" : "x2",
      "level" : "action",
      "name" : "addState"
    }, {
      "message" : "Добавляем в состояние 'x2' пункт '[L→x•, ⊣]'.",
      "state" : "x2",
      "item" : {
        "rule" : {
          "left" : "L",
          "right" : "x"
        },
        "dotIndex" : 1,
        "lookAheadSymbol" : "⊣"
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем переход из состояния '=1' в состояние 'x2' по символу 'x'.",
      "from" : "=1",
      "to" : "x2",
      "through" : "x",
      "level" : "action",
      "name" : "addTransition"
    }, {
      "message" : "Просматриваем состояние 'R2'",
      "level" : "comment",
      "name" : "startAddNewTransitions"
    }, {
      "message" : "Просматриваем состояние 'L2'",
      "level" : "comment",
      "name" : "startAddNewTransitions"
    }, {
      "message" : "Просматриваем состояние 'R3'",
      "level" : "comment",
      "name" : "startAddNewTransitions"
    }, {
      "message" : "Просматриваем состояние 'L3'",
      "level" : "comment",
      "name" : "startAddNewTransitions"
    }, {
      "message" : "Просматриваем состояние '*2'",
      "level" : "comment",
      "name" : "startAddNewTransitions"
    }, {
      "message" : "Добавляем состояние 'R4'.",
      "stateName" : "R4",
      "level" : "action",
      "name" : "addState"
    }, {
      "message" : "Добавляем в состояние 'R4' пункт '[L→*R•, ⊣]'.",
      "state" : "R4",
      "item" : {
        "rule" : {
          "left" : "L",
          "right" : "*R"
        },
        "dotIndex" : 2,
        "lookAheadSymbol" : "⊣"
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем переход из состояния '*2' в состояние 'R4' по символу 'R'.",
      "from" : "*2",
      "to" : "R4",
      "through" : "R",
      "level" : "action",
      "name" : "addTransition"
    }, {
      "message" : "Добавляем переход из состояния '*2' в состояние 'L3' по символу 'L'.",
      "from" : "*2",
      "to" : "L3",
      "through" : "L",
      "level" : "action",
      "name" : "addTransition"
    }, {
      "message" : "Добавляем переход из состояния '*2' в состояние '*2' по символу '*'.",
      "from" : "*2",
      "to" : "*2",
      "through" : "*",
      "level" : "action",
      "name" : "addTransition"
    }, {
      "message" : "Добавляем переход из состояния '*2' в состояние 'x2' по символу 'x'.",
      "from" : "*2",
      "to" : "x2",
      "through" : "x",
      "level" : "action",
      "name" : "addTransition"
    }, {
      "message" : "Просматриваем состояние 'x2'",
      "level" : "comment",
      "name" : "startAddNewTransitions"
    }, {
      "message" : "Просматриваем состояние 'R4'",
      "level" : "comment",
      "name" : "startAddNewTransitions"
    }, {
      "message" : "Уплотняем полученный LR-автомат",
      "level" : "comment",
      "name" : "compactLRAutomaton"
    }, {
      "message" : "Удаляем переход из состояния '∇' в состояние '*1' по символу '*'.",
      "from" : "∇",
      "to" : "*1",
      "through" : "*",
      "level" : "action",
      "name" : "deleteTransition"
    }, {
      "message" : "Удаляем переход из состояния '*2' в состояние 'L3' по символу 'L'.",
      "from" : "*2",
      "to" : "L3",
      "through" : "L",
      "level" : "action",
      "name" : "deleteTransition"
    }, {
      "message" : "Удаляем переход из состояния '*1' в состояние 'L2' по символу 'L'.",
      "from" : "*1",
      "to" : "L2",
      "through" : "L",
      "level" : "action",
      "name" : "deleteTransition"
    }, {
      "message" : "Удаляем переход из состояния '*1' в состояние '*1' по символу '*'.",
      "from" : "*1",
      "to" : "*1",
      "through" : "*",
      "level" : "action",
      "name" : "deleteTransition"
    }, {
      "message" : "Удаляем переход из состояния '*2' в состояние 'R4' по символу 'R'.",
      "from" : "*2",
      "to" : "R4",
      "through" : "R",
      "level" : "action",
      "name" : "deleteTransition"
    }, {
      "message" : "Удаляем переход из состояния '*1' в состояние 'x1' по символу 'x'.",
      "from" : "*1",
      "to" : "x1",
      "through" : "x",
      "level" : "action",
      "name" : "deleteTransition"
    }, {
      "message" : "Удаляем переход из состояния '*2' в состояние '*2' по символу '*'.",
      "from" : "*2",
      "to" : "*2",
      "through" : "*",
      "level" : "action",
      "name" : "deleteTransition"
    }, {
      "message" : "Удаляем переход из состояния '*2' в состояние 'x2' по символу 'x'.",
      "from" : "*2",
      "to" : "x2",
      "through" : "x",
      "level" : "action",
      "name" : "deleteTransition"
    }, {
      "message" : "Удаляем переход из состояния '*1' в состояние 'R2' по символу 'R'.",
      "from" : "*1",
      "to" : "R2",
      "through" : "R",
      "level" : "action",
      "name" : "deleteTransition"
    }, {
      "message" : "Удаляем переход из состояния '∇' в состояние 'x1' по символу 'x'.",
      "from" : "∇",
      "to" : "x1",
      "through" : "x",
      "level" : "action",
      "name" : "deleteTransition"
    }, {
      "message" : "Удаляем переход из состояния '=1' в состояние '*2' по символу '*'.",
      "from" : "=1",
      "to" : "*2",
      "through" : "*",
      "level" : "action",
      "name" : "deleteTransition"
    }, {
      "message" : "Удаляем переход из состояния '=1' в состояние 'x2' по символу 'x'.",
      "from" : "=1",
      "to" : "x2",
      "through" : "x",
      "level" : "action",
      "name" : "deleteTransition"
    }, {
      "message" : "Удаляем переход из состояния '=1' в состояние 'L3' по символу 'L'.",
      "from" : "=1",
      "to" : "L3",
      "through" : "L",
      "level" : "action",
      "name" : "deleteTransition"
    }, {
      "message" : "Удаляем состояние 'R2'.",
      "stateName" : "R2",
      "level" : "action",
      "name" : "deleteState"
    }, {
      "message" : "Удаляем состояние 'R4'.",
      "stateName" : "R4",
      "level" : "action",
      "name" : "deleteState"
    }, {
      "message" : "Удаляем состояние 'L2'.",
      "stateName" : "L2",
      "level" : "action",
      "name" : "deleteState"
    }, {
      "message" : "Удаляем состояние '*1'.",
      "stateName" : "*1",
      "level" : "action",
      "name" : "deleteState"
    }, {
      "message" : "Удаляем состояние 'L3'.",
      "stateName" : "L3",
      "level" : "action",
      "name" : "deleteState"
    }, {
      "message" : "Удаляем состояние '*2'.",
      "stateName" : "*2",
      "level" : "action",
      "name" : "deleteState"
    }, {
      "message" : "Удаляем состояние 'x1'.",
      "stateName" : "x1",
      "level" : "action",
      "name" : "deleteState"
    }, {
      "message" : "Удаляем состояние 'x2'.",
      "stateName" : "x2",
      "level" : "action",
      "name" : "deleteState"
    }, {
      "message" : "Добавляем состояние 'R2;R4'.",
      "stateName" : "R2;R4",
      "level" : "action",
      "name" : "addState"
    }, {
      "message" : "Добавляем в состояние 'R2;R4' пункт '[L→*R•, =]'.",
      "state" : "R2;R4",
      "item" : {
        "rule" : {
          "left" : "L",
          "right" : "*R"
        },
        "dotIndex" : 2,
        "lookAheadSymbol" : "="
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем в состояние 'R2;R4' пункт '[L→*R•, ⊣]'.",
      "state" : "R2;R4",
      "item" : {
        "rule" : {
          "left" : "L",
          "right" : "*R"
        },
        "dotIndex" : 2,
        "lookAheadSymbol" : "⊣"
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем состояние 'L2;L3'.",
      "stateName" : "L2;L3",
      "level" : "action",
      "name" : "addState"
    }, {
      "message" : "Добавляем в состояние 'L2;L3' пункт '[R→L•, ⊣]'.",
      "state" : "L2;L3",
      "item" : {
        "rule" : {
          "left" : "R",
          "right" : "L"
        },
        "dotIndex" : 1,
        "lookAheadSymbol" : "⊣"
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем в состояние 'L2;L3' пункт '[R→L•, =]'.",
      "state" : "L2;L3",
      "item" : {
        "rule" : {
          "left" : "R",
          "right" : "L"
        },
        "dotIndex" : 1,
        "lookAheadSymbol" : "="
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем состояние '*1;*2'.",
      "stateName" : "*1;*2",
      "level" : "action",
      "name" : "addState"
    }, {
      "message" : "Добавляем в состояние '*1;*2' пункт '[L→*•R, ⊣]'.",
      "state" : "*1;*2",
      "item" : {
        "rule" : {
          "left" : "L",
          "right" : "*R"
        },
        "dotIndex" : 1,
        "lookAheadSymbol" : "⊣"
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем в состояние '*1;*2' пункт '[L→*•R, =]'.",
      "state" : "*1;*2",
      "item" : {
        "rule" : {
          "left" : "L",
          "right" : "*R"
        },
        "dotIndex" : 1,
        "lookAheadSymbol" : "="
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем в состояние '*1;*2' пункт '[R→•L, ⊣]'.",
      "state" : "*1;*2",
      "item" : {
        "rule" : {
          "left" : "R",
          "right" : "L"
        },
        "dotIndex" : 0,
        "lookAheadSymbol" : "⊣"
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем в состояние '*1;*2' пункт '[R→•L, =]'.",
      "state" : "*1;*2",
      "item" : {
        "rule" : {
          "left" : "R",
          "right" : "L"
        },
        "dotIndex" : 0,
        "lookAheadSymbol" : "="
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем в состояние '*1;*2' пункт '[L→•*R, ⊣]'.",
      "state" : "*1;*2",
      "item" : {
        "rule" : {
          "left" : "L",
          "right" : "*R"
        },
        "dotIndex" : 0,
        "lookAheadSymbol" : "⊣"
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем в состояние '*1;*2' пункт '[L→•x, ⊣]'.",
      "state" : "*1;*2",
      "item" : {
        "rule" : {
          "left" : "L",
          "right" : "x"
        },
        "dotIndex" : 0,
        "lookAheadSymbol" : "⊣"
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем в состояние '*1;*2' пункт '[L→•x, =]'.",
      "state" : "*1;*2",
      "item" : {
        "rule" : {
          "left" : "L",
          "right" : "x"
        },
        "dotIndex" : 0,
        "lookAheadSymbol" : "="
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем в состояние '*1;*2' пункт '[L→•*R, =]'.",
      "state" : "*1;*2",
      "item" : {
        "rule" : {
          "left" : "L",
          "right" : "*R"
        },
        "dotIndex" : 0,
        "lookAheadSymbol" : "="
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем состояние 'x1;x2'.",
      "stateName" : "x1;x2",
      "level" : "action",
      "name" : "addState"
    }, {
      "message" : "Добавляем в состояние 'x1;x2' пункт '[L→x•, ⊣]'.",
      "state" : "x1;x2",
      "item" : {
        "rule" : {
          "left" : "L",
          "right" : "x"
        },
        "dotIndex" : 1,
        "lookAheadSymbol" : "⊣"
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем в состояние 'x1;x2' пункт '[L→x•, =]'.",
      "state" : "x1;x2",
      "item" : {
        "rule" : {
          "left" : "L",
          "right" : "x"
        },
        "dotIndex" : 1,
        "lookAheadSymbol" : "="
      },
      "level" : "action",
      "name" : "addItem"
    }, {
      "message" : "Добавляем переход из состояния '=1' в состояние 'L2;L3' по символу 'L'.",
      "from" : "=1",
      "to" : "L2;L3",
      "through" : "L",
      "level" : "action",
      "name" : "addTransition"
    }, {
      "message" : "Добавляем переход из состояния '*1;*2' в состояние 'L2;L3' по символу 'L'.",
      "from" : "*1;*2",
      "to" : "L2;L3",
      "through" : "L",
      "level" : "action",
      "name" : "addTransition"
    }, {
      "message" : "Добавляем переход из состояния '*1;*2' в состояние 'R2;R4' по символу 'R'.",
      "from" : "*1;*2",
      "to" : "R2;R4",
      "through" : "R",
      "level" : "action",
      "name" : "addTransition"
    }, {
      "message" : "Добавляем переход из состояния '=1' в состояние 'x1;x2' по символу 'x'.",
      "from" : "=1",
      "to" : "x1;x2",
      "through" : "x",
      "level" : "action",
      "name" : "addTransition"
    }, {
      "message" : "Добавляем переход из состояния '*1;*2' в состояние 'x1;x2' по символу 'x'.",
      "from" : "*1;*2",
      "to" : "x1;x2",
      "through" : "x",
      "level" : "action",
      "name" : "addTransition"
    }, {
      "message" : "Добавляем переход из состояния '∇' в состояние 'x1;x2' по символу 'x'.",
      "from" : "∇",
      "to" : "x1;x2",
      "through" : "x",
      "level" : "action",
      "name" : "addTransition"
    }, {
      "message" : "Добавляем переход из состояния '∇' в состояние '*1;*2' по символу '*'.",
      "from" : "∇",
      "to" : "*1;*2",
      "through" : "*",
      "level" : "action",
      "name" : "addTransition"
    }, {
      "message" : "Добавляем переход из состояния '*1;*2' в состояние '*1;*2' по символу '*'.",
      "from" : "*1;*2",
      "to" : "*1;*2",
      "through" : "*",
      "level" : "action",
      "name" : "addTransition"
    }, {
      "message" : "Добавляем переход из состояния '=1' в состояние '*1;*2' по символу '*'.",
      "from" : "=1",
      "to" : "*1;*2",
      "through" : "*",
      "level" : "action",
      "name" : "addTransition"
    } ]
  }
}

POST api/{v1+}/build/lr1 (png)

Строит LR(1)-автомат. Результат возвращает в формате png.

Заголовки запроса

Имя Описание

Content-Type

image/png

Параметры пути

Имя Описание

version

версия API

Тело запроса

Поле Тип Обязательное Описание

.grammar

Object

Да

Грамматика, по которой требуется построить LR-автомат

.grammar.terminals

Array

Да

Список терминалов грамматики.

.grammar.nonTerminals

Array

Да

Список нетерминалов грамматики

.grammar.rules

Array

Да

Список правил грамматики

.grammar.rules[].left

String

Да

Нетерминал левой части правила грамматики

.grammar.rules[].right

String

Да

Символы правой части правила грамматики

.grammar.startSymbol

String

Да

Аксиома грамматики (нетерминал)

.buildOptions

Object

Нет

Параметры построения LR-автомата

.buildOptions.namesGenerationStrategy

String

Нет

Стратегия генерации имен состояний при построении автомата

visualizeOperations.colorizeTransitions

Boolean

Нет

Нужно ли окрашивать переходы автомата. По умолчанию не окрашиваются.

visualizeOperations.colorizeStateNames

Boolean

Нет

Окрашивать ли имена состояний. По умолчанию не окрашиваются.

visualizeOperations.stateNameStyle

String

Нет

Стиль оформления названия состояния. По умолчанию 'onBlackBackground'.

Заголовки ответа

Имя Описание

Content-Type

application/json

curl

$ curl 'http://localhost:8080/api/v1/build/lr1' -i -X POST \
    -H 'Content-Type: application/json' \
    -H 'Accept: image/png' \
    -d '{
  "grammar" : {
    "terminals" : [ "i", "+", "(", ")" ],
    "nonTerminals" : [ "E", "T" ],
    "rules" : [ {
      "left" : "E",
      "right" : "T"
    }, {
      "left" : "E",
      "right" : "E+T"
    }, {
      "left" : "T",
      "right" : "i"
    }, {
      "left" : "T",
      "right" : "(E)"
    } ],
    "startSymbol" : "E"
  }
}'

Пример запроса

POST /api/v1/build/lr1 HTTP/1.1
Content-Type: application/json
Accept: image/png
Content-Length: 342
Host: localhost:8080

{
  "grammar" : {
    "terminals" : [ "i", "+", "(", ")" ],
    "nonTerminals" : [ "E", "T" ],
    "rules" : [ {
      "left" : "E",
      "right" : "T"
    }, {
      "left" : "E",
      "right" : "E+T"
    }, {
      "left" : "T",
      "right" : "i"
    }, {
      "left" : "T",
      "right" : "(E)"
    } ],
    "startSymbol" : "E"
  }
}

Пример ответа

Пример построения lr(1)

POST api/{v1+}/build/lr1 (zip)

Строит LR(1)-автомат. Лог построения возвращает в zip архиве с изображениями автомата.

Заголовки запроса

Имя Описание

Accept

application/octet-stream

Параметры пути

Имя Описание

version

версия API

Тело запроса

Поле Тип Обязательное Описание

.grammar

Object

Да

Грамматика, по которой требуется построить LR-автомат

.grammar.terminals

Array

Да

Список терминалов грамматики.

.grammar.nonTerminals

Array

Да

Список нетерминалов грамматики

.grammar.rules

Array

Да

Список правил грамматики

.grammar.rules[].left

String

Да

Нетерминал левой части правила грамматики

.grammar.rules[].right

String

Да

Символы правой части правила грамматики

.grammar.startSymbol

String

Да

Аксиома грамматики (нетерминал)

.buildOptions

Object

Нет

Параметры построения LR-автомата

.buildOptions.namesGenerationStrategy

String

Нет

Стратегия генерации имен состояний при построении автомата

visualizeOperations.visualizeOperations

Array

Нет

Номера операций, которые нужно визуализировать. Если не указаны, то визуализируются все операции

visualizeOperations.colorizeTransitions

Boolean

Нет

Нужно ли окрашивать переходы автомата. По умолчанию не окрашиваются.

visualizeOperations.colorizeStateNames

Boolean

Нет

Окрашивать ли имена состояний. По умолчанию не окрашиваются.

visualizeOperations.stateNameStyle

String

Нет

Стиль оформления названия состояния. По умолчанию 'onBlackBackground'.

Заголовки ответа

Имя Описание

Content-Type

application/octet-stream (zip)

curl

$ curl 'http://localhost:8080/api/v1/build/lr1' -i -X POST \
    -H 'Content-Type: application/json' \
    -H 'Accept: application/octet-stream' \
    -d '{
  "grammar" : {
    "terminals" : [ "i", "+", "(", ")" ],
    "nonTerminals" : [ "E", "T" ],
    "rules" : [ {
      "left" : "E",
      "right" : "T"
    }, {
      "left" : "E",
      "right" : "E+T"
    }, {
      "left" : "T",
      "right" : "i"
    }, {
      "left" : "T",
      "right" : "(E)"
    } ],
    "startSymbol" : "E"
  }
}'

Пример запроса

POST /api/v1/build/lr1 HTTP/1.1
Content-Type: application/json
Accept: application/octet-stream
Content-Length: 342
Host: localhost:8080

{
  "grammar" : {
    "terminals" : [ "i", "+", "(", ")" ],
    "nonTerminals" : [ "E", "T" ],
    "rules" : [ {
      "left" : "E",
      "right" : "T"
    }, {
      "left" : "E",
      "right" : "E+T"
    }, {
      "left" : "T",
      "right" : "i"
    }, {
      "left" : "T",
      "right" : "(E)"
    } ],
    "startSymbol" : "E"
  }
}

POST api/{v1+}/grammar/first

Строит множества FIRST для каждого символа грамматики.

Заголовки запроса

Имя Описание

Accept

application/json

Параметры пути

Имя Описание

version

версия API

Тело запроса

Поле Тип Обязательное Описание

.terminals

Array

Да

Список терминалов грамматики.

.nonTerminals

Array

Да

Список нетерминалов грамматики

.rules

Array

Да

Список правил грамматики

.rules[].left

String

Да

Нетерминал левой части правила грамматики

.rules[].right

String

Да

Символы правой части правила грамматики

.startSymbol

String

Да

Аксиома грамматики (нетерминал)

Заголовки ответа

Имя Описание

Content-Type

application/json

Тело ответа

Поле Тип Обязательное Описание

*

Array

Да

Символы грамматики

*.[]

Array

Да

Множество FIRST для соответствующего символа грамматики

curl

$ curl 'http://localhost:8080/api/v1/grammar/first' -i -X POST \
    -H 'Content-Type: application/json' \
    -H 'Accept: application/json' \
    -d '{
  "terminals" : [ "a", "b" ],
  "nonTerminals" : [ "S", "A" ],
  "rules" : [ {
    "left" : "S",
    "right" : "AA"
  }, {
    "left" : "A",
    "right" : "aA"
  }, {
    "left" : "A",
    "right" : "b"
  } ],
  "startSymbol" : "S"
}'
Примеры

Пример запроса

POST /api/v1/grammar/first HTTP/1.1
Content-Type: application/json
Accept: application/json
Content-Length: 235
Host: localhost:8080

{
  "terminals" : [ "a", "b" ],
  "nonTerminals" : [ "S", "A" ],
  "rules" : [ {
    "left" : "S",
    "right" : "AA"
  }, {
    "left" : "A",
    "right" : "aA"
  }, {
    "left" : "A",
    "right" : "b"
  } ],
  "startSymbol" : "S"
}

Пример ответа

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 46

{
  "A" : [ "a", "b" ],
  "S" : [ "a", "b" ]
}

Грамматика

Грамматика передаётся в теле запроса при вызове методов построения LR-автоматов (POST api/{v1+}/build/lr0 (json), POST api/{v1+}/build/lalr1 (json), POST api/{v1+}/build/lr1 (json)).

Грамматика задаётся четвёркой:

  • список терминалов (terminals)

  • список нетерминалов (nonTerminals)

  • список правил (rules)

  • аксиома (startSymbol)

Терминалы

Терминалы передаются в поле terminals.

Это список символов, каждый из которых:

  • представляет собой строку длины 1

  • не должен совпадать ни с одним нетерминалом

  • не должен совпадать с прочими терминалами

Нетерминалы

Нетерминалы передаются в поле nonTerminals.

Это список символов, каждый из которых:

  • представляет собой строку длины 1

  • не должен совпадать ни с одним терминалом

  • не должен совпадать с прочими нетерминалами

Правила

Правила передаются в поле rules.

Каждое правило состоит из двух частей:

  • left - нетерминал левой части (должен содержаться в списке нетерминалов)

  • right - строка, задающая правую часть правила

Правая часть правила представляет собой последовательность символов, где каждый символ должен находится в объединении списков терминалов и нетерминалов.

Если right - пустая строка, правило считается ε-правилом.

Аксиома

Аксиома передаётся в поле startSymbol.

Это нетерминал из списка нетерминалов, с которого начинается вывод.

Аксиома должна принадлежать множеству нетерминалов

LR-автомат

LR-автомат возвращается в поле automaton при вызове методов построения:

LR-автомат состоит из:

Состояния

Состояния передаются в поле states

Каждое состояние содержит:

  • name - уникальное имя состояния

  • items - список LR-пунктов, принадлежащих состоянию

LR-пункты

Каждый элемент списка items представляет собой LR-пункт.

LR-пункт состоит из:

Поле dotIndex определяет положение точки в правой части правила:

  • 0 - точка стоит перед первым символом правой части правила

  • length(right) - точка стоит в конце правой части правила правила

  • 0 < dotIndex < length(right) - точка стоит в середине правой части правила на соответствующей позиции

Если правая часть правила пустая (ε-правило), допустимое значение dotIndex равно 0.

Состав LR-пунктов зависит от типа строящегося автомата:

В случае использования LR(1)-пунктов, добавляется поле lookAheadSymbol - символ предпросмотра. Значением поля является символ из списка рассматриваемых терминалов или же символ завершения строки .

Переходы

Переходы передаются в поле transitions.

Каждый переход содержит:

  • from - имя состояния, из которого осуществляется переход (Исходное состояние)

  • to - имя состояния, в которое осуществляется переход (Целевое состояние)

  • through - символ перехода

Символ through принадлежит объединению списков терминалов и нетерминалов исходной грамматики.

LR-автомат полностью восстанавливается последовательным применением операций из лога построения.

Лог построения LR-автоматов

Вместе с LR-автоматом (POST api/{v1+}/build/lr0 (json), POST api/{v1+}/build/lalr1 (json), POST api/{v1+}/build/lr1 (json)) в ответе возвращается лог построения автомата.

Лог представляет из себя массив операций, которые нужно произвести, чтобы построить требуемый автомат.

У каждой операции есть имя (name) и пояснительное сообщение (message).

Уровни операций

Операции различаются по уровню важности (level). Существует 2 уровня операций:

  • action

  • comment

action

Операция уровня action - ключевая операция, которую необходимо выполнить для построения автомата. Без её выполнения автомат будет построен некорректно или его дальнейшее построение окажется вовсе невозможным.

Таких операций всего 6. Вот их имена:

  • addState

  • deleteState

  • addItem

  • addTransition

  • deleteTransition

  • addLookAheadSymbol

Операции уровня action также имеют дополнительные поля (помимо name, level, message), которые описаны ниже.

comment

Операция уровня comment - вспомогательная, опциональная операция, помогающая восстановить рассуждения, которые производились, чтобы выполнить очередную операцию уровня action.

Поддерживаемые action операции

addState

Каждое состояние в автомате имеет уникальное имя.

Операция addState добавляет новое состояние c указанным именем в строящийся LR-автомат. В поле stateName операциии addState находится имя добавляемого состояния.

deleteState

Операция deleteState удаляет состояние c указанным именем в строящемся LR-автомате. В поле stateName операциии deleteState находится имя удаляемого состояния.

addItem

Операция addItem добавляет LR-пункт в одно из состояний строящегося автомата.

В поле state находится имя состояния строящегося автомата, в которое добавляется LR-пункт

В поле item находится добавляемый в это состояние LR-пункт

addTransition

Операция addTransition добавляет переход из одного состояние строящегося LR-автомата в другое.

  • В поле from находится имя состояния LR-автомата из которого осуществляется переход

  • В поле to находится имя состояния LR-автомата в которое осуществляется переход

  • В поле through находится символ грамматики через который осуществляется переход

deleteTransition

Операция deleteTransition удаляет переход из одного состояние строящегося LR-автомата в другое.

  • В поле from находится имя состояния LR-автомата из которого осуществляется переход

  • В поле to находится имя состояния LR-автомата в которое осуществляется переход

  • В поле through находится символ грамматики через который осуществляется переход

addLookAheadSymbol

Операция addLookAheadSymbol добавляет символ предпросмотра lookAheadSymbol к LR-пункту item в состоянии с именем stateName.

Пункт item, в который добавляется символ, описывается в секции.

Поддерживемые comment операции

  • buildLrAutomaton - начало построения LR-автомата.

  • extendGrammar - расширение исходной грамматики (добавление нового стартового правила).

  • startAddNewTransitions - начало обработки очередного состояния автомата - просмотр LR-пунктов состояния и поиск возможных переходов

  • compactLRAutomaton - при построении LALR(1)-автоматов классическим алгоритмом. Начало ужатия LR(1)-автомата до LALR(1) автомата путем объединения состояний с одинаковыми множествами ядер.

Параметры построения автомата

В запросах на построение LR-автоматов можно передать параметры, которые будут учитываться при построении

namesGenerationStrategy

Задает стратегию генерации имен состояния строящегося LR-автомата. Поддерживаются 2 стратегии:

byTransitionSymbol - по символу перехода.

Стартовому состоянию дается имя . Имя очередного состояния, добавляемого в процессе построения формируются в формате:

TRANSITION_SYMBOL + NUMBER

где:

  • TRANSITION_SYMBOL - лексическое значение символа, по которому осуществляется переход в новое состояние

  • NUMBER - порядковый номер состояния, присваиваемый автоматически при его добавлении в автомат. Нумерация начинается с 1 для первого добавленного состояния и увеличивается на 1 для каждого нового состояния.

используется по умолчанию

endToEndNumeric - сквозная нумерация состояний.

Стартовому состоянию дается имя 0. Каждое последующее добавляемое в автомат состояние получает имя в виде следующего целого числа (1, 2, 3, …​).

lalr1BuildAlgorithm

Задает алгоритм, с применением которого будет строиться LALR(1)-автомат.

Поддерживается 2 алгоритма:

classic - классический алгоритм построения LALR(1)-автомата.

Сперва строится LR(1)-автомат. После чего состояния с одинаковыми множествами ядер объединяются.

используется по умолчанию

channel - канальный алгоритм.

Эффективный алгоритм построения LALR(1)-автомата с применением механизмов спонтанной генерации символов предпросмотра на пунктах ядер lr(0)-автомата и их последующего распространения на другие пункты до тех пор, пока процесс не стабилизируется.

enableBuildLog

Передавать ли в ответе лог построения автомата. По умолчанию false.

Параметры визуализации автомата

В запросах на построение LR-автоматов можно передать параметры, которые будут учитываться при его визуализации.

visualizeOperations

Массив номеров операций лога построения, которые нужно визуализировать. Операции нумеруются с 0.

colorizeTransitions

Окрашивать ли переходы автомата в разные цвета. С каждым символом перехода связан свой цвет.

Поддерживается 20 цветов. После исчерпания палитры цвета начинают повторяться.

colorizeStateNames

Окрашивать ли имена состояний в цвет перехода, по которому это состояние было впервые добавлено в автомат.

Применяется только с включенным параметром colorizeTransitions
Не поддерживается методами POST api/{v1+}/build/lalr1 (png), POST api/{v1+}/build/lalr1 (zip) при использовании алгоритма classic.

stateNameStyle

Стиль оформления названия состояния.

Поддерживается 2 стиля:

onBlackBackground - название состояния на чёрном фоне.

используется по умолчанию

boldOnWhiteBackground - название состояния жирным шрифтом на белом фоне.