Skip to content

Commit

Permalink
Merge pull request #216 from piknotech/frontend
Browse files Browse the repository at this point in the history
Create Frontend package
  • Loading branch information
Ericson2314 authored Dec 1, 2021
2 parents ede899b + ee48e33 commit 11e3e78
Show file tree
Hide file tree
Showing 25 changed files with 214 additions and 140 deletions.
10 changes: 9 additions & 1 deletion .github/workflows/haskell-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@ jobs:
run: |
touch cabal.project
echo "packages: $GITHUB_WORKSPACE/source/." >> cabal.project
echo "packages: $GITHUB_WORKSPACE/source/packages/frontend" >> cabal.project
echo "packages: $GITHUB_WORKSPACE/source/packages/grammar" >> cabal.project
echo "packages: $GITHUB_WORKSPACE/source/packages/tabular" >> cabal.project
cat cabal.project
Expand All @@ -188,14 +189,19 @@ jobs:
echo "PKGDIR_happy_tabular=${PKGDIR_happy_tabular}" >> "$GITHUB_ENV"
PKGDIR_happy_grammar="$(find "$GITHUB_WORKSPACE/unpacked" -maxdepth 1 -type d -regex '.*/happy-grammar-[0-9.]*')"
echo "PKGDIR_happy_grammar=${PKGDIR_happy_grammar}" >> "$GITHUB_ENV"
PKGDIR_happy_frontend="$(find "$GITHUB_WORKSPACE/unpacked" -maxdepth 1 -type d -regex '.*/happy-frontend-[0-9.]*')"
echo "PKGDIR_happy_frontend=${PKGDIR_happy_frontend}" >> "$GITHUB_ENV"
PKGDIR_happy="$(find "$GITHUB_WORKSPACE/unpacked" -maxdepth 1 -type d -regex '.*/happy-[0-9.]*')"
echo "PKGDIR_happy=${PKGDIR_happy}" >> "$GITHUB_ENV"
rm -f cabal.project cabal.project.local
touch cabal.project
touch cabal.project.local
echo "packages: ${PKGDIR_happy_frontend}" >> cabal.project
echo "packages: ${PKGDIR_happy_tabular}" >> cabal.project
echo "packages: ${PKGDIR_happy_grammar}" >> cabal.project
echo "packages: ${PKGDIR_happy}" >> cabal.project
if [ $((HCNUMVER >= 80200)) -ne 0 ] ; then echo "package happy-frontend" >> cabal.project ; fi
if [ $((HCNUMVER >= 80200)) -ne 0 ] ; then echo " ghc-options: -Werror=missing-methods" >> cabal.project ; fi
if [ $((HCNUMVER >= 80200)) -ne 0 ] ; then echo "package happy-tabular" >> cabal.project ; fi
if [ $((HCNUMVER >= 80200)) -ne 0 ] ; then echo " ghc-options: -Werror=missing-methods" >> cabal.project ; fi
if [ $((HCNUMVER >= 80200)) -ne 0 ] ; then echo "package happy-grammar" >> cabal.project ; fi
Expand All @@ -204,7 +210,7 @@ jobs:
if [ $((HCNUMVER >= 80200)) -ne 0 ] ; then echo " ghc-options: -Werror=missing-methods" >> cabal.project ; fi
cat >> cabal.project <<EOF
EOF
$HCPKG list --simple-output --names-only | perl -ne 'for (split /\s+/) { print "constraints: $_ installed\n" unless /^(containers|happy|happy-tabular|happy-grammar|mtl|transformers)$/; }' >> cabal.project.local
$HCPKG list --simple-output --names-only | perl -ne 'for (split /\s+/) { print "constraints: $_ installed\n" unless /^(containers|happy|happy-tabular|happy-grammar|happy-frontend|mtl|transformers)$/; }' >> cabal.project.local
cat cabal.project
cat cabal.project.local
- name: dump install plan
Expand Down Expand Up @@ -239,6 +245,8 @@ jobs:
${CABAL} -vnormal check
cd ${PKGDIR_happy_grammar} || false
${CABAL} -vnormal check
cd ${PKGDIR_happy_frontend} || false
${CABAL} -vnormal check
cd ${PKGDIR_happy} || false
${CABAL} -vnormal check
- name: unconstrained build
Expand Down
1 change: 1 addition & 0 deletions cabal.project
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
packages:
packages/frontend
packages/grammar
packages/tabular
./
33 changes: 2 additions & 31 deletions happy.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -142,11 +142,6 @@ extra-source-files:
tests/rank2.y
tests/shift01.y

