Skip to content

Commit

Permalink
Initialize YAPB
Browse files Browse the repository at this point in the history
  • Loading branch information
kwanghoon committed Jun 25, 2020
0 parents commit 82336b9
Show file tree
Hide file tree
Showing 124 changed files with 61,199 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
.stack-work/
*~
21 changes: 21 additions & 0 deletions ChangeLog.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Changelog
All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.1.0] - 2020-06-25
### Added
- Readme.md

### Changed
- Rename genlrparser into yapb
- Write packages.yaml (generating yapb.cabal automatically) for making yapb available as a Hackage library

### Fixed
- Fixed hard-coded usage of genlrparser-exe in GenLRParserTable.hs

### Removed
- n/a


30 changes: 30 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
Copyright Author name here (c) 2020

All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.

* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.

* Neither the name of Author name here nor the names of other
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
162 changes: 162 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@

## YAPB: Yet Another Parser Builder

### A programmable parser builder system
- Allows to write LALR(1) parser specifications in Haskell
- Provides an automatic syntax completion method

### Library, tools, and examples
- yapb: a library for a programmable parser builder system
- yapb-exe: a wrapper interface to YAPB
- conv-exe: a grammar format utility for conversion of a readable grammar (.lgrm) format into the Haskell data format (.grm)
- syncomp-exe: a syntax completion server for Emacs
- Examples:
-- parser-exe: an arithmetic parser
-- polyrpc-exe: a polyrpc programming language system including a parser, a poly rpc type checker, a slicing compiler, a poly cs type checker, and an poly cs interpter.

### Download and build
~~~
$ git clone https://github.com/kwanghoon/yapb
$ cd yapb
$ stack build
~~~

