Skip to content

Commit e84275a

Browse files
author
Andreas Westerwick
committed
lex parse stack
0 parents  commit e84275a

File tree

11 files changed

+437
-0
lines changed

11 files changed

+437
-0
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
.stack-work/

LICENSE

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
Copyright (c) Andreas Westerwick 2018
2+
3+
All rights reserved.
4+
5+
Redistribution and use in source and binary forms, with or without
6+
modification, are permitted provided that the following conditions
7+
are met:
8+
1. Redistributions of source code must retain the above copyright
9+
notice, this list of conditions and the following disclaimer.
10+
2. Redistributions in binary form must reproduce the above copyright
11+
notice, this list of conditions and the following disclaimer in the
12+
documentation and/or other materials provided with the distribution.
13+
3. Neither the name of the author nor the names of his contributors
14+
may be used to endorse or promote products derived from this software
15+
without specific prior written permission.
16+
17+
THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND
18+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20+
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
21+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23+
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24+
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25+
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26+
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27+
SUCH DAMAGE.

Language/FIRRTL.hs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
-- | A parser for FIRRTL.
2+
module Language.FIRRTL
3+
( module Language.FIRRTL.AST
4+
, module Language.FIRRTL.Parser
5+
) where
6+
7+
import Language.FIRRTL.AST
8+
import Language.FIRRTL.Parser
9+