flag bootstrap
description: Optimize the implementation of happy using a pre-built happy
manual: True
default: True

source-repository head
type: git
location: https://github.com/simonmar/happy.git
Expand All @@ -160,42 +155,18 @@ executable happy
containers >= 0.4.2,
mtl >= 2.2.1,
happy-grammar == 1.21.0,
happy-tabular == 1.21.0
happy-tabular == 1.21.0,
happy-frontend == 1.21.0

default-language: Haskell98
default-extensions: CPP, MagicHash, FlexibleContexts, NamedFieldPuns
ghc-options: -Wall
other-modules:
Paths_happy
AbsSyn
GenUtils
Lexer
Mangler
ParseMonad
ParseMonad.Class
Parser
ProduceCode
ProduceGLRCode
Target
AttrGrammar
ParamRules
PrettyGrammar

if flag(bootstrap)
-- TODO put this back when Cabal can use it's qualified goals to better
-- understand bootstrapping, see
-- https://github.com/haskell/cabal/issues/7189
--build-tools: happy
cpp-options: -DHAPPY_BOOTSTRAP
other-modules:
ParseMonad.Bootstrapped
Parser.Bootstrapped
AttrGrammarParser
else
other-modules:
ParseMonad.Oracle
Parser.Oracle


test-suite tests
type: exitcode-stdio-1.0
Expand Down
1 change: 1 addition & 0 deletions packages/frontend/LICENSE
2 changes: 2 additions & 0 deletions packages/frontend/Setup.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
import Distribution.Simple
main = defaultMain
81 changes: 81 additions & 0 deletions packages/frontend/happy-frontend.cabal
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
name: happy-frontend
version: 1.21.0
license: BSD2
license-file: LICENSE
copyright: (c) Andy Gill, Simon Marlow
author: Andy Gill and Simon Marlow
maintainer: Simon Marlow <[email protected]>
bug-reports: https://github.com/simonmar/happy/issues
stability: stable
homepage: https://www.haskell.org/happy/
category: Development
cabal-version: >= 1.10
build-type: Simple
synopsis: A yacc-like frontend for happy

Description:
Happy is a parser generator for Haskell.
Happy-Frontend is responsible for parsing .y- and .ly-files
and mangling them into a Grammar datatype.
These .y- and .ly-files work similar to yacc's .y-files, but
have some Haskell-specific features.

tested-with:
GHC == 7.0.4
GHC == 7.4.2
GHC == 7.6.3
GHC == 7.8.4
GHC == 7.10.3
GHC == 8.0.2
GHC == 8.2.2
GHC == 8.4.4
GHC == 8.6.5
GHC == 8.8.4
GHC == 8.10.4
GHC == 9.0.1

flag bootstrap
description: Optimize the implementation of happy using a pre-built happy
manual: True
default: True

library
hs-source-dirs: src
exposed-modules: Happy.Frontend,
Happy.Frontend.AbsSyn,
Happy.Frontend.Mangler,
Happy.Frontend.PrettyGrammar

build-depends: base < 5,
array,
containers >= 0.4.2,
transformers >= 0.5.6.2,
mtl >= 2.2.2,
happy-grammar == 1.21.0