### How to write and run a parser
~~~
$ ls app/parser/*.hs
app/parser/Lexer.hs app/parser/Main.hs app/parser/Parser.hs app/parser/Token.hs
$ cat app/parser/Lexer.hs
module Lexer(lexerSpec) where
import Prelude hiding (EQ)
import CommonParserUtil
import Token
mkFn :: Token -> (String -> Maybe Token)
mkFn tok = \text -> Just tok
skip :: String -> Maybe Token
skip = \text -> Nothing
lexerSpec :: LexerSpec Token
lexerSpec = LexerSpec
{
endOfToken = END_OF_TOKEN,
lexerSpecList =
[ ("[ \t\n]", skip),
("[0-9]+" , mkFn INTEGER_NUMBER),
("\\(" , mkFn OPEN_PAREN),
("\\)" , mkFn CLOSE_PAREN),
("\\+" , mkFn ADD),
("\\-" , mkFn SUB),
("\\*" , mkFn MUL),
("\\/" , mkFn DIV),
("\\=" , mkFn EQ),
("\\;" , mkFn SEMICOLON),
("[a-zA-Z][a-zA-Z0-9]*" , mkFn IDENTIFIER)
]
}
$ cat app/parser/Parser.hs
module Parser where
import CommonParserUtil
import Token
import Expr
parserSpec :: ParserSpec Token AST
parserSpec = ParserSpec
{
startSymbol = "SeqExpr'",
parserSpecList =
[
("SeqExpr' -> SeqExpr", \rhs -> get rhs 1),
("SeqExpr -> SeqExpr ; AssignExpr",
\rhs -> toAstSeq (
fromAstSeq (get rhs 1) ++ [fromAstExpr (get rhs 3)]) ),
("SeqExpr -> AssignExpr", \rhs -> toAstSeq [fromAstExpr (get rhs 1)]),
("AssignExpr -> identifier = AssignExpr",
\rhs -> toAstExpr (Assign (getText rhs 1) (fromAstExpr (get rhs 3))) ),
("AssignExpr -> AdditiveExpr", \rhs -> get rhs 1),
("AdditiveExpr -> AdditiveExpr + MultiplicativeExpr",
\rhs -> toAstExpr (
BinOp Expr.ADD (fromAstExpr (get rhs 1)) (fromAstExpr (get rhs 3))) ),
("AdditiveExpr -> AdditiveExpr - MultiplicativeExpr",
\rhs -> toAstExpr (
BinOp Expr.SUB (fromAstExpr (get rhs 1)) (fromAstExpr (get rhs 3))) ),
("AdditiveExpr -> MultiplicativeExpr", \rhs -> get rhs 1),
("MultiplicativeExpr -> MultiplicativeExpr * PrimaryExpr",
\rhs -> toAstExpr (
BinOp Expr.MUL (fromAstExpr (get rhs 1)) (fromAstExpr (get rhs 3))) ),
("MultiplicativeExpr -> MultiplicativeExpr / PrimaryExpr",
\rhs -> toAstExpr (
BinOp Expr.DIV (fromAstExpr (get rhs 1)) (fromAstExpr (get rhs 3))) ),
("MultiplicativeExpr -> PrimaryExpr", \rhs -> get rhs 1),
("PrimaryExpr -> identifier", \rhs -> toAstExpr (Var (getText rhs 1)) ),
("PrimaryExpr -> integer_number",
\rhs -> toAstExpr (Lit (read (getText rhs 1))) ),
("PrimaryExpr -> ( AssignExpr )", \rhs -> get rhs 2)
],
baseDir = "./",
actionTblFile = "action_table.txt",
gotoTblFile = "goto_table.txt",
grammarFile = "prod_rules.txt",
parserSpecFile = "mygrammar.grm",
genparserexe = "yapb-exe"
}
$ cat app/parser/example/oneline.arith
1 + 2 - 3 * 4 / 5
$ cat app/parser/example/multiline.arith
x = 123;
x = x + 1;
y = x;
y = y - 1 * 2 / 3;
z = y = x
$ stack exec parser-exe
Enter your file: app/parser/example/oneline.arith
Lexing...
Parsing...
done.
Pretty Printing...
((1 + 2) - ((3 * 4) / 5))
$ stack exec parser-exe
Enter your file: app/parser/example/multiline.arith
Lexing...
Parsing...
done.
Pretty Printing...
(x = 123); (x = (x + 1)); (y = x); (y = (y - ((1 * 2) / 3))); (z = (y = x))
~~~

### Documents
- [Parser generators sharing LR automaton generators and accepting general-purpose programming language-based specifications, J. of KIISE, 47(1), January 2020](http://swlab.jnu.ac.kr/paper/kiise202001.pdf) Written in Korean.
- [A topdown approach to writing a compiler](https://github.com/kwanghoon/swlab_parser_builder/blob/master/doc/tutorial_swlab_parser_builder.txt) Written in Korean.
- Parser tool architecture
* <img src="https://github.com/kwanghoon/genlrparser/blob/master/doc/parsertoolarchitecture.png"/>
- C++/Java/Python parser builder systems using YAPB
-- [Java parser](https://github.com/kwanghoon/swlab_parser_builder)
-- [C++ parser](https://github.com/tlsdorye/swlab-parser-lib)
-- [Python parser](https://github.com/limjintack/swlab_parser_python).

2 changes: 2 additions & 0 deletions Setup.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
import Distribution.Simple
main = defaultMain
10 changes: 10 additions & 0 deletions app/conv/Main.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
module Main where

import ReadGrammar

-- How to run:
-- $ stack exec conv-exe grm/polyrpc.lgrm

main = test conversion


30 changes: 30 additions & 0 deletions app/parser/Lexer.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
module Lexer(lexerSpec) where

import Prelude hiding (EQ)
import CommonParserUtil
import Token

mkFn :: Token -> (String -> Maybe Token)
mkFn tok = \text -> Just tok

skip :: String -> Maybe Token
skip = \text -> Nothing

lexerSpec :: LexerSpec Token
lexerSpec = LexerSpec
{
endOfToken = END_OF_TOKEN,
lexerSpecList =
[ ("[ \t\n]", skip),
("[0-9]+" , mkFn INTEGER_NUMBER),
("\\(" , mkFn OPEN_PAREN),
("\\)" , mkFn CLOSE_PAREN),
("\\+" , mkFn ADD),
("\\-" , mkFn SUB),
("\\*" , mkFn MUL),
("\\/" , mkFn DIV),
("\\=" , mkFn EQ),
("\\;" , mkFn SEMICOLON),
("[a-zA-Z][a-zA-Z0-9]*" , mkFn IDENTIFIER)
]
}
42 changes: 42 additions & 0 deletions app/parser/Main.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
module Main where

import CommonParserUtil

import Lexer
import Terminal
import Parser
import Expr

import System.IO

main :: IO ()
main = do
fileName <- readline "Enter your file: "
case fileName of
"exit" -> return ()
line -> doProcess line

doProcess line = do
text <- readFile line
putStrLn "Lexing..."
terminalList <- lexing lexerSpec text
putStrLn "Parsing..."
exprSeqAst <- parsing parserSpec terminalList
putStrLn "Pretty Printing..."
putStrLn (pprintAst exprSeqAst)


readline msg = do
putStr msg
hFlush stdout
readline'

readline' = do
ch <- getChar
if ch == '\n' then
return ""
else
do line <- readline'
return (ch:line)


64 changes: 64 additions & 0 deletions app/parser/Parser.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
module Parser where

import CommonParserUtil
import Token
import Expr


parserSpec :: ParserSpec Token AST
parserSpec = ParserSpec
{
startSymbol = "SeqExpr'",

parserSpecList =
[
("SeqExpr' -> SeqExpr", \rhs -> get rhs 1),

("SeqExpr -> SeqExpr ; AssignExpr",
\rhs -> toAstSeq (
fromAstSeq (get rhs 1) ++ [fromAstExpr (get rhs 3)]) ),

("SeqExpr -> AssignExpr", \rhs -> toAstSeq [fromAstExpr (get rhs 1)]),

("AssignExpr -> identifier = AssignExpr",
\rhs -> toAstExpr (Assign (getText rhs 1) (fromAstExpr (get rhs 3))) ),

("AssignExpr -> AdditiveExpr", \rhs -> get rhs 1),

("AdditiveExpr -> AdditiveExpr + MultiplicativeExpr",
\rhs -> toAstExpr (
BinOp Expr.ADD (fromAstExpr (get rhs 1)) (fromAstExpr (get rhs 3))) ),

("AdditiveExpr -> AdditiveExpr - MultiplicativeExpr",
\rhs -> toAstExpr (
BinOp Expr.SUB (fromAstExpr (get rhs 1)) (fromAstExpr (get rhs 3))) ),

("AdditiveExpr -> MultiplicativeExpr", \rhs -> get rhs 1),

("MultiplicativeExpr -> MultiplicativeExpr * PrimaryExpr",
\rhs -> toAstExpr (
BinOp Expr.MUL (fromAstExpr (get rhs 1)) (fromAstExpr (get rhs 3))) ),

("MultiplicativeExpr -> MultiplicativeExpr / PrimaryExpr",
\rhs -> toAstExpr (
BinOp Expr.DIV (fromAstExpr (get rhs 1)) (fromAstExpr (get rhs 3))) ),

("MultiplicativeExpr -> PrimaryExpr", \rhs -> get rhs 1),

("PrimaryExpr -> identifier", \rhs -> toAstExpr (Var (getText rhs 1)) ),

("PrimaryExpr -> integer_number",
\rhs -> toAstExpr (Lit (read (getText rhs 1))) ),

("PrimaryExpr -> ( AssignExpr )", \rhs -> get rhs 2)
],

baseDir = "./",
actionTblFile = "action_table.txt",
gotoTblFile = "goto_table.txt",
grammarFile = "prod_rules.txt",
parserSpecFile = "mygrammar.grm",
genparserexe = "yapb-exe"
}


Loading

0 comments on commit 82336b9

Please sign in to comment.