module DrawLR0Parser exposing (..) -- import GrammarABequallyOften as ConcreteGrammar -- import Round import AppWithUndo import AuxiliaryStuff import Browser import ContextFreeGrammar import Debug exposing (log) import Html exposing (Attribute, Html, button, div, input, text) import Html.Attributes as Att import Html.Events exposing (onClick, onInput, onMouseEnter, onMouseLeave) import Html.Events.Extra.Mouse as Mouse import LR0Parser import ParseTree exposing (..) import Svg exposing (..) import Svg.Attributes import Svg.Events import SvgAuxiliary exposing (..) import Tgrammar as Grammar import Tree exposing (..) import TreeToSvg import ZoomSvg exposing (ZoomSvg) {-- main : Program () Model Msg main = Browser.element { init = init , view = view , update = update , subscriptions = \_ -> Sub.none -- subscriptions is stuff we want to listen to, beyond the input elements of our web app -- this could, for example, be web sockets ... } --} main = Browser.element (AppWithUndo.addUndoButton recordMessage { init = init , view = view , update = update , subscriptions = \_ -> Sub.none -- subscriptions is stuff we want to listen to, beyond the input elements of our web app -- this could, for example, be web sockets ... } ) type alias Model = { trees : List (Tree String) , svgCanvas : ZoomSvg Msg , inputWord : String -- the value of the input field , restInputWord : List Char -- the portion not yet read by parser , stack : List ( ParseTree Char Grammar.Nonterminal, Grammar.State ) } type Msg = SvgCanvasMessage ZoomSvg.Message | InputChanged String | MakeParserStep | ResetParser recordMessage : Msg -> Bool recordMessage message = case message of SvgCanvasMessage _ -> False _ -> True init : () -> ( Model, Cmd Msg ) init _ = ( { trees = [ Tree { data = "dummy root" , children = [ Tree.leaf "dummy tree" , Tree { data = "dummy child", children = [ Tree.leaf "another dummy leaf" ] } ] } , Tree { data = "A" , children = [ Tree.leaf "B" , Tree.leaf "C" ] } ] , svgCanvas = ZoomSvg.makeZoomableSvgCanvas SvgCanvasMessage viewboxLeft viewboxTop viewboxWidth viewboxHeight viewboxWidth viewboxHeight , inputWord = Grammar.exampleInputWord , restInputWord = String.toList Grammar.exampleInputWord , stack = [] } , Cmd.none ) update : Msg -> Model -> ( Model, Cmd Msg ) update msg model = case msg of InputChanged s -> ( { model | inputWord = s, restInputWord = String.toList s, stack = [] }, Cmd.none ) ResetParser -> ( { model | restInputWord = String.toList model.inputWord, stack = [] }, Cmd.none ) MakeParserStep -> let ( newRestInputWord, newStack, success ) = LR0Parser.lr0parserStep Grammar.dkAutomaton model.restInputWord model.stack parseTrees : List (ParseTree Char Grammar.Nonterminal) parseTrees = List.map Tuple.first (List.reverse newStack) stringTrees : List (Tree String) stringTrees = List.map parseTreeToTreeString parseTrees in ( { model | restInputWord = newRestInputWord , stack = newStack , trees = stringTrees } , Cmd.none ) SvgCanvasMessage childMessage -> ( { model | svgCanvas = ZoomSvg.update childMessage model.svgCanvas }, Cmd.none ) css path = Html.node "link" [ Att.rel "stylesheet", Att.href path ] [] view : Model -> Html Msg view model = div [ Att.style "padding" "10px" , Att.style "width" "100vw" ] [ css "https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css" , css "style.css" , Html.p [] [ Html.text "source can be found under ", Html.code [] [ Html.text "/TI/elm/cfg-in-class/DrawLR0Parser.elm" ] ] , Html.h2 [] [ Html.text "LR0-Parser step by step " ] , div [ -- , Html.Attributes.style "border" "1pt black solid" Att.style "margin" "20px" , Att.class "svgdiv row" ] [ div [ Att.class "col-sm-2" ] [ div [] [ Html.input [ Att.style "margin" "5px", Att.value model.inputWord, Html.Events.onInput InputChanged ] [] ] , div [] [ Html.button [ Att.style "margin" "5px", Html.Events.onClick MakeParserStep ] [ Html.text "step" ] , Html.button [ Att.style "margin" "5px", Html.Events.onClick ResetParser ] [ Html.text "reset" ] ] ] , div [ Att.class "col-sm-10" ] [ div [] [ Html.pre [] [ Html.text (String.fromList model.restInputWord ++ "\n" ++ LR0Parser.stackToString (List.reverse model.stack) ) ] ] , div [ Att.style "border" "1pt solid black" ] [ ZoomSvg.view model.svgCanvas [] (TreeToSvg.drawTreePlain False model.svgCanvas.zoom { rootBox | top = rootBox.top + 50 } (Tree { data = "dummy root", children = model.trees } ) ) ] ] ] ]