default-language: Haskell98
default-extensions: CPP, MagicHash, FlexibleContexts
ghc-options: -Wall
other-modules:
Happy.Frontend.ParseMonad
Happy.Frontend.ParseMonad.Class
Happy.Frontend.AttrGrammar
Happy.Frontend.Parser
Happy.Frontend.Lexer
Happy.Frontend.ParamRules


if flag(bootstrap)
-- TODO put this back when Cabal can use it's qualified goals to better
-- understand bootstrapping, see
-- https://github.com/haskell/cabal/issues/7189
--build-tools: happy
cpp-options: -DHAPPY_BOOTSTRAP
other-modules:
Happy.Frontend.ParseMonad.Bootstrapped
Happy.Frontend.Parser.Bootstrapped
Happy.Frontend.AttrGrammar.Parser
else
other-modules:
Happy.Frontend.ParseMonad.Oracle
Happy.Frontend.Parser.Oracle
40 changes: 40 additions & 0 deletions packages/frontend/src/Happy/Frontend.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
module Happy.Frontend where

import Happy.Frontend.AbsSyn
import Happy.Frontend.Parser
import Happy.Frontend.ParseMonad.Class

parseYFileContents :: String -> ParseResult AbsSyn
parseYFileContents contents = runFromStartP ourParser contents 1

data FileType = Y | LY

fileNameAndType :: String -> Maybe (String, FileType)
fileNameAndType = nameType . reverse where
nameType ('y':'.':f) = Just (reverse f, Y)
nameType ('y':'l':'.':f) = Just (reverse f, LY)
nameType _ = Nothing

-- Delit, converting an ly file into a y file.
deLitify :: String -> String
deLitify = deLit where
deLit ('>':' ':r) = deLit1 r
deLit ('>':'\t':r) = '\t' : deLit1 r
deLit ('>':'\n':r) = deLit r
deLit ('>':_) = error "Error when de-litify-ing"
deLit ('\n':r) = '\n' : deLit r
deLit r = deLit2 r
deLit1 ('\n':r) = '\n' : deLit r
deLit1 (c:r) = c : deLit1 r
deLit1 [] = []
deLit2 ('\n':r) = '\n' : deLit r
deLit2 (_:r) = deLit2 r
deLit2 [] = []

-- Iff happy is built with bootstrapping, attribute grammars are supported
supportsParsingAttributeGrammars :: Bool
#ifdef HAPPY_BOOTSTRAP
supportsParsingAttributeGrammars = True
#else
supportsParsingAttributeGrammars = False
#endif
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Abstract syntax for grammar files.

Here is the abstract syntax of the language we parse.

