Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix similar function header parsing error #75

Merged
merged 5 commits into from
Jan 26, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion core/deno.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@
},
"name": "@dalbit-yaksok/core",
"exports": "./mod.ts",
"version": "0.2.0-RC.7"
"version": "0.2.0-RC.8"
}
33 changes: 33 additions & 0 deletions core/prepare/parse/dynamicRule/functions/declare-rule/common.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { Expression, Identifier } from '../../../../../node/base.ts'
import { type Token, TOKEN_TYPE } from '../../../../tokenize/token.ts'
import type { PatternUnit } from '../../../type.ts'

export function functionHeaderToPattern(tokens: Token[]): PatternUnit[] {
const units = tokens.map(mapTokenToPatternUnit).filter(Boolean)
return units as NonNullable<(typeof units)[number]>[]
}

function mapTokenToPatternUnit(token: Token): PatternUnit | null {
if (token.type === TOKEN_TYPE.IDENTIFIER) {
return {
type: Identifier,
value: token.value,
}
}

if (token.type === TOKEN_TYPE.OPENING_PARENTHESIS) {
return {
type: Expression,
value: '(',
}
}

if (token.type === TOKEN_TYPE.CLOSING_PARENTHESIS) {
return {
type: Expression,
value: ')',
}
}

return null
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { Evaluable, Expression, Identifier } from '../../../../../node/base.ts'
import { DeclareFFI, FFIBody } from '../../../../../node/ffi.ts'
import { EOL } from '../../../../../node/misc.ts'
import { Token } from '../../../../tokenize/token.ts'
import { PatternUnit, Rule } from '../../../type.ts'
import { functionHeaderToPattern } from './common.ts'

const PREFIX: PatternUnit[] = [
{
type: Identifier,
value: '번역',
},
{
type: Expression,
value: '(',
},
{
type: Evaluable,
},
{
type: Expression,
value: ')',
},
{
type: Expression,
value: ',',
},
]

const SUFFIX: PatternUnit[] = [
{
type: EOL,
},
{
type: FFIBody,
},
]

export function tokensToFFIDeclareRule(headerTokens: Token[]): Rule {
const headerPattern = functionHeaderToPattern(headerTokens)
const pattern = [...PREFIX, ...headerPattern, ...SUFFIX]

return {
pattern,
factory: (nodes, matchedTokens) => {
const runtime = (nodes[2] as Identifier).value
const body = (nodes[nodes.length - 1] as FFIBody).code
const name = headerTokens
.map((token) => token.value)
.join('')
.trim()

return new DeclareFFI(
{
name,
runtime,
body,
},
matchedTokens,
)
},
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { Expression, Identifier } from '../../../../../node/base.ts'
import { Block } from '../../../../../node/block.ts'
import { DeclareFunction } from '../../../../../node/function.ts'
import { EOL } from '../../../../../node/misc.ts'
import { Token } from '../../../../tokenize/token.ts'
import { PatternUnit, Rule } from '../../../type.ts'
import { functionHeaderToPattern } from './common.ts'

const PREFIX: PatternUnit[] = [
{
type: Identifier,
value: '약속',
},
{
type: Expression,
value: ',',
},
]

const SUFFIX: PatternUnit[] = [
{
type: EOL,
},
{
type: Block,
},
]

export function tokensToYaksokDeclareRule(headerTokens: Token[]): Rule {
const headerPattern = functionHeaderToPattern(headerTokens)
const pattern = [...PREFIX, ...headerPattern, ...SUFFIX]

return {
pattern,
factory: (nodes, matchedNodes) => {
const body = nodes[nodes.length - 1] as Block

const name = headerTokens
.map((token) => token.value)
.join('')
.trim()

return new DeclareFunction(
{
body,
name,
},
matchedNodes,
)
},
}
}
29 changes: 9 additions & 20 deletions core/prepare/parse/dynamicRule/functions/get-function-templates.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,8 @@ import {
} from '../../../../type/function-template.ts'
import { Token, TOKEN_TYPE } from '../../../tokenize/token.ts'

export function getFunctionTemplatesFromTokens(
tokens: Token[],
functionDeclareRanges: [number, number][],
type: string,
) {
const functionTemplatesTokens = functionDeclareRanges.map(([start, end]) =>
tokens.slice(start, end),
)

const functionTemplates = functionTemplatesTokens.map((tokens) =>
convertTokensToFunctionTemplate(tokens, type),
)

return functionTemplates
}

function convertTokensToFunctionTemplate(
export function convertTokensToFunctionTemplate(
_tokens: Token[],
type: string,
): FunctionTemplate {
const tokens = _tokens.map((token) => ({ ...token }))

Expand All @@ -52,9 +35,16 @@ function convertTokensToFunctionTemplate(
}
}

if (token.value.includes('/')) {
return {
type: 'static',
value: [...token.value.split('/'), token.value],
}
}

return {
type: 'static',
value: [...token.value.split('/'), token.value],
value: [token.value],
}
})
.filter(Boolean) as FunctionTemplatePiece[]
Expand All @@ -69,7 +59,6 @@ function convertTokensToFunctionTemplate(
return {
name: functionName,
pieces,
type,
}
}

Expand Down
40 changes: 21 additions & 19 deletions core/prepare/parse/dynamicRule/functions/index.ts
Original file line number Diff line number Diff line change
@@ -1,33 +1,35 @@
import { getFunctionTemplatesFromTokens } from './get-function-templates.ts'
import { convertTokensToFunctionTemplate } from './get-function-templates.ts'
import { tokensToFFIDeclareRule } from './declare-rule/ffi-declare-rule.ts'
import { createFunctionInvokeRule } from './invoke-rule.ts'
import { getFunctionDeclareRanges } from '../../../../util/get-function-declare-ranges.ts'

import { getFunctionDeclareRanges } from '../../../../util/get-function-declare-ranges.ts'
import type { Token } from '../../../tokenize/token.ts'
import { tokensToYaksokDeclareRule } from './declare-rule/yaksok-declare-rule.ts'

export function createLocalDynamicRules(
tokens: Token[],
functionDeclareRanges: [number, number][] = getFunctionDeclareRanges(
tokens,
),
functionDeclareRanges = getFunctionDeclareRanges(tokens),
) {
const yaksokTemplates = getFunctionTemplatesFromTokens(
tokens,
functionDeclareRanges,
'yaksok',
)
const getTokensFromRange = getTokensFromRangeFactory(tokens)

const ffiTemplates = getFunctionTemplatesFromTokens(
tokens,
functionDeclareRanges,
'ffi',
)
const yaksokHeaders = functionDeclareRanges.yaksok.map(getTokensFromRange)
const ffiHeaders = functionDeclareRanges.ffi.map(getTokensFromRange)

const invokingRules = [...yaksokHeaders, ...ffiHeaders]
.map(convertTokensToFunctionTemplate)
.flatMap(createFunctionInvokeRule)
.toSorted((a, b) => b.pattern.length - a.pattern.length)

const yaksokInvokeRules = yaksokTemplates.flatMap(createFunctionInvokeRule)
const ffiInvokeRules = ffiTemplates.flatMap(createFunctionInvokeRule)
const ffiDeclareRules = ffiHeaders.map(tokensToFFIDeclareRule)

const allRules = [...yaksokInvokeRules, ...ffiInvokeRules].toSorted(
const yaksokDeclareRules = yaksokHeaders.map(tokensToYaksokDeclareRule)
const declareRules = [...ffiDeclareRules, ...yaksokDeclareRules].toSorted(
(a, b) => b.pattern.length - a.pattern.length,
)

return allRules
return [declareRules, invokingRules]
}

const getTokensFromRangeFactory =
(tokens: Token[]) => (range: [number, number]) =>
tokens.slice(range[0], range[1])
2 changes: 1 addition & 1 deletion core/prepare/parse/dynamicRule/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,5 @@ export function createDynamicRule(codeFile: CodeFile) {

const mentioningRules = getRulesFromMentioningFile(codeFile)

return [...mentioningRules, ...localRules]
return [...localRules, mentioningRules]
}
7 changes: 4 additions & 3 deletions core/prepare/parse/index.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import { convertTokensToNodes } from '../lex/convert-tokens-to-nodes.ts'
import { getTokensFromNodes } from '../../util/merge-tokens.ts'
import { createDynamicRule } from './dynamicRule/index.ts'
import { SetVariable } from '../../node/variable.ts'
import { YaksokError } from '../../error/common.ts'
import { callParseRecursively } from './srParse.ts'
import { Identifier } from '../../node/base.ts'
import { parseIndent } from './parse-indent.ts'
import { Block } from '../../node/block.ts'

import type { CodeFile } from '../../type/code-file.ts'
import type { Rule } from './type.ts'
import { getTokensFromNodes } from '../../util/merge-tokens.ts'
import { YaksokError } from '../../error/common.ts'

interface ParseResult {
ast: Block
Expand All @@ -19,7 +19,8 @@ interface ParseResult {
export function parse(codeFile: CodeFile): ParseResult {
try {
const dynamicRules = createDynamicRule(codeFile)
const indentedNodes = parseIndent(convertTokensToNodes(codeFile.tokens))
const nodes = convertTokensToNodes(codeFile.tokens)
const indentedNodes = parseIndent(nodes)

const childNodes = callParseRecursively(indentedNodes, dynamicRules)
const childTokens = getTokensFromNodes(childNodes)
Expand Down
89 changes: 0 additions & 89 deletions core/prepare/parse/rule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -289,95 +289,6 @@ export const BASIC_RULES: Rule[][] = [
],
factory: (_nodes, tokens) => new RangeOperator(tokens),
},
{
pattern: [
{
type: Identifier,
value: '약속',
},
{
type: Expression,
value: ',',
},
{
type: FunctionInvoke,
},
{
type: EOL,
},
{
type: Block,
},
],
factory: (nodes, tokens) => {
const [_, __, functionInvoke, ___, body] = nodes as [
unknown,
unknown,
FunctionInvoke,
unknown,
Block,
]

const functionName = functionInvoke.name

return new DeclareFunction(
{
body,
name: functionName,
},
tokens,
)
},
flags: [RULE_FLAGS.IS_STATEMENT],
},
{
pattern: [
{
type: Identifier,
value: '번역',
},
{
type: ValueWithParenthesis,
},
{
type: Expression,
value: ',',
},
{
type: FunctionInvoke,
},
{
type: EOL,
},
{
type: FFIBody,
},
],
factory: (nodes, tokens) => {
const [_, runtimeNode, __, functionInvoke, ___, body] =
nodes as [
unknown,
ValueWithParenthesis,
unknown,
FunctionInvoke,
unknown,
FFIBody,
]

const functionName = functionInvoke.name
const runtime = (runtimeNode.value as Identifier).value

return new DeclareFFI(
{
body: body.code,
name: functionName,
runtime,
},
tokens,
)
},
flags: [RULE_FLAGS.IS_STATEMENT],
},
],
]

Expand Down
Loading
Loading