Language/FIRRTL/AST.hs

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
{-# LANGUAGE OverloadedStrings #-}
2+
3+
module Language.FIRRTL.AST where
4+
5+
import Data.Text (Text)
6+
7+
type Identifier = Text
8+
9+
10+
data Circuit = Circuit Identifier (Maybe Info) [Module]
11+
deriving (Eq, Show)
12+
13+
data Module
14+
= Module Identifier (Maybe Info) [Port] Statement
15+
| ExternalModule Identifier (Maybe Info) [Port]
16+
deriving (Eq, Show)
17+
18+
data Port = Port Direction Identifier Type (Maybe Info)
19+
deriving (Eq, Show)
20+
21+
data Direction = Input | Output
22+
deriving (Eq, Show)
23+
24+
data Type
25+
= UIntType (Maybe Int)
26+
| SIntType (Maybe Int)
27+
| FixedType (Maybe Int) (Maybe Int)
28+
| ClockType
29+
| AnalogType (Maybe Int)
30+
| BundleType [Field]
31+
| VectorType Type Int
32+
deriving (Eq, Show)
33+
34+
data Field = Field (Maybe Flip) Identifier Type
35+
deriving (Eq, Show)
36+
37+
data Statement
38+
= Wire Identifier Type (Maybe Info)
39+
| Register Identifier Type Exp (Maybe (Exp, Exp)) (Maybe Info)
40+
| Memory Identifier (Maybe Info) Type Int Int Int RuW [Identifier] [Identifier] [Identifier]
41+
| Instance Identifier Identifier (Maybe Info)
42+
| Node Identifier Exp (Maybe Info)
43+
| Connect Exp Exp (Maybe Info)
44+
| PartialConnect Exp Exp (Maybe Info)
45+
| Invalidate Exp (Maybe Info)
46+
| Attach [Exp] (Maybe Info)
47+
| Conditional Exp (Maybe Info) Statement (Maybe Statement)
48+
| Stop Exp Exp Int (Maybe Info)
49+
| Printf Exp Exp Text [Exp] (Maybe Info)
50+
| Empty (Maybe Info)
51+
| Group [Statement]
52+
deriving (Eq, Show)
53+
54+
data RuW = Old | New | Undefined
55+
deriving (Eq, Show)
56+
57+
data Flip = Flip
58+
deriving (Eq, Show)
59+
60+
newtype Info = Info Text
61+
deriving (Eq, Show)
62+
63+
data Exp
64+
= UIntFromInt (Maybe Int) Int
65+
| UIntFromBits (Maybe Int) Text
66+
| SIntFromInt (Maybe Int) Int
67+
| SIntFromBits (Maybe Int) Text
68+
| Reference Identifier
69+
| Subfield Exp Identifier
70+
| Subindex Exp Int
71+
| Subaccess Exp Exp
72+
| Multiplexor Exp Exp Exp
73+
| ValidIf Exp Exp
74+
| PrimOp [Exp] [Int]
75+
deriving (Eq, Show)
76+

Language/FIRRTL/Parser.hs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
2+
module Language.FIRRTL.Parser where
3+
4+
import Data.Text
5+
6+
import Language.FIRRTL.AST
7+
import Language.FIRRTL.Parser.Lex
8+
import Language.FIRRTL.Parser.Parse
9+
import Language.FIRRTL.Parser.Tokens
10+
11+
parseFile :: [(Text, Text)] -> FilePath -> Text -> Circuit
12+
parseFile env file content = circuit tokens
13+
where
14+
tokens = fmap relocate $ lexer file content
15+
relocate :: Token -> Token
16+
relocate (Token t s (Position _ l c)) = Token t s $ Position file l c
17+

Language/FIRRTL/Parser/Lex.x

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
{
2+
{-# OPTIONS_GHC -w #-}
3+
module Language.FIRRTL.Parser.Lex
4+
( lexer
5+
) where
6+
7+
import Data.Char (ord)
8+
import qualified Data.Text as T
9+
import qualified Data.Text.Encoding as T
10+
11+
import Language.FIRRTL.Parser.Tokens
12+
13+
}
14+
15+
$any = [.\n\r]
16+
@newline = [\n\r] | \r\n
17+
@comment = "/*" $any* "*/"
18+
| "//" .* @newline
19+
20+
-- Numbers
21+
22+
$nonZeroDecimalDigit = [1-9]
23+
$decimalDigit = [0-9]
24+
@binaryDigit = [0-1]
25+
@octalDigit = [0-7]
26+
@hexDigit = [0-9a-fA-F]
27+
28+
$sign = [\+\-]
29+
30+
@decimalBase = "'" [dD]
31+
@binaryBase = "'" [bB]
32+
@octalBase = "'" [oO]
33+
@hexBase = "'" [s]? [hH]
34+
35+
@binaryValue = @binaryDigit ("_" | @binaryDigit)*
36+
@octalValue = @octalDigit ("_" | @octalDigit)*
37+
@hexValue = @hexDigit ("_" | @hexDigit)*
38+
39+
@unsignedNumber = $decimalDigit ("_" | $decimalDigit)*
40+
41+
@size = $sign? @unsignedNumber
42+
43+
@decimalNumber
44+
= @unsignedNumber
45+
| @size? @decimalBase @unsignedNumber
46+
47+
@binaryNumber = @size? @binaryBase @binaryValue
48+
@octalNumber = @size? @octalBase @octalValue
49+
@hexNumber = @size? @hexBase @hexValue
50+
51+
-- $exp = [eE]
52+
53+
-- @realNumber = unsignedNumber "." unsignedNumber | unsignedNumber ( "." unsignedNumber)? exp sign? unsignedNumber
54+
@number = @decimalNumber | @octalNumber | @binaryNumber | @hexNumber
55+
56+
-- Strings
57+
58+
@string = \" [^\r\n]* \"
59+
60+
-- Identifiers
61+
62+
@escapedIdentifier = "\" ($printable # $white)+ $white
63+
@simpleIdentifier = [a-zA-Z_] [a-zA-Z0-9_\$]*
64+
@systemIdentifier = "$" [a-zA-Z0-9_\$]+
65+
66+
67+
tokens :-
68+
69+
@comment ;
70+
71+
$white ;
72+
73+
. { tok Tok_Unknown }
74+
75+
{
76+
tok :: TokenName -> AlexPosn -> String -> Token
77+
tok t (AlexPn _ l c) s = Token t s $ Position "" l c
78+
79+
lexer :: String -> T.Text -> [Token]
80+
lexer file text = go (alexStartPos, '\n', text `T.snoc` '\n')
81+
where
82+
go inp@(pos, _, cs) = case {-# SCC "alexScan" #-} alexScan inp 0 of
83+
AlexEOF -> []
84+
AlexError inp' -> error (errMsg inp')
85+
AlexSkip inp' _ -> go inp'
86+
AlexToken inp' len act -> act pos (T.unpack $ T.take len cs) : go inp'
87+
88+
errMsg (AlexPn _ line col, _, cs) =
89+
file ++ ": lexical error (line " ++ show line ++ ", col " ++ show col ++ ")\n"
90+
++ " near " ++ show (T.unpack $ T.take 40 cs)
91+
92+
-----------------------------------------------------------
93+
94+
type AlexInput = (AlexPosn, -- current position,
95+
Char, -- previous char
96+
T.Text) -- current input string
97+
98+
alexInputPrevChar :: AlexInput -> Char
99+
alexInputPrevChar (_,c,_) = c
100+
101+
alexGetChar :: AlexInput -> Maybe (Char,AlexInput)
102+
alexGetChar (p,_,cs) | T.null cs = Nothing
103+
| {-# SCC "alexSkip" #-} alexSkip c = alexGetChar (p', c, cs')
104+
| otherwise = p' `seq` cs' `seq` Just (c, (p', c, cs'))
105+
where
106+
c = T.head cs
107+
cs' = T.tail cs
108+
p' = alexMove p c
109+
110+
alexGetByte :: AlexInput -> Maybe (Int,AlexInput)
111+
alexGetByte i = case alexGetChar i of
112+
Nothing -> Nothing
113+
Just (c, j) -> Just (ord c, j)
114+
115+
alexSkip :: Char -> Bool
116+
alexSkip '\xFEFF' = True
117+
alexSkip _ = False
118+
119+
-----------------------------------------------------------
120+
121+
data AlexPosn = AlexPn !Int !Int !Int
122+
deriving (Eq,Show)
123+
124+
alexStartPos :: AlexPosn
125+
alexStartPos = AlexPn 0 1 1
126+
127+
alexMove :: AlexPosn -> Char -> AlexPosn
128+
alexMove (AlexPn a l c) '\t' = AlexPn (a+1) l (((c+7) `div` 8)*8+1)
129+
alexMove (AlexPn a l _) '\n' = AlexPn (a+1) (l+1) 1
130+
alexMove (AlexPn a l c) _ = AlexPn (a+1) l (c+1)
131+
}
132+
133+

Language/FIRRTL/Parser/Parse.y

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
{
2+
module Language.FIRRTL.Parser.Parse where
3+
4+
import Data.Bits
5+
import Data.List
6+
7+
import Language.FIRRTL.AST
8+
import Language.FIRRTL.Parser.Tokens
9+
}
10+
11+
%name circuit
12+
%tokentype { Token }
13+
%error { parseError }
14+
15+
%expect 0
16+
17+
%token
18+
19+
"add" { Token Tok_Add _ _ }
20+
21+
%%
22+
23+
Circuit :: { Circuit }
24+
: { Circuit mempty Nothing mempty }
25+
26+
27+
{
28+
parseError :: [Token] -> a
29+
parseError a = case a of
30+
[] -> error "Parse error: no tokens left to parse."
31+
Token t s p : _ -> error $ "Parse error: unexpected token '" ++ s ++ "' (" ++ show t ++ ") at " ++ show p ++ "."
32+
33+
toString :: Token -> String
34+
toString = tail . init . tokenString
35+
36+
}
37+

Language/FIRRTL/Parser/Tokens.hs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
2+
module Language.FIRRTL.Parser.Tokens where
3+
4+
import Data.Text
5+
import Text.Printf
6+
7+
tokenString :: Token -> String
8+
tokenString (Token _ s _) = s
9+
10+
data Position = Position String Int Int deriving Eq
11+
12+
instance Show Position where
13+
show (Position f l c) = printf "%s:%d:%d" f l c
14+
15+
data Token = Token TokenName String Position deriving (Show, Eq)
16+
17+
data TokenName
18+
= Tok_Add
19+
| Tok_Unknown
20+
deriving (Show, Eq)
21+

Setup.hs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
module Main (main) where
2+
3+
import Distribution.Simple (defaultMain)
4+
5+
main :: IO ()
6+
main = defaultMain

firrtl.cabal

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
name: firrtl
2+
version: 0.0.1
3+
4+
category: Language, Hardware, Embedded
5+
6+
synopsis: FIRRTL preprocessor, parser, and AST.
7+
8+
description:
9+
A parser and supporting a small subset of FIRRTL.
10+
Intended for machine generated, synthesizable code.
11+
12+
author: Andreas Westerwick <[email protected]>
13+
maintainer: Andreas Westerwick <[email protected]>
14+
15+
license: BSD3
16+
license-file: LICENSE
17+
18+
homepage: http://github.com/foshardware/firrtl
19+
20+
build-type: Simple
21+
cabal-version: >= 1.10
22+
23+
library
24+
default-language: Haskell2010
25+
build-tools:
26+
alex,
27+
happy
28+
build-depends:
29+
base,
30+
array,
31+
text
32+
33+
exposed-modules:
34+
Language.FIRRTL
35+
Language.FIRRTL.AST
36+
Language.FIRRTL.Parser
37+
Language.FIRRTL.Parser.Lex
38+
Language.FIRRTL.Parser.Parse
39+
Language.FIRRTL.Parser.Tokens
40+
41+
ghc-options: -W
42+
43+
source-repository head
44+
type: git
45+
location: git://github.com/foshardware/firrtl.git
46+

0 commit comments

Comments
 (0)