> module AbsSyn (
> module Happy.Frontend.AbsSyn (
> AbsSyn(..), Directive(..),
> getTokenType, getTokenSpec, getParserNames, getLexer,
> getImportedIdentity, getMonad, getError,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
> module AttrGrammar
> module Happy.Frontend.AttrGrammar
> ( AgToken (..)
> , AgRule (..)
> , HasLexer (..)
Expand All @@ -9,7 +9,7 @@
> ) where

> import Data.Char
> import ParseMonad.Class
> import Happy.Frontend.ParseMonad.Class

> data AgToken
> = AgTok_LBrace
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ or a conditional statement.

> {
> {-# OPTIONS_GHC -w #-}
> module AttrGrammarParser (agParser) where
> import ParseMonad.Class
> import ParseMonad.Bootstrapped
> import AttrGrammar
> module Happy.Frontend.AttrGrammar.Parser (agParser) where
> import Happy.Frontend.ParseMonad.Class
> import Happy.Frontend.ParseMonad.Bootstrapped
> import Happy.Frontend.AttrGrammar
> }

> %name agParser
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ The lexer.
(c) 1993-2001 Andy Gill, Simon Marlow
-----------------------------------------------------------------------------

> module Lexer (
> module Happy.Frontend.Lexer (
> Token(..),
> TokenId(..),
> HasLexer(..) ) where

> import ParseMonad.Class
> import Happy.Frontend.ParseMonad.Class

> import Data.Char ( isSpace, isAlphaNum, isDigit, digitToInt )

Expand Down
33 changes: 22 additions & 11 deletions src/Mangler.lhs → ...s/frontend/src/Happy/Frontend/Mangler.lhs
Original file line number Diff line number Diff line change
Expand Up @@ -6,29 +6,29 @@ The Grammar data type.

Mangler converts AbsSyn to Grammar

> module Mangler (mangler) where
> module Happy.Frontend.Mangler (mangler) where

> import Happy.Grammar
> import GenUtils
> import AbsSyn
> import Happy.Frontend.AbsSyn
#ifdef HAPPY_BOOTSTRAP
> import ParseMonad.Class
> import AttrGrammar
> import Happy.Frontend.ParseMonad.Class
> import Happy.Frontend.AttrGrammar
#endif

This is only supported in the bootstrapped version
#ifdef HAPPY_BOOTSTRAP
> import AttrGrammarParser
> import Data.List ( findIndices, groupBy, intersperse, nub, sortBy )
> import Happy.Frontend.AttrGrammar.Parser
> import Data.List ( findIndices, groupBy, intersperse, nub )
> import Control.Monad ( when )
#endif

> import ParamRules
> import Happy.Frontend.ParamRules

> import Data.Array ( Array, (!), accumArray, array, listArray )
> import Data.Char ( isAlphaNum, isDigit, isLower )
> import Data.List ( zip4 )
> import Data.List ( zip4, sortBy )
> import Data.Maybe ( fromMaybe )
> import Data.Ord

> import Control.Monad.Writer ( Writer, MonadWriter(..), mapWriter, runWriter )

Expand Down Expand Up @@ -129,13 +129,13 @@ Deal with priorities...

> prios = [ (name,mkPrio i dir)
> | (i,dir) <- priodir
> , nm <- AbsSyn.getPrioNames dir
> , nm <- getPrioNames dir
> , name <- lookupName nm
> ]

> prioByString = [ (name, mkPrio i dir)
> | (i,dir) <- priodir
> , name <- AbsSyn.getPrioNames dir
> , name <- getPrioNames dir
> ]

Translate the rules from string to name-based.
Expand Down Expand Up @@ -261,6 +261,17 @@ Get the token specs in terms of Names.
> attributetype = attrType
> })

Gofer-like stuff:

> combinePairs :: (Ord a) => [(a,b)] -> [(a,[b])]
> combinePairs xs =
> combine [ (a,[b]) | (a,b) <- sortBy (comparing fst) xs]
> where
> combine [] = []
> combine ((a,b):(c,d):r) | a == c = combine ((a,b++d) : r)
> combine (a:r) = a : combine r
>

For combining actions with possible error messages.

> addLine :: Int -> String -> String
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module ParamRules(expand_rules, Prod1(..), Rule1(..)) where
module Happy.Frontend.ParamRules(expand_rules, Prod1(..), Rule1(..)) where

import AbsSyn
import Happy.Frontend.AbsSyn
import Control.Monad.Writer
import Control.Monad.Except
import Data.List(partition,intersperse)
Expand Down
8 changes: 8 additions & 0 deletions packages/frontend/src/Happy/Frontend/ParseMonad.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
module Happy.Frontend.ParseMonad (module X) where

-- We use the bootstrapped version if it is available
#ifdef HAPPY_BOOTSTRAP
import Happy.Frontend.ParseMonad.Bootstrapped as X
#else
import Happy.Frontend.ParseMonad.Oracle as X
#endif
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@
{-# OPTIONS_GHC -fno-warn-orphans #-}
#endif

module ParseMonad.Bootstrapped where
module Happy.Frontend.ParseMonad.Bootstrapped where

import Control.Monad.Reader
import ParseMonad.Class
import Happy.Frontend.ParseMonad.Class

type P = ReaderT (String, Int) ParseResult

Expand Down
Loading

0 comments on commit 11e3e78

Please sign in to comment.